What changed, and why it matters
This commit updates a single unit test file for Bitcoin PSBT (Partially Signed Bitcoin Transaction) fee handling. It replaces a fake/mock input object with a real parsed PSBT input that includes a BIP32 derivation path, so the test exercises more of the actual production parsing code. There is no change to firmware behavior, no bug fix, and no security patch in the shipped code.
No action required; this is a test-quality improvement. Routine review/merge is sufficient.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff modifies ports/stm32/boards/Passport/modules/tests/unit/psbt_fee.py. It adds constants PSBT_IN_BIP32_DERIVATION and hash160, defines owned-key test data (MY_XFP, OWNED_PUBKEY, OWNED_SCRIPT), fixes psbt_field() to encode the key length prefix correctly, adds make_owned_input() to build a real psbtInputProxy, removes the FakeOwnedInput class, and updates the test to call validate() on the parsed input and assert num_our_keys/required_key. The production code under test (psbtObject.consider_inputs / SignPsbtCommonFlow) is unchanged.
Changed components
ports/stm32/boards/Passport/modules/tests/unit/psbt_fee.pyInspect captured patch +22 / −28
### ports/stm32/boards/Passport/modules/tests/unit/psbt_fee.py
@@ -10,17 +10,22 @@
from flows.sign_psbt_common_flow import SignPsbtCommonFlow
from psbt import psbtInputProxy, psbtObject
from public_constants import (
+ PSBT_IN_BIP32_DERIVATION,
PSBT_IN_NON_WITNESS_UTXO,
PSBT_IN_WITNESS_UTXO,
)
-from serializations import CTxOut, ser_compact_size
+from serializations import CTxOut, hash160, ser_compact_size
P2WPKH_SCRIPT = b'\x00\x14' + (b'\x11' * 20)
+MY_XFP = 0x12345678
+OWNED_PUBKEY = b'\x02' + (b'\x55' * 32)
+OWNED_SCRIPT = b'\x00\x14' + hash160(OWNED_PUBKEY)
-def psbt_field(key_type, value):
- return b'\x01' + bytes([key_type]) + ser_compact_size(len(value)) + value
+def psbt_field(key_type, value, key=b''):
+ full_key = bytes([key_type]) + key
+ return ser_compact_size(len(full_key)) + full_key + ser_compact_size(len(value)) + value
def previous_tx(txout):
@@ -36,6 +41,13 @@ def make_input(witness_txout, non_witness_txout=None):
return psbtInputProxy(BytesIO(data + b'\x00'), 0)
+def make_owned_input():
+ txout = CTxOut(2000, OWNED_SCRIPT)
+ data = psbt_field(PSBT_IN_WITNESS_UTXO, txout.serialize())
+ data += psbt_field(PSBT_IN_BIP32_DERIVATION, pack('<II', MY_XFP, 0), OWNED_PUBKEY)
+ return psbtInputProxy(BytesIO(data + b'\x00'), 0)
+
+
def assert_raises(exc_type, callback):
try:
callback()
@@ -58,28 +70,6 @@ def assert_raises(exc_type, callback):
assert_raises(AssertionError, lambda: script_mismatch.get_utxo(0))
-class FakeOwnedInput:
- def __init__(self):
- self.fully_signed = False
- self.witness_utxo = True
- self.utxo = None
- self.required_key = None
- self.num_our_keys = 1
- self.is_segwit = True
- self.subpaths = {}
- self.tap_subpaths = {}
-
- def has_utxo(self):
- return True
-
- def get_utxo(self, _idx):
- return CTxOut(2000, P2WPKH_SCRIPT)
-
- def determine_my_signing_key(self, _idx, utxo, _xfp, _psbt):
- self.amount = utxo.nValue
- self.required_key = b'key'
-
-
class FakePrevout:
n = 0
@@ -89,9 +79,9 @@ class FakeTxIn:
class FakeInputPSBT:
- def __init__(self, psbt_input):
+ def __init__(self, psbt_input, my_xfp=0):
self.inputs = [psbt_input]
- self.my_xfp = 0
+ self.my_xfp = my_xfp
self.total_value_in = None
self.fee_is_verified = True
self.presigned_inputs = set()
@@ -110,9 +100,13 @@ def input_iter(self):
psbtObject.consider_inputs(external_input_psbt)
assert not external_input_psbt.fee_is_verified
- owned_input_psbt = FakeInputPSBT(FakeOwnedInput())
+ owned_input = make_owned_input()
+ owned_input.validate(0, FakeTxIn(), MY_XFP)
+ owned_input_psbt = FakeInputPSBT(owned_input, MY_XFP)
psbtObject.consider_inputs(owned_input_psbt)
assert owned_input_psbt.fee_is_verified
+ assert owned_input.num_our_keys == 1
+ assert owned_input.required_key == OWNED_PUBKEY
finally:
history.verify_amount = original_verify_amount
Why this scored 12/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.