waddrmgr: add new DerivationInfo method to managedAddress, update ScopedKeyManager
In this commit, we add the new DerivationInfo method to the current default implementation of the ManagedPubKeyAddress interface. In doing this, we replace the account field with the derivationPath, as we can obtain the account field from the derivationPath itself.
This commit is contained in:
parent
05d73f6899
commit
bd81968215
2 changed files with 82 additions and 20 deletions
|
@ -108,7 +108,7 @@ type ManagedPubKeyAddress interface {
|
|||
// 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() (bool, KeyScope, DerivationPath)
|
||||
DerivationInfo() (KeyScope, DerivationPath, bool)
|
||||
}
|
||||
|
||||
// ManagedScriptAddress extends ManagedAddress and represents a pay-to-script-hash
|
||||
|
@ -125,7 +125,7 @@ type ManagedScriptAddress interface {
|
|||
// the private key associated with the public key.
|
||||
type managedAddress struct {
|
||||
manager *ScopedKeyManager
|
||||
account uint32
|
||||
derivationPath DerivationPath
|
||||
address btcutil.Address
|
||||
imported bool
|
||||
internal bool
|
||||
|
@ -181,7 +181,7 @@ func (a *managedAddress) lock() {
|
|||
//
|
||||
// This is part of the ManagedAddress interface implementation.
|
||||
func (a *managedAddress) Account() uint32 {
|
||||
return a.account
|
||||
return a.derivationPath.Account
|
||||
}
|
||||
|
||||
// AddrType returns the address type of the managed address. This can be used
|
||||
|
@ -316,11 +316,33 @@ func (a *managedAddress) ExportPrivKey() (*btcutil.WIF, error) {
|
|||
return btcutil.NewWIF(pk, a.manager.rootManager.chainParams, a.compressed)
|
||||
}
|
||||
|
||||
// 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.
|
||||
//
|
||||
// This is part of the ManagedPubKeyAddress interface implementation.
|
||||
func (a *managedAddress) DerivationInfo() (KeyScope, DerivationPath, bool) {
|
||||
var (
|
||||
scope KeyScope
|
||||
path DerivationPath
|
||||
)
|
||||
|
||||
// If this key is imported, then we can't return any information as we
|
||||
// don't know precisely how the key was derived.
|
||||
if a.imported {
|
||||
return scope, path, false
|
||||
}
|
||||
|
||||
return a.manager.Scope(), a.derivationPath, true
|
||||
}
|
||||
|
||||
// newManagedAddressWithoutPrivKey returns a new managed address based on the
|
||||
// passed account, public key, and whether or not the public key should be
|
||||
// compressed.
|
||||
func newManagedAddressWithoutPrivKey(m *ScopedKeyManager, account uint32, pubKey *btcec.PublicKey,
|
||||
compressed bool, addrType AddressType) (*managedAddress, error) {
|
||||
func newManagedAddressWithoutPrivKey(m *ScopedKeyManager,
|
||||
derivationPath DerivationPath, pubKey *btcec.PublicKey, compressed bool,
|
||||
addrType AddressType) (*managedAddress, error) {
|
||||
|
||||
// Create a pay-to-pubkey-hash address from the public key.
|
||||
var pubKeyHash []byte
|
||||
|
@ -387,7 +409,7 @@ func newManagedAddressWithoutPrivKey(m *ScopedKeyManager, account uint32, pubKey
|
|||
return &managedAddress{
|
||||
manager: m,
|
||||
address: address,
|
||||
account: account,
|
||||
derivationPath: derivationPath,
|
||||
imported: false,
|
||||
internal: false,
|
||||
addrType: addrType,
|
||||
|
@ -401,8 +423,9 @@ func newManagedAddressWithoutPrivKey(m *ScopedKeyManager, account uint32, pubKey
|
|||
// newManagedAddress returns a new managed address based on the passed account,
|
||||
// private key, and whether or not the public key is compressed. The managed
|
||||
// address will have access to the private and public keys.
|
||||
func newManagedAddress(s *ScopedKeyManager, account uint32, privKey *btcec.PrivateKey,
|
||||
compressed bool, addrType AddressType) (*managedAddress, error) {
|
||||
func newManagedAddress(s *ScopedKeyManager, derivationPath DerivationPath,
|
||||
privKey *btcec.PrivateKey, compressed bool,
|
||||
addrType AddressType) (*managedAddress, error) {
|
||||
|
||||
// Encrypt the private key.
|
||||
//
|
||||
|
@ -419,7 +442,7 @@ func newManagedAddress(s *ScopedKeyManager, account uint32, privKey *btcec.Priva
|
|||
// and then add the private key to it.
|
||||
ecPubKey := (*btcec.PublicKey)(&privKey.PublicKey)
|
||||
managedAddr, err := newManagedAddressWithoutPrivKey(
|
||||
s, account, ecPubKey, compressed, addrType,
|
||||
s, derivationPath, ecPubKey, compressed, addrType,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -434,8 +457,9 @@ func newManagedAddress(s *ScopedKeyManager, account uint32, privKey *btcec.Priva
|
|||
// account and extended key. The managed address will have access to the
|
||||
// private and public keys if the provided extended key is private, otherwise it
|
||||
// will only have access to the public key.
|
||||
func newManagedAddressFromExtKey(s *ScopedKeyManager, account uint32,
|
||||
key *hdkeychain.ExtendedKey, addrType AddressType) (*managedAddress, error) {
|
||||
func newManagedAddressFromExtKey(s *ScopedKeyManager,
|
||||
derivationPath DerivationPath, key *hdkeychain.ExtendedKey,
|
||||
addrType AddressType) (*managedAddress, error) {
|
||||
|
||||
// Create a new managed address based on the public or private key
|
||||
// depending on whether the generated key is private.
|
||||
|
@ -446,9 +470,10 @@ func newManagedAddressFromExtKey(s *ScopedKeyManager, account uint32,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the temp private key big integer is cleared after use.
|
||||
// Ensure the temp private key big integer is cleared after
|
||||
// use.
|
||||
managedAddr, err = newManagedAddress(
|
||||
s, account, privKey, true, addrType,
|
||||
s, derivationPath, privKey, true, addrType,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -460,7 +485,8 @@ func newManagedAddressFromExtKey(s *ScopedKeyManager, account uint32,
|
|||
}
|
||||
|
||||
managedAddr, err = newManagedAddressWithoutPrivKey(
|
||||
s, account, pubKey, true, addrType,
|
||||
s, derivationPath, pubKey, true,
|
||||
addrType,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -221,11 +221,17 @@ func (s *ScopedKeyManager) keyToManaged(derivedKey *hdkeychain.ExtendedKey,
|
|||
addrType = s.addrSchema.ExternalAddrType
|
||||
}
|
||||
|
||||
derivationPath := DerivationPath{
|
||||
Account: account,
|
||||
Branch: branch,
|
||||
Index: index,
|
||||
}
|
||||
|
||||
// Create a new managed address based on the public or private key
|
||||
// depending on whether the passed key is private. Also, zero the key
|
||||
// after creating the managed address from it.
|
||||
ma, err := newManagedAddressFromExtKey(
|
||||
s, account, derivedKey, addrType,
|
||||
s, derivationPath, derivedKey, addrType,
|
||||
)
|
||||
defer derivedKey.Zero()
|
||||
if err != nil {
|
||||
|
@ -515,9 +521,15 @@ func (s *ScopedKeyManager) importedAddressRowToManaged(row *dbImportedAddressRow
|
|||
return nil, managerError(ErrCrypto, str, err)
|
||||
}
|
||||
|
||||
// Since this is an imported address, we won't populate the full
|
||||
// derivation path, as we don't have enough information to do so.
|
||||
derivationPath := DerivationPath{
|
||||
Account: row.account,
|
||||
}
|
||||
|
||||
compressed := len(pubBytes) == btcec.PubKeyBytesLenCompressed
|
||||
ma, err := newManagedAddressWithoutPrivKey(
|
||||
s, row.account, pubKey, compressed,
|
||||
s, derivationPath, pubKey, compressed,
|
||||
s.addrSchema.ExternalAddrType,
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -740,12 +752,21 @@ func (s *ScopedKeyManager) nextAddresses(ns walletdb.ReadWriteBucket,
|
|||
break
|
||||
}
|
||||
|
||||
// Now that we know this key can be used, we'll create the
|
||||
// proper derivation path so this information can be available
|
||||
// to callers.
|
||||
derivationPath := DerivationPath{
|
||||
Account: account,
|
||||
Branch: branchNum,
|
||||
Index: nextIndex - 1,
|
||||
}
|
||||
|
||||
// Create a new managed address based on the public or private
|
||||
// key depending on whether the generated key is private.
|
||||
// Also, zero the next key after creating the managed address
|
||||
// from it.
|
||||
addr, err := newManagedAddressFromExtKey(
|
||||
s, account, nextKey, addrType,
|
||||
s, derivationPath, nextKey, addrType,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -920,12 +941,21 @@ func (s *ScopedKeyManager) extendAddresses(ns walletdb.ReadWriteBucket,
|
|||
break
|
||||
}
|
||||
|
||||
// Now that we know this key can be used, we'll create the
|
||||
// proper derivation path so this information can be available
|
||||
// to callers.
|
||||
derivationPath := DerivationPath{
|
||||
Account: account,
|
||||
Branch: branchNum,
|
||||
Index: nextIndex - 1,
|
||||
}
|
||||
|
||||
// Create a new managed address based on the public or private
|
||||
// key depending on whether the generated key is private.
|
||||
// Also, zero the next key after creating the managed address
|
||||
// from it.
|
||||
addr, err := newManagedAddressFromExtKey(
|
||||
s, account, nextKey, addrType,
|
||||
s, derivationPath, nextKey, addrType,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1452,17 +1482,23 @@ func (s *ScopedKeyManager) ImportPrivateKey(ns walletdb.ReadWriteBucket,
|
|||
s.rootManager.mtx.Unlock()
|
||||
}
|
||||
|
||||
// The full derivation path for an imported key is incomplete as we
|
||||
// don't know exactly how it was derived.
|
||||
importedDerivationPath := DerivationPath{
|
||||
Account: ImportedAddrAccount,
|
||||
}
|
||||
|
||||
// Create a new managed address based on the imported address.
|
||||
var managedAddr *managedAddress
|
||||
if !s.rootManager.WatchOnly() {
|
||||
managedAddr, err = newManagedAddress(
|
||||
s, ImportedAddrAccount, wif.PrivKey,
|
||||
s, importedDerivationPath, wif.PrivKey,
|
||||
wif.CompressPubKey, s.addrSchema.ExternalAddrType,
|
||||
)
|
||||
} else {
|
||||
pubKey := (*btcec.PublicKey)(&wif.PrivKey.PublicKey)
|
||||
managedAddr, err = newManagedAddressWithoutPrivKey(
|
||||
s, ImportedAddrAccount, pubKey, wif.CompressPubKey,
|
||||
s, importedDerivationPath, pubKey, wif.CompressPubKey,
|
||||
s.addrSchema.ExternalAddrType,
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue