waddrmgr: use proper version for account key of non-watch-only accounts
This commit is contained in:
parent
adb3d77c86
commit
9d909110f9
2 changed files with 105 additions and 0 deletions
|
@ -144,6 +144,8 @@ type addrKey string
|
|||
type accountInfo struct {
|
||||
acctName string
|
||||
|
||||
acctType accountType
|
||||
|
||||
// The account key is used to derive the branches which in turn derive
|
||||
// the internal and external addresses. The accountKeyPriv will be nil
|
||||
// when the address manager is locked.
|
||||
|
|
|
@ -1,18 +1,50 @@
|
|||
package waddrmgr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/btcsuite/btcutil/hdkeychain"
|
||||
"github.com/btcsuite/btcwallet/internal/zero"
|
||||
"github.com/btcsuite/btcwallet/walletdb"
|
||||
)
|
||||
|
||||
// HDVersion represents the different supported schemes of hierarchical
|
||||
// derivation.
|
||||
type HDVersion uint32
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
// 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
|
||||
|
@ -331,6 +363,7 @@ func (s *ScopedKeyManager) loadAccountInfo(ns walletdb.ReadBucket,
|
|||
case *dbDefaultAccountRow:
|
||||
acctInfo = &accountInfo{
|
||||
acctName: row.name,
|
||||
acctType: row.acctType,
|
||||
acctKeyEncrypted: row.privKeyEncrypted,
|
||||
nextExternalIndex: row.nextExternalIndex,
|
||||
nextInternalIndex: row.nextInternalIndex,
|
||||
|
@ -363,6 +396,7 @@ func (s *ScopedKeyManager) loadAccountInfo(ns walletdb.ReadBucket,
|
|||
case *dbWatchOnlyAccountRow:
|
||||
acctInfo = &accountInfo{
|
||||
acctName: row.name,
|
||||
acctType: row.acctType,
|
||||
nextExternalIndex: row.nextExternalIndex,
|
||||
nextInternalIndex: row.nextInternalIndex,
|
||||
addrSchema: row.addrSchema,
|
||||
|
@ -472,6 +506,29 @@ func (s *ScopedKeyManager) AccountProperties(ns walletdb.ReadBucket,
|
|||
props.IsWatchOnly = s.rootManager.WatchOnly() ||
|
||||
acctInfo.acctKeyPriv == nil
|
||||
props.AddrSchema = acctInfo.addrSchema
|
||||
|
||||
// Export the account public key with the correct version
|
||||
// corresponding to the manager's key scope for non-watch-only
|
||||
// accounts. This isn't done for watch-only accounts to maintain
|
||||
// the account public key consistent with what the caller
|
||||
// provided. Note that his is only done for the default key
|
||||
// scopes, as we only know the HD versions for those.
|
||||
isDefaultKeyScope := false
|
||||
for _, scope := range DefaultKeyScopes {
|
||||
if s.scope == scope {
|
||||
isDefaultKeyScope = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if acctInfo.acctType == accountDefault && isDefaultKeyScope {
|
||||
props.AccountPubKey, err = s.cloneKeyWithVersion(
|
||||
acctInfo.acctKeyPub,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve "+
|
||||
"account public key: %v", err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
props.AccountName = ImportedAddrAccountName // reserved, nonchangable
|
||||
props.IsWatchOnly = s.rootManager.WatchOnly()
|
||||
|
@ -2118,3 +2175,49 @@ func (s *ScopedKeyManager) ForEachInternalActiveAddress(ns walletdb.ReadBucket,
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// cloneKeyWithVersion clones an extended key to use the version corresponding
|
||||
// to the manager's key scope. This should only be used for non-watch-only
|
||||
// accounts as they are stored within the database using the legacy BIP-0044
|
||||
// version by default.
|
||||
func (s *ScopedKeyManager) cloneKeyWithVersion(key *hdkeychain.ExtendedKey) (
|
||||
*hdkeychain.ExtendedKey, error) {
|
||||
|
||||
// Determine the appropriate version based on the current network and
|
||||
// key scope.
|
||||
var version HDVersion
|
||||
net := s.rootManager.ChainParams().Net
|
||||
switch net {
|
||||
case wire.MainNet:
|
||||
switch s.scope {
|
||||
case KeyScopeBIP0044:
|
||||
version = HDVersionMainNetBIP0044
|
||||
case KeyScopeBIP0049Plus:
|
||||
version = HDVersionMainNetBIP0049
|
||||
case KeyScopeBIP0084:
|
||||
version = HDVersionMainNetBIP0084
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported scope %v", s.scope)
|
||||
}
|
||||
|
||||
case wire.TestNet, wire.TestNet3:
|
||||
switch s.scope {
|
||||
case KeyScopeBIP0044:
|
||||
version = HDVersionTestNetBIP0044
|
||||
case KeyScopeBIP0049Plus:
|
||||
version = HDVersionTestNetBIP0049
|
||||
case KeyScopeBIP0084:
|
||||
version = HDVersionTestNetBIP0084
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported scope %v", s.scope)
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported net %v", net)
|
||||
}
|
||||
|
||||
var versionBytes [4]byte
|
||||
binary.BigEndian.PutUint32(versionBytes[:], uint32(version))
|
||||
|
||||
return key.CloneWithVersion(versionBytes[:])
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue