Merge bitcoin/bitcoin#35619: test: ExtendedPrivateKey follow-ups
What changed, and why it matters
This commit only changes Bitcoin Core's internal functional test code. It replaces hard-coded test keys and addresses with ones generated from a new test helper class, and unifies how tests tell nodes not to create a default wallet. There is no change to the actual Bitcoin Core software that users run, so it cannot affect live wallets, transactions, or network security.
No security action needed. Treat as ordinary test-maintenance cleanup.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The merge commit updates four test files. wallet_importdescriptors.py now uses the ExtendedPrivateKey test helper to derive xpub/xprv material and expected addresses on the fly instead of using static strings. wallet_listdescriptors.py and wallet_taproot.py replace custom no-op init_wallet overrides with the standard self.wallet_names = [] mechanism. test_framework.py adds a docstring pointer. No consensus, wallet, P2P, or RPC runtime code is modified.
Changed components
test/functional/wallet_importdescriptors.pytest/functional/wallet_listdescriptors.pytest/functional/wallet_taproot.pytest/functional/test_framework/test_framework.pyInspect captured patch +18 / −24
### test/functional/test_framework/test_framework.py
@@ -400,6 +400,7 @@ def import_deterministic_coinbase_privkeys(self):
self.init_wallet(node=i)
def init_wallet(self, *, node):
+ """Refer to the self.wallet_names docstring on how to use this"""
wallet_name = self.default_wallet_name if self.wallet_names is None else self.wallet_names[node] if node < len(self.wallet_names) else False
if wallet_name is not False:
n = self.nodes[node]
### test/functional/wallet_importdescriptors.py
@@ -19,7 +19,7 @@
import threading
import time
-from test_framework.address import key_to_p2sh_p2wpkh, key_to_p2wpkh, script_to_p2wsh
+from test_framework.address import key_to_p2pkh, key_to_p2sh_p2wpkh, key_to_p2wpkh, script_to_p2wsh
from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.descriptors import descsum_create
@@ -583,28 +583,24 @@ def run_test(self):
# Make sure ranged imports import keys in order
w1 = self.nodes[1].get_wallet_rpc('w1')
self.log.info('Key ranges should be imported in order')
- xpub = "tpubDAXcJ7s7ZwicqjprRaEWdPoHKrCS215qxGYxpusRLLmJuT69ZSicuGdSfyvyKpvUNYBW1s2U3NSrT6vrCYB9e6nZUEvrqnwXPF8ArTCRXMY"
- addresses = [
- 'bcrt1qtmp74ayg7p24uslctssvjm06q5phz4yrxucgnv', # m/0'/0'/0
- 'bcrt1q8vprchan07gzagd5e6v9wd7azyucksq2xc76k8', # m/0'/0'/1
- 'bcrt1qtuqdtha7zmqgcrr26n2rqxztv5y8rafjp9lulu', # m/0'/0'/2
- 'bcrt1qau64272ymawq26t90md6an0ps99qkrse58m640', # m/0'/0'/3
- 'bcrt1qsg97266hrh6cpmutqen8s4s962aryy77jp0fg0', # m/0'/0'/4
- ]
-
- self.test_importdesc({'desc': descsum_create('wpkh([80002067/0h/0h]' + xpub + '/*)'),
+ root_xprv = ExtendedPrivateKey.generate()
+ root_fingerprint = root_xprv._fingerprint().hex()
+ xprv = root_xprv.derive_path("m/0'/0'")
+ xpub = xprv.pubkey().to_string()
+ addresses = [key_to_p2wpkh(xprv.derive_path(f"m/{i}").pubkey().pubkey.get_bytes()) for i in range(0, 5)]
+ self.test_importdesc({'desc': descsum_create(f'wpkh([{root_fingerprint}/0h/0h]{xpub}/*)'),
'active': True,
'range' : [0, 2],
'timestamp': 'now'
},
success=True)
- self.test_importdesc({'desc': descsum_create('sh(wpkh([abcdef12/0h/0h]' + xpub + '/*))'),
+ self.test_importdesc({'desc': descsum_create(f'sh(wpkh([{root_fingerprint}/0h/0h]{xpub}/*))'),
'active': True,
'range' : [0, 2],
'timestamp': 'now'
},
success=True)
- self.test_importdesc({'desc': descsum_create('pkh([12345678/0h/0h]' + xpub + '/*)'),
+ self.test_importdesc({'desc': descsum_create(f'pkh([{root_fingerprint}/0h/0h]{xpub}/*)'),
'active': True,
'range' : [0, 2],
'timestamp': 'now'
@@ -616,16 +612,18 @@ def run_test(self):
received_addr = w1.getnewaddress('', 'bech32')
assert_raises_rpc_error(-4, 'This wallet has no available keys', w1.getrawchangeaddress, 'bech32')
assert_equal(received_addr, expected_addr)
+
+ key_origin = f'[{root_fingerprint}/0h/0h/{i}]'
bech32_addr_info = w1.getaddressinfo(received_addr)
- assert_equal(bech32_addr_info['desc'][:23], 'wpkh([80002067/0h/0h/{}]'.format(i))
+ assert_equal(bech32_addr_info['desc'].startswith(f'wpkh({key_origin}'), True)
shwpkh_addr = w1.getnewaddress('', 'p2sh-segwit')
shwpkh_addr_info = w1.getaddressinfo(shwpkh_addr)
- assert_equal(shwpkh_addr_info['desc'][:26], 'sh(wpkh([abcdef12/0h/0h/{}]'.format(i))
+ assert_equal(shwpkh_addr_info['desc'].startswith(f'sh(wpkh({key_origin}'), True)
pkh_addr = w1.getnewaddress('', 'legacy')
pkh_addr_info = w1.getaddressinfo(pkh_addr)
- assert_equal(pkh_addr_info['desc'][:22], 'pkh([12345678/0h/0h/{}]'.format(i))
+ assert_equal(pkh_addr_info['desc'].startswith(f'pkh({key_origin}'), True)
assert_equal(w1.getwalletinfo()['keypoolsize'], 4 * 3) # After retrieving a key, we don't refill the keypool again, so it's one less for each address type
w1.keypoolrefill()
@@ -682,7 +680,7 @@ def run_test(self):
},
success=True)
address = w1.getrawchangeaddress('legacy')
- assert_equal(address, "mpA2Wh9dvZT7yfELq1UnrUmAoc5qCkMetg")
+ assert_equal(address, key_to_p2pkh(xprv.derive_path("m/0").pubkey().pubkey.get_bytes()))
self.log.info('Check can deactivate active descriptor')
self.test_importdesc({'desc': descsum_create('pkh([12345678]' + xpub + '/*)'),
### test/functional/wallet_listdescriptors.py
@@ -23,14 +23,11 @@
class ListDescriptorsTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
+ self.wallet_names = []
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
- # do not create any wallet by default
- def init_wallet(self, *, node):
- return
-
def run_test(self):
node = self.nodes[0]
assert_raises_rpc_error(-18, 'No wallet is loaded.', node.listdescriptors)
### test/functional/wallet_taproot.py
@@ -56,6 +56,7 @@ class WalletTaprootTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
self.setup_clean_chain = True
+ self.wallet_names = []
self.extra_args = [['-keypool=100'], ['-keypool=100']]
def skip_test_if_missing_module(self):
@@ -64,9 +65,6 @@ def skip_test_if_missing_module(self):
def setup_network(self):
self.setup_nodes()
- def init_wallet(self, *, node):
- pass
-
@staticmethod
def make_desc(pattern, privmap, keys, pub_only = False):
pat = pattern.replace("$H", H_POINT)Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.