waddrmgr: include master key fingerprint in derivation path
Following the previous commit, some external hardware signers require a master key fingerprint to be present within the PSBT input derivation paths so that the signer can recognize which inputs are relevant and must be signed.
This commit is contained in:
parent
35b4b237c9
commit
7fa80abc44
3 changed files with 29 additions and 20 deletions
|
@ -1218,7 +1218,7 @@ func (m *Manager) Unlock(ns walletdb.ReadBucket, passphrase []byte) error {
|
||||||
// We'll also derive any private keys that are pending due to
|
// We'll also derive any private keys that are pending due to
|
||||||
// them being created while the address manager was locked.
|
// them being created while the address manager was locked.
|
||||||
for _, info := range manager.deriveOnUnlock {
|
for _, info := range manager.deriveOnUnlock {
|
||||||
addressKey, _, err := manager.deriveKeyFromPath(
|
addressKey, _, _, err := manager.deriveKeyFromPath(
|
||||||
ns, info.managedAddr.InternalAccount(),
|
ns, info.managedAddr.InternalAccount(),
|
||||||
info.branch, info.index, true,
|
info.branch, info.index, true,
|
||||||
)
|
)
|
||||||
|
|
|
@ -72,6 +72,12 @@ type DerivationPath struct {
|
||||||
// Index is the final child in the derivation path. This denotes the
|
// Index is the final child in the derivation path. This denotes the
|
||||||
// key index within as a child of the account and branch.
|
// key index within as a child of the account and branch.
|
||||||
Index uint32
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyScope represents a restricted key scope from the primary root key within
|
// KeyScope represents a restricted key scope from the primary root key within
|
||||||
|
@ -448,6 +454,7 @@ func (s *ScopedKeyManager) loadAccountInfo(ns walletdb.ReadBucket,
|
||||||
Account: acctInfo.acctKeyPub.ChildIndex(),
|
Account: acctInfo.acctKeyPub.ChildIndex(),
|
||||||
Branch: branch,
|
Branch: branch,
|
||||||
Index: index,
|
Index: index,
|
||||||
|
MasterKeyFingerprint: acctInfo.masterKeyFingerprint,
|
||||||
}
|
}
|
||||||
lastExtKey, err := s.deriveKey(acctInfo, branch, index, hasPrivateKey)
|
lastExtKey, err := s.deriveKey(acctInfo, branch, index, hasPrivateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -469,6 +476,7 @@ func (s *ScopedKeyManager) loadAccountInfo(ns walletdb.ReadBucket,
|
||||||
Account: acctInfo.acctKeyPub.ChildIndex(),
|
Account: acctInfo.acctKeyPub.ChildIndex(),
|
||||||
Branch: branch,
|
Branch: branch,
|
||||||
Index: index,
|
Index: index,
|
||||||
|
MasterKeyFingerprint: acctInfo.masterKeyFingerprint,
|
||||||
}
|
}
|
||||||
lastIntKey, err := s.deriveKey(acctInfo, branch, index, hasPrivateKey)
|
lastIntKey, err := s.deriveKey(acctInfo, branch, index, hasPrivateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -580,7 +588,7 @@ func (s *ScopedKeyManager) DeriveFromKeyPath(ns walletdb.ReadBucket,
|
||||||
watchOnly := s.rootManager.WatchOnly()
|
watchOnly := s.rootManager.WatchOnly()
|
||||||
private := !s.rootManager.IsLocked() && !watchOnly
|
private := !s.rootManager.IsLocked() && !watchOnly
|
||||||
|
|
||||||
addrKey, _, err := s.deriveKeyFromPath(
|
addrKey, _, _, err := s.deriveKeyFromPath(
|
||||||
ns, kp.InternalAccount, kp.Branch, kp.Index, private,
|
ns, kp.InternalAccount, kp.Branch, kp.Index, private,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -601,18 +609,18 @@ func (s *ScopedKeyManager) DeriveFromKeyPath(ns walletdb.ReadBucket,
|
||||||
// This function MUST be called with the manager lock held for writes.
|
// This function MUST be called with the manager lock held for writes.
|
||||||
func (s *ScopedKeyManager) deriveKeyFromPath(ns walletdb.ReadBucket,
|
func (s *ScopedKeyManager) deriveKeyFromPath(ns walletdb.ReadBucket,
|
||||||
internalAccount, branch, index uint32, private bool) (
|
internalAccount, branch, index uint32, private bool) (
|
||||||
*hdkeychain.ExtendedKey, *hdkeychain.ExtendedKey, error) {
|
*hdkeychain.ExtendedKey, *hdkeychain.ExtendedKey, uint32, error) {
|
||||||
|
|
||||||
// Look up the account key information.
|
// Look up the account key information.
|
||||||
acctInfo, err := s.loadAccountInfo(ns, internalAccount)
|
acctInfo, err := s.loadAccountInfo(ns, internalAccount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, 0, err
|
||||||
}
|
}
|
||||||
private = private && acctInfo.acctKeyPriv != nil
|
private = private && acctInfo.acctKeyPriv != nil
|
||||||
|
|
||||||
addrKey, err := s.deriveKey(acctInfo, branch, index, private)
|
addrKey, err := s.deriveKey(acctInfo, branch, index, private)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
acctKey := acctInfo.acctKeyPub
|
acctKey := acctInfo.acctKeyPub
|
||||||
|
@ -620,7 +628,7 @@ func (s *ScopedKeyManager) deriveKeyFromPath(ns walletdb.ReadBucket,
|
||||||
acctKey = acctInfo.acctKeyPriv
|
acctKey = acctInfo.acctKeyPriv
|
||||||
}
|
}
|
||||||
|
|
||||||
return addrKey, acctKey, nil
|
return addrKey, acctKey, acctInfo.masterKeyFingerprint, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// chainAddressRowToManaged returns a new managed address based on chained
|
// chainAddressRowToManaged returns a new managed address based on chained
|
||||||
|
@ -634,7 +642,7 @@ func (s *ScopedKeyManager) chainAddressRowToManaged(ns walletdb.ReadBucket,
|
||||||
// function, we use the internal isLocked to avoid a deadlock.
|
// function, we use the internal isLocked to avoid a deadlock.
|
||||||
private := !s.rootManager.isLocked() && !s.rootManager.watchOnly()
|
private := !s.rootManager.isLocked() && !s.rootManager.watchOnly()
|
||||||
|
|
||||||
addressKey, acctKey, err := s.deriveKeyFromPath(
|
addressKey, acctKey, masterKeyFingerprint, err := s.deriveKeyFromPath(
|
||||||
ns, row.account, row.branch, row.index, private,
|
ns, row.account, row.branch, row.index, private,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -651,6 +659,7 @@ func (s *ScopedKeyManager) chainAddressRowToManaged(ns walletdb.ReadBucket,
|
||||||
Account: acctKey.ChildIndex(),
|
Account: acctKey.ChildIndex(),
|
||||||
Branch: row.branch,
|
Branch: row.branch,
|
||||||
Index: row.index,
|
Index: row.index,
|
||||||
|
MasterKeyFingerprint: masterKeyFingerprint,
|
||||||
}, acctInfo,
|
}, acctInfo,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,7 @@ func (w *Wallet) FetchInputInfo(prevOut *wire.OutPoint) (*wire.MsgTx,
|
||||||
PkScript: pkScript,
|
PkScript: pkScript,
|
||||||
}, &psbt.Bip32Derivation{
|
}, &psbt.Bip32Derivation{
|
||||||
PubKey: pubKeyAddr.PubKey().SerializeCompressed(),
|
PubKey: pubKeyAddr.PubKey().SerializeCompressed(),
|
||||||
MasterKeyFingerprint: 0, // TODO
|
MasterKeyFingerprint: derivationPath.MasterKeyFingerprint,
|
||||||
Bip32Path: []uint32{
|
Bip32Path: []uint32{
|
||||||
keyScope.Purpose + hdkeychain.HardenedKeyStart,
|
keyScope.Purpose + hdkeychain.HardenedKeyStart,
|
||||||
keyScope.Coin + hdkeychain.HardenedKeyStart,
|
keyScope.Coin + hdkeychain.HardenedKeyStart,
|
||||||
|
|
Loading…
Reference in a new issue