diff --git a/core/src/apps/bitcoin/sign_tx/approvers.py b/core/src/apps/bitcoin/sign_tx/approvers.py index bd7771bc50..d16d85fd49 100644 --- a/core/src/apps/bitcoin/sign_tx/approvers.py +++ b/core/src/apps/bitcoin/sign_tx/approvers.py @@ -170,6 +170,10 @@ class BasicApprover(Approver): if self.external_in > self.orig_external_in: description = "PayJoin" + elif tx_info.rbf_disabled() and any( + not orig.rbf_disabled() for orig in orig_txs + ): + description = "Finalize transaction" elif len(orig_txs) > 1: description = "Transaction meld" else: diff --git a/core/src/apps/bitcoin/sign_tx/tx_info.py b/core/src/apps/bitcoin/sign_tx/tx_info.py index bf483a6c9f..4975d8aa53 100644 --- a/core/src/apps/bitcoin/sign_tx/tx_info.py +++ b/core/src/apps/bitcoin/sign_tx/tx_info.py @@ -69,6 +69,10 @@ _BIP32_MAX_LAST_ELEMENT = const(1000000) # Setting nSequence to this value for every input in a transaction disables nLockTime. _SEQUENCE_FINAL = const(0xFFFFFFFF) +# Setting nSequence to a value greater than this for every input in a transaction +# disables replace-by-fee opt-in. +_MAX_BIP125_RBF_SEQUENCE = const(0xFFFFFFFD) + class TxInfoBase: def __init__(self, signer: Signer) -> None: @@ -122,6 +126,9 @@ class TxInfoBase: def lock_time_disabled(self) -> bool: return self.min_sequence == _SEQUENCE_FINAL + def rbf_disabled(self) -> bool: + return self.min_sequence > _MAX_BIP125_RBF_SEQUENCE + def get_tx_check_digest(self) -> bytes: return self.h_tx_check.get_digest()