4da76ca247 test: Test migration of tx with both spendable and watchonly (Ava Chow)
c62a8d03a8 wallet: Keep txs that belong to both watchonly and migrated wallets (Ava Chow)
71cb28ea8c test: Make sure that migration test does not rescan on reloading (Ava Chow)
78ba0e6748 wallet: Reload the wallet if migration exited early (Ava Chow)
9332c7edda wallet: Write bestblock to watchonly and solvable wallets (Ava Chow)
Pull request description:
A transaction does not necessarily have to belong to either the migrated wallet (with the private keys) and the watchonly wallet (with watchonly things), it could have multiple outputs with each isminetype. So we should be putting such transactions in one or the other wallet, but rather putting it in both.
I've added a test for this behavior, however the test also revealed a few other issues. Notably, it revealed that `migratewallet` would have the watchonly wallet rescan from genesis when it is reloaded at the end of migration. This could be a cause for migration appearing to be very slow. This is resolved by first writing best block records to the watchonly and solvable wallets, as well as updating the test to make sure that rescans don't happen.
The change to avoid rescans also found an issue where some of our early exits would result in unloading the wallet even though nothing happened. So there is also a commit to reload the wallet for such early exits.
ACKs for top commit:
ryanofsky:
Code review ACK 4da76ca247. This looks great. The code is actually cleaner than before, two bugs are fixed, and the test checking for rescanning is pretty clever and broadens test coverage.
furszy:
Code review ACK 4da76ca2
Tree-SHA512: 5fc210cff16ca6720d7b2d0616d7e3f295c974147854abc704cf99a3bfaad17572ada084859e7a1b1ca94da647ad130303219678f429b7995f85e040236db35c
@ -431,7 +448,7 @@ class WalletMigrationTest(BitcoinTestFramework):
bals=wallet.getbalances()
wallet.migratewallet()
self.migrate_wallet(wallet)
assert_equal(bals,wallet.getbalances())
@ -450,7 +467,7 @@ class WalletMigrationTest(BitcoinTestFramework):
assert_raises_rpc_error(-4,"Error: Wallet decryption failed, the wallet passphrase was not provided or was incorrect",wallet.migratewallet,None,"badpass")
assert_raises_rpc_error(-4,"The passphrase contains a null character",wallet.migratewallet,None,"pass\0with\0null")
wallet.migratewallet(passphrase="pass")
self.migrate_wallet(wallet,passphrase="pass")
info=wallet.getwalletinfo()
assert_equal(info["descriptors"],True)
@ -512,7 +529,7 @@ class WalletMigrationTest(BitcoinTestFramework):
self.log.info("Test migration of the wallet named as the empty string")
wallet=self.create_legacy_wallet("")
wallet.migratewallet()
self.migrate_wallet(wallet)
info=wallet.getwalletinfo()
assert_equal(info["descriptors"],True)
assert_equal(info["format"],"sqlite")
@ -534,7 +551,7 @@ class WalletMigrationTest(BitcoinTestFramework):
assert_equal(info["descriptors"],False)
assert_equal(info["format"],"bdb")
wallet.migratewallet()
self.migrate_wallet(wallet)
info=wallet.getwalletinfo()
assert_equal(info["descriptors"],True)
assert_equal(info["format"],"sqlite")
@ -622,7 +639,7 @@ class WalletMigrationTest(BitcoinTestFramework):