waddrmgr: introduce concept of scopes for key managers
In this commit, we introduce the concept of scopes for individual key managers. Each scope will lock down a key manager to a particular purpose and coin type within the BIP0043 hierarchy. Each scope will also have a set address type schema. This schema will be consulted when creating addresses for a particular scoped key manager. Finally, we introduce 3 new default scopes: * BIP 44 * BIP 84 * BIP 49++ (BIP49 but uses p2wkh for change addresses)
This commit is contained in:
parent
f4ef7cdd29
commit
6f6abef1d6
1 changed files with 124 additions and 0 deletions
124
waddrmgr/scoped_manager.go
Normal file
124
waddrmgr/scoped_manager.go
Normal file
|
@ -0,0 +1,124 @@
|
|||
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,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
Loading…
Reference in a new issue