Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions allways/validator/forward.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,10 @@ def extend_fulfilled_near_timeout(self: Validator) -> None:
if tx_info is None:
continue # dest tx invisible or below canonical payout — neither tier qualifies

if not self.swap_verifier.is_dest_tx_fresh(swap, tx_info):
bt.logging.debug(f'{ctx}: dest tx failed replay check for extension')
continue

# A finalize this step may have just pushed the deadline out. Mirror
# the reservation-side gate in try_extend_reservation: once the swap
# is no longer near timeout, skip challenge/propose so the next
Expand Down
15 changes: 14 additions & 1 deletion tests/test_forward.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@ def make_validator(swap: Swap, block: int, finalized_target, tx_info=_UNSET):
optimistic_extensions=ext,
chain_providers={'btc': provider},
contract_client=contract_client,
swap_verifier=SimpleNamespace(fee_divisor=100),
swap_verifier=SimpleNamespace(
fee_divisor=100,
is_dest_tx_fresh=lambda _swap, _tx: True,
),
)


Expand Down Expand Up @@ -124,6 +127,16 @@ def test_verifies_canonical_payout_and_miner_sender(self):
assert call.kwargs['expected_amount'] != 1
assert call.kwargs['expected_amount'] > 0

def test_skips_extension_when_dest_tx_fails_replay_check(self):
swap = make_fulfilled_swap()
v = make_validator(swap, block=PROPOSE_BLOCK, finalized_target=None)
v.swap_verifier.is_dest_tx_fresh = MagicMock(return_value=False)

extend_fulfilled_near_timeout(v)

v.optimistic_extensions.maybe_propose_timeout.assert_not_called()
v.optimistic_extensions.maybe_challenge_timeout.assert_not_called()

def test_skips_extension_when_dest_tx_fails_canonical_check(self):
# Provider returns None when the dest tx doesn't match the canonical
# amount or expected sender. The extension path must then skip propose
Expand Down