diff options
| author | Adam Soltys <[email protected]> | 2026-08-04 09:28:36 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-08-04 09:28:36 -0700 |
| commit | e462bc1e7756dcbf7c651ee282e96ee8c48b5a14 (patch) | |
| tree | bdb0a8276fffc8cce54adfb978ea6d22cec290b8 /src/ark/validate.js | |
| parent | 9fd8887dcdd5e0fc1067a91032bfd18eb25f0202 (diff) | |
| download | coinosv3-e462bc1e7756dcbf7c651ee282e96ee8c48b5a14.tar.gz coinosv3-e462bc1e7756dcbf7c651ee282e96ee8c48b5a14.zip | |
A wallet too small to renew warns before its coins expire; dust never dies
The warning: when the Spending balance minus round fee is under the
330-sat round minimum AND a vtxo enters the renewal window, auto-refresh
can't save the coins — a wallet-screen notice (and a daily local
notification, when permitted) says to receive any amount or spend
before the deadline. New walletNotices feature hook renders under the
balance card.
The amnesty: sub-dust vtxos have no unilateral exit to protect, and
regtest proves captaind keeps cosigning their spends past expiryHeight —
even after the watchman claims the backing on-chain
(tools/ark/expired-dust-test.js). Only hal's own receive validation
stood in the way; it now exempts sub-330 vtxos from the expiry check.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015QwAtBSpKvECqp1rHLHjJk
Diffstat (limited to 'src/ark/validate.js')
| -rw-r--r-- | src/ark/validate.js | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/src/ark/validate.js b/src/ark/validate.js index f7aecb9..d09f6ec 100644 --- a/src/ark/validate.js +++ b/src/ark/validate.js @@ -36,8 +36,14 @@ export async function validateVtxo(vtxo, { serverPubkey, chain, expectPubkeys, a if (!vtxo.genesis.length) fail('vtxo has no genesis transitions'); // -- expiry -- + // Sub-dust vtxos outlive their expiryHeight: they have no unilateral exit + // to protect (below dust there is no on-chain output they could become), + // and the coinos ASP keeps honoring them off-chain after sweeping their + // round — an explicit IOU where the trustless path never existed anyway. const tip = await chain.tipHeight(); - if (vtxo.expiryHeight <= tip) fail(`vtxo expired at ${vtxo.expiryHeight}, tip ${tip}`); + if (vtxo.expiryHeight <= tip && vtxo.amountSat >= 330) { + fail(`vtxo expired at ${vtxo.expiryHeight}, tip ${tip}`); + } // -- anchor: onchain, confirmed, and its output matches what the first // transition claims to spend -- |
