Skip to content

v2.1.0

Choose a tag to compare

@jesuspirate jesuspirate released this 04 Jun 23:38
v2.1.0
687e031

v2.1.0 — Arbiter substitution: absent arbiters can no longer strand a dispute

Compatibility: SOFT lockstep — far gentler than v2.0.0. Every existing flow
works across v2.0.x and v2.1 (locks, votes, claims, legacy + holder-only).
The new powers only apply to locks CREATED on v2.1: a v2.0.x winner cannot
use a backup-carried share until they update, in which case the trade simply
behaves like today's absent-arbiter case until they do. No funds at risk in
mixed versions.

Arbiter substitution (the headline)

  • The arbiter share (index 2) is now encrypted to a deterministic PRIORITY
    ORDER over the community pool — the assigned arbiter + 2 backups — derived
    identically on every client from data already in the trade (no coordinator).
    Buyer/seller shares stay strictly single-holder; a pool arbiter still holds
    only one of the three slots. The cryptographic 2-of-3 is unchanged.
  • If the assigned arbiter goes absent during a live dispute, a backup becomes
    eligible after a grace floor of min(4h, half the trade's remaining life) —
    chain-derived, so every client agrees on the boundary. Backups see the
    dispute in their NEEDS queue with a floor countdown, then a step-in
    affordance; their vote carries the deciding share exactly like the assigned
    arbiter's would.
  • The arbiter slot is DERIVED from all arbiter votes by priority: the
    assigned arbiter's vote always supersedes a backup's pre-settlement, and
    any arrival order converges to the same state. The trade view shows
    "backup arbiter stepped in" when it happens.

Healing substitution (the disputed-expiry limbo fix)

  • Field-found: a 1-1 disputed trade that expired could only be rescued by the
    ONE participant who hadn't voted — the absent assigned arbiter itself. The
    same single point of failure, twice. Funds sat in limbo until that exact
    device came online.
  • Now, on v2.1 locks, ANY pool arbiter's client auto-heals an expired
    unresolved trade on load: a REFUND-only healing vote (the reducer rejects
    any other healing outcome) that carries the share the refund recipient
    needs to reconstruct and claim. "Sats will be returned automatically" is
    now backed by three devices instead of one. No grace floor in healing —
    the assigned arbiter had the trade's entire life to act.

Vote #1 — one task, one button (all verticals)

  • The off-chain deed-doer votes first everywhere: the seller ships (Market),
    the buyer sends the fiat (Exchange), the VOLUNTEER pays the bill (Bill Pay —
    first vote moved to the volunteer; the owner now confirms second), the
    borrower acknowledges the loan (Lending, with forward-leaning copy:
    "Loan received — I'll repay on time").
  • At that moment there is no real duality, so the screen shows ONE primary
    task button. The refund path demotes to a quiet two-tap "cancel this trade"
    hatch whose routing copy derives from the payout engine ("sats return to
    the seller" / "refund me") — it cannot lie about where the money goes.
    Vote #2 keeps dual buttons (a genuine confirm-or-deny); arbiters keep
    "Side with…"; oversold orders keep their single-refund override.

Trade lifecycle honesty

  • The locker is RELEASED at RESOLVE: once a trade resolves in someone else's
    favor, it stops counting toward "active trades / in escrow", and its Me
    chip reads Done — only the winner stays active until they claim. (Chat and
    re-broadcast still work; nothing is hidden.)
  • Sub-material leftovers no longer dangle a net-loss "Recover ₿1" button —
    the recovery card accumulates quietly until the pile is worth the
    Lightning fees, matching the dust line used everywhere else.

Tester + release tooling

  • Local builds show an amber "v2.1.0 · dev " chip so a refresh
    visibly confirms the new bundle landed; shipped builds stay clean.
  • Me › Advanced (power-user): TEST TRADE EXPIRY — a per-device CREATE-expiry
    override (consensus-safe: committed wire data) for live substitution
    testing; a 1800s trade opens the backup floor in ~15 minutes.
  • ship.sh now syncs src-tauri/tauri.conf.json from package.json at bump time
    (the stale-desktop-metadata footgun is structurally dead), and exports the
    clean-build flag for release stamps.
  • Dependabot updates arrive grouped; the escrow crypto deps
    (shamir-secret-sharing, @fedimint/*) always arrive as individual PRs for
    hand review.

Docs (in-repo)

  • docs/DESIGN-arbiter-substitution.md — the full substitution + healing
    design, maintainer-locked decisions, determinism invariants, test matrix.
  • docs/RFC-fedimint-escrow-module.md — the consensus-enforced 2-of-3 escrow
    module RFC, now discussed with the Fedimint community
    (fedimint-sdk discussion #300).

2151 tests green. Vote immutability is permanent policy: nothing in this
release (or any other) can flip a cast vote — healing can only ever route
the refund to the engine-computed recipient.