From 070ef357c02c855f39988813480dc72d4533d6dd Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Sat, 30 Apr 2022 23:33:45 +0300 Subject: [PATCH] wallet: fix metadata updates on HD derivation (#4819) * wallet: Use temporary structure to update metadata correctly while generating new hd keys * wallet: Make sure to never update an already existing key_origin while deriving hd keys --- src/hdchain.cpp | 3 +++ src/wallet/wallet.cpp | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/hdchain.cpp b/src/hdchain.cpp index 8871f7d030..1649da5ff0 100644 --- a/src/hdchain.cpp +++ b/src/hdchain.cpp @@ -187,6 +187,9 @@ void CHDChain::DeriveChildExtKey(uint32_t nAccountIndex, bool fInternal, uint32_ changeKey.Derive(extKeyRet, nChildIndex); #ifdef ENABLE_WALLET + // We should never ever update an already existing key_origin here + assert(!metadata.has_key_origin); + assert(metadata.key_origin.path.empty()); metadata.key_origin.path.push_back(44 | 0x80000000); metadata.key_origin.path.push_back(Params().ExtCoinType() | 0x80000000); metadata.key_origin.path.push_back(nAccountIndex | 0x80000000); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f6b7c778c5..e453f19ea5 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -365,12 +365,17 @@ void CWallet::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey // derive child key at next index, skip keys already known to the wallet CExtKey childKey; + CKeyMetadata metadataTmp; uint32_t nChildIndex = fInternal ? acc.nInternalChainCounter : acc.nExternalChainCounter; do { - hdChainTmp.DeriveChildExtKey(nAccountIndex, fInternal, nChildIndex, childKey, metadata); + // NOTE: DeriveChildExtKey updates metadata, use temporary structure to make sure + // we start with the original (non-updated) data each time. + metadataTmp = metadata; + hdChainTmp.DeriveChildExtKey(nAccountIndex, fInternal, nChildIndex, childKey, metadataTmp); // increment childkey index nChildIndex++; } while (HaveKey(childKey.key.GetPubKey().GetID())); + metadata = metadataTmp; secretRet = childKey.key; CPubKey pubkey = secretRet.GetPubKey();