This PR reworks wallet_migration.py to use previous releases to produce legacy wallets for testing so that the test will continue to work once legacy wallets are removed.
Split from #28710
<!--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/31248.
<!--021abf342d371248e50ceaed478a90ca-->
See the guideline for information on the review process.
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.
122 | + assert_equal(a, b) 123 | + 124 | + def assert_balances_equal(self, a, b): 125 | + a.pop("lastprocessedblock", None) 126 | + b.pop("lastprocessedblock", None) 127 | + assert_equal(a, b)
I wonder if this diff can be removed by just using 28 as the previous release, with the -deprecatedrpc=create_bdb option enabled?
Indeed, removed.
left a question/nit
97 | @@ -98,6 +98,15 @@ 98 | "fe6e347a66043946920c72c9c4afca301968101e6b82fb90a63d7885ebcceb32": {"tag": "v25.0", "tarball": "bitcoin-25.0-riscv64-linux-gnu.tar.gz"}, 99 | "5708fc639cdfc27347cccfd50db9b73b53647b36fb5f3a4a93537cbe8828c27f": {"tag": "v25.0", "tarball": "bitcoin-25.0-x86_64-apple-darwin.tar.gz"}, 100 | "33930d432593e49d58a9bff4c30078823e9af5d98594d2935862788ce8a20aec": {"tag": "v25.0", "tarball": "bitcoin-25.0-x86_64-linux-gnu.tar.gz"}, 101 | + 102 | + "e198461d981b675d39caaec4d5e69e79d7fd52c3d3508f5821e2effe7d4f12c2": {"tag": "v26.1", "tarball": "bitcoin-26.1-aarch64-linux-gnu.tar.gz"},
should be 28?
Oops yes.
509 | - bals = wallet.getbalances() 510 | - 511 | - wallet.unloadwallet() 512 | - 513 | - assert_raises_rpc_error(-8, "RPC endpoint wallet and wallet_name parameter specify different wallets", wallet.migratewallet, "someotherwallet") 514 | - assert_raises_rpc_error(-8, "Either RPC endpoint wallet or wallet_name parameter must be provided", self.nodes[0].migratewallet)
Looks like this coverage should be preserved?
Done. Also added a test for non-existent wallets and this uncovered a bug.
The previous error message for non-existent wallets of "Already a
descriptor wallet" is misleading. Return a more specific error when a
non-existent wallet is specified.
186 | basic1_restored_wi = basic1_restored.getwalletinfo() 187 | assert_equal(basic1_restored_wi['balance'], bal) 188 | assert_equal(basic1_restored.listaddressgroupings(), addr_gps) 189 | self.assert_list_txs_equal(basic1_restored.listtransactions(), txs) 190 | 191 | # restart node and verify that everything is still there
Nit
# restart master node and verify that everything is still there
Will do if I need to retouch.
Done
205 | @@ -193,12 +206,12 @@ def test_basic(self): 206 | send_value = random.randint(1, 4) 207 | default.sendtoaddress(addr, send_value) 208 | basic2_balance += send_value 209 | - self.generate(self.nodes[0], 1) 210 | + self.generate(self.master_node, 1) 211 | assert_equal(basic2.getbalance(), basic2_balance) 212 | basic2_txs = basic2.listtransactions() 213 | 214 | # Now migrate and test that we still see have the same balance/transactions
Not in the diff but still
- # Now migrate and test that we still see have the same balance/transactions
+ # Now migrate and test that we still have the same balance/transactions
Will do if I need to retouch.
Done
63 | file_magic = f.read(16) 64 | assert_equal(file_magic, b'SQLite format 3\x00') 65 | - assert_equal(self.nodes[0].get_wallet_rpc(wallet_name).getwalletinfo()["format"], "sqlite") 66 | + assert_equal(self.master_node.get_wallet_rpc(wallet_name).getwalletinfo()["format"], "sqlite") 67 | 68 | def create_legacy_wallet(self, wallet_name, **kwargs):
Should this not be called create_legacy_wallet_and_get_rpc now highlighting that it returns the wallet RPC from the old node?
It returned RPC originally, and I don't think that adding a rename to the diff would be helpful.
489 | - assert_raises_rpc_error(-4, "The passphrase contains a null character", wallet.migratewallet, None, "pass\0with\0null") 490 | - 491 | - # Check the wallet is still active post-migration failure. 492 | - # If not, it will throw an exception and abort the test. 493 | - wallet.walletpassphrase("pass", 99999) 494 | - wallet.getnewaddress()
Don't we need to check for these in the old node?
No, the master node migrates a copy of the wallet. The old node will have the original copy which remains unchanged regardless.
517 | - info = wallet.getwalletinfo() 518 | - assert_equal(info["descriptors"], True) 519 | - assert_equal(info["format"], "sqlite") 520 | - wallet.gettransaction(txid) 521 | - 522 | - assert_equal(bals, wallet.getbalances())
This notloaded wallet migration testing is removed because it is effectively tested in test_unloaded_by_path below?
notloaded is specifically tested because legacy wallets won't be able to be loaded.
553 | + backup_path = self.master_node.wallets_path / backup_filename 554 | assert backup_path.exists() 555 | assert_equal(str(backup_path), res['backup_path']) 556 | assert {"name": backup_filename} not in walletdir_list["wallets"] 557 | 558 | + self.master_node.setmocktime(0)
+1 for adding this. Is the reason for the absence of this unsetting here not causing any issue earlier when wallet.setmocktime(curr_time) was added that no subsequent test in this file below relies on mock time?
Yes, no test relies on the time.
797 | 798 | # The specific assertion in MarkConflicted being tested requires that the parent tx is already loaded 799 | - # by the time the child tx is loaded. Since transactions end up being loaded in txid order due to how both 800 | - # and sqlite store things, we can just grind the child tx until it has a txid that is greater than the parent's. 801 | + # by the time the child tx is loaded. Since transactions end up being loaded in txid order due to how 802 | + # sqlite stores things, we can just grind the child tx until it has a txid that is greater than the parent's.
TIL!
784 | self.log.info("Test migration when wallet contains conflicting transactions")
785 | - def_wallet = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
786 | + def_wallet = self.master_node.get_wallet_rpc(self.default_wallet_name)
787 |
788 | wallet = self.create_legacy_wallet("conflicts")
789 | def_wallet.sendtoaddress(wallet.getnewaddress(), 10)
I have noticed this pattern in most of these tests that I found a little difficult to read. Slightly more verbose naming would make it easier to parse like below. I am not suggesting this change to be done in this PR because this pattern existed earlier as well but can be updated in the future if others find this helpful as well.
- def_wallet.sendtoaddress(wallet.getnewaddress(), 10)
+ def_descriptor_wallet.sendtoaddress(legacy_wallet.getnewaddress(), 10)
49 | + self.skip_if_no_previous_releases() 50 | + 51 | + def setup_nodes(self): 52 | + self.add_nodes(self.num_nodes, versions=[ 53 | + None, 54 | + 280000,
Would be nice to have the commit message mention this instead of use previous releases, which gives an impression multiple previous releases are being used. Couple suggestions:
- test: Rework migratewallet to use previous releases
+ test: Rework migratewallet to use previous release
+ test: Rework migratewallet to use v28 release
Will do if I need to retouch.
Done
tACK a76ad56a80d9c9a60352bb98b363131e359a383b
Certainly useful because it reflects how the end users would do wallet migration after the upcoming release.
Make is successful but around 15 functional tests are failing in my system that seem unrelated to this change because they are failing in master as well. All of the failures are due to timeouts, probably an issue with my setup.
Asked few questions and left suggestions. Found few really good tests in this file in the end!
225 | @@ -213,7 +226,7 @@ def test_basic(self):
226 | assert_raises_rpc_error(-4, "Error: This wallet is already a descriptor wallet", self.nodes[0].migratewallet, "basic2")
nit in a76ad56a80d9c9a60352bb98b363131e359a383b: Forgot to use the node alias?
Fixed
Nothing blocking
ACK a76ad56a80d9c9a60352bb98b363131e359a383b 🌆
<details><summary>Show signature</summary>
Signature:
untrusted comment: signature from minisign secret key on empty file; verify via: minisign -Vm "${path_to_any_empty_file}" -P RWTRmVTMeKV5noAMqVlsMugDDCyyTSbA3Re5AkUrhvLVln0tSaFWglOw -x "${path_to_this_whole_four_line_signature_blob}"
RUTRmVTMeKV5npGrKx1nqXCw5zeVHdtdYURB/KlyA/LMFgpNCs+SkW9a8N95d+U4AP1RJMi+krxU1A3Yux4bpwZNLvVBKy0wLgM=
trusted comment: ACK a76ad56a80d9c9a60352bb98b363131e359a383b 🌆
HCc+p5XHbLShm3UVysnAgJ/8rST3S/1pk8jnPZ3GPMEsR3fcUEEInTLmM4hfPEkuoPZDBo5hxMjqw+XscDFVDA==
</details>
Only trivial style-only changes
re-ACK 55347a5018b2c252c56548f0a6dc1e88e42f66b6 🥊
<details><summary>Show signature</summary>
Signature:
untrusted comment: signature from minisign secret key on empty file; verify via: minisign -Vm "${path_to_any_empty_file}" -P RWTRmVTMeKV5noAMqVlsMugDDCyyTSbA3Re5AkUrhvLVln0tSaFWglOw -x "${path_to_this_whole_four_line_signature_blob}"
RUTRmVTMeKV5npGrKx1nqXCw5zeVHdtdYURB/KlyA/LMFgpNCs+SkW9a8N95d+U4AP1RJMi+krxU1A3Yux4bpwZNLvVBKy0wLgM=
trusted comment: re-ACK 55347a5018b2c252c56548f0a6dc1e88e42f66b6 🥊
MpkIAt2IslqUp6iGZwemtEtxGbYa3VS9/DYQNG/mmqspN0jFhAArSyIr+Y9WjIHMT3dtzucXcRiti0dnGrX9AQ==
</details>
re-ACK 55347a5
Reviewed the range diff - only minor comment, commit message, renaming changes. Ran cmake again.
git range-diff a76ad56...55347a5
The PR title and description can be updated similar to the commit message of 55347a5.
@ryanofsky Do you think this is rfm?
@ryanofsky Do you think this is rfm?
Looks like it, only 2 acks, but this is mostly a test change, and the nontest change is pretty obvious. Will run tests and merge