Documentation ¶
Overview ¶
Package waddrmgr provides a secure hierarchical deterministic wallet address manager.
Overview ¶
One of the fundamental jobs of a wallet is to manage addresses, private keys, and script data associated with them. At a high level, this package provides the facilities to perform this task with a focus on security and also allows recovery through the use of hierarchical deterministic keys (BIP0032) generated from a caller provided seed. The specific structure used is as described in BIP0044. This setup means as long as the user writes the seed down (even better is to use a mnemonic for the seed), all their addresses and private keys can be regenerated from the seed.
There are two master keys which are protected by two independent passphrases. One is intended for public facing data, while the other is intended for private data. The public password can be hardcoded for callers who don't want the additional public data protection or the same password can be used if a single password is desired. These choices provide a usability versus security tradeoff. However, keep in mind that extended hd keys, as called out in BIP0032 need to be handled more carefully than normal EC public keys because they can be used to generate all future addresses. While this is part of what makes them attractive, it also means an attacker getting access to your extended public key for an account will allow them to know all derived addresses you will use and hence reduces privacy. For this reason, it is highly recommended that you do not hard code a password which allows any attacker who gets a copy of your address manager database to access your effectively plain text extended public keys.
Each master key in turn protects the three real encryption keys (called crypto keys) for public, private, and script data. Some examples include payment addresses, extended hd keys, and scripts associated with pay-to-script-hash addresses. This scheme makes changing passphrases more efficient since only the crypto keys need to be re-encrypted versus every single piece of information (which is what is needed for *rekeying*). This results in a fully encrypted database where access to it does not compromise address, key, or script privacy. This differs from the handling by other wallets at the time of this writing in that they divulge your addresses, and worse, some even expose the chain code which can be used by the attacker to know all future addresses that will be used.
The address manager is also hardened against memory scrapers. This is accomplished by typically having the address manager locked meaning no private keys or scripts are in memory. Unlocking the address manager causes the crypto private and script keys to be decrypted and loaded in memory which in turn are used to decrypt private keys and scripts on demand. Relocking the address manager actively zeros all private material from memory. In addition, temp private key material used internally is zeroed as soon as it's used.
Locking and Unlocking ¶
As previously mentioned, this package provide facilities for locking and unlocking the address manager to protect access to private material and remove it from memory when locked. The Lock, Unlock, and IsLocked functions are used for this purpose.
Creating a New Address Manager ¶
A new address manager is created via the Create function. This function accepts a wallet database namespace, passphrases, network, and perhaps most importantly, a cryptographically random seed which is used to generate the master node of the hierarchical deterministic keychain which allows all addresses and private keys to be recovered with only the seed. The GenerateSeed function in the hdkeychain package can be used as a convenient way to create a random seed for use with this function. The address manager is locked immediately upon being created.
Opening an Existing Address Manager ¶
An existing address manager is opened via the Open function. This function accepts an existing wallet database namespace, the public passphrase, and network. The address manager is opened locked as expected since the open function does not take the private passphrase to unlock it.
Closing the Address Manager ¶
The Close method should be called on the address manager when the caller is done with it. While it is not required, it is recommended because it sanely shuts down the database and ensures all private and public key material is purged from memory.
Managed Addresses ¶
Each address returned by the address manager satisifies the ManagedAddress interface as well as either the ManagedPubKeyAddress or ManagedScriptAddress interfaces. These interfaces provide the means to obtain relevant information about the addresses such as their private keys and scripts.
Chained Addresses ¶
Most callers will make use of the chained addresses for normal operations. Internal addresses are intended for internal wallet uses such as change outputs, while external addresses are intended for uses such payment addresses that are shared. The NextInternalAddresses and NextExternalAddresses functions provide the means to acquire one or more of the next addresses that have not already been provided. In addition, the LastInternalAddress and LastExternalAddress functions can be used to get the most recently provided internal and external address, respectively.
Requesting Existing Addresses ¶
In addition to generating new addresses, access to old addresses is often required. Most notably, to sign transactions in order to redeem them. The Address function provides this capability and returns a ManagedAddress.
Importing Addresses ¶
While the recommended approach is to use the chained addresses discussed above because they can be deterministically regenerated to avoid losing funds as long as the user has the master seed, there are many addresses that already exist, and as a result, this package provides the ability to import existing private keys in Wallet Import Format (WIF) and hence the associated public key and address.
Importing Scripts ¶
In order to support pay-to-script-hash transactions, the script must be securely stored as it is needed to redeem the transaction. This can be useful for a variety of scenarios, however the most common use is currently multi-signature transactions.
Syncing ¶
The address manager also supports storing and retrieving a block hash and height which the manager is known to have all addresses synced through. The manager itself does not have any notion of which addresses are synced or not. It only provides the storage as a convenience for the caller.
Network ¶
The address manager must be associated with a given network in order to provide appropriate addresses and reject imported addresses and scripts which don't apply to the associated network.
Errors ¶
All errors returned from this package are of type ManagerError. This allows the caller to programmatically ascertain the specific reasons for failure by examining the ErrorCode field of the type asserted ManagerError. For certain error codes, as documented by the specific error codes, the underlying error will be contained in the Err field.
Bitcoin Improvement Proposals ¶
This package includes concepts outlined by the following BIPs:
BIP0032 (https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) BIP0043 (https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki) BIP0044 (https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)
Index ¶
- Constants
- Variables
- func Create(ns walletdb.ReadWriteBucket, rootKey *hdkeychain.ExtendedKey, ...) error
- func DeleteBirthdayBlock(ns walletdb.ReadWriteBucket) error
- func DisableLog()
- func IsDefaultScope(scope KeyScope) bool
- func IsError(err error, code ErrorCode) bool
- func PutBirthdayBlock(ns walletdb.ReadWriteBucket, block BlockStamp) error
- func PutSyncedTo(ns walletdb.ReadWriteBucket, bs *BlockStamp) error
- func UseLogger(logger btclog.Logger)
- func ValidateAccountName(name string) error
- type AccountProperties
- type AddressType
- type BlockStamp
- type CryptoKeyType
- type DerivationPath
- type EncryptorDecryptor
- type ErrorCode
- type HDVersion
- type Identity
- type KeyScope
- type ManagedAddress
- type ManagedPubKeyAddress
- type ManagedScriptAddress
- type ManagedTaprootScriptAddress
- type Manager
- func (m *Manager) ActiveScopedKeyManagers() []*ScopedKeyManager
- func (m *Manager) AddrAccount(ns walletdb.ReadBucket, address ltcutil.Address) (*ScopedKeyManager, uint32, error)
- func (m *Manager) Address(ns walletdb.ReadBucket, address ltcutil.Address) (ManagedAddress, error)
- func (m *Manager) Birthday() time.Time
- func (m *Manager) BirthdayBlock(ns walletdb.ReadBucket) (BlockStamp, bool, error)
- func (m *Manager) BlockHash(ns walletdb.ReadBucket, height int32) (*chainhash.Hash, error)
- func (m *Manager) ChainParams() *chaincfg.Params
- func (m *Manager) ChangePassphrase(ns walletdb.ReadWriteBucket, oldPassphrase, newPassphrase []byte, private bool, ...) error
- func (m *Manager) Close()
- func (m *Manager) ConvertToWatchingOnly(ns walletdb.ReadWriteBucket) error
- func (m *Manager) Decrypt(keyType CryptoKeyType, in []byte) ([]byte, error)
- func (m *Manager) Encrypt(keyType CryptoKeyType, in []byte) ([]byte, error)
- func (m *Manager) FetchScopedKeyManager(scope KeyScope) (*ScopedKeyManager, error)
- func (m *Manager) ForEachAccountAddress(ns walletdb.ReadBucket, account uint32, fn func(maddr ManagedAddress) error) error
- func (m *Manager) ForEachActiveAccountAddress(ns walletdb.ReadBucket, account uint32, fn func(maddr ManagedAddress) error) error
- func (m *Manager) ForEachActiveAddress(ns walletdb.ReadBucket, fn func(addr ltcutil.Address) error) error
- func (m *Manager) ForEachRelevantActiveAddress(ns walletdb.ReadBucket, fn func(addr ltcutil.Address) error) error
- func (m *Manager) IsLocked() bool
- func (m *Manager) IsWatchOnlyAccount(ns walletdb.ReadBucket, keyScope KeyScope, account uint32) (bool, error)
- func (m *Manager) Lock() error
- func (m *Manager) LookupAccount(ns walletdb.ReadBucket, name string) (KeyScope, uint32, error)
- func (m *Manager) MarkUsed(ns walletdb.ReadWriteBucket, address ltcutil.Address) error
- func (m *Manager) NeuterRootKey(ns walletdb.ReadWriteBucket) error
- func (m *Manager) NewScopedKeyManager(ns walletdb.ReadWriteBucket, scope KeyScope, addrSchema ScopeAddrSchema) (*ScopedKeyManager, error)
- func (m *Manager) ScopesForExternalAddrType(addrType AddressType) []KeyScope
- func (m *Manager) ScopesForInternalAddrTypes(addrType AddressType) []KeyScope
- func (m *Manager) SetBirthday(ns walletdb.ReadWriteBucket, birthday time.Time) error
- func (m *Manager) SetBirthdayBlock(ns walletdb.ReadWriteBucket, block BlockStamp, verified bool) error
- func (m *Manager) SetSyncedTo(ns walletdb.ReadWriteBucket, bs *BlockStamp) error
- func (m *Manager) SyncedTo() BlockStamp
- func (m *Manager) Unlock(ns walletdb.ReadBucket, passphrase []byte) error
- func (m *Manager) WatchOnly() bool
- type ManagerError
- type MigrationManager
- func (m *MigrationManager) CurrentVersion(ns walletdb.ReadBucket) (uint32, error)
- func (m *MigrationManager) Name() string
- func (m *MigrationManager) Namespace() walletdb.ReadWriteBucket
- func (m *MigrationManager) SetVersion(ns walletdb.ReadWriteBucket, version uint32) error
- func (m *MigrationManager) Versions() []migration.Version
- type ObtainUserInputFunc
- type OpenCallbacks
- type ScopeAddrSchema
- type ScopedIndex
- type ScopedKeyManager
- func (s *ScopedKeyManager) AccountName(ns walletdb.ReadBucket, account uint32) (string, error)
- func (s *ScopedKeyManager) AccountProperties(ns walletdb.ReadBucket, account uint32) (*AccountProperties, error)
- func (s *ScopedKeyManager) AddrAccount(ns walletdb.ReadBucket, address ltcutil.Address) (uint32, error)
- func (s *ScopedKeyManager) AddrSchema() ScopeAddrSchema
- func (s *ScopedKeyManager) Address(ns walletdb.ReadBucket, address ltcutil.Address) (ManagedAddress, error)
- func (s *ScopedKeyManager) ChainParams() *chaincfg.Params
- func (s *ScopedKeyManager) Close()
- func (s *ScopedKeyManager) DeriveFromKeyPath(ns walletdb.ReadBucket, kp DerivationPath) (ManagedAddress, error)
- func (s *ScopedKeyManager) DeriveFromKeyPathCache(kp DerivationPath) (*btcec.PrivateKey, error)
- func (s *ScopedKeyManager) ExtendExternalAddresses(ns walletdb.ReadWriteBucket, account uint32, lastIndex uint32) error
- func (s *ScopedKeyManager) ExtendInternalAddresses(ns walletdb.ReadWriteBucket, account uint32, lastIndex uint32) error
- func (s *ScopedKeyManager) ForEachAccount(ns walletdb.ReadBucket, fn func(account uint32) error) error
- func (s *ScopedKeyManager) ForEachAccountAddress(ns walletdb.ReadBucket, account uint32, fn func(maddr ManagedAddress) error) error
- func (s *ScopedKeyManager) ForEachActiveAccountAddress(ns walletdb.ReadBucket, account uint32, fn func(maddr ManagedAddress) error) error
- func (s *ScopedKeyManager) ForEachActiveAddress(ns walletdb.ReadBucket, fn func(addr ltcutil.Address) error) error
- func (s *ScopedKeyManager) ForEachInternalActiveAddress(ns walletdb.ReadBucket, fn func(addr ltcutil.Address) error) error
- func (s *ScopedKeyManager) ImportPrivateKey(ns walletdb.ReadWriteBucket, wif *ltcutil.WIF, bs *BlockStamp) (ManagedPubKeyAddress, error)
- func (s *ScopedKeyManager) ImportPublicKey(ns walletdb.ReadWriteBucket, pubKey *btcec.PublicKey, bs *BlockStamp) (ManagedAddress, error)
- func (s *ScopedKeyManager) ImportScript(ns walletdb.ReadWriteBucket, script []byte, bs *BlockStamp) (ManagedScriptAddress, error)
- func (s *ScopedKeyManager) ImportTaprootScript(ns walletdb.ReadWriteBucket, tapscript *Tapscript, bs *BlockStamp, ...) (ManagedTaprootScriptAddress, error)
- func (s *ScopedKeyManager) ImportWitnessScript(ns walletdb.ReadWriteBucket, script []byte, bs *BlockStamp, ...) (ManagedScriptAddress, error)
- func (s *ScopedKeyManager) InvalidateAccountCache(account uint32)
- func (s *ScopedKeyManager) IsWatchOnlyAccount(ns walletdb.ReadBucket, account uint32) (bool, error)
- func (s *ScopedKeyManager) LastAccount(ns walletdb.ReadBucket) (uint32, error)
- func (s *ScopedKeyManager) LastExternalAddress(ns walletdb.ReadBucket, account uint32) (ManagedAddress, error)
- func (s *ScopedKeyManager) LastInternalAddress(ns walletdb.ReadBucket, account uint32) (ManagedAddress, error)
- func (s *ScopedKeyManager) LookupAccount(ns walletdb.ReadBucket, name string) (uint32, error)
- func (s *ScopedKeyManager) MarkUsed(ns walletdb.ReadWriteBucket, address ltcutil.Address) error
- func (s *ScopedKeyManager) NewAccount(ns walletdb.ReadWriteBucket, name string) (uint32, error)
- func (s *ScopedKeyManager) NewAccountWatchingOnly(ns walletdb.ReadWriteBucket, name string, pubKey *hdkeychain.ExtendedKey, ...) (uint32, error)
- func (s *ScopedKeyManager) NewRawAccount(ns walletdb.ReadWriteBucket, number uint32) error
- func (s *ScopedKeyManager) NewRawAccountWatchingOnly(ns walletdb.ReadWriteBucket, number uint32, pubKey *hdkeychain.ExtendedKey, ...) error
- func (s *ScopedKeyManager) NextExternalAddresses(ns walletdb.ReadWriteBucket, account uint32, numAddresses uint32) ([]ManagedAddress, error)
- func (s *ScopedKeyManager) NextInternalAddresses(ns walletdb.ReadWriteBucket, account uint32, numAddresses uint32) ([]ManagedAddress, error)
- func (s *ScopedKeyManager) RenameAccount(ns walletdb.ReadWriteBucket, account uint32, name string) error
- func (s *ScopedKeyManager) Scope() KeyScope
- type ScryptOptions
- type SecretKeyGenerator
- type Tapscript
- type TapscriptType
- type ValidatableManagedAddress
Constants ¶
const ( // MaxAccountNum is the maximum allowed account number. This value was // chosen because accounts are hardened children and therefore must not // exceed the hardened child range of extended keys and it provides a // reserved account at the top of the range for supporting imported // addresses. MaxAccountNum = hdkeychain.HardenedKeyStart - 2 // 2^31 - 2 // MaxAddressesPerAccount is the maximum allowed number of addresses // per account number. This value is based on the limitation of the // underlying hierarchical deterministic key derivation. MaxAddressesPerAccount = hdkeychain.HardenedKeyStart - 1 // ImportedAddrAccount is the account number to use for all imported // addresses. This is useful since normal accounts are derived from // the root hierarchical deterministic key and imported addresses do // not fit into that model. ImportedAddrAccount = MaxAccountNum + 1 // 2^31 - 1 // ImportedAddrAccountName is the name of the imported account. ImportedAddrAccountName = "imported" // DefaultAccountNum is the number of the default account. DefaultAccountNum = 0 // ExternalBranch is the child number to use when performing BIP0044 // style hierarchical deterministic key derivation for the external // branch. ExternalBranch uint32 = 0 // InternalBranch is the child number to use when performing BIP0044 // style hierarchical deterministic key derivation for the internal // branch. InternalBranch uint32 = 1 )
const ( // MaxReorgDepth represents the maximum number of block hashes we'll // keep within the wallet at any given point in order to recover from // long reorgs. MaxReorgDepth = 10000 )
Variables ¶
var ( // ErrPubKeyMismatch is returned when address validation fails as the // derived public key doesn't match the key held within the address // struct. ErrPubKeyMismatch = fmt.Errorf("derived pubkey doesn't match original") // ErrAddrMismatch is returned when addr validation fails due to a // re-derived address not matching the address ErrAddrMismatch = fmt.Errorf("derived addr doesn't match original") // ErrInvalidSignature is returned when we go to generate a signature // to verify against the public key and that signature comes back as // invalid. ErrInvalidSignature = fmt.Errorf("private key sig doesn't validate " + "against pubkey") )
var ( // KeyScopeBIP0049Plus is the key scope of our modified BIP0049 // derivation. We say this is BIP0049 "plus", as we'll actually use // p2wkh change all change addresses. KeyScopeBIP0049Plus = KeyScope{ Purpose: 49, Coin: 2, } // KeyScopeBIP0049PlusWithBitcoinCoinID is KeyScopeBIP0049Plus but with the // Bitcoin Coin ID, because when ltcwallet first forked from btcwallet, they // didn't change the ID, so we must look for these too. KeyScopeBIP0049PlusWithBitcoinCoinID = KeyScope{ Purpose: 49, Coin: 0, } // KeyScopeBIP0084 is the key scope for BIP0084 derivation. BIP0084 // will be used to derive all p2wkh addresses. KeyScopeBIP0084 = KeyScope{ Purpose: 84, Coin: 2, } // KeyScopeBIP0084WithBitcoinCoinID is KeyScopeBIP0084 with the bitcoin // coin ID. KeyScopeBIP0084WithBitcoinCoinID = KeyScope{ Purpose: 84, Coin: 0, } // KeyScopeBIP0086 is the key scope for BIP0086 derivation. BIP0086 // will be used to derive all p2tr addresses. KeyScopeBIP0086 = KeyScope{ Purpose: 86, Coin: 2, } // KeyScopeBIP0044 is the key scope for BIP0044 derivation. Legacy // wallets will only be able to use this key scope, and no keys beyond // it. KeyScopeBIP0044 = KeyScope{ Purpose: 44, Coin: 2, } // KeyScopeBIP0044WithBitcoinCoinID is KeyScopeBIP0044 with the bitcoin coin // ID. KeyScopeBIP0044WithBitcoinCoinID = KeyScope{ Purpose: 44, Coin: 0, } // DefaultKeyScopes is the set of default key scopes that will be // created by the root manager upon initial creation. DefaultKeyScopes = []KeyScope{ KeyScopeBIP0049Plus, KeyScopeBIP0084WithBitcoinCoinID, KeyScopeBIP0084, KeyScopeBIP0084WithBitcoinCoinID, KeyScopeBIP0086, KeyScopeBIP0044, KeyScopeBIP0044WithBitcoinCoinID, KeyScopeBIP0049PlusWithBitcoinCoinID, KeyScopeBIP0084WithBitcoinCoinID, } // ScopeAddrMap is a map from the default key scopes to the scope // address schema for each scope type. This will be consulted during // the initial creation of the root key manager. ScopeAddrMap = map[KeyScope]ScopeAddrSchema{ KeyScopeBIP0049Plus: { ExternalAddrType: NestedWitnessPubKey, InternalAddrType: WitnessPubKey, }, KeyScopeBIP0049PlusWithBitcoinCoinID: { ExternalAddrType: NestedWitnessPubKey, InternalAddrType: WitnessPubKey, }, KeyScopeBIP0084: { ExternalAddrType: WitnessPubKey, InternalAddrType: WitnessPubKey, }, KeyScopeBIP0084WithBitcoinCoinID: { ExternalAddrType: WitnessPubKey, InternalAddrType: WitnessPubKey, }, KeyScopeBIP0086: { ExternalAddrType: TaprootPubKey, InternalAddrType: TaprootPubKey, }, KeyScopeBIP0044: { InternalAddrType: PubKeyHash, ExternalAddrType: PubKeyHash, }, KeyScopeBIP0044WithBitcoinCoinID: { InternalAddrType: PubKeyHash, ExternalAddrType: PubKeyHash, }, } // KeyScopeBIP0049AddrSchema is the address schema for the traditional // BIP-0049 derivation scheme. This exists in order to support importing // accounts from other wallets that don't use our modified BIP-0049 // derivation scheme (internal addresses are P2WKH instead of NP2WKH). KeyScopeBIP0049AddrSchema = ScopeAddrSchema{ ExternalAddrType: NestedWitnessPubKey, InternalAddrType: NestedWitnessPubKey, } // ImportedDerivationPath is the derivation path for an imported // address. The Account, Branch, and Index members are not known, so // they are left blank. ImportedDerivationPath = DerivationPath{ InternalAccount: ImportedAddrAccount, } )
var Break = managerError(ErrCallBackBreak, "callback break", nil)
Break is a global err used to signal a break from the callback function by returning an error with the code ErrCallBackBreak
var DefaultScryptOptions = ScryptOptions{
N: 262144,
R: 8,
P: 1,
}
DefaultScryptOptions is the default options used with scrypt.
var FastScryptOptions = ScryptOptions{
N: 16,
R: 8,
P: 1,
}
FastScryptOptions are the scrypt options that should be used for testing purposes only where speed is more important than security.
var (
// LatestMgrVersion is the most recent manager version.
LatestMgrVersion = getLatestVersion()
)
Functions ¶
func Create ¶
func Create(ns walletdb.ReadWriteBucket, rootKey *hdkeychain.ExtendedKey, pubPassphrase, privPassphrase []byte, chainParams *chaincfg.Params, config *ScryptOptions, birthday time.Time) error
Create creates a new address manager in the given namespace.
The seed must conform to the standards described in hdkeychain.NewMaster and will be used to create the master root node from which all hierarchical deterministic addresses are derived. This allows all chained addresses in the address manager to be recovered by using the same seed.
If the provided seed value is nil the address manager will be created in watchingOnly mode in which case no default accounts or scoped managers are created - it is up to the caller to create a new one with NewAccountWatchingOnly and NewScopedKeyManager.
All private and public keys and information are protected by secret keys derived from the provided private and public passphrases. The public passphrase is required on subsequent opens of the address manager, and the private passphrase is required to unlock the address manager in order to gain access to any private keys and information.
If a config structure is passed to the function, that configuration will override the defaults.
A ManagerError with an error code of ErrAlreadyExists will be returned the address manager already exists in the specified namespace.
func DeleteBirthdayBlock ¶
func DeleteBirthdayBlock(ns walletdb.ReadWriteBucket) error
DeleteBirthdayBlock removes the birthday block from the database.
NOTE: This does not alter the birthday block verification state.
func DisableLog ¶
func DisableLog()
DisableLog disables all library log output. Logging output is disabled by default until either UseLogger or SetLogWriter are called.
func IsDefaultScope ¶
IsDefaultScope return true if the given scope belongs to the list of default scopes.
func PutBirthdayBlock ¶
func PutBirthdayBlock(ns walletdb.ReadWriteBucket, block BlockStamp) error
PutBirthdayBlock stores the provided birthday block to the database.
The block is serialized as follows:
[0:4] block height [4:36] block hash [36:44] block timestamp
NOTE: This does not alter the birthday block verification state.
func PutSyncedTo ¶
func PutSyncedTo(ns walletdb.ReadWriteBucket, bs *BlockStamp) error
PutSyncedTo stores the provided synced to blockstamp to the database.
func UseLogger ¶
UseLogger uses a specified Logger to output package logging info. This should be used in preference to SetLogWriter if the caller is also using btclog.
func ValidateAccountName ¶
ValidateAccountName validates the given account name and returns an error, if any.
Types ¶
type AccountProperties ¶
type AccountProperties struct { // AccountNumber is the internal number used to reference the account. AccountNumber uint32 // AccountName is the user-identifying name of the account. AccountName string // ExternalKeyCount is the number of internal keys that have been // derived for the account. ExternalKeyCount uint32 // InternalKeyCount is the number of internal keys that have been // derived for the account. InternalKeyCount uint32 // ImportedKeyCount is the number of imported keys found within the // account. ImportedKeyCount uint32 // AccountPubKey is the account's public key that can be used to // derive any address relevant to said account. // // NOTE: This may be nil for imported accounts. AccountPubKey *hdkeychain.ExtendedKey // MasterKeyFingerprint represents the fingerprint of the root key // corresponding to the master public key (also known as the key with // derivation path m/). This may be required by some hardware wallets // for proper identification and signing. MasterKeyFingerprint uint32 // KeyScope is the key scope the account belongs to. KeyScope KeyScope // IsWatchOnly indicates whether the is set up as watch-only, i.e., it // doesn't contain any private key information. IsWatchOnly bool // AddrSchema, if non-nil, specifies an address schema override for // address generation only applicable to the account. AddrSchema *ScopeAddrSchema }
AccountProperties contains properties associated with each account, such as the account name, number, and the nubmer of derived and imported keys.
type AddressType ¶
type AddressType uint8
AddressType represents the various address types waddrmgr is currently able to generate, and maintain.
NOTE: These MUST be stable as they're used for scope address schema recognition within the database.
const ( // PubKeyHash is a regular p2pkh address. PubKeyHash AddressType = iota // Script reprints a raw script address. Script // RawPubKey is just raw public key to be used within scripts, This // type indicates that a scoped manager with this address type // shouldn't be consulted during historical rescans. RawPubKey // NestedWitnessPubKey represents a p2wkh output nested within a p2sh // output. Using this address type, the wallet can receive funds from // other wallet's which don't yet recognize the new segwit standard // output types. Receiving funds to this address maintains the // scalability, and malleability fixes due to segwit in a backwards // compatible manner. NestedWitnessPubKey // WitnessPubKey represents a p2wkh (pay-to-witness-key-hash) address // type. WitnessPubKey // WitnessScript represents a p2wsh (pay-to-witness-script-hash) address // type. WitnessScript // TaprootPubKey represents a p2tr (pay-to-taproot) address type that // uses BIP-0086 (for the derivation path and for calculating the tap // root hash/tweak). TaprootPubKey // TaprootScript represents a p2tr (pay-to-taproot) address type that // commits to a script and not just a single key. TaprootScript )
type BlockStamp ¶
BlockStamp defines a block (by height and a unique hash) and is used to mark a point in the blockchain that an address manager element is synced to.
func FetchBirthdayBlock ¶
func FetchBirthdayBlock(ns walletdb.ReadBucket) (BlockStamp, error)
FetchBirthdayBlock retrieves the birthday block from the database.
The block is serialized as follows:
[0:4] block height [4:36] block hash [36:44] block timestamp
func FetchStartBlock ¶
func FetchStartBlock(ns walletdb.ReadBucket) (*BlockStamp, error)
FetchStartBlock loads the start block stamp for the manager from the database.
type CryptoKeyType ¶
type CryptoKeyType byte
CryptoKeyType is used to differentiate between different kinds of crypto keys.
const ( // CKTPrivate specifies the key that is used for encryption of private // key material such as derived extended private keys and imported // private keys. CKTPrivate CryptoKeyType = iota // CKTScript specifies the key that is used for encryption of scripts. CKTScript // CKTPublic specifies the key that is used for encryption of public // key material such as dervied extended public keys and imported public // keys. CKTPublic )
Crypto key types.
type DerivationPath ¶
type DerivationPath struct { // InternalAccount is the internal account number used within the // wallet's database to identify accounts. InternalAccount uint32 // Account is the account, or the first immediate child from the scoped // manager's hardened coin type key. Account uint32 // Branch is the branch to be derived from the account index above. For // BIP0044-like derivation, this is either 0 (external) or 1 // (internal). However, we allow this value to vary arbitrarily within // its size range. Branch uint32 // Index is the final child in the derivation path. This denotes the // key index within as a child of the account and branch. Index uint32 // MasterKeyFingerprint represents the fingerprint of the root key (also // known as the key with derivation path m/) corresponding to the // account public key. This may be required by some hardware wallets for // proper identification and signing. MasterKeyFingerprint uint32 }
DerivationPath represents a derivation path from a particular key manager's scope. Each ScopedKeyManager starts key derivation from the end of their cointype hardened key: m/purpose'/cointype'. The fields in this struct allow further derivation to the next three child levels after the coin type key. This restriction is in the spriti of BIP0044 type derivation. We maintain a degree of coherency with the standard, but allow arbitrary derivations beyond the cointype key. The key derived using this path will be exactly: m/purpose'/cointype'/account/branch/index, where purpose' and cointype' are bound by the scope of a particular manager.
type EncryptorDecryptor ¶
type EncryptorDecryptor interface { Encrypt(in []byte) ([]byte, error) Decrypt(in []byte) ([]byte, error) Bytes() []byte CopyBytes([]byte) Zero() }
EncryptorDecryptor provides an abstraction on top of snacl.CryptoKey so that our tests can use dependency injection to force the behaviour they need.
type ErrorCode ¶
type ErrorCode int
ErrorCode identifies a kind of error.
const ( // ErrDatabase indicates an error with the underlying database. When // this error code is set, the Err field of the ManagerError will be // set to the underlying error returned from the database. ErrDatabase ErrorCode = iota // ErrUpgrade indicates the manager needs to be upgraded. This should // not happen in practice unless the version number has been increased // and there is not yet any code written to upgrade. ErrUpgrade // ErrKeyChain indicates an error with the key chain typically either // due to the inability to create an extended key or deriving a child // extended key. When this error code is set, the Err field of the // ManagerError will be set to the underlying error. ErrKeyChain // ErrCrypto indicates an error with the cryptography related operations // such as decrypting or encrypting data, parsing an EC public key, // or deriving a secret key from a password. When this error code is // set, the Err field of the ManagerError will be set to the underlying // error. ErrCrypto // ErrInvalidKeyType indicates an error where an invalid crypto // key type has been selected. ErrInvalidKeyType // ErrNoExist indicates that the specified database does not exist. ErrNoExist // ErrAlreadyExists indicates that the specified database already exists. ErrAlreadyExists // ErrCoinTypeTooHigh indicates that the coin type specified in the provided // network parameters is higher than the max allowed value as defined // by the maxCoinType constant. ErrCoinTypeTooHigh // ErrAccountNumTooHigh indicates that the specified account number is higher // than the max allowed value as defined by the MaxAccountNum constant. ErrAccountNumTooHigh // ErrLocked indicates that an operation, which requires the account // manager to be unlocked, was requested on a locked account manager. ErrLocked // ErrWatchingOnly indicates that an operation, which requires the // account manager to have access to private data, was requested on // a watching-only account manager. ErrWatchingOnly // ErrInvalidAccount indicates that the requested account is not valid. ErrInvalidAccount // ErrAddressNotFound indicates that the requested address is not known to // the account manager. ErrAddressNotFound // ErrAccountNotFound indicates that the requested account is not known to // the account manager. ErrAccountNotFound // ErrDuplicateAddress indicates an address already exists. ErrDuplicateAddress // ErrDuplicateAccount indicates an account already exists. ErrDuplicateAccount // ErrTooManyAddresses indicates that more than the maximum allowed number of // addresses per account have been requested. ErrTooManyAddresses // ErrWrongPassphrase indicates that the specified passphrase is incorrect. // This could be for either public or private master keys. ErrWrongPassphrase // ErrWrongNet indicates that the private key to be imported is not for the // the same network the account manager is configured for. ErrWrongNet // ErrCallBackBreak is used to break from a callback function passed // down to the manager. ErrCallBackBreak // ErrEmptyPassphrase indicates that the private passphrase was refused // due to being empty. ErrEmptyPassphrase // ErrScopeNotFound is returned when a target scope cannot be found // within the database. ErrScopeNotFound // ErrBirthdayBlockNotSet is returned when we attempt to retrieve the // wallet's birthday but it has not been set yet. ErrBirthdayBlockNotSet // ErrBlockNotFound is returned when we attempt to retrieve the hash for // a block that we do not know of. ErrBlockNotFound // ErrAccountNotCached is returned when we attempt to perform an // operation that relies on an account begin cached but it isn't. ErrAccountNotCached )
These constants are used to identify a specific ManagerError.
type HDVersion ¶
type HDVersion uint32
HDVersion represents the different supported schemes of hierarchical derivation. Reference: https://github.com/satoshilabs/slips/blob/master/slip-0132.md#registered-hd-version-bytes
const ( // HDVersionMainNetBIP0044 is the HDVersion for BIP-0044 on the main // network. HDVersionMainNetBIP0044 HDVersion = 0x0488b21e // xpub // HDVersionMainNetBIP0049 is the HDVersion for BIP-0049 on the main // network. HDVersionMainNetBIP0049 HDVersion = 0x049d7cb2 // ypub // HDVersionMainNetBIP0084 is the HDVersion for BIP-0084 on the main // network. HDVersionMainNetBIP0084 HDVersion = 0x04b24746 // zpub // HDVersionTestNetBIP0044 is the HDVersion for BIP-0044 on the test // network. HDVersionTestNetBIP0044 HDVersion = 0x043587cf // tpub // HDVersionTestNetBIP0049 is the HDVersion for BIP-0049 on the test // network. HDVersionTestNetBIP0049 HDVersion = 0x044a5262 // upub // HDVersionTestNetBIP0084 is the HDVersion for BIP-0084 on the test // network. HDVersionTestNetBIP0084 HDVersion = 0x045f1cf6 // vpub // HDVersionSimNetBIP0044 is the HDVersion for BIP-0044 on the // simulation test network. There aren't any other versions defined for // the simulation test network. HDVersionSimNetBIP0044 HDVersion = 0x0420bd3a // spub )
type Identity ¶
type Identity func() []byte
Identity is a closure that returns the identifier of an address.
func ScriptHashIdentity ¶
ScriptHashIdentity returns the identity closure for a p2sh script.
func TaprootIdentity ¶
func TaprootIdentity(taprootKey *btcec.PublicKey) Identity
TaprootIdentity returns the identity closure for a p2tr script.
func WitnessScriptHashIdentity ¶
WitnessScriptHashIdentity returns the identity closure for a p2wsh script.
type KeyScope ¶
type KeyScope struct { // Purpose is the purpose of this key scope. This is the first child of // the master HD key. Purpose uint32 // Coin is a value that represents the particular coin which is the // child of the purpose key. With this key, any accounts, or other // children can be derived at all. Coin uint32 }
KeyScope represents a restricted key scope from the primary root key within the HD chain. From the root manager (m/) we can create a nearly arbitrary number of ScopedKeyManagers of key derivation path: m/purpose'/cointype'. These scoped managers can then me managed indecently, as they house the encrypted cointype key and can derive any child keys from there on.
type ManagedAddress ¶
type ManagedAddress interface { // InternalAccount returns the internal account the address is // associated with. InternalAccount() uint32 // Address returns a ltcutil.Address for the backing address. Address() ltcutil.Address // AddrHash returns the key or script hash related to the address AddrHash() []byte // Imported returns true if the backing address was imported instead // of being part of an address chain. Imported() bool // Internal returns true if the backing address was created for internal // use such as a change output of a transaction. Internal() bool // Compressed returns true if the backing address is compressed. Compressed() bool // Used returns true if the backing address has been used in a transaction. Used(ns walletdb.ReadBucket) bool // AddrType returns the address type of the managed address. This can // be used to quickly discern the address type without further // processing AddrType() AddressType }
ManagedAddress is an interface that provides acces to information regarding an address managed by an address manager. Concrete implementations of this type may provide further fields to provide information specific to that type of address.
type ManagedPubKeyAddress ¶
type ManagedPubKeyAddress interface { ManagedAddress // PubKey returns the public key associated with the address. PubKey() *btcec.PublicKey // ExportPubKey returns the public key associated with the address // serialized as a hex encoded string. ExportPubKey() string // PrivKey returns the private key for the address. It can fail if the // address manager is watching-only or locked, or the address does not // have any keys. PrivKey() (*btcec.PrivateKey, error) // ExportPrivKey returns the private key associated with the address // serialized as Wallet Import Format (WIF). ExportPrivKey() (*ltcutil.WIF, error) // DerivationInfo contains the information required to derive the key // that backs the address via traditional methods from the HD root. For // imported keys, the first value will be set to false to indicate that // we don't know exactly how the key was derived. DerivationInfo() (KeyScope, DerivationPath, bool) }
ManagedPubKeyAddress extends ManagedAddress and additionally provides the public and private keys for pubkey-based addresses.
type ManagedScriptAddress ¶
type ManagedScriptAddress interface { ManagedAddress // Script returns the script associated with the address. Script() ([]byte, error) }
ManagedScriptAddress extends ManagedAddress and represents a pay-to-script-hash style of bitcoin addresses. It additionally provides information about the script.
type ManagedTaprootScriptAddress ¶
type ManagedTaprootScriptAddress interface { ManagedScriptAddress // TaprootScript returns all the information needed to derive the script // tree root hash needed to arrive at the tweaked taproot key. TaprootScript() (*Tapscript, error) }
ManagedTaprootScriptAddress extends ManagedScriptAddress and represents a pay-to-taproot script address. It additionally provides information about the script.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager represents a concurrency safe crypto currency address manager and key store.
func Open ¶
func Open(ns walletdb.ReadBucket, pubPassphrase []byte, chainParams *chaincfg.Params) (*Manager, error)
Open loads an existing address manager from the given namespace. The public passphrase is required to decrypt the public keys used to protect the public information such as addresses. This is important since access to BIP0032 extended keys means it is possible to generate all future addresses.
If a config structure is passed to the function, that configuration will override the defaults.
A ManagerError with an error code of ErrNoExist will be returned if the passed manager does not exist in the specified namespace.
func (*Manager) ActiveScopedKeyManagers ¶
func (m *Manager) ActiveScopedKeyManagers() []*ScopedKeyManager
ActiveScopedKeyManagers returns a slice of all the active scoped key managers currently known by the root key manager.
func (*Manager) AddrAccount ¶
func (m *Manager) AddrAccount(ns walletdb.ReadBucket, address ltcutil.Address) (*ScopedKeyManager, uint32, error)
AddrAccount returns the account to which the given address belongs. We also return the scoped manager that owns the addr+account combo.
func (*Manager) Address ¶
func (m *Manager) Address(ns walletdb.ReadBucket, address ltcutil.Address) (ManagedAddress, error)
Address returns a managed address given the passed address if it is known to the address manager. A managed address differs from the passed address in that it also potentially contains extra information needed to sign transactions such as the associated private key for pay-to-pubkey and pay-to-pubkey-hash addresses and the script associated with pay-to-script-hash addresses.
func (*Manager) Birthday ¶
Birthday returns the birthday, or earliest time a key could have been used, for the manager.
func (*Manager) BirthdayBlock ¶
func (m *Manager) BirthdayBlock(ns walletdb.ReadBucket) (BlockStamp, bool, error)
BirthdayBlock returns the birthday block, or earliest block a key could have been used, for the manager. A boolean is also returned to indicate whether the birthday block has been verified as correct.
func (*Manager) BlockHash ¶
BlockHash returns the block hash at a particular block height. This information is useful for comparing against the chain back-end to see if a reorg is taking place and how far back it goes.
func (*Manager) ChainParams ¶
ChainParams returns the chain parameters for this address manager.
func (*Manager) ChangePassphrase ¶
func (m *Manager) ChangePassphrase(ns walletdb.ReadWriteBucket, oldPassphrase, newPassphrase []byte, private bool, config *ScryptOptions) error
ChangePassphrase changes either the public or private passphrase to the provided value depending on the private flag. In order to change the private password, the address manager must not be watching-only. The new passphrase keys are derived using the scrypt parameters in the options, so changing the passphrase may be used to bump the computational difficulty needed to brute force the passphrase.
func (*Manager) Close ¶
func (m *Manager) Close()
Close cleanly shuts down the manager. It makes a best try effort to remove and zero all private key and sensitive public key material associated with the address manager from memory.
func (*Manager) ConvertToWatchingOnly ¶
func (m *Manager) ConvertToWatchingOnly(ns walletdb.ReadWriteBucket) error
ConvertToWatchingOnly converts the current address manager to a locked watching-only address manager.
WARNING: This function removes private keys from the existing address manager which means they will no longer be available. Typically the caller will make a copy of the existing wallet database and modify the copy since otherwise it would mean permanent loss of any imported private keys and scripts.
Executing this function on a manager that is already watching-only will have no effect.
func (*Manager) Decrypt ¶
func (m *Manager) Decrypt(keyType CryptoKeyType, in []byte) ([]byte, error)
Decrypt in using the crypto key type specified by keyType.
func (*Manager) Encrypt ¶
func (m *Manager) Encrypt(keyType CryptoKeyType, in []byte) ([]byte, error)
Encrypt in using the crypto key type specified by keyType.
func (*Manager) FetchScopedKeyManager ¶
func (m *Manager) FetchScopedKeyManager(scope KeyScope) (*ScopedKeyManager, error)
FetchScopedKeyManager attempts to fetch an active scoped manager according to its registered scope. If the manger is found, then a nil error is returned along with the active scoped manager. Otherwise, a nil manager and a non-nil error will be returned.
func (*Manager) ForEachAccountAddress ¶
func (m *Manager) ForEachAccountAddress(ns walletdb.ReadBucket, account uint32, fn func(maddr ManagedAddress) error) error
ForEachAccountAddress calls the given function with each address of the given account stored in the manager, breaking early on error.
func (*Manager) ForEachActiveAccountAddress ¶
func (m *Manager) ForEachActiveAccountAddress(ns walletdb.ReadBucket, account uint32, fn func(maddr ManagedAddress) error) error
ForEachActiveAccountAddress calls the given function with each active address of the given account stored in the manager, across all active scopes, breaking early on error.
TODO(tuxcanfly): actually return only active addresses
func (*Manager) ForEachActiveAddress ¶
func (m *Manager) ForEachActiveAddress(ns walletdb.ReadBucket, fn func(addr ltcutil.Address) error) error
ForEachActiveAddress calls the given function with each active address stored in the manager, breaking early on error.
func (*Manager) ForEachRelevantActiveAddress ¶
func (m *Manager) ForEachRelevantActiveAddress(ns walletdb.ReadBucket, fn func(addr ltcutil.Address) error) error
ForEachRelevantActiveAddress invokes the given closure on each active address relevant to the wallet. Ideally, only addresses within the default key scopes would be relevant, but due to a bug (now fixed) in which change addresses could be created outside of the default key scopes, we now need to check for those as well.
func (*Manager) IsLocked ¶
IsLocked returns whether or not the address managed is locked. When it is unlocked, the decryption key needed to decrypt private keys used for signing is in memory.
func (*Manager) IsWatchOnlyAccount ¶
func (m *Manager) IsWatchOnlyAccount(ns walletdb.ReadBucket, keyScope KeyScope, account uint32) (bool, error)
IsWatchOnlyAccount determines if the account with the given key scope is set up as watch-only.
func (*Manager) Lock ¶
Lock performs a best try effort to remove and zero all secret keys associated with the address manager.
This function will return an error if invoked on a watching-only address manager.
func (*Manager) LookupAccount ¶
LookupAccount returns the corresponding key scope and account number for the account with the given name.
func (*Manager) NeuterRootKey ¶
func (m *Manager) NeuterRootKey(ns walletdb.ReadWriteBucket) error
NeuterRootKey is a special method that should be used once a caller is *certain* that no further scoped managers are to be created. This method will *delete* the encrypted master HD root private key from the database.
func (*Manager) NewScopedKeyManager ¶
func (m *Manager) NewScopedKeyManager(ns walletdb.ReadWriteBucket, scope KeyScope, addrSchema ScopeAddrSchema) (*ScopedKeyManager, error)
NewScopedKeyManager creates a new scoped key manager from the root manager. A scoped key manager is a sub-manager that only has the coin type key of a particular coin type and BIP0043 purpose. This is useful as it enables callers to create an arbitrary BIP0043 like schema with a stand alone manager. Note that a new scoped manager cannot be created if: the wallet is watch only, the manager hasn't been unlocked, or the root key has been. neutered from the database.
TODO(roasbeef): addrtype of raw key means it'll look in scripts to possibly mark as gucci?
func (*Manager) ScopesForExternalAddrType ¶
func (m *Manager) ScopesForExternalAddrType(addrType AddressType) []KeyScope
ScopesForExternalAddrType returns the set of key scopes that are able to produce the target address type as external addresses.
func (*Manager) ScopesForInternalAddrTypes ¶
func (m *Manager) ScopesForInternalAddrTypes(addrType AddressType) []KeyScope
ScopesForInternalAddrTypes returns the set of key scopes that are able to produce the target address type as internal addresses.
func (*Manager) SetBirthday ¶
SetBirthday sets the birthday, or earliest time a key could have been used, for the manager.
func (*Manager) SetBirthdayBlock ¶
func (m *Manager) SetBirthdayBlock(ns walletdb.ReadWriteBucket, block BlockStamp, verified bool) error
SetBirthdayBlock sets the birthday block, or earliest time a key could have been used, for the manager. The verified boolean can be used to specify whether this birthday block should be sanity checked to determine if there exists a better candidate to prevent less block fetching.
func (*Manager) SetSyncedTo ¶
func (m *Manager) SetSyncedTo(ns walletdb.ReadWriteBucket, bs *BlockStamp) error
SetSyncedTo marks the address manager to be in sync with the recently-seen block described by the blockstamp. When the provided blockstamp is nil, the oldest blockstamp of the block the manager was created at and of all imported addresses will be used. This effectively allows the manager to be marked as unsynced back to the oldest known point any of the addresses have appeared in the block chain.
func (*Manager) SyncedTo ¶
func (m *Manager) SyncedTo() BlockStamp
SyncedTo returns details about the block height and hash that the address manager is synced through at the very least. The intention is that callers can use this information for intelligently initiating rescans to sync back to the best chain from the last known good block.
func (*Manager) Unlock ¶
func (m *Manager) Unlock(ns walletdb.ReadBucket, passphrase []byte) error
Unlock derives the master private key from the specified passphrase. An invalid passphrase will return an error. Otherwise, the derived secret key is stored in memory until the address manager is locked. Any failures that occur during this function will result in the address manager being locked, even if it was already unlocked prior to calling this function.
This function will return an error if invoked on a watching-only address manager.
type ManagerError ¶
type ManagerError struct { ErrorCode ErrorCode // Describes the kind of error Description string // Human-readable description of the issue Err error // Underlying error }
ManagerError provides a single type for errors that can happen during address manager operation. It is used to indicate several types of failures including errors with caller requests such as invalid accounts or requesting private keys against a locked address manager, errors with the database (ErrDatabase), errors with keychain derivation (ErrKeyChain), and errors related to crypto (ErrCrypto).
The caller can use type assertions to determine if an error is a ManagerError and access the ErrorCode field to ascertain the specific reason for the failure.
The ErrDatabase, ErrKeyChain, and ErrCrypto error codes will also have the Err field set with the underlying error.
func (ManagerError) Error ¶
func (e ManagerError) Error() string
Error satisfies the error interface and prints human-readable errors.
func (ManagerError) Unwrap ¶
func (e ManagerError) Unwrap() error
Unwrap returns the underlying error, if any.
type MigrationManager ¶
type MigrationManager struct {
// contains filtered or unexported fields
}
MigrationManager is an implementation of the migration.Manager interface that will be used to handle migrations for the address manager. It exposes the necessary parameters required to successfully perform migrations.
func NewMigrationManager ¶
func NewMigrationManager(ns walletdb.ReadWriteBucket) *MigrationManager
NewMigrationManager creates a new migration manager for the address manager. The given bucket should reflect the top-level bucket in which all of the address manager's data is contained within.
func (*MigrationManager) CurrentVersion ¶
func (m *MigrationManager) CurrentVersion(ns walletdb.ReadBucket) (uint32, error)
CurrentVersion returns the current version of the service's database.
NOTE: This method is part of the migration.Manager interface.
func (*MigrationManager) Name ¶
func (m *MigrationManager) Name() string
Name returns the name of the service we'll be attempting to upgrade.
NOTE: This method is part of the migration.Manager interface.
func (*MigrationManager) Namespace ¶
func (m *MigrationManager) Namespace() walletdb.ReadWriteBucket
Namespace returns the top-level bucket of the service.
NOTE: This method is part of the migration.Manager interface.
func (*MigrationManager) SetVersion ¶
func (m *MigrationManager) SetVersion(ns walletdb.ReadWriteBucket, version uint32) error
SetVersion sets the version of the service's database.
NOTE: This method is part of the migration.Manager interface.
func (*MigrationManager) Versions ¶
func (m *MigrationManager) Versions() []migration.Version
Versions returns all of the available database versions of the service.
NOTE: This method is part of the migration.Manager interface.
type ObtainUserInputFunc ¶
ObtainUserInputFunc is a function that reads a user input and returns it as a byte stream. It is used to accept data required during upgrades, for e.g. wallet seed and private passphrase.
type OpenCallbacks ¶
type OpenCallbacks struct { // ObtainSeed is a callback function that is potentially invoked during // upgrades. It is intended to be used to request the wallet seed // from the user (or any other mechanism the caller deems fit). ObtainSeed ObtainUserInputFunc // ObtainPrivatePass is a callback function that is potentially invoked // during upgrades. It is intended to be used to request the wallet // private passphrase from the user (or any other mechanism the caller // deems fit). ObtainPrivatePass ObtainUserInputFunc }
OpenCallbacks houses caller-provided callbacks that may be called when opening an existing manager. The open blocks on the execution of these functions.
type ScopeAddrSchema ¶
type ScopeAddrSchema struct { // ExternalAddrType is the address type for all keys within branch 0. ExternalAddrType AddressType // InternalAddrType is the address type for all keys within branch 1 // (change addresses). InternalAddrType AddressType }
ScopeAddrSchema is the address schema of a particular KeyScope. This will be persisted within the database, and will be consulted when deriving any keys for a particular scope to know how to encode the public keys as addresses.
type ScopedIndex ¶
type ScopedIndex struct { // Scope is the BIP44 account' used to derive the child key. Scope KeyScope // Index is the BIP44 address_index used to derive the child key. Index uint32 }
ScopedIndex is a tuple of KeyScope and child Index. This is used to compactly identify a particular child key, when the account and branch can be inferred from context.
type ScopedKeyManager ¶
type ScopedKeyManager struct {
// contains filtered or unexported fields
}
ScopedKeyManager is a sub key manager under the main root key manager. The root key manager will handle the root HD key (m/), while each sub scoped key manager will handle the cointype key for a particular key scope (m/purpose'/cointype'). This abstraction allows higher-level applications built upon the root key manager to perform their own arbitrary key derivation, while still being protected under the encryption of the root key manager.
func (*ScopedKeyManager) AccountName ¶
func (s *ScopedKeyManager) AccountName(ns walletdb.ReadBucket, account uint32) (string, error)
AccountName returns the account name for the given account number stored in the manager.
func (*ScopedKeyManager) AccountProperties ¶
func (s *ScopedKeyManager) AccountProperties(ns walletdb.ReadBucket, account uint32) (*AccountProperties, error)
AccountProperties returns properties associated with the account, such as the account number, name, and the number of derived and imported keys.
func (*ScopedKeyManager) AddrAccount ¶
func (s *ScopedKeyManager) AddrAccount(ns walletdb.ReadBucket, address ltcutil.Address) (uint32, error)
AddrAccount returns the account to which the given address belongs.
func (*ScopedKeyManager) AddrSchema ¶
func (s *ScopedKeyManager) AddrSchema() ScopeAddrSchema
AddrSchema returns the set address schema for the target ScopedKeyManager.
func (*ScopedKeyManager) Address ¶
func (s *ScopedKeyManager) Address(ns walletdb.ReadBucket, address ltcutil.Address) (ManagedAddress, error)
Address returns a managed address given the passed address if it is known to the address manager. A managed address differs from the passed address in that it also potentially contains extra information needed to sign transactions such as the associated private key for pay-to-pubkey and pay-to-pubkey-hash addresses and the script associated with pay-to-script-hash addresses.
func (*ScopedKeyManager) ChainParams ¶
func (s *ScopedKeyManager) ChainParams() *chaincfg.Params
ChainParams returns the chain parameters for this address manager.
func (*ScopedKeyManager) Close ¶
func (s *ScopedKeyManager) Close()
Close cleanly shuts down the manager. It makes a best try effort to remove and zero all private key and sensitive public key material associated with the address manager from memory.
func (*ScopedKeyManager) DeriveFromKeyPath ¶
func (s *ScopedKeyManager) DeriveFromKeyPath(ns walletdb.ReadBucket, kp DerivationPath) (ManagedAddress, error)
DeriveFromKeyPath attempts to derive a maximal child key (under the BIP0044 scheme) from a given key path. If key derivation isn't possible, then an error will be returned.
NOTE: The key will be derived from the account stored in the database under the InternalAccount number.
func (*ScopedKeyManager) DeriveFromKeyPathCache ¶
func (s *ScopedKeyManager) DeriveFromKeyPathCache( kp DerivationPath) (*btcec.PrivateKey, error)
DeriveFromKeyPathCache is identical to DeriveFromKeyPath, however it'll fail if the account refracted in the DerivationPath isn't already in the in-memory cache. Callers looking for faster private key retrieval can opt to call this method, which may fail if things aren't in the cache, then fall back to the normal variant. The account can information can be drawn into the cache if the normal DeriveFromKeyPath method is used, or the account is looked up via any other means.
func (*ScopedKeyManager) ExtendExternalAddresses ¶
func (s *ScopedKeyManager) ExtendExternalAddresses(ns walletdb.ReadWriteBucket, account uint32, lastIndex uint32) error
ExtendExternalAddresses ensures that all valid external keys through lastIndex are derived and stored in the wallet. This is used to ensure that wallet's persistent state catches up to a external child that was found during recovery.
func (*ScopedKeyManager) ExtendInternalAddresses ¶
func (s *ScopedKeyManager) ExtendInternalAddresses(ns walletdb.ReadWriteBucket, account uint32, lastIndex uint32) error
ExtendInternalAddresses ensures that all valid internal keys through lastIndex are derived and stored in the wallet. This is used to ensure that wallet's persistent state catches up to an internal child that was found during recovery.
func (*ScopedKeyManager) ForEachAccount ¶
func (s *ScopedKeyManager) ForEachAccount(ns walletdb.ReadBucket, fn func(account uint32) error) error
ForEachAccount calls the given function with each account stored in the manager, breaking early on error.
func (*ScopedKeyManager) ForEachAccountAddress ¶
func (s *ScopedKeyManager) ForEachAccountAddress(ns walletdb.ReadBucket, account uint32, fn func(maddr ManagedAddress) error) error
ForEachAccountAddress calls the given function with each address of the given account stored in the manager, breaking early on error.
func (*ScopedKeyManager) ForEachActiveAccountAddress ¶
func (s *ScopedKeyManager) ForEachActiveAccountAddress(ns walletdb.ReadBucket, account uint32, fn func(maddr ManagedAddress) error) error
ForEachActiveAccountAddress calls the given function with each active address of the given account stored in the manager, breaking early on error.
TODO(tuxcanfly): actually return only active addresses
func (*ScopedKeyManager) ForEachActiveAddress ¶
func (s *ScopedKeyManager) ForEachActiveAddress(ns walletdb.ReadBucket, fn func(addr ltcutil.Address) error) error
ForEachActiveAddress calls the given function with each active address stored in the manager, breaking early on error.
func (*ScopedKeyManager) ForEachInternalActiveAddress ¶
func (s *ScopedKeyManager) ForEachInternalActiveAddress(ns walletdb.ReadBucket, fn func(addr ltcutil.Address) error) error
ForEachInternalActiveAddress invokes the given closure on each _internal_ active address belonging to the scoped key manager, breaking early on error.
func (*ScopedKeyManager) ImportPrivateKey ¶
func (s *ScopedKeyManager) ImportPrivateKey(ns walletdb.ReadWriteBucket, wif *ltcutil.WIF, bs *BlockStamp) (ManagedPubKeyAddress, error)
ImportPrivateKey imports a WIF private key into the address manager. The imported address is created using either a compressed or uncompressed serialized public key, depending on the CompressPubKey bool of the WIF.
All imported addresses will be part of the account defined by the ImportedAddrAccount constant.
NOTE: When the address manager is watching-only, the private key itself will not be stored or available since it is private data. Instead, only the public key will be stored. This means it is paramount the private key is kept elsewhere as the watching-only address manager will NOT ever have access to it.
This function will return an error if the address manager is locked and not watching-only, or not for the same network as the key trying to be imported. It will also return an error if the address already exists. Any other errors returned are generally unexpected.
func (*ScopedKeyManager) ImportPublicKey ¶
func (s *ScopedKeyManager) ImportPublicKey(ns walletdb.ReadWriteBucket, pubKey *btcec.PublicKey, bs *BlockStamp) (ManagedAddress, error)
ImportPublicKey imports a public key into the address manager.
All imported addresses will be part of the account defined by the ImportedAddrAccount constant.
func (*ScopedKeyManager) ImportScript ¶
func (s *ScopedKeyManager) ImportScript(ns walletdb.ReadWriteBucket, script []byte, bs *BlockStamp) (ManagedScriptAddress, error)
ImportScript imports a user-provided script into the address manager. The imported script will act as a pay-to-script-hash address.
All imported script addresses will be part of the account defined by the ImportedAddrAccount constant.
When the address manager is watching-only, the script itself will not be stored or available since it is considered private data.
This function will return an error if the address manager is locked and not watching-only, or the address already exists. Any other errors returned are generally unexpected.
func (*ScopedKeyManager) ImportTaprootScript ¶
func (s *ScopedKeyManager) ImportTaprootScript(ns walletdb.ReadWriteBucket, tapscript *Tapscript, bs *BlockStamp, witnessVersion byte, isSecretScript bool) (ManagedTaprootScriptAddress, error)
ImportTaprootScript imports a user-provided taproot script into the address manager. The imported script will act as a pay-to-taproot address.
func (*ScopedKeyManager) ImportWitnessScript ¶
func (s *ScopedKeyManager) ImportWitnessScript(ns walletdb.ReadWriteBucket, script []byte, bs *BlockStamp, witnessVersion byte, isSecretScript bool) (ManagedScriptAddress, error)
ImportWitnessScript imports a user-provided script into the address manager. The imported script will act as a pay-to-witness-script-hash address.
All imported script addresses will be part of the account defined by the ImportedAddrAccount constant.
When the address manager is watching-only, the script itself will not be stored or available since it is considered private data.
This function will return an error if the address manager is locked and not watching-only, or the address already exists. Any other errors returned are generally unexpected.
func (*ScopedKeyManager) InvalidateAccountCache ¶
func (s *ScopedKeyManager) InvalidateAccountCache(account uint32)
InvalidateAccountCache invalidates the cache for the given account, forcing a database read to retrieve the account information.
func (*ScopedKeyManager) IsWatchOnlyAccount ¶
func (s *ScopedKeyManager) IsWatchOnlyAccount(ns walletdb.ReadBucket, account uint32) (bool, error)
IsWatchOnlyAccount determines if the given account belonging to this scoped manager is set up as watch-only.
func (*ScopedKeyManager) LastAccount ¶
func (s *ScopedKeyManager) LastAccount(ns walletdb.ReadBucket) (uint32, error)
LastAccount returns the last account stored in the manager. If no accounts, returns twos-complement representation of -1
func (*ScopedKeyManager) LastExternalAddress ¶
func (s *ScopedKeyManager) LastExternalAddress(ns walletdb.ReadBucket, account uint32) (ManagedAddress, error)
LastExternalAddress returns the most recently requested chained external address from calling NextExternalAddress for the given account. The first external address for the account will be returned if none have been previously requested.
This function will return an error if the provided account number is greater than the MaxAccountNum constant or there is no account information for the passed account. Any other errors returned are generally unexpected.
func (*ScopedKeyManager) LastInternalAddress ¶
func (s *ScopedKeyManager) LastInternalAddress(ns walletdb.ReadBucket, account uint32) (ManagedAddress, error)
LastInternalAddress returns the most recently requested chained internal address from calling NextInternalAddress for the given account. The first internal address for the account will be returned if none have been previously requested.
This function will return an error if the provided account number is greater than the MaxAccountNum constant or there is no account information for the passed account. Any other errors returned are generally unexpected.
func (*ScopedKeyManager) LookupAccount ¶
func (s *ScopedKeyManager) LookupAccount(ns walletdb.ReadBucket, name string) (uint32, error)
LookupAccount loads account number stored in the manager for the given account name
func (*ScopedKeyManager) MarkUsed ¶
func (s *ScopedKeyManager) MarkUsed(ns walletdb.ReadWriteBucket, address ltcutil.Address) error
MarkUsed updates the used flag for the provided address.
func (*ScopedKeyManager) NewAccount ¶
func (s *ScopedKeyManager) NewAccount(ns walletdb.ReadWriteBucket, name string) (uint32, error)
NewAccount creates and returns a new account stored in the manager based on the given account name. If an account with the same name already exists, ErrDuplicateAccount will be returned. Since creating a new account requires access to the cointype keys (from which extended account keys are derived), it requires the manager to be unlocked.
func (*ScopedKeyManager) NewAccountWatchingOnly ¶
func (s *ScopedKeyManager) NewAccountWatchingOnly(ns walletdb.ReadWriteBucket, name string, pubKey *hdkeychain.ExtendedKey, masterKeyFingerprint uint32, addrSchema *ScopeAddrSchema) (uint32, error)
NewAccountWatchingOnly is similar to NewAccount, but for watch-only wallets.
The master key fingerprint denotes the fingerprint of the root key corresponding to the account public key (also known as the key with derivation path m/). This may be required by some hardware wallets for proper identification and signing.
An optional address schema may also be provided to override the ScopedKeyManager's address schema. This will affect all addresses derived from the account.
func (*ScopedKeyManager) NewRawAccount ¶
func (s *ScopedKeyManager) NewRawAccount(ns walletdb.ReadWriteBucket, number uint32) error
NewRawAccount creates a new account for the scoped manager. This method differs from the NewAccount method in that this method takes the account number *directly*, rather than taking a string name for the account, then mapping that to the next highest account number.
func (*ScopedKeyManager) NewRawAccountWatchingOnly ¶
func (s *ScopedKeyManager) NewRawAccountWatchingOnly( ns walletdb.ReadWriteBucket, number uint32, pubKey *hdkeychain.ExtendedKey, masterKeyFingerprint uint32, addrSchema *ScopeAddrSchema) error
NewRawAccountWatchingOnly creates a new watching only account for the scoped manager. This method differs from the NewAccountWatchingOnly method in that this method takes the account number *directly*, rather than taking a string name for the account, then mapping that to the next highest account number.
The master key fingerprint denotes the fingerprint of the root key corresponding to the account public key (also known as the key with derivation path m/). This may be required by some hardware wallets for proper identification and signing.
An optional address schema may also be provided to override the ScopedKeyManager's address schema. This will affect all addresses derived from the account.
func (*ScopedKeyManager) NextExternalAddresses ¶
func (s *ScopedKeyManager) NextExternalAddresses(ns walletdb.ReadWriteBucket, account uint32, numAddresses uint32) ([]ManagedAddress, error)
NextExternalAddresses returns the specified number of next chained addresses that are intended for external use from the address manager.
func (*ScopedKeyManager) NextInternalAddresses ¶
func (s *ScopedKeyManager) NextInternalAddresses(ns walletdb.ReadWriteBucket, account uint32, numAddresses uint32) ([]ManagedAddress, error)
NextInternalAddresses returns the specified number of next chained addresses that are intended for internal use such as change from the address manager.
func (*ScopedKeyManager) RenameAccount ¶
func (s *ScopedKeyManager) RenameAccount(ns walletdb.ReadWriteBucket, account uint32, name string) error
RenameAccount renames an account stored in the manager based on the given account number with the given name. If an account with the same name already exists, ErrDuplicateAccount will be returned.
func (*ScopedKeyManager) Scope ¶
func (s *ScopedKeyManager) Scope() KeyScope
Scope returns the exact KeyScope of this scoped key manager.
type ScryptOptions ¶
type ScryptOptions struct {
N, R, P int
}
ScryptOptions is used to hold the scrypt parameters needed when deriving new passphrase keys.
type SecretKeyGenerator ¶
type SecretKeyGenerator func( passphrase *[]byte, config *ScryptOptions) (*snacl.SecretKey, error)
SecretKeyGenerator is the function signature of a method that can generate secret keys for the address manager.
func SetSecretKeyGen ¶
func SetSecretKeyGen(keyGen SecretKeyGenerator) SecretKeyGenerator
SetSecretKeyGen replaces the existing secret key generator, and returns the previous generator.
type Tapscript ¶
type Tapscript struct { // Type is the type of the tapscript. Type TapscriptType // ControlBlock houses the main information about the internal key and // the resulting key's parity. And, in case of the // TapscriptTypePartialReveal type, the control block also contains the // inclusion proof and the leaf version for the revealed script. ControlBlock *txscript.ControlBlock // Leaves is the full set of tap leaves in their proper order. This is // only set if the Type is TapscriptTypeFullTree. Leaves []txscript.TapLeaf // RevealedScript is the script of the single revealed script. Is only // set if the Type is TapscriptTypePartialReveal. RevealedScript []byte // RootHash is the root hash of a tapscript tree that is committed to in // the Taproot output. This is only set if the Type is // TaprootKeySpendRootHash. RootHash []byte // FullOutputKey is the fully tweaked Taproot output key as it appears // on the chain. This is only set if the Type is TaprootFullKeyOnly. FullOutputKey *btcec.PublicKey }
Tapscript is a struct that holds either a full taproot tapscript with all individual leaves or a single leaf and the corresponding proof to arrive at the root hash.
func (*Tapscript) TaprootKey ¶
TaprootKey calculates the tweaked taproot key from the given internal key and the tree information in this tapscript struct. If any information required to calculate the root hash is missing, this method returns an error.
type TapscriptType ¶
type TapscriptType uint8
TapscriptType is a special type denoting the different variants of tapscripts.
const ( // TapscriptTypeFullTree is the type of tapscript that knows its full // tree with all individual leaves present. TapscriptTypeFullTree TapscriptType = 0 // TapscriptTypePartialReveal is the type of tapscript that only knows // a single revealed leaf and the merkle/inclusion proof for the rest of // the tree. TapscriptTypePartialReveal TapscriptType = 1 // TaprootKeySpendRootHash is the type of tapscript that only knows the // root hash of the Taproot commitment and therefore only allows for key // spends within the wallet, since a full control block cannot be // constructed. TaprootKeySpendRootHash TapscriptType = 2 // TaprootFullKeyOnly is the type of tapscript that only knows the final // Taproot key and no additional information about its internal key or // the type of tap tweak that was used. This can be useful for tracking // arbitrary Taproot outputs without the goal of ever being able to // spend from them through the internal wallet. TaprootFullKeyOnly TapscriptType = 3 )
type ValidatableManagedAddress ¶
type ValidatableManagedAddress interface { ManagedPubKeyAddress // Validate takes a random message and a private key and ensures that: // 1. The private key properly maps back to the target address. // // 2. The public key generated by the private key matches the public // key of the address. // // 3. We're able to generate a valid ECDSA/Schnorr signature based on // the passed private key validated against the internal public key. Validate(msg [32]byte, priv *btcec.PrivateKey) error }
ValidatableManagedAddress is a type of managed pubkey address that can perform external validation to catch unintended mutations between the derivation process and the ultimate address being created. This may help to catch things like hardware issue, or cosmic ray bit flips.