Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,8 @@ rustflags = [
# "-Lnative=/home/me/Android/Sdk/ndk/27.3.13750724/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android",
# "-lstatic=c++abi",
]

# Increase the default thread stack size to 40 MiB.
# Our callstack can get pretty big (especially in debug mode).
[env]
RUST_MIN_STACK = "41943040"
28 changes: 21 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,14 @@ jobs:
- target: x86_64-pc-windows-gnu
os: ubuntu-22.04

runs-on: ${{ matrix.host }}
runs-on: ${{ matrix.os }}
if: github.event_name == 'push' || !github.event.pull_request.draft
steps:
- uses: actions/checkout@v4
- name: Setup build environment (cli tools, dependencies)
uses: ./.github/actions/setup-build-environment
with:
host: ${{ matrix.host }}
host: ${{ matrix.os }}
target: ${{ matrix.target }}

- name: Build binary
Expand All @@ -117,21 +117,21 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-22.04, macos-15]
runs-on: ${{ matrix.host }}
runs-on: ${{ matrix.os }}
if: github.event_name == 'push' || !github.event.pull_request.draft
steps:
- uses: actions/checkout@v4
- name: Setup build environment (cli tools, dependencies)
uses: ./.github/actions/setup-build-environment
with:
host: ${{ matrix.host }}
host: ${{ matrix.os }}

- name: Run monero-harness tests
if: matrix.host == 'ubuntu-22.04'
if: matrix.os == 'ubuntu-22.04'
run: cargo test --package monero-harness --all-features

- name: Run library tests for swap
run: cargo test --package swap --lib
- name: Run library tests
run: cargo test --lib

docker_tests:
strategy:
Expand Down Expand Up @@ -182,6 +182,20 @@ jobs:
test_name: alice_broken_wallet_rpc_after_started_btc_early_refund
- package: swap
test_name: happy_path_alice_does_not_send_transfer_proof
- package: swap
test_name: partial_refund_bob_claims_amnesty
- package: swap
test_name: partial_refund_alice_burns
- package: swap
test_name: partial_refund_alice_grants_final_amnesty
- package: swap
test_name: swap_rejected_deposit_too_small
- package: swap
test_name: partial_refund_bob_restart_detects_withhold
- package: swap
test_name: alice_and_bob_refund_using_cancel_and_refund_command_partial_refund
- package: swap
test_name: alice_and_bob_refund_using_cancel_and_refund_command_partial_refund_withheld
- package: monero-tests
test_name: reserve_proof
- package: monero-tests
Expand Down
2 changes: 2 additions & 0 deletions .helix/ignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
src-tauri/gen/
monero-sys/monero/
monero-sys/monero-depends/

46 changes: 0 additions & 46 deletions AGENT.md

This file was deleted.

1 change: 1 addition & 0 deletions AGENT.md
50 changes: 50 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
- Read CONTRIBUTING.md and the code style guidelines!
- When asked about libp2p, check if a rust-libp2p folder exists which contains the cloned rust libp2p codebase. Read through to figure out what the best response it. If its a question about best practice when implementing protocols read @rust-libp2p/protocols/ specificially.
- Never do `cargo clean`. Building `monero-sys` takes ages, and cleaning the build cache will cause a full rebuilt (horrible).
`cargo clean` has never fixed a build problem.
- Before suggesting a change, always give at least a short (1 sentence) summary of which function you are editing and why.
- When being asked to add something, check whether there is a similar thing already implemented, the architecture of which you can follow.
For example, when asked to add a new Tauri command, check out how other tauri commands are implemented and what conventions they follow.
-

- Think about seperation of concerns. This has many facets. But the most ofen there are questions like:
"Which part of the code should decide how to handle this situation". In the context of an error, the solution is:
- Never use fallback values. They lead to
- swallowed errors
- breaking invariances
- breaking other implicit assumptions
- destroy any meaning the value might have had.
Instead, if an error/invlaid state is encountered, the error should be propagated.
This is most often correctly done by using anyhow's "Context" and the question mark operator`.context("Failed to <foo>")?`.
- Keep error handling simple: it is basically never wrong to just propagate the error using `?` and maybe add some basic context.

Other facetts of seperation of concern include:
- should this function need to have access to this <implementation detail>?
- should this function decide a parameter itself or just take an argument?

We follow the principle of LEAST SURPRISE. Take a step back, and come back with a fresh view. Then ask yourself: "would I expect this function to do <X>?".
If not, then don't do it.

- coding style tips:
- keep the code succint. Prefer `if let` and `let ... else` to `match` whenever possible.
- avoid nesting if possible.
- prefer early returns to nesting.

- Docker tests: We have an extended test suite that simulates a whole blockchain environment for the purpose of testing swaps end to end.
The docker tests are located in `swap/tests` and can be executed using `just docker_test <name>`. Get a list of all docker tests by `just list-docker-tests`.
- If you changed something could possibly affect the success of a swap, make sure to run the integration tests that could possibly be affected.
Be very liberal with assuming what might be affected.
- If not explicitly instructed yet, ask the user whether you should add {unit, integration} tests if you just added / changed some behaviour/code
- The docker tests are long (multiple minutes) and produce tens of thousands of log messages.
Don't try to read all of that output, it will fill you context up before finishing
the initialization.
Instead, spawn them as a background-task (each as it's own).
Then you can simply check in on the current status by checking it's output every minute or so.
If you are claude, use claude codes native background task system and read from the `/tmp/claude/tasks/foo/output.tmp` pipe file, or whatever the path is.
If you are not claude, then do the thing that best accomplishises this.

- Before claiming you finished, make sure everything compiles (`cargo c --all-features`).
Also all tests (`cargo c --tests`) and all targets (`cargo c --all-targets`) must compile.



32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- Protocol: Reduce cancel timelock to 24 blocks (4 hours).
Swaps can now be refunded after 4 hours, instead of the previous 12 hours.
This also means the refund window ends after `4 + 24 = 28` hours instead of the previous `12 + 24 = 36` hours.
The punish timelock, which determines the length of the refund window, remains at 72 blocks (24 hours).

- Protocol: Add possibility for maker to require an "anti-spam deposit".
The deposit is a part of the Bitcoin refund which the maker may withhold during a 30 minute timeframe.
The deposit can still be released after the fact, by granting mercy.
Both parties will refuse an anti-spam deposit that makes up more than 20% of the swap's Bitcoin.

- GUI: Add a reputation chip for each offer showing the number of successful, refunded and bad swaps.
Bad swaps are swaps during which the maker has behaved in a way that hurt the taker, like: punishing the taker or withholding the anti-spam deposit.
This can be remedied by cooperative redeem / granting mercy respectively.

- GUI: Add a chip for each offer showing the guaranteed refund percentage and the required anti-spam deposit percentage.
Colorcoded on a gradient with 100% refund being green and 90% being yellow.

- ASB + CONTROLLER: Add `set-withhold-deposit <swap-id> <true / false>` and `grant-mercy <swap-id>` commands.
`set-withhold-deposit` must be called before the maker reaches `XmrRefunded` to be effective.
`TxWithhold` will be published after the asb refunded the Monero.
`grant-mercy` can only be called once the maker has entered `BtcWithheld`.

- ASB: New config option `maker.refund_policy.anti_spam_deposit_ratio`.
It sets the ratio of the Bitcoin lock that will go into the deposit in case of a refund.
Set it to `0.02` for an anti-spam deposit of 2%.
Set it to `0.00` to offer full refunds (0% anti-spam deposit).
Defaults to `0.00`.
```toml
[maker.refund_policy]
anti_spam_deposit_ratio = 0.02
```

## [3.7.0] - 2026-03-05

- ASB + CONTROLLER: Add `withdraw-btc` and `refresh-bitcoin-wallet` JSON-RPC commands. `withdraw-btc` allows withdrawing BTC from the internal Bitcoin wallet to a specified address. The amount parameter on the wire protocol is in satoshis (`Option<u64>`, `null` to sweep the entire balance). The `asb-controller` accepts human-friendly amounts (e.g. `0.1 BTC`, `10000 sat`). `refresh-bitcoin-wallet` syncs the internal Bitcoin wallet with the blockchain.
Expand Down
1 change: 0 additions & 1 deletion CLAUDE.md

This file was deleted.

1 change: 1 addition & 0 deletions CLAUDE.md
33 changes: 25 additions & 8 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,38 @@ Thank you for wanting to contribute to this project!

There are a couple of things we are going to look out for in PRs and knowing them upfront is going to reduce the number of times we will be going back and forth, making things more efficient.

0. **Read and comply with our [AI Policy](AI_POLICY.md)**
1. We have CI checks in place that validate formatting and code style.
Make sure `dprint check` and `cargo clippy` both finish without any warnings or errors.
If you don't already have it installed, you can obtain in [various ways](https://dprint.dev/install/).
2. Run the test suite with [cargo-nextest](https://nexte.st/docs/running/).
Install it using `cargo install cargo-nextest` and execute `cargo nextest run`.
3. All text document (`CHANGELOG.md`, `README.md`, etc) should follow the [semantic linebreaks](https://sembr.org/) specification.
4. We strive for atomic commits with good commit messages.
Make sure the branch is building with `--all-features` and `--all-targets` without errors
and all tests are passed.
2. All text document (`CHANGELOG.md`, `README.md`, etc) should follow the [semantic linebreaks](https://sembr.org/) specification.
3. We strive for atomic commits with good commit messages.
As an inspiration, read [this](https://chris.beams.io/posts/git-commit/) blogpost.
An atomic commit is a cohesive diff with formatting checks, linter and build passing.
Ideally, all tests are passing as well but we acknowledge that this is not always possible depending on the change you are making.
5. If you are making any user visible changes, include a changelog entry.
4. If you are making any user visible changes, include a changelog entry.

## Contributing issues

When contributing a feature request, please focus on your _problem_ as much as possible.
It is okay to include ideas on how the feature should be implemented but they should be 2nd nature of your request.

For more loosely-defined problems and ideas, consider starting a [discussion](https://github.com/comit-network/xmr-btc-swap/discussions/new) instead of opening an issue.
## Code style

### General

- File structure
- The content of each file should be ordered in terms of importance / level of abstraction
- Public `struct`s, `enum`s and important constants should be at the top
- `impl` blocks should be below the type declarations
- Both the type declaration part and the implementation part of the file should be internally ordered by level of abstraction/ importance
- For example, `fn main` should always be at least at the top of the implementation
- Prefer early returns over nested `if`/`match` statements
- Don't use fallback values or silent failures

### Rust

- Use `cargo fmt` for formatting
- Make use of the powerful `if let` and `let ... else` pattern to enable early returns
- Make use of anyhows `.context` method and the `?` operator for concise error reporting

Loading
Loading