aboutsummaryrefslogtreecommitdiffstats
path: root/src/ark
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-08-18 20:13:56 -0700
committerAdam Soltys <[email protected]>2026-08-18 20:13:56 -0700
commit6b09b097535c0c32aa40c1a09320cfd95a2207a1 (patch)
treee7a068dd2fa266383b7fa19b93fb56980d8172cb /src/ark
parent1d0e26f5815f817f489c709bdf25f4708d18cd7d (diff)
downloadcoinosv3-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.js17
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) {