diff options
| author | Adam Soltys <[email protected]> | 2026-08-18 20:13:56 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-08-18 20:13:56 -0700 |
| commit | 6b09b097535c0c32aa40c1a09320cfd95a2207a1 (patch) | |
| tree | e7a068dd2fa266383b7fa19b93fb56980d8172cb /src/ark | |
| parent | 1d0e26f5815f817f489c709bdf25f4708d18cd7d (diff) | |
| download | coinosv3-6b09b097535c0c32aa40c1a09320cfd95a2207a1.tar.gz coinosv3-6b09b097535c0c32aa40c1a09320cfd95a2207a1.zip | |
The claim sorts its coins the way the server counts them: HTLC vtxos line up by outpoint in internal byte order — the display-hex sort read the txid backwards and nine-coin receives bounced off the positional check
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 | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/src/ark/manager.js b/src/ark/manager.js index c1121db..5eeffd3 100644 --- a/src/ark/manager.js +++ b/src/ark/manager.js @@ -1152,10 +1152,19 @@ export class ArkManager { } if (action.step === 'htlcsReady') { const keys = this._key(action.keyIndex); - // 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))); + // ClaimLightningReceive matches cosign parts to its HTLC list + // positionally, ordered by OUTPOINT IN INTERNAL BYTE ORDER (Rust's + // natural OutPoint sort). Sorting by display-hex id — reversed txid — + // ordered them differently and the claim bounced with "cosign inputs + // do not match htlcs" (bites only multi-vtxo receives; verified live + // against a 9-vtxo 215k receive). + const byOutpoint = (a, b) => { + for (let i = 0; i < 32; i++) { + if (a.point.raw[i] !== b.point.raw[i]) return a.point.raw[i] - b.point.raw[i]; + } + return a.point.vout - b.point.vout; + }; + const decoded = action.htlcBytes.map((b) => decodeVtxo(hex.decode(b))).sort(byOutpoint); // preimage not revealed yet + HTLCs near expiry: abandon rather than // commit (the inbound HTLC times out and the sender is refunded) if (!action.preimageRevealed) { |
