aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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) {