@@ -256,16 +256,25 @@ void CWallet::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey
256256 if (internal) {
257257 chainChildKey.Derive (childKey, hdChain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
258258 metadata.hdKeypath = " m/0'/1'/" + std::to_string (hdChain.nInternalChainCounter ) + " '" ;
259+ metadata.key_origin .path .push_back (0 | BIP32_HARDENED_KEY_LIMIT);
260+ metadata.key_origin .path .push_back (1 | BIP32_HARDENED_KEY_LIMIT);
261+ metadata.key_origin .path .push_back (hdChain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
259262 hdChain.nInternalChainCounter ++;
260263 }
261264 else {
262265 chainChildKey.Derive (childKey, hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
263266 metadata.hdKeypath = " m/0'/0'/" + std::to_string (hdChain.nExternalChainCounter ) + " '" ;
267+ metadata.key_origin .path .push_back (0 | BIP32_HARDENED_KEY_LIMIT);
268+ metadata.key_origin .path .push_back (0 | BIP32_HARDENED_KEY_LIMIT);
269+ metadata.key_origin .path .push_back (hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
264270 hdChain.nExternalChainCounter ++;
265271 }
266272 } while (HaveKey (childKey.key .GetPubKey ().GetID ()));
267273 secret = childKey.key ;
268274 metadata.hd_seed_id = hdChain.seed_id ;
275+ CKeyID master_id = masterKey.key .GetPubKey ().GetID ();
276+ std::copy (master_id.begin (), master_id.begin () + 4 , metadata.key_origin .fingerprint );
277+ metadata.has_key_origin = true ;
269278 // update the chain model in the database
270279 if (!batch.WriteHDChain (hdChain))
271280 throw std::runtime_error (std::string (__func__) + " : Writing HD chain model failed" );
@@ -355,6 +364,41 @@ bool CWallet::WriteKeyMetadata(const CKeyMetadata& meta, const CPubKey& pubkey,
355364 return WalletBatch (*database).WriteKeyMetadata (meta, pubkey, overwrite);
356365}
357366
367+ void CWallet::UpgradeKeyMetadata ()
368+ {
369+ AssertLockHeld (cs_wallet); // mapKeyMetadata
370+ if (IsLocked () || IsWalletFlagSet (WALLET_FLAG_KEY_ORIGIN_METADATA)) {
371+ return ;
372+ }
373+
374+ for (auto & meta_pair : mapKeyMetadata) {
375+ CKeyMetadata& meta = meta_pair.second ;
376+ if (!meta.hd_seed_id .IsNull () && !meta.has_key_origin && meta.hdKeypath != " s" ) { // If the hdKeypath is "s", that's the seed and it doesn't have a key origin
377+ CKey key;
378+ GetKey (meta.hd_seed_id , key);
379+ CExtKey masterKey;
380+ masterKey.SetSeed (key.begin (), key.size ());
381+ // Add to map
382+ CKeyID master_id = masterKey.key .GetPubKey ().GetID ();
383+ std::copy (master_id.begin (), master_id.begin () + 4 , meta.key_origin .fingerprint );
384+ if (!ParseHDKeypath (meta.hdKeypath , meta.key_origin .path )) {
385+ throw std::runtime_error (" Invalid stored hdKeypath" );
386+ }
387+ meta.has_key_origin = true ;
388+ if (meta.nVersion < CKeyMetadata::VERSION_WITH_KEY_ORIGIN) {
389+ meta.nVersion = CKeyMetadata::VERSION_WITH_KEY_ORIGIN;
390+ }
391+
392+ // Write meta to wallet
393+ CPubKey pubkey;
394+ if (GetPubKey (meta_pair.first , pubkey)) {
395+ WriteKeyMetadata (meta, pubkey, true );
396+ }
397+ }
398+ }
399+ SetWalletFlag (WALLET_FLAG_KEY_ORIGIN_METADATA);
400+ }
401+
358402bool CWallet::LoadCryptedKey (const CPubKey &vchPubKey, const std::vector<unsigned char > &vchCryptedSecret)
359403{
360404 return CCryptoKeyStore::AddCryptedKey (vchPubKey, vchCryptedSecret);
@@ -453,8 +497,11 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool accept_no_key
453497 return false ;
454498 if (!crypter.Decrypt (pMasterKey.second .vchCryptedKey , _vMasterKey))
455499 continue ; // try another master key
456- if (CCryptoKeyStore::Unlock (_vMasterKey, accept_no_keys))
500+ if (CCryptoKeyStore::Unlock (_vMasterKey, accept_no_keys)) {
501+ // Now that we've unlocked, upgrade the key metadata
502+ UpgradeKeyMetadata ();
457503 return true ;
504+ }
458505 }
459506 }
460507 return false ;
@@ -1414,6 +1461,7 @@ CPubKey CWallet::DeriveNewSeed(const CKey& key)
14141461
14151462 // set the hd keypath to "s" -> Seed, refers the seed to itself
14161463 metadata.hdKeypath = " s" ;
1464+ metadata.has_key_origin = false ;
14171465 metadata.hd_seed_id = seed.GetID ();
14181466
14191467 {
@@ -4494,16 +4542,9 @@ bool CWallet::GetKeyOrigin(const CKeyID& keyID, KeyOriginInfo& info) const
44944542 meta = it->second ;
44954543 }
44964544 }
4497- if (!meta.hdKeypath .empty ()) {
4498- if (!ParseHDKeypath (meta.hdKeypath , info.path )) return false ;
4499- // Get the proper master key id
4500- CKey key;
4501- GetKey (meta.hd_seed_id , key);
4502- CExtKey masterKey;
4503- masterKey.SetSeed (key.begin (), key.size ());
4504- // Compute identifier
4505- CKeyID masterid = masterKey.key .GetPubKey ().GetID ();
4506- std::copy (masterid.begin (), masterid.begin () + 4 , info.fingerprint );
4545+ if (meta.has_key_origin ) {
4546+ std::copy (meta.key_origin .fingerprint , meta.key_origin .fingerprint + 4 , info.fingerprint );
4547+ info.path = meta.key_origin .path ;
45074548 } else { // Single pubkeys get the master fingerprint of themselves
45084549 std::copy (keyID.begin (), keyID.begin () + 4 , info.fingerprint );
45094550 }
0 commit comments