wallet: plumb the mnemonic entropy through CWallet

Wires the key store secret to the database records: load and store paths on
CWallet, the two ReadKeyValue arms, and the export path.

GetMnemonicPhrase now prefers the entropy record and verifies it before printing:
a phrase is only returned if expanding it reproduces the seed derivation actually
uses. It falls back to the existing fMnemonicSeed path, so wallets that store the
entropy AS the seed keep working unchanged.

IsMnemonicSeed() now means "a phrase is available" rather than "the seed is the
entropy", which is what every caller actually wants.

Still a no-op on every existing wallet: nothing creates an entropy record yet, so
GetMnemonicEntropy returns false and the old code path is taken.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-23 06:37:43 +02:00
co-authored by Claude Opus 5
parent 3caec548ae
commit 2d7dd90c55
3 changed files with 149 additions and 2 deletions
+32
View File
@@ -860,6 +860,38 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
ssValue >> nOrigin;
pwallet->hdSeedOrigin = (int)nOrigin;
}
else if (strType == "mnementropy")
{
uint256 entropyFp;
RawHDSeed entropy;
ssKey >> entropyFp;
ssValue >> entropy;
if (MnemonicEntropyFingerprint(entropy) != entropyFp)
{
strErr = "Error reading wallet database: mnemonic entropy corrupt";
return false;
}
if (!pwallet->LoadMnemonicEntropy(entropy))
{
strErr = "Error reading wallet database: LoadMnemonicEntropy failed";
return false;
}
}
else if (strType == "cmnementropy")
{
uint256 entropyFp;
vector<unsigned char> vchCryptedSecret;
ssKey >> entropyFp;
ssValue >> vchCryptedSecret;
if (!pwallet->LoadCryptedMnemonicEntropy(entropyFp, vchCryptedSecret))
{
strErr = "Error reading wallet database: LoadCryptedMnemonicEntropy failed";
return false;
}
wss.fIsEncrypted = true;
}
} catch (...)
{
return false;