python client: use default value for nSequence if not given
What changed, and why it matters
This commit fixes a small bug in the Python helper library that builds unsigned Bitcoin transactions from PSBT data. Previously, if a PSBT did not explicitly include a per-input sequence number, the code would crash with an assertion error. The change follows the BIP-370 standard and HWI by treating a missing sequence number as the default final value (0xffffffff). This is a client-side convenience fix; it does not change how the Ledger device itself validates or signs transactions.
Treat as a minor bugfix / spec-compliance improvement. Review whether any downstream code relied on the assertion to reject malformed PSBTs, and verify that the default sequence value is only applied where BIP-370 permits it. No urgent security response is indicated by the diff alone.
Security signals we found
Behavioral change in transaction serialization helper
Removes an assertion that could cause crashes on valid PSBTs missing optional sequence fields
Aligns implementation with BIP-370 and HWI upstream behavior
No evidence of memory corruption, cryptographic, or device-level vulnerability in the diff
Evidence from the diff
In bitcoin_client/ledger_bitcoin/psbt.py, get_unsigned_tx() no longer asserts that psbt_in.sequence is non-None. Instead it applies the BIP-370 default: sequence = psbt_in.sequence if psbt_in.sequence is not None else 0xffffffff. This aligns the local PSBT parser with HWI and the BIP-370 PSBT specification, which states that an omitted PSBT_IN_SEQUENCE should be interpreted as the final sequence number. The Ledger firmware’s signing logic is unaffected; this only affects the Python client’s construction of the unsigned transaction used for display or serialization.
Changed components
bitcoin_client/ledger_bitcoin/psbt.pyget_unsigned_tx() methodInspect captured patch +3 / −2
### bitcoin_client/ledger_bitcoin/psbt.py
@@ -1126,9 +1126,10 @@ def get_unsigned_tx(self) -> CTransaction:
for psbt_in in self.inputs:
assert psbt_in.prev_txid is not None
assert psbt_in.prev_out is not None
- assert psbt_in.sequence is not None
- txin = CTxIn(COutPoint(uint256_from_str(psbt_in.prev_txid), psbt_in.prev_out), b"", psbt_in.sequence)
+ # If omitted, the sequence number is assumed to be the final sequence number
+ sequence = psbt_in.sequence if psbt_in.sequence is not None else 0xffffffff
+ txin = CTxIn(COutPoint(uint256_from_str(psbt_in.prev_txid), psbt_in.prev_out), b"", sequence)
tx.vin.append(txin)
for psbt_out in self.outputs:Why this scored 24/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.