Skip to content

hardfork(v4): Spam deterrence + cancel timelock reduction (#675)#899

Merged
Einliterflasche merged 1 commit intomasterfrom
hardfork/v4
Mar 16, 2026
Merged

hardfork(v4): Spam deterrence + cancel timelock reduction (#675)#899
Einliterflasche merged 1 commit intomasterfrom
hardfork/v4

Conversation

@Einliterflasche
Copy link
Copy Markdown

This is the result of #675. Read that for more details.

* fix react bug nullish check

* add tx_refund_amnesty

* move TxPartialRefund to partial_refund.rs and TxFullRefund to full_refund.rs and add backwards compatible BobRefundType for abstracting over refund signatures

* remove unnecessary functions on BobRefundType

* move run_swap_setup of alice into seperate function

* change tx_refund_encsig to tx_partial_refund_encsig in Message3

* add amnesty_amount and tx_partial_refund_fee to swap_setup

* add tx_partial_refund_fee to NewSwap

* fix compilation errors in bitcoin wallet tests

* bob: estimate partial refund fee

* allow Alice to send full refund encisg and amnesty sig during swap setup (optional)

* add tx_partial_refund_fee and btc_amnesty_amoutn to all Alice states

* rename tx_refund_encsig to tx_full_refund_encsig while keeping db backwards compatible

* add tx_refund_amnesty_fee to swap setup messages and alice/bob states

* add tx_refund_amnesty_fee to Bob State1, verify partial_refund and refund_amnesty signatures before accepting

* remove unnecessary serde(with = bitcoin::amount::serde::as_sats) as it is the default

* add tx_partial_refund_fee and tx_refund_amnesty_fee to all bob and alice states + make them optional for db compatibility

* fix merge conflict

* add PartiallyRefunded, AmnestyPublished, AmnestyConfirmed states for Bob

* add Bob::BtcPartialRefundPublished state

* add new states to match arms

* fix compilation errors in tests

* add btc_amnesty_amount (optional) to all Bob states

* add construct_tx_partial_refund and signed_partial_refund_transaction to Bob's State6

* alice: actually send TxPartialRefund encsig

* add ensure_broadcasted function to BitcoinWallet trait

* bob state machine: publish best bitcoin refund transaction depending on which signatures we have

* inline publish_best_btc_refund_tx

* rename BobRefundType to RefundSignatures

* fix btc_amnesty_amount type

* bob: refactor btc refund publish logic

* add PartialRefund and Amnesty events to SwapProgressEvent

* bob: handle BtcPartialRefundPublished

* bob: publish TxRefundAmnesty if we have the key or wait for Alice to do it

* bob: handle BtcAmnestyPublished and BtcAmestyConfirmed

* asb: add refund_policy to Config, apply it in event loop

* update tests to have refund policy

* alice: actually use btc_amnesty_amount in run_swap_setup

* tracing: force ansi output for terminal layer. if anything breaks with docker or something this is the fault

* remove yarn@4 from package.json as package manager

* remove unnecessary env var from just asb-testnet command

* state-machine(alice): make btc_amnesty_amount optional

* gui: show bitcoin amnesty in SwapSetupInflight page

* state-machine(alice): wait for either TxFullRefund or TxPartialRefund

* implement BitcoinWallet::ensure_broadcasted

* state-machine(alice): add BtcPartiallyRefunded and XmrRefundable states

* add justfile aliases for gui linting

* state-machine(alice): add XmrRefundable state

* tiny gui fixes

* gui: update types to reflect new states

* bob: send sig for TxRefundAmnesty, alice: publish it

* alice: extract monero private key from partial_refund also

* switch all uses of BitcoinWallet::broadcast to BitcoinWallet::ensure_broadcasted

* add remaining_refund_timelock

* add RemainingRefundTimelock to ExpiredTimelocks

* fix warnings

* add TxRefundBurn (see comment on #675 for explanation)

* add TxFinalAmnesty

* state-machine(bob): add new states (WaitingForRemainingRefundTimelockExpiration, RemainingRefundTimelockExpired, BtcRefundBurnPublished, BtcRefundBurnt, BtcFinalAmnestyPublished, BtcFinalAmnstyReceived)

* swap-setup: exchange signatures and fees for TxRefundBurn and TxFinalAmnesty

* state-machine(bob): add tx_final_amnesty_fee and tx_refund_burn_fee to all bob states and implement new state transitions

* swap-setup/state-machine(bob): make alice's sig on TxRefundAmnesty non-optional

* fix tests: pass remaining_refund_timelock

* alice: sent encsig for TxFullRefund during swap setup when btc_amnesty_amount == 0

* bob: make fee fiels in state puiblic

* tests: add integration test for partial refund + amnesty
:

* alice: don't try to publish TxRefundAmnesty

* add new integration test to ci

* fmt

* controller: output table when running get-swaps

* controller: display more information about swaps

* swap-setup(alice+bob): only construct TxRefundAmnesty/TxRefundBurn/TxFinalAmnesty when the amnsty output is greater than zero

* just command for listing docker tests

* store should_publish_tx_refund_burn in alice states

* alice: add states BtcRefundBurn{Published, Confirmed} and BtcFinalAmnesty{Granted, Published, Confirmed}

* add new tests to ci.yml

* add new integration tests for burn scenarios, add BurnRefund command to asb RpcServer

* unify ai agent instructions

* swap-controller: add set-burn-on-refund <swap-id> <true/false>

* add docker test instructions to AGENTS.md

* asb: add final amnesty command to asb cli and controller + integration test

* add basic gui components for new states

* add placeholder components for partial refund path

* add mock swap states with stepping controls in dev mode

* improve components for the partial refund path

* add RefundPolicyWire (same as RefundPolicy for now) to quote, bump protocol version

* gui: extend mocking system, make it possible to view SwapSetupInflight component for mock swap

* wait for tx refund confirmation in refund command

* gui: small react refactors

* undo debugging code

* extract earnest deposit chip into component

* gui: update lanugage in partial refund components

* gui: simplify language in PartialRefund TxClaim page

* bob: emit new tauri event when waiting for timelock on the remaining bitcoin refund to expire

* fix compilation errors

* gui: add new page when waiting for timelock on remaining refund to expire

* gui: add WaitingForEarnestDeposit page to mock paths

* fix compilation warnings

* move to yarn@4 again

* state-machine(alice+bob): rename states to match new transaction names

Rename the states as follows:
 - RemainingRefundTimelock -> ReclaimTimelock
 - RefundBurn -> Withhold
 - RefundAmnesty -> Reclaim
 - FinalAmnesty -> Mercy

* bitcoin(transaction): rename partial refund TXs

* asb(config)+protocol(quote): anti_spam_deposit_ratio instead of taker_guaranteed_refund

* update terminology accross state machines, commands, etc

* try to fix stackoverflow when selecting offer

* fix: electrum pool bug preventing btc tx publishing

In get_script_history we treated _any_ error returned
by any of the nodes as a total error if the script
history returned by the other nodes is empty. This
specifically causes the publishing of tx lock to
fail/be falsely recognized as failed when at least
one of the nodes is unreachable or errors for some
other reason.

We now accept the result if at least one of the node
returns a script history.

* update transaction weights, field names in mockSwapEvents

* alice: sanity check for anti spam deposit ratio
alice+bob: sanity check anti spam deposit (greater than fees)

* alice+bob: add sanity checks for amnesty amount

Alice and Bob now check at swap setup that the amnesty
amount is either zero or at least greather than the sum of the fees
of TxPartialRefund, TxReclaim, TxWithhold and TxMercy.

An upper bound (currently 20% of the lock amount)
is also introduced.

* swap: delete unit tests regarding buy-xmr (which was removed)

* add some code style guidelines to CONTRIBUTING.md

* fix typo - actually enable deny(unconditioned_recursion)

* update unit tests

* ci: fix typo -> build and unit tests run again

* bump version to 4.0.0

* update field names to match new tx names

* silence wallet2 unused-parameter warnings

* fix tauri dependency version mismatch

* refactor: distinguish between txcancelled and txcancelpublished

* fix gui chip for anti spam deposit

* make sanity check for deposit amount for precise, send errors to peer instead of just disconnecting

* swap_setup(bob+alice): share sanity check error with peer before ending stream

* fix gui states, timelock display

* bob: propagate permantent swap_setup_error and don't retry them

e.g. swap was rejected due to the anti spam deposit not covering
tx fees, etc.

* test: add integration tests

 - too small anti spam deposit -> swap rejected
   -> error gets propagated and bob doesn't retry

 - bob goes offline during WaitingForReclaimTimelock
   -> alice publishes TxWithhold -> bob comes back
   online and goes to BtcWithheld

* build: enforce higher stack size

* state-machine(bob): simplify BtcCancelled logic

it's not actually simple, but a bit better

* gui: bump minimum compatible version to 4.0.0

* gui: add local reputation chip to maker offers

also rephrase anti-spam deposit chip

* fix typo: successfull -> successful

* docs: update logo

* docs: use yarn v4 via corepack

* docs: update primary color to match new website

* docs: remove sidebar pointing to nextra repo

* docs: rephrase feedback section to explicitly mention support

* docs: update install instructions, make release independant

* docs: migrate to nextra v4

* docs: fix primary color issue after migration to nextra v4

* docs: make installation instructions step based

* bob: extend manual refund to complete partial refund path

* test(bob): add integration tests for bob manual refund on partial refund

* asb: extend manual refund command to publish TxWithhold if appropriate

* tests: use manual refund for alice as well in integration tests, add to ci

* fix: properly center circular progress subtitle

* fix: expand explanation for anti spam deposit on offer acceptance page

* prune: remove redundant main message of BitcoinPartialRefundPage

* clean-up: we don't need RUST_MIN_STCK in commands anymore because we have it in .carg/config.toml

* gui: add hard version limit

Distinguishes between merely outdated makers and
makers whose version it known to be incompatible.

* docs: rephrase some things

* docs: rephrase, reorganize some things

* fix(cli/watcher): skip refund when refund is already complete

* docs: add anti-spam deposit FAQ, start rewrite of first swap guide

Still missing later parts and new screenshots for the guide.

* gui: add warning to never share private keys

* fix(asb): properly check swap isn't running before mercy

We assume that the swap is running if either of the channels
between `EventLoop` and `EventLoopHandle` are still open.

If they are closed it means the `EventLoopHandle` was dropped.
Since the `EventLoopHandle` is stored in `Swap`, the channels
are dropped -> closed when the `Swap` stops running.

* build: bump `swap` edition to 2024

* asb: extract cooperative handling to function

* state-machine(bob): clean up BtcCancelled handling

 - handle both FullRefund and PartialRefund scenario
   with the same logic like in cancel_and_refund.rs
 - try to refund before assuming we've been punished
   instead of going to BtcPunished when the punish
   timelock expires
 - make parse_rpc_error more resilient by walking the
   whole anyhow error chain

* fix compilation errors

* gui: rephrase introductory slides

* mock: add more mock offers to gui

* gui: make amnesty deposit chip color based on percentage

* gui: update time estimate for "cancelling swap"

To 10min

* gui: individual tooltips for each category of reputation chip

* gui: rephrase state names, SwapStatusAlert

* gui: replace all mentions of "earnest deposit" with "anti-spam deposit"

* docs: update refund / punish guide, add anti spam deposit page

* remove outdated comments

* gui: remove alerts for partial refund pages, rephrase a little, add links to docs + servers

* fix test

* state-machine(bob): treat all verification errors for BtcRefund as indication we've been punished

* bob(state-machine): add retry block for ReclaimTimelockExpired

* build: cache monero-depends in target/ always (not target-check/)

* bob(state-machine): retry BitcoinWithholdPublished

* state-machine(alice, bob): add retries in various places

* gui: make AntiSpamDepositChip clickable (link to docs)

* gui: add anti spam deposit info slides

* docs: use accordion style for FAQ, add server links + scammer alert

* docs: fix typo

* protocol: reduce cancel timelock to 24 blocks (4h)

* changelog: Update changelog

* gui(mock): show mock SwapStatusAlerts in History tab in mock mode

* config: update config

---------

Co-authored-by: einliterflasche <einliterflasche@pm.me>
@Einliterflasche Einliterflasche merged commit 48bf043 into master Mar 16, 2026
2 of 69 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants