package waddrmgr import ( "fmt" "sync" "github.com/roasbeef/btcd/btcec" "github.com/roasbeef/btcd/chaincfg" "github.com/roasbeef/btcutil" "github.com/roasbeef/btcutil/hdkeychain" "github.com/roasbeef/btcwallet/internal/zero" "github.com/roasbeef/btcwallet/walletdb" ) // 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 DerivationPath struct { // 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 } // 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 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 } // String returns a human readable version describing the keypath encapsulated // by the target key scope. func (k *KeyScope) String() string { return fmt.Sprintf("m/%v'/%v'", k.Purpose, k.Coin) } // 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 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 } 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: 0, } // KeyScopeBIP0084 is the key scope for BIP0084 derivation. BIP0084 // will be used to derive all p2wkh addresses. KeyScopeBIP0084 = KeyScope{ Purpose: 84, Coin: 0, } // 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: 0, } // DefaultKeyScopes is the set of default key scopes that will be // created by the root manager upon initial creation. DefaultKeyScopes = []KeyScope{ KeyScopeBIP0049Plus, KeyScopeBIP0084, KeyScopeBIP0044, } // 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, }, KeyScopeBIP0084: { ExternalAddrType: WitnessPubKey, InternalAddrType: WitnessPubKey, }, KeyScopeBIP0044: { InternalAddrType: PubKeyHash, ExternalAddrType: PubKeyHash, }, } )