From 62c4ec136e8a9a24587c0e4bc8a4ae12bb8af9a0 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Thu, 17 Jul 2025 15:00:03 +0700 Subject: [PATCH 1/5] test: remove duplicated code from wallet_mnemonicbits.py by using helper get_mnemonic --- test/functional/wallet_mnemonicbits.py | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/test/functional/wallet_mnemonicbits.py b/test/functional/wallet_mnemonicbits.py index 02c70a72551e..ddf4a8c432f1 100755 --- a/test/functional/wallet_mnemonicbits.py +++ b/test/functional/wallet_mnemonicbits.py @@ -88,22 +88,14 @@ def run_test(self): self.nodes[0].loadwallet("wallet_160") self.nodes[0].loadwallet("wallet_192") self.nodes[0].loadwallet("wallet_224") - if self.options.descriptors: - self.nodes[0].createwallet("wallet_256", False, True, "", False, True) # blank Descriptors - self.nodes[0].get_wallet_rpc("wallet_256").upgradetohd() - assert_equal(len(self.get_mnemonic(self.nodes[0].get_wallet_rpc(self.default_wallet_name)).split()), 12) # 12 words by default - assert_equal(len(self.nodes[0].get_wallet_rpc("wallet_160").listdescriptors(True)["descriptors"][0]["mnemonic"].split()), 15) # 15 words - assert_equal(len(self.nodes[0].get_wallet_rpc("wallet_192").listdescriptors(True)["descriptors"][0]["mnemonic"].split()), 18) # 18 words - assert_equal(len(self.nodes[0].get_wallet_rpc("wallet_224").listdescriptors(True)["descriptors"][0]["mnemonic"].split()), 21) # 21 words - assert_equal(len(self.nodes[0].get_wallet_rpc("wallet_256").listdescriptors(True)["descriptors"][0]["mnemonic"].split()), 24) # 24 words - else: - self.nodes[0].createwallet("wallet_256", False, True) # blank HD legacy - self.nodes[0].get_wallet_rpc("wallet_256").upgradetohd() - assert_equal(len(self.nodes[0].get_wallet_rpc(self.default_wallet_name).dumphdinfo()["mnemonic"].split()), 12) # 12 words by default - assert_equal(len(self.nodes[0].get_wallet_rpc("wallet_160").dumphdinfo()["mnemonic"].split()), 15) # 15 words - assert_equal(len(self.nodes[0].get_wallet_rpc("wallet_192").dumphdinfo()["mnemonic"].split()), 18) # 18 words - assert_equal(len(self.nodes[0].get_wallet_rpc("wallet_224").dumphdinfo()["mnemonic"].split()), 21) # 21 words - assert_equal(len(self.nodes[0].get_wallet_rpc("wallet_256").dumphdinfo()["mnemonic"].split()), 24) # 24 words + self.nodes[0].createwallet("wallet_256", blank=True, descriptors=self.options.descriptors) # blank wallet + self.nodes[0].get_wallet_rpc("wallet_256").upgradetohd() + + assert_equal(len(self.get_mnemonic(self.nodes[0].get_wallet_rpc(self.default_wallet_name)).split()), 12) # 12 words by default + assert_equal(len(self.get_mnemonic(self.nodes[0].get_wallet_rpc("wallet_160")).split()), 15) # 15 words + assert_equal(len(self.get_mnemonic(self.nodes[0].get_wallet_rpc("wallet_192")).split()), 18) # 18 words + assert_equal(len(self.get_mnemonic(self.nodes[0].get_wallet_rpc("wallet_224")).split()), 21) # 21 words + assert_equal(len(self.get_mnemonic(self.nodes[0].get_wallet_rpc("wallet_256")).split()), 24) # 24 words if __name__ == '__main__': From cfffdc5d10bbf293d0114e94b311a934b4ee2277 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Thu, 17 Jul 2025 15:30:31 +0700 Subject: [PATCH 2/5] fix: copyright for wallet_upgradetohd.py --- test/functional/wallet_upgradetohd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/wallet_upgradetohd.py b/test/functional/wallet_upgradetohd.py index 0fc1c7e4d12b..05e69cede14f 100755 --- a/test/functional/wallet_upgradetohd.py +++ b/test/functional/wallet_upgradetohd.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016 The Dash Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """ From 0a4db75dfb79d8301e5e1538f18ede4cf7718502 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Thu, 17 Jul 2025 15:43:27 +0700 Subject: [PATCH 3/5] test: add test for upgradetohd with user specified mnemonic and passphrase --- test/functional/wallet_mnemonicbits.py | 31 +++++++++++++++++++++++++- test/functional/wallet_upgradetohd.py | 3 ++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/test/functional/wallet_mnemonicbits.py b/test/functional/wallet_mnemonicbits.py index ddf4a8c432f1..f37993f46c88 100755 --- a/test/functional/wallet_mnemonicbits.py +++ b/test/functional/wallet_mnemonicbits.py @@ -4,6 +4,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test -mnemonicbits wallet option.""" +from test_framework.blocktools import COINBASE_MATURITY from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, @@ -45,7 +46,6 @@ def run_test(self): mnemonic_pre = self.get_mnemonic(self.nodes[0]) - self.nodes[0].encryptwallet('pass') self.nodes[0].walletpassphrase('pass', 100) if self.options.descriptors: @@ -97,6 +97,35 @@ def run_test(self): assert_equal(len(self.get_mnemonic(self.nodes[0].get_wallet_rpc("wallet_224")).split()), 21) # 21 words assert_equal(len(self.get_mnemonic(self.nodes[0].get_wallet_rpc("wallet_256")).split()), 24) # 24 words + self.test_upgradetohd_custom() + + def test_upgradetohd_custom(self): + self.log.info("Test upgradetohd with user defined mnemonic") + self.nodes[0].createwallet("w-custom-1a", blank=True) + self.nodes[0].createwallet("w-custom-1b", blank=True) + self.nodes[0].createwallet("w-custom-2", blank=True) + custom_mnemonic = "similar behave slot swim scissors throw planet view ghost laugh drift calm" + # this address belongs to custom mnemonic with no passphrase + custom_address_1 = "yLpq97zZUsFQ2rdMqhcPKkYT36MoPK4Hob" + # this address belongs to custom mnemonic with passphrase "custom-passphrase" + custom_address_2 = "yYBPeZQcqgQHu9dxA5pKBWtYbK2hwfFHxf" + + self.nodes[0].get_wallet_rpc('w-custom-1a').upgradetohd(custom_mnemonic) + self.nodes[0].get_wallet_rpc('w-custom-1b').upgradetohd(custom_mnemonic, "") + self.nodes[0].get_wallet_rpc('w-custom-2').upgradetohd(custom_mnemonic, "custom-passphrase") + self.generate(self.nodes[0], COINBASE_MATURITY + 1) + + self.nodes[0].get_wallet_rpc(self.default_wallet_name).sendtoaddress(custom_address_1, 11) + self.nodes[0].get_wallet_rpc(self.default_wallet_name).sendtoaddress(custom_address_2, 12) + self.generate(self.nodes[0], 1) + self.restart_node(0) + self.nodes[0].loadwallet('w-custom-1a') + self.nodes[0].loadwallet('w-custom-1b') + self.nodes[0].loadwallet('w-custom-2') + assert_equal(11, self.nodes[0].get_wallet_rpc('w-custom-1a').getbalance()) + assert_equal(11, self.nodes[0].get_wallet_rpc('w-custom-1b').getbalance()) + assert_equal(12, self.nodes[0].get_wallet_rpc('w-custom-2').getbalance()) + if __name__ == '__main__': WalletMnemonicbitsTest().main () diff --git a/test/functional/wallet_upgradetohd.py b/test/functional/wallet_upgradetohd.py index 05e69cede14f..5820313029cb 100755 --- a/test/functional/wallet_upgradetohd.py +++ b/test/functional/wallet_upgradetohd.py @@ -5,7 +5,8 @@ """ wallet_upgradetohd.py -Test upgrade to a Hierarchical Deterministic wallet via upgradetohd rpc +Test upgrade to a Hierarchical Deterministic wallet via upgradetohd rpc for legacy wallets +For tests of upgradetohd for descriptor wallets see wallet_mnemonicbits.py """ import shutil From 0d41057e665f9dac9d7ca42c871c94309931695d Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Thu, 17 Jul 2025 20:02:06 +0700 Subject: [PATCH 4/5] test: prepare test_upgradetohd_custom for extra options --- test/functional/wallet_mnemonicbits.py | 29 +++++++++++++++----------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/test/functional/wallet_mnemonicbits.py b/test/functional/wallet_mnemonicbits.py index f37993f46c88..53fabb60010e 100755 --- a/test/functional/wallet_mnemonicbits.py +++ b/test/functional/wallet_mnemonicbits.py @@ -101,30 +101,35 @@ def run_test(self): def test_upgradetohd_custom(self): self.log.info("Test upgradetohd with user defined mnemonic") - self.nodes[0].createwallet("w-custom-1a", blank=True) - self.nodes[0].createwallet("w-custom-1b", blank=True) - self.nodes[0].createwallet("w-custom-2", blank=True) + wname_1a = "w-custom-1a" + wname_1b = "w-custom-1b" + wname_2 = "w-custom-2" + + wnames = [wname_1a, wname_1b, wname_2] + for wname in wnames: + self.nodes[0].createwallet(wname, blank=True) + custom_mnemonic = "similar behave slot swim scissors throw planet view ghost laugh drift calm" # this address belongs to custom mnemonic with no passphrase custom_address_1 = "yLpq97zZUsFQ2rdMqhcPKkYT36MoPK4Hob" # this address belongs to custom mnemonic with passphrase "custom-passphrase" custom_address_2 = "yYBPeZQcqgQHu9dxA5pKBWtYbK2hwfFHxf" - self.nodes[0].get_wallet_rpc('w-custom-1a').upgradetohd(custom_mnemonic) - self.nodes[0].get_wallet_rpc('w-custom-1b').upgradetohd(custom_mnemonic, "") - self.nodes[0].get_wallet_rpc('w-custom-2').upgradetohd(custom_mnemonic, "custom-passphrase") + self.nodes[0].get_wallet_rpc(wname_1a).upgradetohd(custom_mnemonic) + self.nodes[0].get_wallet_rpc(wname_1b).upgradetohd(custom_mnemonic, "") + self.nodes[0].get_wallet_rpc(wname_2).upgradetohd(custom_mnemonic, "custom-passphrase") self.generate(self.nodes[0], COINBASE_MATURITY + 1) self.nodes[0].get_wallet_rpc(self.default_wallet_name).sendtoaddress(custom_address_1, 11) self.nodes[0].get_wallet_rpc(self.default_wallet_name).sendtoaddress(custom_address_2, 12) self.generate(self.nodes[0], 1) self.restart_node(0) - self.nodes[0].loadwallet('w-custom-1a') - self.nodes[0].loadwallet('w-custom-1b') - self.nodes[0].loadwallet('w-custom-2') - assert_equal(11, self.nodes[0].get_wallet_rpc('w-custom-1a').getbalance()) - assert_equal(11, self.nodes[0].get_wallet_rpc('w-custom-1b').getbalance()) - assert_equal(12, self.nodes[0].get_wallet_rpc('w-custom-2').getbalance()) + for wname in wnames: + self.nodes[0].loadwallet(wname) + + assert_equal(11, self.nodes[0].get_wallet_rpc(wname_1a).getbalance()) + assert_equal(11, self.nodes[0].get_wallet_rpc(wname_1b).getbalance()) + assert_equal(12, self.nodes[0].get_wallet_rpc(wname_2).getbalance()) if __name__ == '__main__': From d842fea69ff25dbe13b2a5e35939932c12d66051 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Thu, 17 Jul 2025 20:26:56 +0700 Subject: [PATCH 5/5] test: extra tests for upgradetohd with & without wallet encryption --- test/functional/wallet_mnemonicbits.py | 61 +++++++++++++++++++------- 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/test/functional/wallet_mnemonicbits.py b/test/functional/wallet_mnemonicbits.py index 53fabb60010e..1a66abf2229f 100755 --- a/test/functional/wallet_mnemonicbits.py +++ b/test/functional/wallet_mnemonicbits.py @@ -10,6 +10,13 @@ assert_equal, ) +custom_mnemonic = "similar behave slot swim scissors throw planet view ghost laugh drift calm" +# this address belongs to custom mnemonic with no passphrase +custom_address_1 = "yLpq97zZUsFQ2rdMqhcPKkYT36MoPK4Hob" +# this address belongs to custom mnemonic with passphrase "custom-passphrase" +custom_address_2 = "yYBPeZQcqgQHu9dxA5pKBWtYbK2hwfFHxf" + + class WalletMnemonicbitsTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -97,35 +104,55 @@ def run_test(self): assert_equal(len(self.get_mnemonic(self.nodes[0].get_wallet_rpc("wallet_224")).split()), 21) # 21 words assert_equal(len(self.get_mnemonic(self.nodes[0].get_wallet_rpc("wallet_256")).split()), 24) # 24 words - self.test_upgradetohd_custom() - def test_upgradetohd_custom(self): + self.generate(self.nodes[0], COINBASE_MATURITY + 1) + + self.nodes[0].get_wallet_rpc(self.default_wallet_name).sendtoaddress(custom_address_1, 11) + self.nodes[0].get_wallet_rpc(self.default_wallet_name).sendtoaddress(custom_address_2, 12) + self.generate(self.nodes[0], 1) + + self.log.info("Test upgradetohd with user defined mnemonic") - wname_1a = "w-custom-1a" - wname_1b = "w-custom-1b" - wname_2 = "w-custom-2" + self.test_upgradetohd_custom(False, False) + self.log.info("Test upgradetohd with user defined mnemonic, encrypt wallet after creation") + self.test_upgradetohd_custom(True, False) + + self.log.info("Test upgradetohd with user defined mnemonic, encrypt wallet after upgradetohd") + self.test_upgradetohd_custom(False, True) + + def test_upgradetohd_custom(self, to_encrypt_1, to_encrypt_2): + wname_1a = f"w-custom-1a-{to_encrypt_1}-{to_encrypt_2}" + wname_1b = f"w-custom-1b-{to_encrypt_1}-{to_encrypt_2}" + wname_2 = f"w-custom-2-{to_encrypt_1}-{to_encrypt_2}" wnames = [wname_1a, wname_1b, wname_2] + for wname in wnames: self.nodes[0].createwallet(wname, blank=True) + if to_encrypt_1: + self.nodes[0].get_wallet_rpc(wname).encryptwallet("123") + self.nodes[0].get_wallet_rpc(wname).walletpassphrase("123", 100) + + if to_encrypt_1: + self.nodes[0].get_wallet_rpc(wname_1a).upgradetohd(custom_mnemonic, "", "123") + self.nodes[0].get_wallet_rpc(wname_1b).upgradetohd(custom_mnemonic, "", "123") + self.nodes[0].get_wallet_rpc(wname_2).upgradetohd(custom_mnemonic, "custom-passphrase", "123") + else: + self.nodes[0].get_wallet_rpc(wname_1a).upgradetohd(custom_mnemonic) + self.nodes[0].get_wallet_rpc(wname_1b).upgradetohd(custom_mnemonic, "") + self.nodes[0].get_wallet_rpc(wname_2).upgradetohd(custom_mnemonic, "custom-passphrase") - custom_mnemonic = "similar behave slot swim scissors throw planet view ghost laugh drift calm" - # this address belongs to custom mnemonic with no passphrase - custom_address_1 = "yLpq97zZUsFQ2rdMqhcPKkYT36MoPK4Hob" - # this address belongs to custom mnemonic with passphrase "custom-passphrase" - custom_address_2 = "yYBPeZQcqgQHu9dxA5pKBWtYbK2hwfFHxf" - self.nodes[0].get_wallet_rpc(wname_1a).upgradetohd(custom_mnemonic) - self.nodes[0].get_wallet_rpc(wname_1b).upgradetohd(custom_mnemonic, "") - self.nodes[0].get_wallet_rpc(wname_2).upgradetohd(custom_mnemonic, "custom-passphrase") - self.generate(self.nodes[0], COINBASE_MATURITY + 1) + if to_encrypt_2: + for wname in wnames: + self.nodes[0].get_wallet_rpc(wname).encryptwallet("123") + self.nodes[0].get_wallet_rpc(wname).walletpassphrase("123", 100) - self.nodes[0].get_wallet_rpc(self.default_wallet_name).sendtoaddress(custom_address_1, 11) - self.nodes[0].get_wallet_rpc(self.default_wallet_name).sendtoaddress(custom_address_2, 12) - self.generate(self.nodes[0], 1) self.restart_node(0) for wname in wnames: self.nodes[0].loadwallet(wname) + if to_encrypt_1 or to_encrypt_2: + self.nodes[0].get_wallet_rpc(wname).walletpassphrase("123", 100) assert_equal(11, self.nodes[0].get_wallet_rpc(wname_1a).getbalance()) assert_equal(11, self.nodes[0].get_wallet_rpc(wname_1b).getbalance())