test: make device signing cases more granular
What changed, and why it matters
This commit only changes test code. It makes the automated test suite more flexible by letting device simulators opt out of one specific test case involving unusual key derivation paths, while still running the rest of the tests. There is no change to the actual wallet software that users run, and no security fix or vulnerability is present in the diff.
No security action needed. Treat as routine test-maintenance change.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit refactors test/test_device.py and the per-device emulator classes in test/test_*.py. It adds a new boolean flag supports_arbitrary_keypool_paths (default True) and wraps the arbitrary-path getkeypool test in a conditional. It also adjusts TestSignTx input counting logic for segwit/sh_wit/wit/legacy combinations. No production code is modified.
Changed components
test/test_bitbox02.pytest/test_coldcard.pytest/test_device.pytest/test_digitalbitbox.pytest/test_jade.pytest/test_keepkey.pytest/test_trezor.pyInspect captured patch +19 / −9
diff --git a/test/test_bitbox02.py b/test/test_bitbox02.py
index a9d64b9..400da4a 100644
--- a/test/test_bitbox02.py
+++ b/test/test_bitbox02.py
@@ -43,6 +43,7 @@ class BitBox02Emulator(DeviceEmulator):
self.include_xpubs = True
self.supports_device_multiple_multisig = True
self.supports_legacy = False
+ self.supports_arbitrary_keypool_paths = True
def start(self):
super().start()
diff --git a/test/test_coldcard.py b/test/test_coldcard.py
index c30742b..4259d1e 100755
--- a/test/test_coldcard.py
+++ b/test/test_coldcard.py
@@ -45,6 +45,7 @@ class ColdcardSimulator(DeviceEmulator):
self.include_xpubs = False
self.supports_device_multiple_multisig = True
self.supports_legacy = True
+ self.supports_arbitrary_keypool_paths = True
def start(self):
super().start()
diff --git a/test/test_device.py b/test/test_device.py
index abc6ef1..fb88ee7 100644
--- a/test/test_device.py
+++ b/test/test_device.py
@@ -36,6 +36,7 @@ class DeviceEmulator():
self.include_xpubs = None
self.supports_device_multiple_multisig = None
self.supports_legacy = None
+ self.supports_arbitrary_keypool_paths = True
def start(self):
assert self.type is not None
@@ -313,13 +314,14 @@ class TestGetKeypool(DeviceTestCase):
addr_info = self.wrpc.getaddressinfo(self.wrpc.getrawchangeaddress('bech32'))
self.assertTrue(addr_info['hdkeypath'].startswith("m/84h/1h/3h/1/"))
- keypool_desc = self.do_command(self.dev_args + ['getkeypool', '--path', 'm/0h/0h/4h/*', '0', '20'])
- self.assertIsInstance(keypool_desc, list, f"getkeypool returned error: {keypool_desc}")
- import_result = self.wrpc.importdescriptors(keypool_desc)
- self.assertTrue(import_result[0]['success'])
- for _ in range(0, 21):
- addr_info = self.wrpc.getaddressinfo(self.wrpc.getnewaddress('', 'bech32'))
- self.assertTrue(addr_info['hdkeypath'].startswith("m/0h/0h/4h/"))
+ if self.emulator.supports_arbitrary_keypool_paths:
+ keypool_desc = self.do_command(self.dev_args + ['getkeypool', '--path', 'm/0h/0h/4h/*', '0', '20'])
+ self.assertIsInstance(keypool_desc, list, f"getkeypool returned error: {keypool_desc}")
+ import_result = self.wrpc.importdescriptors(keypool_desc)
+ self.assertTrue(import_result[0]['success'])
+ for _ in range(0, 21):
+ addr_info = self.wrpc.getaddressinfo(self.wrpc.getnewaddress('', 'bech32'))
+ self.assertTrue(addr_info['hdkeypath'].startswith("m/0h/0h/4h/"))
keypool_desc = self.do_command(self.dev_args + ['getkeypool', '--path', '/0h/0h/4h/*', '0', '20'])
self.assertEqual(keypool_desc['error'], 'Path must start with m/')
@@ -498,10 +500,12 @@ class TestSignTx(DeviceTestCase):
in_amt = 1
number_inputs = 0
# Single-sig
- if "segwit" in input_types:
+ if "segwit" in input_types or "sh_wit" in input_types:
self.wpk_rpc.sendtoaddress(sh_wpkh_addr, in_amt)
+ number_inputs += 1
+ if "segwit" in input_types or "wit" in input_types:
self.wpk_rpc.sendtoaddress(wpkh_addr, in_amt)
- number_inputs += 2
+ number_inputs += 1
if "legacy" in input_types:
self.wpk_rpc.sendtoaddress(pkh_addr, in_amt)
number_inputs += 1
diff --git a/test/test_digitalbitbox.py b/test/test_digitalbitbox.py
index 1a98c95..9fc41ed 100755
--- a/test/test_digitalbitbox.py
+++ b/test/test_digitalbitbox.py
@@ -43,6 +43,7 @@ class BitBox01Emulator(DeviceEmulator):
self.include_xpubs = False
self.supports_device_multiple_multisig = True
self.supports_legacy = True
+ self.supports_arbitrary_keypool_paths = True
def start(self):
super().start()
diff --git a/test/test_jade.py b/test/test_jade.py
index 238c88f..f5fef76 100755
--- a/test/test_jade.py
+++ b/test/test_jade.py
@@ -53,6 +53,7 @@ class JadeEmulator(DeviceEmulator):
self.include_xpubs = False
self.supports_device_multiple_multisig = True
self.supports_legacy = True
+ self.supports_arbitrary_keypool_paths = True
def start(self):
super().start()
diff --git a/test/test_keepkey.py b/test/test_keepkey.py
index 845a097..ff9cf84 100755
--- a/test/test_keepkey.py
+++ b/test/test_keepkey.py
@@ -65,6 +65,7 @@ class KeepkeyEmulator(DeviceEmulator):
self.include_xpubs = False
self.supports_device_multiple_multisig = True
self.supports_legacy = True
+ self.supports_arbitrary_keypool_paths = True
def start(self):
super().start()
diff --git a/test/test_trezor.py b/test/test_trezor.py
index 335fa57..b61c1f0 100755
--- a/test/test_trezor.py
+++ b/test/test_trezor.py
@@ -64,6 +64,7 @@ class TrezorEmulator(DeviceEmulator):
self.include_xpubs = False
self.supports_device_multiple_multisig = True
self.supports_legacy = True
+ self.supports_arbitrary_keypool_paths = True
def start(self):
super().start()
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.