diff options
| author | mtg0001 <106211915+mtg0001@users.noreply.github.com> | 2026-08-01 21:43:45 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-01 21:43:45 -0300 |
| commit | 5a5478669c487963e99491112abc065c59973966 (patch) | |
| tree | e2e73a4e2283c5dae4fa342ec98cdf8d719017ca /src/selftest.cpp | |
| parent | fc071066c9de259795a210e449b364ac126416ad (diff) | |
Keep new phrase addresses recoverable (#102)
-newphrase installed a seed but left the wallet's visible address as the pre-seed random key and the old random pool intact, so the next address handed out -- a mining payout included -- could be one the twelve words cannot reproduce, while the window said a recovery phrase existed. Installing a phrase now clears the stale pool records (private keys stay in wallet.dat), reserves a derived default receiving key, tolerates already-stored derived keys so repeated installs do not stall the pool, and -restorephrase reports what it recovered rather than the wallet's total transaction count. Self-test covers installing a phrase over a pre-existing random pool.
Diffstat (limited to 'src/selftest.cpp')
| -rw-r--r-- | src/selftest.cpp | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/src/selftest.cpp b/src/selftest.cpp index b733c60..bc9fa5a 100644 --- a/src/selftest.cpp +++ b/src/selftest.cpp | |||
| @@ -327,10 +327,35 @@ static int RunWalletHDSelfTest() | |||
| 327 | throw std::runtime_error("LoadWallet failed"); | 327 | throw std::runtime_error("LoadWallet failed"); |
| 328 | 328 | ||
| 329 | std::string strError; | 329 | std::string strError; |
| 330 | TopUpKeyPool(); | ||
| 331 | int nRandomPoolSize = 0; | ||
| 332 | CRITICAL_BLOCK(cs_keyPool) | ||
| 333 | nRandomPoolSize = (int)mapKeyPool.size(); | ||
| 334 | nFail += Check(nRandomPoolSize == KEYPOOL_SIZE, | ||
| 335 | "a wallet can start with a random key pool") ? 0 : 1; | ||
| 336 | |||
| 330 | nFail += Check(SetHDSeedFromMnemonic(strPhraseA, strError), | 337 | nFail += Check(SetHDSeedFromMnemonic(strPhraseA, strError), |
| 331 | "a valid phrase installs a seed") ? 0 : 1; | 338 | "a valid phrase installs a seed") ? 0 : 1; |
| 332 | nFail += Check(HaveHDSeed(), "the wallet reports having a seed") ? 0 : 1; | 339 | nFail += Check(HaveHDSeed(), "the wallet reports having a seed") ? 0 : 1; |
| 333 | 340 | ||
| 341 | int nPoolAfterSeed = 0; | ||
| 342 | CRITICAL_BLOCK(cs_keyPool) | ||
| 343 | nPoolAfterSeed = (int)mapKeyPool.size(); | ||
| 344 | nFail += Check(nPoolAfterSeed == 0, | ||
| 345 | "installing a phrase clears the old random key pool") ? 0 : 1; | ||
| 346 | nFail += Check(nHDNext == 1, | ||
| 347 | "installing a phrase reserves one derived default key") ? 0 : 1; | ||
| 348 | |||
| 349 | CKey keyFirstDerived; | ||
| 350 | if (!DeriveHDKey(0, keyFirstDerived, strError)) | ||
| 351 | throw std::runtime_error("default derivation failed: " + strError); | ||
| 352 | std::vector<unsigned char> vchDefaultKey; | ||
| 353 | bool fDefaultRead = CWalletDB("r").ReadDefaultKey(vchDefaultKey); | ||
| 354 | nFail += Check(fDefaultRead && vchDefaultKey == keyFirstDerived.GetPubKey(), | ||
| 355 | "the default receiving key is derived from the phrase") ? 0 : 1; | ||
| 356 | nFail += Check(WalletHasPrivateKey(vchDefaultKey), | ||
| 357 | "the derived default key is stored in wallet.dat") ? 0 : 1; | ||
| 358 | |||
| 334 | std::vector<unsigned char> vchBefore = vchHDMaster; | 359 | std::vector<unsigned char> vchBefore = vchHDMaster; |
| 335 | nFail += Check(!SetHDSeedFromMnemonic("not a mnemonic at all", strError), | 360 | nFail += Check(!SetHDSeedFromMnemonic("not a mnemonic at all", strError), |
| 336 | "an invalid phrase is refused") ? 0 : 1; | 361 | "an invalid phrase is refused") ? 0 : 1; |
| @@ -378,8 +403,6 @@ static int RunWalletHDSelfTest() | |||
| 378 | // With a seed installed the pool must be derived from it, and the | 403 | // With a seed installed the pool must be derived from it, and the |
| 379 | // counter must move exactly once per key. | 404 | // counter must move exactly once per key. |
| 380 | SetHDSeedFromMnemonic(strPhraseA, strError); | 405 | SetHDSeedFromMnemonic(strPhraseA, strError); |
| 381 | CRITICAL_BLOCK(cs_keyPool) | ||
| 382 | mapKeyPool.clear(); | ||
| 383 | unsigned int nNextBefore = nHDNext; | 406 | unsigned int nNextBefore = nHDNext; |
| 384 | TopUpKeyPool(); | 407 | TopUpKeyPool(); |
| 385 | 408 | ||