The keys and scripts created for the Legacy Wallet needed to be persisted in order for the migration to work properly.
Fixes #32277.
The keys and scripts created for the Legacy Wallet needed to be persisted in order for the migration to work properly.
Fixes #32277.
<!--e57a25ab6845829454e8d69fc972939a-->
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
<!--006a51241073e994b41acfe9ec718e94-->
For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/32281.
<!--021abf342d371248e50ceaed478a90ca-->
See the guideline for information on the review process.
| Type | Reviewers |
|---|---|
| ACK | achow101, davidgumberg, furszy |
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.
<!--174a7506f384e20aa4161008e828411d-->
Reviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
568 | @@ -569,6 +569,22 @@ bool HasLegacyRecords(CWallet& wallet, DatabaseBatch& batch) 569 | return false; 570 | } 571 | 572 | +bool HasAnyRecordWithKeyPrefix(CWallet& wallet, const std::string& dbkey_prefix)
I don't think this is really necessary, especially since it's test only.
Ok, I can move it to the bench file.
Could just remove it.
41 | @@ -42,6 +42,11 @@ static void WalletMigration(benchmark::Bench& bench) 42 | const CScript& script = scripts_watch_only.emplace_back(GetScriptForDestination(dest)); 43 | assert(legacy_spkm->LoadWatchOnly(script)); 44 | assert(wallet->SetAddressBook(dest, strprintf("watch_%d", w), /*purpose=*/std::nullopt)); 45 | + { 46 | + WalletBatch batch(wallet->GetDatabase());
Can create a single batch instance outside the loop and use it everywhere. The "database" on this test is a plain map in memory. No thread synchronization is needed, writes are done sequential.
62 | @@ -58,6 +63,11 @@ static void WalletMigration(benchmark::Bench& bench) 63 | mtx.vout.emplace_back(COIN, scripts_watch_only.at(j % NUM_WATCH_ONLY_ADDR)); 64 | mtx.vin.resize(2); 65 | wallet->AddToWallet(MakeTransactionRef(mtx), TxStateInactive{}, /*update_wtx=*/nullptr, /*fFlushOnClose=*/false, /*rescanning_old_block=*/true); 66 | + { 67 | + WalletBatch batch(wallet->GetDatabase()); 68 | + batch.WriteKey(pubkey, key.GetPrivKey(), CKeyMetadata());
The empty metadata field smells bad. Double check migration.
I've checked that keys (500 txs on local addresses) and scripts (20 wo imported addresses) are being migrated correctly (the first at ApplyMigrationData in for (auto& desc_spkm : data.desc_spkms) { and the second at DoMigration in for (const auto& [desc_str, creation_time] : data->watch_descs) {).
I think empty metadata is fine, there isn't really much metadata to be had for imports and randomly generated keys. It's basically just the creation time.
The keys and scripts created for the Legacy Wallet
needed to be persisted in order for the migration to work
properly.
Can you comment on #32277 (comment)?
ACK 7912cd41258d59e41f3c961a3be35a8921194670
42 | @@ -42,6 +43,7 @@ static void WalletMigration(benchmark::Bench& bench)
43 | const CScript& script = scripts_watch_only.emplace_back(GetScriptForDestination(dest));
44 | assert(legacy_spkm->LoadWatchOnly(script));
45 | assert(wallet->SetAddressBook(dest, strprintf("watch_%d", w), /*purpose=*/std::nullopt));
For context on my comment in #32277 (comment), SetAddressBook() includes a write to the database, and so does AddToWallet(tx)
This is the reason why some records were persisted, but none that were strictly "legacy" records as mentioned in #32277 (comment).
(@furszy)
Tested ACK 7912cd41258d59e4
Either of the two DB writes added here seems to fix the issue in my testing, but it's better to be consistent and write both.
I am no longer confident the change to success introduced in #32149 makes sense:
Now, any wallet which fails the HasLegacyRecords() check gets flagged as success = true, before it was only wallets with the blank flag set which got success = true for free. On second thought, should #32149 have explicitly handled the empty watchonly wallet case, rather than having to reason about the correctness/completeness of HasLegacyRecords()
This bug was an instance of a more general class of crash during migration: #32111. This would still be a bug if #32111 was fixed, but might not have resulted in a crash.
utACK 7912cd41258d5