The repo pins channel=stable (no rustfmt version), so CI now pulls
rustfmt 1.9.0, which reformats code last touched by an older rustfmt.
main itself failed `cargo fmt --check` under the current toolchain;
this is a formatting-only sweep across 24 files to make the fmt gate
green. No behavior change; tests + clippy -D warnings still pass.
- config: grin is a supported tip chain (voucher model verified against the node),
so FEATURE_TIPS with only grin enabled no longer fails closed at boot.
- social_tips: revert_sweep_on_reorg now preserves sweep_txid instead of nulling
it. Address-scan chains (btc/ltc/xmr/wow) overwrite it via confirm_sweep_onchain
on the next cycle, so preserving the orphaned value is harmless; grin needs the
kernel excess to re-date a re-mined sweep via get_kernel, so nulling it stranded
reorged grin tips in 'claiming'. Test updated to assert preservation.
- lws import_account: retry the birthday backfill rescan (3 attempts, backoff) so
a transient failure no longer strands a new account at the chain tip. The
already-registered Some(_) no-op is unchanged, so this cannot reintroduce the
balance-reset bug.
Grin as a new asset arm in the tips machinery (no grin-lws change, no custodial
grin_transactions/grin_outputs port):
- GrinClient::get_outputs([commit]) (funding: present+height=confirmed) +
get_kernel(excess) (sweep spend-height); reached via state.chains.grin.
- create-gating (supported_tip_asset grin, validate 66-hex commitment,
confirmations_for_asset grin=10), grin_commitment column (migration).
- confirmation worker grin arm: get_outputs present -> confs; amount AUTO-VERIFY
with warn (voucher hides amount; not a theft vector; matches legacy).
- sweep reconciler grin arm: get_outputs-absent + get_kernel height at depth 10 ->
settle; absence-without-kernel -> no settle (recoverable, never missettle);
reorg revert only on commitment reappearing; probe error never settles/reverts.
- 5 grin tests + pure-helper unit tests; 251 lib + 24 tips green.
Amount-verification note: the voucher's bulletproof rewind nonce is random +
untransmitted, so it can't be rewound today; a clean non-custodial fast-follow is
to have the client send the per-voucher rewind nonce and verify via rangeproof
rewind (nonce reveals amount only, not spend authority).
Escrow settlement, audited guards ported verbatim:
- mark_tip_claiming: status IN('pending','claiming') AND confs>=required AND
funding_amount_verified AND sweep_confirmed_at IS NULL (double-claim guard).
- confirm_tip_sweep: RECORD-not-settle, first-recorder-wins (COALESCE +
sweep_txid IS NULL OR =$3) — RBF-steal safe; reconciler owns claiming->claimed.
- confirm_sweep_onchain: SOLE writer of 'claimed', one-way status='claiming' AND
sweep_confirmed_at IS NULL lock; settles only after on-chain sweep confirms to
per-asset depth (btc/ltc 1, wow 4, xmr 10).
- clawback: 5-status set incl 'cancelled', blocked once sweep_confirmed_at set.
- revert_sweep_on_reorg: only from 'claimed', re-opens to 'claiming' + clears txid.
- sweep_reconciler: address-history-driven (not recorded txid), pick_winner
(earliest height, lexi-smallest tie), pg advisory locks on a pinned conn for
single-instance safety; reorg pass reverts only on affirmative vanish, never on
probe error. DMs stubbed, exactly-once stamps kept.
- POST claim/confirm-sweep/clawback endpoints + openapi.
- 16 integration + 12 reconciler unit tests; build clean; SocialTipRow dead_code
allow removed (all fields now read).
- attach_funding_to_tip: atomic guarded UPDATE (COALESCE + CASE), idempotent on
same txid, 400 on a different txid; non-drafts land pending_confirmation so the
verifier (not the caller) owns the ->pending transition.
- worker (src/tips/confirmation.rs): XMR/WOW confirmation counting via LWS;
amount verification for BTC/LTC (Electrum full history, confirmed-only) +
XMR/WOW (classify_funding_amount, separate-then-subtract net). Verified->pending,
Short->funding_mismatch; Unfunded/Drained/LwsError never mutate status (outage-
safe). Spawned behind FEATURE_TIPS on a 60s loop w/ catch_unwind guard.
- POST /tips/social/:id/attach-funding endpoint + openapi.
- 5 DB tests + 6 classify unit tests; build clean.