Skip to content

Releases

v0.2.6 — the three M3 acceptance items

Choose a tag to compare

@mandrigin mandrigin released this 08 Oct 15:02
4b76e2f

Closes the three items Logos listed in logos-co/rfp#123 as blocking M3 acceptance.

Documentation and one example only. No crate behaviour, deployment, or protocol code changed from v0.2.5 (c99ff8ce). The three demo recordings stay attached to the v0.2.5 release; they are not duplicated here.

The LEZ/BTC SDK now has a name and a map

docs/sdk-lez-btc.md says the artefact is lez-btc-swap-sdk (crates/btc-swap-sdk) with lez-swap-sdk-core (crates/swap-sdk-core), and maps offer discovery, negotiation, escrow creation, claim, and refund to the public API and to the test that drives each one. It also states the boundaries: discovery and negotiation are ports with no shipped Delivery or Chat transport, and LEZ transactions are built in lez-bridge-adapter, not in the SDK.

crates/btc-swap-sdk/examples/full-lifecycle.rs is a runnable walk through all five stages:

cargo run -p lez-btc-swap-sdk --example full-lifecycle

It publishes an offer, discovers it, negotiates a countersigned agreement, activates, drives both locks and both claims to Completed, then replays the same agreement on a swap nobody claims and takes it through both ordered refunds. Fixed secrets, no I/O, and it compiles under --all-targets with pedantic Clippy denied.

The testnet guide documents the route we actually ran

docs/bitcoin-testnet4-setup.md previously described a self-hosted Testnet4 node and an operator-allowlisted HTTPS gateway. It did not describe the keyless public RPC provider on Testnet3 that docs/evidence/testnet3-provider-20260918/ records, and it never said which swap direction that route serves.

It now opens with a route table and covers three routes, each with wallet creation, funding, and the directions it serves:

Route Network Node wallet Directions
A — self-hosted Core 31.1 Testnet4 required both
B — exact allowlisted HTTPS gateway Testnet4 required both
C — keyless public RPC provider Testnet3 none TakerSellsForeign only

The walletless public-provider route serves TakerSellsForeign only. A provider exposes no wallet RPCs, and in TakerSellsLez the Maker funds the Bitcoin second lock from bitcoin.wallet on its own node. In TakerSellsForeign the Taker's first lock is signed externally and handed over as funding_transaction_hex, and the Maker's only Bitcoin action is the follow-up claim, which needs no wallet.

The guide's "no public RPC, peer, gateway, faucet, funds, or transaction was used for certification" line is now scoped to the M3 private-local certification it describes, since later public runs exist.

Traceability

Rows U1, U8, S8 and D1 updated with evidence links, marked BTC-done with XMR and ZEC still planned. F2 is deliberately untouched: it turns on Logos's acceptance, not on our documentation. docs/milestone-3-review.md names the SDK artefact and carries a note that no gate result, evidence hash, run identity, or claim boundary in that dated review was changed.

v0.2.5

Choose a tag to compare

@mandrigin mandrigin released this 28 Sep 19:40
c99ff8c

v0.2.5

Answers the Logos QA review of v0.2.4 (98f492ad) — the findings Danish named for this
release. Two product fixes, three new end-to-end scenarios that pin behaviour nothing
asserted before, and the operator packaging that makes chain-outage reporting work.

Product fixes

A claim now requires both legs funded, not a phase that once said so (CODE-4, #97)

SwapCoordinator kept no per-leg funding state: confirmation depth arrived as a transient
proof, was compared inline and discarded, so phase alone carried both legs. Both claim
gates therefore accepted a claim whenever the phase was BothLegsLocked. A presence check
would not have been enough — on the double-removal path the maker transaction id is
retained, so is_some() misses exactly the reported case.

Two per-leg flags now record "met its own confirmation policy and has not regressed
since", maintained in the four observers and required by both claim gates. Three new
lifecycle tests cover it, and all three fail without the fix.

Worth stating plainly: this was never reachable in a released Bitcoin swap. The BTC
path does not call the coordinator's removal entry points; remove-then-re-add exists only
on the Zcash path. It is a latent hole in shared shipped code.

One missing chain tool no longer stops the Maker, and outages get reported
(CODE-3 + PKG-1, #96)

The bug was an asymmetry. At runtime a missing or hash-changed route-health probe already
degraded just its own route to unavailable. Only at startup parse was it fatal, and it
happened six lines before the owner socket is bound — so with Type=notify there was no
socket, no ready file and no sd_notify, and systemd reported a start timeout rather than
a bad config. Startup is now as tolerant as runtime: the route is kept, reads unavailable,
and recovers by itself once the operator installs the executable the digest names. Two
further fatal exits — the initial reconciliation and the periodic tick, which killed the
daemon on any error including a transient one — are now logged and retried.

Packaging ships what was missing: a route-health example config, an operator guide, and
both installed by install-maker-node-service.sh. The guide leads with the sharp edge —
a route left out of the file reads unavailable, not unprobed, so the Maker will
refuse to quote or publish on it and will withdraw its live offers there. That is
deliberate fail-closed behaviour, but it has to be documented to be safe.

Test coverage the review asked for

  • The cooperative claim is a plain Taproot key-path spend (COV-1, #98) — asserted on a
    real chain transaction now, not only in prose: one input, one 64-byte Schnorr signature,
    no script. Production has always refused anything else; nothing checked it end to end.
  • The Maker will not lock before the Taker's lock confirms (COV-4, #98) — the miner is
    held so the Taker's lock sits unconfirmed, and the Maker must sit with it for 90 s
    before the block arrives.
  • A swap in flight needs nothing off chain (COV-3, #99) — Logos Chat and Delivery are
    both cut after the first lock and stay down until the swap completes. The Maker reports
    both unavailable and degraded, the swap finishes on chain state alone, and degraded
    clears by itself when they return. The outage tests we had all acted before a swap
    started.

Fixed reported issues

  • #91 — the desks show the real connection state (a local RPC client was answering an
    undeliverable call with its own ok:false envelope as a successful call, so the desks
    read as connected with both Nodes stopped)
  • #92 — native bridge command

Not in this release, by the milestone split

CODE-1 and CODE-2 (Zcash refund-deadline ordering) belong to the Zcash milestone, DOC-1
(Monero setup docs) to the Monero milestone, and DOC-3 (doc packets, third-party review
reports) to the audit milestone.

COV-6 says all v0.2.4 evidence is regtest/devnet. That is not right — three
public-network evidence folders ship in the v0.2.4 tag, covering both directions plus a
refund run with corrected timings on LEZ testnet and Bitcoin testnet4.

Images

Published to ghcr.io/gateway-fm/lez-atomic-swaps/ at tag v0.2.5, from release-images
run 36473887545 —
green including the job that pulls the published images and runs the bundle's start.sh on a
fresh runner, which is the check that matters for anyone installing this.

Every digest below was read back anonymously, so each line also proves the package is public:

Image Digest at v0.2.5
lez-maker-node sha256:8aa3fcfd9c501697fa6772d5d4fb95b2956298ea1c6653a3e189f5a547c94db4
lez-taker-node sha256:7f01f407e1e4cc3f59ecf1ccf32f3288043341f200fe1a42a67a39f2b8bc747d
lez-services sha256:2449e3ef47dc49a762768540592dbe110afb287969787e2a96ff4661de797d6c
lez-basecamp-ui sha256:225bcdc6f31e04f02fc3b30ffd495eaa794ee35feff512bd8aede2cfb8e15a2c
lez-bitcoin-core sha256:1d0d9f7b5b86dd4625f13075ee9ca4af394f4581342983d5b61ffbd1d708a54b
lez-btc-explorer sha256:189404fb79ef5dc2fce3cd398b64936631c02dc59974584169d1e4cb497088db
lez-btc-miner sha256:1051c6ba6e11ce6f68a88df6597b388dfaad476deee2a9cd01bf254cc398475d
lez-explorer sha256:7ce87ca7e3120d0ecc974c8d947f2ac394a29de479336e8cc3b4f71ce0aa3158
lez-tools sha256:70967d5f828250fa3fe27fde17b68d7eb3469693c5d522427cbe907f224c074c

To verify one without docker:

img=lez-maker-node
tok=$(curl -sf "https://ghcr.io/token?scope=repository:gateway-fm/lez-atomic-swaps/$img:pull" | jq -r .token)
curl -sfI -H "Authorization: Bearer $tok" \
  -H 'Accept: application/vnd.oci.image.index.v1+json' \
  "https://ghcr.io/v2/gateway-fm/lez-atomic-swaps/$img/manifests/v0.2.5" | grep -i docker-content-digest

Basecamp apps for this release are lez_atomic_swap_maker and lez_atomic_swap_taker at
0.2.5 in the module catalog, built from this tag.

Evidence

Full local regression: 43 of 43 passed, none failed. 26 node-e2e.py scenarios (13 in
each direction), both Basecamp desk suites, and 15 desk scenarios (8 forward, 7 reversed).
Both phases closed rc=0. Ran 14:00 UTC 2026-09-26 → 02:21 UTC 2026-09-27 and is attached
as regression-v0.2.5.tar.gz, which carries both logs, a RESULTS.txt of every result line,
and a PROVENANCE.md recording exactly what ran against what.

Two scenarios in this release are new: early-lock (the Maker must not lock before the
Taker's lock confirms) and offline-after-lock (Logos Chat and Delivery cut after the first
lock). Both passed in every direction they support.

The run absorbed eight stalls of the upstream Bedrock defect — the sequencer keeps
producing blocks while nothing finalizes — each one detected and recovered by recreating the
LEZ chain. The last two desk scenarios ran in a second runner invocation after one of those
recreations produced a chain that never finalized at all; the log marks the boundary and
PROVENANCE.md explains it rather than leaving it to be inferred from timestamps.

Demo recordings (DOC-2), attached to this release. Each is a by-product of a scenario
that passed while being recorded, with the desk's own narration burned in as subtitles, every
step driven through the QML inspector:

Recording Shows
TakerSellsForeign-happy.mp4 take → lock → Maker locks → claim → Maker claims → completed
TakerSellsForeign-maker-refund.mp4 the Taker never claims; both legs refund, in timelock order
TakerSellsForeign-concurrent.mp4 two swaps taken, locked and claimed interleaved

media/README.md said refund and overlapping-swap cases were "not visually demonstrated";
that sentence was the DOC-2 gap and is now corrected rather than left to understate what
ships.

Verification

Both product fixes have a test that was checked to fail without the fix, not merely to
pass with it:

  • CODE-4 — crates/swap-core/tests/transition_properties.rs. The generated model had no
    RemoveMakerLock action at all, so across 512 cases per run it never removed two locks,
    which is why the defect survived a property suite. With that action added and the
    invariant "an accepted claim means both legs are funded now", proptest shrinks to exactly
    the reported shape — TakerLock(2), MakerLock, MakerClaim, TakerClaim, RemoveMakerLock, TakerClaim, the last claim accepted after the maker leg left the chain. Removing the two
    both_legs_funded() calls fails it in 26 cases. The seed is checked in.
  • CODE-3 — a_missing_probe_executable_degrades_its_route_and_the_daemon_still_starts
    in crates/maker-node/tests/route_health.rs, which runs the real daemon binary. Reverting
    the startup tolerance makes it fail with "Maker daemon exited early", which is the
    reported symptom itself.

Five defects were found in this work while reviewing it, and CI caught none of them: an
early-lock assertion that filtered Bitcoin effects for a lock the Maker makes on LEZ; a
refund assertion that treated "no refund recorded" as "refund had the right shape"; an
unthrottled failure log in a one-second tick; and two probe requirements missing from the
operator guide (a symlinked probe is refused, and the probe's directory is validated too).
Four of the five were assertions or documentation that could not fail — the specific hazard
of closing coverage findings, since such work looks like progress either way.

The whole stack was then regressed again after merging, as one commit rather than as the
pre-merge branch head, so the evidence is for what this tag actually contains: 45 of 45,
zero failures, both phases rc=0. Committed under
docs/evidence/regression-v0.2.5-20260928/ and attached as regression-v0.2.5.tar.gz.

Phase Result
node-e2e.py, TakerSellsForeign 14 / 14
node-e2e.py, TakerSellsLez 14 / 14
...
Read more

v0.2.4

Choose a tag to compare

@mandrigin mandrigin released this 21 Sep 12:33
98f492a

v0.2.4 answers the Logos review of v0.2.3 (logos-co/ecosystem#182) and what the
public-network runs that followed it turned up. Swaps now settle unattended on the
official LEZ testnet against a Bitcoin test network, in both directions, with both
refund paths recorded; a Taker no longer needs a Bitcoin node or a Bitcoin wallet
of its own; and four recovery and safety defects that only a public network shows
are fixed.

Evidence on public networks

Every folder says what created each transaction, lists every intervention, and
looks each transaction up on its chain.

Run Bitcoin served by What it shows
testnet4-20260919 our own Bitcoin Core (internal node), testnet4 five swaps on the official LEZ testnet: both directions completed, both directions refunded on both legs, and a swap whose Maker never locked, refunded — no Maker action in any of them
testnet3-provider-20260918 a keyless public RPC provider (external node, PublicNode), testnet3 one swap between two Nodes with no Bitcoin node and no Bitcoin wallet: the Taker's lock signed in an offline owner wallet, every read and broadcast through the provider, the Maker's claim unattended
testnet-20260918 our own Bitcoin Core, testnet4 the first public runs and the traced swap behind #68: the Maker's follow-up claim, unattended

| corrected timing profile | our own Bitcoin Core, testnet4 | one TakerSellsLez swap, both sides locked and no claim, both legs refunded on the profile this release ships — the Bitcoin came back 7 h 16 min before the later LEZ refund window. Attached to this release as evidence-corrected-timings-refund-v0.2.4.tar.gz (run on 22–23 September, after the tag; it changes no code) |

How to run it yourself: docs/testnet-run.md.

What changed

Found on the public networks

  • The Maker finishes a swap on its own (#68, fixes #67): once its lock was
    projected after the cutoff, the Maker never sent its follow-up claim until an
    operator queued one. The review flagged this as gating M3.
  • A first-lock refund no longer strands the Taker (#64): a Maker lock that
    arrived late, an observer that froze after a refund was admitted, and a
    finalized LEZ refund rejected because its window end lagged the clock.
  • The order of the two refunds is checked (#88): a Bitcoin claim has no
    deadline on chain, so only the order of the refunds protects either side, and
    nothing checked it. With the first public profile a Taker selling LEZ could have
    refunded its LEZ and still claimed the Maker's Bitcoin. The Bitcoin refund delay
    now differs by direction, a profile states the pace the chain may keep, and a
    Node refuses to load a profile that breaks the order.
  • A reorganisation no longer makes a lock unrefundable (#88): a lock mined
    below its planned height was judged impossible, for good. Seen after a
    nine-block testnet4 reorg; the refund now waits for the height both roles signed.
  • A Maker refuses a swap it cannot serve in time (#88): it prepares its LEZ
    escrows one at a time and had accepted a second Taker-sells-BTC swap it could
    not reach before the cutoff.
  • The Node prices its own Bitcoin lock, under a cap, or refuses it (#75, part
    of #70): two 10,000 sat locks had each paid 56,064 sat. The same lock paid
    3,100 sat in this release's runs. The Taker sees the fee before sending
    (#79, fixes #70).
  • The desks say what is happening (#76, fixes #69 and #71): a sent,
    unconfirmed claim is shown as sent; a failed Maker is reported first, with its
    reason; the refund height is named.
  • The owner can move an open swap to an upgraded actor (#86, fixes #73):
    maker_actor_repin_v1, for the swap a Node upgrade stops as
    actor_deployment_invalid.
  • A node's warnings block readiness on mainnet only (#88); the testnet profile's
    LEZ discovery window fits one-minute blocks (#88).

Networks and wallets

  • The stack runs on the official LEZ testnet and Bitcoin testnet4 (#58), on
    LEZ v0.2.4 and spel 7f13e71 with the escrow guest rebuilt for them (#59);
    the local devnet runs LEZ v0.2.4 too (#83, fixes #82).
  • testnet3, and mainnet settles only against mainnet (#78): the network is
    configuration only, and a Node refuses to pair mainnet with a test chain.
  • Observe through a node that is not yours (#80): any Bitcoin Core from 24,
    no spender index, JSON-RPC 1.x replies accepted. A Taker without a Bitcoin
    wallet locks from the owner's own wallet
    (#81, both for #49): the Node answers
    -32018 bitcoin_funding_required with the address and amount, and the take is
    replayed with a transaction signed elsewhere.
  • A role can pay its Bitcoin claims into its own wallet (#61).

Desks, devnet and records

  • Catalog packages ship the shared QML kit, and a native macOS desk route (#56,
    fixes #50). The Taker desk can act on a swap again (#88; a regression from #64,
    never released).
  • maker_offer_list filters by state and the desk asks only for what it renders
    (#77, part of #52).
  • The devnet's LEZ services stop on the signal they handle (#84), and recreating
    the LEZ chain survives a chain that dies in its first minute (#88).
  • The release bundle starts again (#89): its tools image lacked the library the
    LEZ v0.2.4 wallet code links, so start.sh could not mint an identity. Found by
    running the release workflow before the tag.
  • A bundle's evidence export names its commit (#74, fixes #72); escrow compute
    units measured against the deployed testnet program (#66); the planned ZEC flow
    reconciled with what exists (#85).

Verified

  • Public networks: the three evidence folders above.
  • Full regression on the local devnet (LEZ v0.2.4), one run on the tree that
    was merged: every node-e2e.py scenario in both directions (11/11 and 12/12),
    both desk suites, every desk scenario in both directions (7/7 and 7/7) —
    39 passed, 0 failed.
  • Basic regression on the release commit's tree after the stack was merged and
    the version set: happy and concurrent in both directions, a Taker refund and
    a Maker refund, both desk suites and the desk happy in both directions —
    10 passed, 0 failed. The result lines and full logs of both runs are attached
    to this release (regression-v0.2.4.tar.gz); the tables are in #88.
  • All 14 CI checks on the release commit, and the release workflow end to end
    before the tag (every image built, then the bundle pulled them on a fresh runner
    and brought the stack up, Nodes ready and both desk suites green), and again on the tag.

Known, upstream

The local LEZ v0.2.4 chain stops finalizing after anything from a minute to a few
hours: Bedrock 0.2.1 drops a sequencer inscription that is in flight when an epoch
turns, and the channel never finalizes again. It is not ours and cannot be dodged
from our side; up.sh --fresh-lez is the remedy and node-e2e.py checks finality
before each scenario
(deploy/README.md).
We have not seen it on the official LEZ testnet.

Install

  • Prebuilt stack: download the bundle attached to this release and run
    scripts/start.sh (pulls ghcr.io/gateway-fm/lez-atomic-swaps/lez-*:v0.2.4);
    scripts/start.sh --swap adds one complete swap through the two desks.
  • Basecamp apps: add the catalog
    https://raw.githubusercontent.com/mandrigin/logos-modules-release-base/main/logos-repo.json
    in Basecamp's package manager and install LEZ / BTC Maker and
    LEZ / BTC Taker 0.2.4.

Not in this release

  • Mainnet. Networks are chosen by configuration and mainnet never pairs with a
    test chain, but nothing here has run on mainnet.
  • ZEC in the desks: designed and proven at the service layer, not delivered by the
    apps (docs/m6-zec-reconciliation.md).

Container images

Every image deploy/compose.yaml pulls, published to GHCR at this tag. linux/arm64 only.

docker pull ghcr.io/gateway-fm/lez-atomic-swaps/lez-bitcoin-core:v0.2.4  # (sha256:ce06a6edf137031c48416196189753d1916eb42791896864582e4b7f1bd18bb7)
docker pull ghcr.io/gateway-fm/lez-atomic-swaps/lez-btc-miner:v0.2.4     # (sha256:28f7349b4304c377a3f69e8cf1f9103b39e0c3c398659e95999028ad96dc8973)
docker pull ghcr.io/gateway-fm/lez-atomic-swaps/lez-btc-explorer:v0.2.4  # (sha256:6efc21b7677e5baf28c9969eb44bdd33a7913d5282592963bf49bfa2f85d8200)
docker pull ghcr.io/gateway-fm/lez-atomic-swaps/lez-services:v0.2.4      # (sha256:fd4975ef1e20f116036e099d7a548d167e945a632ddc5e149f2d08eaaadc55da)
docker pull ghcr.io/gateway-fm/lez-atomic-swaps/lez-explorer:v0.2.4      # (sha256:bb6f58b395cffd5d0faafbd1e3326d2d0f4b68d6d7634eac7a7c48751ac1357c)
docker pull ghcr.io/gateway-fm/lez-atomic-swaps/lez-maker-node:v0.2.4    # (sha256:36217255d7c0ba40d65dfff35fdfd94a5bd46c45a1d55fefe999fc35d11cc82e)
docker pull ghcr.io/gateway-fm/lez-atomic-swaps/lez-taker-node:v0.2.4    # (sha256:502b550da361a93575b3c3614260c443492742ce66f10938d71195980a887062)
docker pull ghcr.io/gateway-fm/lez-atomic-swaps/lez-basecamp-ui:v0.2.4   # (sha256:f58dae8515b2d4accefe81fc0310c205da52edaffaedd9814fb425dd595302e2)
docker pull ghcr.io/gateway-fm/lez-atomic-swaps/lez-tools:v0.2.4         # (sha256:f6c5aaccf7e22b3882df9f9ba07bd13e72ceb1e3af5fbfb693f2cb6a8900f4c3)

Entry points

Read more

v0.2.3 — dependency advisory fixed, refund and desk follow-ups

Choose a tag to compare

@mandrigin mandrigin released this 15 Sep 20:51
838cb71

A maintenance release on top of v0.2.2: the TLS dependency moves past a new
advisory, the maker-refund scenario no longer aborts on a stale action
generation, and the Maker desk names the right asset while it waits for the
Taker's claim.

What changed

  • rustls 0.23.45 (#51): RUSTSEC-2026-0285 (rustls 0.23.42 accepted TLS 1.3
    handshake messages across encryption-level boundaries) was published after
    v0.2.2; every audited host graph moves to rustls 0.23.45 and
    rustls-webpki 0.103.15. The crate is reachable only through the JSON-RPC
    HTTP client the Nodes use over loopback to their sidecars. The pinned
    escrow guest graph carries a documented exception.
  • DCO on pull requests only (#51): the sign-off check no longer runs on
    pushes to main, where GitHub's squash commit is authored with the merger's
    noreply address and failed every merge without checking anything new.
  • maker-refund retries a stale action generation (#53, fixes #47): the
    scenario's Maker refund request re-reads the swap's lease generation and
    resends the same request id when the Node answers that the generation is
    stale, instead of aborting.
  • The Maker desk names the asset the Taker claims (#54, fixes #48): with
    both legs locked the row reads "Waiting for the Taker's LEZ claim" when the
    Taker sells BTC and "Waiting for the Taker's Bitcoin claim" when the Taker
    sells LEZ; the desk runner asserts that exact label in both directions.

Verified

Every change landed with its own verification: #53's maker-refund
retry in both directions through the Node APIs, #54's desk label asserted by
the desk runner in both directions, and #51's dependency audits over every
host graph. On the release commit: all 14 CI checks, and the release
workflow end to end on the release branch (every stack image built, then
the bundle pulled those images on a fresh runner and brought the stack up,
Nodes ready and both desk suites green).

Install

  • Prebuilt stack: download the bundle attached to this release and run
    scripts/start.sh (pulls ghcr.io/gateway-fm/lez-atomic-swaps/lez-*:v0.2.3);
    scripts/start.sh --swap adds one complete swap through the two desks.
  • Basecamp apps: add the catalog
    https://raw.githubusercontent.com/mandrigin/logos-modules-release-base/main/logos-repo.json
    in Basecamp's package manager and install LEZ / BTC Maker and
    LEZ / BTC Taker 0.2.3.

Container images

Every image deploy/compose.yaml pulls, published to GHCR at this tag. linux/arm64 only.

docker pull ghcr.io/gateway-fm/lez-atomic-swaps/lez-bitcoin-core:v0.2.3  # (sha256:e364b36ecc34fdbc2ba24444a45d9cf7f2a9075ad325be004111382e71682bc6)
docker pull ghcr.io/gateway-fm/lez-atomic-swaps/lez-btc-miner:v0.2.3     # (sha256:20f0e1c539ea128df72ea319dd28bbd873e84f529f68a1c291670c5bd7905b04)
docker pull ghcr.io/gateway-fm/lez-atomic-swaps/lez-btc-explorer:v0.2.3  # (sha256:f13170fa290b39389166ecd4b366494cd63cf504b69eb98cac252a44b5417530)
docker pull ghcr.io/gateway-fm/lez-atomic-swaps/lez-services:v0.2.3      # (sha256:50957f59bfadcbd8a92b3cfd8add5574f96e3f494fda49cd133618c56075337b)
docker pull ghcr.io/gateway-fm/lez-atomic-swaps/lez-explorer:v0.2.3      # (sha256:2818ac10e94f02d2b59b514f0c34418c2068f4879d086e1e1b97215f3ffe4cc4)
docker pull ghcr.io/gateway-fm/lez-atomic-swaps/lez-maker-node:v0.2.3    # (sha256:6b471c6a94d13203eb819e1260b8b25b4d7ab9745cc59d771ed539b97da9a4b9)
docker pull ghcr.io/gateway-fm/lez-atomic-swaps/lez-taker-node:v0.2.3    # (sha256:29e07ae4accffafd7300edfb25387662083514fb0d8417916770bd218ed9c971)
docker pull ghcr.io/gateway-fm/lez-atomic-swaps/lez-basecamp-ui:v0.2.3   # (sha256:49350820016ceec723f79e958d8ffbd2a7932a62c522bf3263ed9f0d0da59908)
docker pull ghcr.io/gateway-fm/lez-atomic-swaps/lez-tools:v0.2.3         # (sha256:3b819b1d3d572688f040695ad19ac21af8bb062b9afa9bcbbe7d5b63101be3e7)

Entry points

v0.2.2 — every scenario proven both ways, in both directions

Choose a tag to compare

@mandrigin mandrigin released this 13 Sep 18:28
26c2b2e

v0.2.2 — every scenario proven both ways, in both directions

The whole scenario matrix now passes twice on the same Node methods: through
the Nodes' owner APIs and by pressing the real Basecamp desks, in both
Bitcoin directions (the Taker sells BTC, the Taker sells LEZ), including both
refund cases, overlapping swaps, Node restarts, and the two review
follow-ups on configuration and late-observed claims. Doing that on a stack
that had run for a day exposed and fixed a set of defects in the Nodes, the
desks and the local chain tooling. Fourteen narrated recordings and a
per-scenario reproduction guide ship with the evidence.

What changed

  • The Taker sells LEZ (#41, via #42): the reverse direction end to end.
    The Taker locks LEZ first, the Maker locks Bitcoin, the Taker claims
    Bitcoin; refunds and recovery in that direction; both desks label the legs
    by what the owner locks and claims.
  • Wallet balances (#40): each Node reports its own Bitcoin wallet and LEZ
    owner account (maker_wallet_balances_v1, taker_wallet_balances_v1);
    the desks show them under the account selector.
  • Refund only after the cutoff (#43): the Taker desk offers the refund
    once the Maker's lock cutoff has passed, not at the first observation.
  • Fixes found by the scenario runs (#42), each reproduced on the stack,
    fixed and run again in both directions and both ways:
    • an unsent Maker lock is never sent past the cutoff. The recovery path's
      freshness read consults the chain clock, which trails the wall clock
      (Bitcoin's median time by about an hour on mainnet, ten minutes on
      regtest); a Maker restarted just after its cutoff still locked, and the
      Taker then saw a late lock it could neither claim nor refund against.
    • the Taker's second sell-LEZ lock waits for the previous one at the
      sequencer, not in the finalized view, which the devnet's L1 pauses for
      minutes at a time.
    • a submitted Taker claim stays observed across the claim window's close
      (the #32 follow-up); a Maker past its cutoff still projects a lock it
      sent in time; a Maker lock spent by the Taker's claim, and a Maker LEZ
      funding the Taker has claimed, are still canonical locks; exact and
      discovered LEZ refund lookups trail the finalized tip.
    • the LEZ v0.2.0 indexer kept losing its breakpoints on a restart
      (carried source patch); the Node's sidecar client repeats a request
      whose transport failed; owner replies may be 4 MiB.
    • desks: one silent market read in flight at a time and explicit reads
      never dropped; the refunded Maker leg reported as such; the market
      snapshot and the replies that embed one (publish, withdraw, take, lock,
      claim, refund) use a 4 MiB budget while ordinary calls keep 64 KiB.
  • Configuration regression scenarios (#42, the #28 follow-up):
    node-e2e.py regenerated-config (re-rendered live configuration and a
    Taker restart; the swap reloads and completes) and tampered-config (one
    altered byte in a swap's saved copy; the swap is refused after a restart).
  • Test tooling (#42): deploy/scripts/node-e2e.py all [--direction TakerSellsLez] and deploy/scripts/ui-e2e.sh all [--direction TakerSellsLez] [--record] drive the same scenarios through the APIs and
    through the desks; --record films each scenario with narrated subtitles;
    LEZ_BTC_ACTOR_TRACE=1 names every actor decision; dump-swaps.sh
    keeps both Nodes' state before a reset; up.sh --fresh is one unattended
    clean bring-up (#38); the release jobs pull the pinned builder image (#39).
  • Evidence for the review (#42): docs/evidence/review-2026-09-12/
    answers the ecosystem review index item by item, with the harness
    summaries of every scenario, the recorded swaps' on-chain exports and a
    reproduction guide per scenario (REPRODUCE.md).

Verified

On the release commit: workspace clippy and tests; verify-all with both desk
suites; the nine scenarios plus the two configuration scenarios through the
APIs in both directions (22/22); the seven desk scenarios in both directions
(14/14), on clean history (filmed) and again on a day of accumulated history;
all 14 CI checks. Fast timing profile (cutoff 600 s, refunds 900 s/1200 s,
CSV 6 blocks).

Install

  • Prebuilt stack: download the bundle attached to this release and run
    scripts/start.sh (pulls ghcr.io/gateway-fm/lez-atomic-swaps/lez-*:v0.2.2);
    scripts/start.sh --swap adds one complete swap through the two desks.
  • Basecamp apps: add the catalog
    https://raw.githubusercontent.com/mandrigin/logos-modules-release-base/main/logos-repo.json
    in Basecamp's package manager and install LEZ / BTC Maker and
    LEZ / BTC Taker 0.2.2.

Not in this release

The Maker's offer list still returns the Node's whole offer history, so a
desk snapshot grows with age (a state filter is the next change). The
verified desk path is the bundled VNC environment; a native Basecamp with the
catalog modules is published but not exercised by these runs. XMR and ZEC
pairs are unchanged. Remote signing with external wallets remains a plan (#30).

Entry points

v0.2.1 — the desks show the terms and the clock; the Nodes recover a late claim

Choose a tag to compare

@mandrigin mandrigin released this 10 Sep 18:04
b54d2b0

v0.2.1 — the desks show the terms and the clock; the Nodes recover a late claim

Both Basecamp desks now run on the Nodes' own APIs, share one UI kit, and show
what a swap is worth and when each window closes. The Nodes expose the
countersigned schedule and every on-chain effect of a swap, and they recover
on their own when a revealing claim can no longer land. The release ships
prebuilt images with a start-script bundle, and both apps are installable from
the Logos module catalog at this version.

What changed

  • Maker terms and Taker amount (#21): the fixed offer preset is gone. The
    Maker desk publishes offers from a swap-shaped form (amounts on both legs,
    minimum, lifetime; the Node's integer-lot price is derived), through the
    guarded maker_offer_publish_v1. The Taker picks any in-bounds amount.
  • One UI kit, two desks (#21): apps/basecamp/common/qml and one
    generated skeleton for both desks; an activity log on each that records every
    request, reply and poll-observed change; on/off swap filters ordered by what
    needs the owner first; no decoration that carries no information.
  • Timelines (#26): terms on taker_swap_monitor_v1 / taker_swap_list_v1
    and maker_actor_monitor_v1 (amounts, required confirmations, Bitcoin refund
    height, the Maker's lock cutoff, the earlier and later refund instants). Every
    running swap row carries the schedule with live countdowns; Maker rows show
    the fill, the offer form shows the spread against the Node's stored price,
    the Taker's order book shows rate, distance from the best, the book spread,
    each offer's expiry and a share slider.
  • Late claim recovery (#32, fixes #25): a revealing claim sent after the
    earlier refund's deadline is dropped by the sequencer with
    OutOfValidityWindow. Both actors now route revision two past that instant
    to recover_maker_leg; the Maker supervisor alternates observation and
    recovery; the Taker Node stops offering claim, watches the Maker's refund,
    retires the stale admission and offers refund at the next generation.
    Verified live: both legs refunded without anyone touching the Maker.
  • Taker restart (#28): persisted swaps pin a per-swap copy of the role
    configuration instead of the live file the entrypoint rewrites on every
    start, so a rebuild or re-bootstrap no longer turns every swap into
    attention_required.
  • On-chain details (#29, closes #22): effects on both monitor methods
    (each lifecycle evidence row with chain, transaction id and confirmations,
    plus the Maker's LEZ lock steps) and a "Details" popup per swap with copyable
    ids and explorer links.
  • Stack lifecycle scripts (#24): deploy/scripts/up.sh (config, images,
    chains, market, Nodes, UI and its suites; --build, --fresh-lez,
    --fresh) and down.sh (--wipe); the market bootstrap runs in the
    throwaway builder container.
  • Prebuilt release (#20, ADR 0215): every image of deploy/compose.yaml
    built for linux/arm64 and published to GHCR on release, with a bundle
    (compose file, start.sh, pinned config, release.env) attached below.
  • Module catalog (#19): per-package flakes; both apps at version 0.2.1 in
    https://github.com/mandrigin/logos-modules-release-base.
  • Third-party API documentation (#16) and reproducible swap evidence
    (#17): docs/api/README.md for integrators; deploy/scripts/export-node-evidence.py
    feeds the LEZ explorer's evidence view.
  • Validity-window reproducers (#18): compat/lez-v0.2-sequencer-reproducers
    runs the reviewer's cases (valid when queued, expired before inclusion, both
    window bounds) on the real v0.2.0 block builder in CI.

Verified

Maker and Taker desk suites, the package contract, verify-market.py and the
Node-API scenarios on the local stack; the late-claim recovery and the Taker
restart reproduced live on that stack; Linux clippy and the crate test suites.

Install

  • Prebuilt stack: download the bundle attached to this release and run
    scripts/start.sh (pulls ghcr.io/gateway-fm/lez-atomic-swaps/lez-*:v0.2.1).
  • Basecamp apps: add the catalog
    https://raw.githubusercontent.com/mandrigin/logos-modules-release-base/main/logos-repo.json
    in Basecamp's package manager and install LEZ / BTC Maker and
    LEZ / BTC Taker 0.2.1.

Not in this release

The claim-window routing is wall-clock based like the second-lock cutoff; the
recovery itself still waits for the chain clocks. The reverse direction
(TakerSellsLez) has no Taker LEZ lock action yet. Remote signing with
external wallets is a plan (#30), not code.

Entry points

v0.2.0 — the Nodes own the BTC↔LEZ swap

Choose a tag to compare

@mandrigin mandrigin released this 07 Sep 16:54
f6bc36a

v0.2.0 — the Nodes own the BTC↔LEZ swap

The Maker Node and the Taker Node now run the whole BTC↔LEZ lifecycle
themselves: reservation, the signing ceremony over Chat, the Bitcoin lock, the
LEZ escrow, claims and both refunds. The demo controller, the launcher and the
long-lived runner host that carried the M3 proof-of-concept lane are gone; the
Basecamp desks talk to the Nodes and nothing else. Everything still runs on one
machine against a standing Bitcoin regtest chain and a standing LEZ v0.2
devnet, and the chains are chosen by configuration alone (ADR 0213, stages 1
to 3).

What changed

  • Node-owned lifecycle (#12): taker_swap_initiate_v1 reserves, plans the
    Bitcoin funding from the Taker's own Core wallet, prepares the LEZ claim
    through the Taker's own sidecar and drives the three-round adaptor ceremony
    in-process on both Nodes; taker_swap_lock_v1 broadcasts the lock; the
    Maker Node supervises its actor to fund the LEZ escrow and claim Bitcoin;
    taker_swap_claim_v1 and taker_swap_refund_v1 / maker_actor_refund_v1
    are the owner's terminal actions. One sidecar per swap, spawned by the Node
    that owns it.
  • Runner lane deleted (#13): 92 scripts, the reference-m3-btc-v1 profile,
    the btc-local-poc-provision crate, the btc-role-preflight binary and the
    lane's manuals (about 50k lines). Builds and the market bootstrap run in
    throwaway containers of deploy/builder; no long-lived container holds the
    Docker socket.
  • Node-API scenario harness (#13): deploy/scripts/node-e2e.py <scenario>
    drives both Nodes over their owner sockets with no UI, each scenario its
    own job in .github/workflows/node-e2e.yml on a self-hosted stack. The
    recovery timing is a configuration profile (LEZ_TIMING_PROFILE=local|fast).
  • Liveness fixes the scenarios found (#13): sidecar request timeout on a
    cold respawn; input locking for concurrent Bitcoin funding plans; a moving
    LEZ finality clock is retried; the LEZ discovery window joins the timing
    profile (2048 blocks meant almost six hours before a refund could be
    asserted); the sidecar accepts a tip that merely extended during a scan; the
    Bitcoin adapter accepts a funding confirmed at or above the signed anchor;
    an admitted Taker refund is driven to completion by the Node; the Maker
    supervisor recovers instead of driving a lock past the cutoff; Maker LEZ
    escrows are prepared one at a time (two prepared together shared a nonce
    pair and the second was dropped after acceptance); the Taker watches the
    Maker's leg at both_legs_locked so a Maker refund is offered as a Taker
    refund; owner requests wait for a swap's actor lock instead of failing.
  • Audited runtime boundaries (#9): checked runtime profiles, an exact
    executable catalog with CI drift rejection, no Maker private-key access from
    Taker initialization.
  • Honest Taker lifecycle reporting (#10): taker_health names what each
    pair's initiation, claim and refund actually are.
  • Hardening: vetted, no-follow bounded file readers on every configured
    path; the actionable Aikido findings resolved.
  • CI: the ZEC and XMR pairs still lint under --all-features; their tests
    are parked while BTC↔LEZ is the product. Dependabot pins updated.

Verified

All nine Node-API scenarios pass on the local stack with the fast timing
profile (Bitcoin regtest, LEZ v0.2 devnet, no UI): happy, replay,
wrong-inputs, restart-taker, restart-maker, survivor, concurrent, taker-refund
and maker-refund. The Basecamp Maker and Taker desks complete a swap through
the Nodes (deploy/scripts/swap-through-ui.sh).

Not in this release

The reverse direction (TakerSellsLez) has no Taker LEZ lock action yet.
ZEC and XMR are untested. The recovery deadlines are local profiles, not
network policy.

Entry points

No assets are attached; the v0.1.1 and v0.1.2 reviewer evidence remains
available on those releases.

v0.1.2 — BTC/LEZ product and public-readiness update

Choose a tag to compare

@mandrigin mandrigin released this 27 Aug 08:27
v0.1.2
1ef2d9b

v0.1.2 — BTC/LEZ product and public-readiness update

This additive maintenance release keeps the M1, M3, and M6 submission scope of
v0.1.1
while publishing the public-readiness and CI hardening completed on the canonical
main branch. The v0.1.1 release remains available and unchanged.

What changed

  • resolved the actionable Aikido and publication-gate findings, including safe
    path handling, least-privileged workflows, immutable Action/image pins,
    full-history secret scanning, dependency and licence enforcement, and
    deterministic shell/Docker/Compose validation;
  • aligned the active public CI surface with the submitted M1/M3/M6 scope while
    preserving the Bitcoin/LEZ implementation, Basecamp Maker/Taker flows, and
    Logos Chat/Delivery discovery and negotiation tests;
  • replaced the publication-oriented README with a product-first introduction,
    Apple Silicon quickstart, architecture tour, and focused contributor paths;
  • updated the pinned dtolnay/rust-toolchain, actions/checkout, and
    actions/setup-node dependencies through reviewed Dependabot changes;
  • made the network-disabled local E2E fail clearly on mismatched Docker image
    architectures and support native cached Rust images on Apple Silicon;
  • retained fail-hard treatment for repository-owned security findings while
    keeping explicitly classified upstream build-image findings visible.

Preserved reviewer evidence

The attached HTML deck, PDF, Basecamp walkthrough, English captions, and
SHA256SUMS are byte-for-byte identical to the reviewed v0.1.1 assets. The
maintenance work therefore changes the code and validation posture, not the
demonstrated five-effect, zero-replay BTC-to-LEZ result.

Asset SHA-256
lez-btc-m1-m3-m6-submission.html 5c90bfa301d43c7aadb072ad5e8e87e0476666d449af33aee199f37ca09ef233
lez-btc-m1-m3-m6-submission.pdf d084df2cec8d23cb9982c0e237f81d9c882554b78d059b308f0d001c17454637
lez-btc-ui-swap-demo.mp4 bb5ec36055e5f8a53f367d6bf03147e4eb78f17a601d305260b30d8229275703
lez-btc-ui-swap-demo.en.vtt ea89663fc45c8fd2881b28fc509841eca86d5739ea16086b1fda1694b353b49c
SHA256SUMS 696f09d79a9b471e03b934c94109729824653a0ae10679bdee5d31438e5095ed

Reviewer entry points

v0.1.1 — RFP-003 M1, M3, and M6 source release

Choose a tag to compare

@mandrigin mandrigin released this 26 Aug 17:46
4986343

v0.1.1 — RFP-003 M1 + M3 + M6 source release

This is Gateway's corrected public source and reviewer release for the LEZ ⇄
Bitcoin vertical slice. It binds the directly browsable, buildable Rust
workspace, the M1 protocol foundation, the M3 BTC/LEZ implementation and
evidence, and the M6 Maker/Taker product surface to one versioned repository
state.

Release: https://github.com/gateway-fm/lez-atomic-swaps/releases/tag/v0.1.1

The default main branch and this tag contain Cargo.toml, Cargo.lock,
crates/, compat/, apps/, tests, and build scripts directly. No patch
series, reconstruction script, personal-remote checkout, or generated binary
is needed to inspect the source.

Release assets

Asset Purpose
lez-btc-m1-m3-m6-submission.html Self-contained, interactive 28-slide deck with no external runtime dependency
lez-btc-m1-m3-m6-submission.pdf Print-ready 28-page export of the deck
lez-btc-ui-swap-demo.mp4 1:53 actual Basecamp BTC→LEZ walkthrough, from offer publication through both chain claims and reconciliation
lez-btc-ui-swap-demo.en.vtt English captions for the walkthrough
SHA256SUMS Digests for release media, evidence, and reviewer documents

Milestone review map

M1 — protocol foundation

The M1 issue maps to the per-leg
protocol and atomicity design, LEZ escrow/SPEL sketch, threat model, PR #48
reproducers, Zcash stack ADR, common SDK surface, persistence ADR, and Logos
daemon integration/fallback design listed in MILESTONES.md.
The complete entry point is docs/milestone-1/README.md.

M3 — BTC/LEZ leg

The M3 issue maps to the witnessed
LEZ settlement ADRs, full-lifecycle SDK/runner source, cryptographic fixtures,
Bitcoin Testnet4 guide, and inline security references listed in
MILESTONES.md.

The D1 behaviours are reviewable as:

Behaviour Public evidence Reproduction
Happy settlement Actual Basecamp walkthrough and matching passed record REPRODUCE.md
Refund/timeout Both-direction two-lock refund record Timeout/refund procedure
Concurrent swaps Opposite-direction overlap record Overlap procedure

All three are private-local functional claims using Bitcoin Core regtest and a
private LEZ v0.2 devnet; no public funds or private key material are published.

M6 — Maker and Taker mini-apps

The M6 issue maps to signed-off
interactive HTML prototypes, Maker pair/price/active/history surfaces, Taker
offer/initiation/progress/ZEC-shield guidance, and Basecamp-loadable role
packages with local-build instructions. Start with
apps/m6-prototypes/,
apps/basecamp/, and the M6 section of
MILESTONES.md.

Verification gates

The release candidate is accepted only after:

./scripts/verify-public-repository.sh
./scripts/run-public-offline-e2e.sh
./scripts/check-architecture-diagrams.sh
./scripts/check-requirements-traceability.sh
node scripts/check-m6-prototype-contract.mjs
shasum -a 256 -c submission/SHA256SUMS

The running-stack verification is read-only for settlement: it starts no swap
and submits no chain effect; its market check creates and withdraws one uniquely
named offer. The dated result is recorded under submission/.

Claim boundary

This release is submitted for Logos review; it does not mark the upstream issue
checkboxes or claim formal acceptance. It does not claim public-network
deployment, production custody, independent cryptographic audit, M2, M4,
complete M5 operations, or M7 mainnet readiness. The normative boundary is
LIMITATIONS.md.