diff options
| author | Adam Soltys <[email protected]> | 2026-08-18 20:11:36 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-08-18 20:11:36 -0700 |
| commit | 1d0e26f5815f817f489c709bdf25f4708d18cd7d (patch) | |
| tree | 8f9159a848aa6e1aa886aa0e2bf95356f7afdbbc /src/ark | |
| parent | ecf7da305d56cee8a8d2306ca7fa5dad4b2f0c39 (diff) | |
| download | coinosv3-1d0e26f5815f817f489c709bdf25f4708d18cd7d.tar.gz coinosv3-1d0e26f5815f817f489c709bdf25f4708d18cd7d.zip | |
A many-coined receive keeps the server's own order: the claim step stops alphabetizing HTLC vtxos the ASP matches positionally, and the expiry guard reads the true earliest deadline instead of whoever sorted first
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_012u4oe1KPx9faCsDBLfZYqi
Diffstat (limited to 'src/ark')
| -rw-r--r-- | src/ark/manager.js | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/src/ark/manager.js b/src/ark/manager.js index e5e04d4..c1121db 100644 --- a/src/ark/manager.js +++ b/src/ark/manager.js @@ -1152,13 +1152,16 @@ export class ArkManager { } if (action.step === 'htlcsReady') { const keys = this._key(action.keyIndex); - const decoded = action.htlcBytes.map((b) => decodeVtxo(hex.decode(b))) - .sort((a, b) => (a.id < b.id ? -1 : 1)); + // Server order, verbatim: ClaimLightningReceive matches cosign parts to + // its HTLC list positionally, so a re-sorted list is rejected as + // "cosign inputs do not match htlcs" (bites only multi-vtxo receives). + const decoded = action.htlcBytes.map((b) => decodeVtxo(hex.decode(b))); // preimage not revealed yet + HTLCs near expiry: abandon rather than // commit (the inbound HTLC times out and the sender is refunded) if (!action.preimageRevealed) { const tip = await this.chain.tipHeight(); - if (tip > decoded[0].policy.htlcExpiry - this._expiryMargin()) { + const minExpiry = Math.min(...decoded.map((v) => v.policy.htlcExpiry)); + if (tip > minExpiry - this._expiryMargin()) { action.step = 'failed'; action.error = 'HTLCs near expiry — abandoned before preimage reveal'; this._movement({ type: 'ln-receive', amountSat: action.amountSat, status: 'failed', detail: action.error }); |
