waddrmgr: add TODO to determine proper address type of imported key

For key scopes which have an address schema where the external and
internal branches differ, we always assume that imported keys use the
external address type defined in the scope's address schema. This may
not always be the case however, and should be handled correctly.
Ideally, we generate two addresses per imported key (only if the
external and internal address types differ) and scan for both in the
chain.
This commit is contained in:
Wilmer Paulino 2021-03-10 18:11:16 -08:00
parent b0a4956231
commit f1b329f680
No known key found for this signature in database
GPG key ID: 6DF57B9F9514972F

View file

@ -177,6 +177,13 @@ var (
ExternalAddrType: NestedWitnessPubKey, ExternalAddrType: NestedWitnessPubKey,
InternalAddrType: NestedWitnessPubKey, InternalAddrType: NestedWitnessPubKey,
} }
// ImportedDerivationPath is the derivation path for an imported
// address. The Account, Branch, and Index members are not known, so
// they are left blank.
ImportedDerivationPath = DerivationPath{
InternalAccount: ImportedAddrAccount,
}
) )
// ScopedKeyManager is a sub key manager under the main root key manager. The // ScopedKeyManager is a sub key manager under the main root key manager. The
@ -665,15 +672,10 @@ func (s *ScopedKeyManager) importedAddressRowToManaged(row *dbImportedAddressRow
return nil, managerError(ErrCrypto, str, err) return nil, managerError(ErrCrypto, str, err)
} }
// Since this is an imported address, we won't populate the full // TODO: Handle imported key being part of internal branch.
// derivation path, as we don't have enough information to do so.
derivationPath := DerivationPath{
InternalAccount: row.account,
}
compressed := len(pubBytes) == btcec.PubKeyBytesLenCompressed compressed := len(pubBytes) == btcec.PubKeyBytesLenCompressed
ma, err := newManagedAddressWithoutPrivKey( ma, err := newManagedAddressWithoutPrivKey(
s, derivationPath, pubKey, compressed, s, ImportedDerivationPath, pubKey, compressed,
s.addrSchema.ExternalAddrType, s.addrSchema.ExternalAddrType,
) )
if err != nil { if err != nil {
@ -1753,22 +1755,12 @@ func (s *ScopedKeyManager) ImportPrivateKey(ns walletdb.ReadWriteBucket,
return nil, err return nil, err
} }
// The full derivation path for an imported key is incomplete as we
// don't know exactly how it was derived.
importedDerivationPath := DerivationPath{
InternalAccount: ImportedAddrAccount,
}
// Create a new managed address based on the imported address. // Create a new managed address based on the imported address.
if !s.rootManager.WatchOnly() { if !s.rootManager.WatchOnly() {
return s.toPrivateManagedAddress( return s.toImportedPrivateManagedAddress(wif)
wif, true, importedDerivationPath,
)
} }
pubKey := (*btcec.PublicKey)(&wif.PrivKey.PublicKey) pubKey := (*btcec.PublicKey)(&wif.PrivKey.PublicKey)
return s.toPublicManagedAddress( return s.toImportedPublicManagedAddress(pubKey, wif.CompressPubKey)
pubKey, wif.CompressPubKey, true, importedDerivationPath,
)
} }
// ImportPublicKey imports a public key into the address manager. // ImportPublicKey imports a public key into the address manager.
@ -1789,14 +1781,7 @@ func (s *ScopedKeyManager) ImportPublicKey(ns walletdb.ReadWriteBucket,
return nil, err return nil, err
} }
// The full derivation path for an imported key is incomplete as we return s.toImportedPublicManagedAddress(pubKey, true)
// don't know exactly how it was derived.
importedDerivationPath := DerivationPath{
InternalAccount: ImportedAddrAccount,
}
return s.toPublicManagedAddress(
pubKey, true, true, importedDerivationPath,
)
} }
// importPublicKey imports a public key into the address manager and updates the // importPublicKey imports a public key into the address manager and updates the
@ -1883,19 +1868,22 @@ func (s *ScopedKeyManager) importPublicKey(ns walletdb.ReadWriteBucket,
return nil return nil
} }
// toPrivateManagedAddress converts a private key to a managed address. // toImportedPrivateManagedAddress converts an imported private key to an
func (s *ScopedKeyManager) toPrivateManagedAddress(wif *btcutil.WIF, // imported managed address.
imported bool, derivationPath DerivationPath) (*managedAddress, error) { func (s *ScopedKeyManager) toImportedPrivateManagedAddress(
wif *btcutil.WIF) (*managedAddress, error) {
// Create a new managed address based on the imported address. // Create a new managed address based on the imported address.
//
// TODO: Handle imported key being part of internal branch.
managedAddr, err := newManagedAddress( managedAddr, err := newManagedAddress(
s, derivationPath, wif.PrivKey, wif.CompressPubKey, s, ImportedDerivationPath, wif.PrivKey, wif.CompressPubKey,
s.addrSchema.ExternalAddrType, s.addrSchema.ExternalAddrType,
) )
if err != nil { if err != nil {
return nil, err return nil, err
} }
managedAddr.imported = imported managedAddr.imported = true
// Add the new managed address to the cache of recent addresses and // Add the new managed address to the cache of recent addresses and
// return it. // return it.
@ -1903,19 +1891,22 @@ func (s *ScopedKeyManager) toPrivateManagedAddress(wif *btcutil.WIF,
return managedAddr, nil return managedAddr, nil
} }
// toPublicManagedAddress converts a public key to a managed address. // toPublicManagedAddress converts an imported public key to an imported managed
func (s *ScopedKeyManager) toPublicManagedAddress(pubKey *btcec.PublicKey, // address.
compressed, imported bool, derivationPath DerivationPath) (*managedAddress, error) { func (s *ScopedKeyManager) toImportedPublicManagedAddress(
pubKey *btcec.PublicKey, compressed bool) (*managedAddress, error) {
// Create a new managed address based on the imported address. // Create a new managed address based on the imported address.
//
// TODO: Handle imported key being part of internal branch.
managedAddr, err := newManagedAddressWithoutPrivKey( managedAddr, err := newManagedAddressWithoutPrivKey(
s, derivationPath, pubKey, compressed, s, ImportedDerivationPath, pubKey, compressed,
s.addrSchema.ExternalAddrType, s.addrSchema.ExternalAddrType,
) )
if err != nil { if err != nil {
return nil, err return nil, err
} }
managedAddr.imported = imported managedAddr.imported = true
// Add the new managed address to the cache of recent addresses and // Add the new managed address to the cache of recent addresses and
// return it. // return it.