wallet: add an optional mnemonic-entropy secret to the key stores

Additive plumbing for storing a BIP39 entropy alongside the HD seed, mirroring
how the seed itself is handled through both key store layers: a plaintext member
on CBasicKeyStore, an encrypted pair on CCryptoKeyStore, encryption during the
unencrypted-to-encrypted conversion in EncryptKeys with the plaintext cleared,
and decryption on unlock.

RawHDSeed and CKeyingMaterial are the same secure_allocator vector type, so the
entropy passes through EncryptSecret/DecryptSecret with no adaptation.

Nothing calls this yet; there is no behaviour change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-23 06:23:09 +02:00
co-authored by Claude Opus 5
parent 143c33de48
commit 2a7fdcc1db
4 changed files with 222 additions and 0 deletions
+36
View File
@@ -68,6 +68,42 @@ bool CBasicKeyStore::GetHDSeed(HDSeed& seedOut) const
}
}
bool CBasicKeyStore::SetMnemonicEntropy(const RawHDSeed& entropy)
{
LOCK(cs_SpendingKeyStore);
if (entropy.empty()) {
// Never "install" nothing: HaveMnemonicEntropy() would stay false while
// the caller was told the call succeeded.
return false;
}
if (!mnemonicEntropy.empty()) {
// Same refuse-to-replace rule as SetHDSeed above, for a sharper reason:
// this is the printable form of the seed. If it could be swapped while
// hdSeed stayed put, the wallet would print a seed phrase that does not
// restore it -- strictly worse than printing none.
return false;
}
mnemonicEntropy = entropy;
return true;
}
bool CBasicKeyStore::HaveMnemonicEntropy() const
{
LOCK(cs_SpendingKeyStore);
return !mnemonicEntropy.empty();
}
bool CBasicKeyStore::GetMnemonicEntropy(RawHDSeed& entropyOut) const
{
LOCK(cs_SpendingKeyStore);
if (mnemonicEntropy.empty()) {
return false;
} else {
entropyOut = mnemonicEntropy;
return true;
}
}
bool CBasicKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
{
LOCK(cs_KeyStore);