Repository navigation
opt3: self-custodial eLTOO crypto layer (P0–P5) + B1 V6 scripts/witnesses - #3
Merged
Merged
Conversation
TxOutput.isUsdsoq now recognises a v7 holding (OP_7<32>) by witness version (isV7UsdsoqHolding || assetType==1) + static isV7UsdsoqHoldingScript helper, so v7 holdings classify as USDSOQ independent of the byte-derived RPC assetType field — which will be absent after the Phase-4 byte removal. First test in this package: dart test green (4 groups). CTxOut migration Phase 3. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Port the node-proven TypeScript soq-lightning-sdk into soqushield_sdk so Opt2
(LSP-trusted, ship-sooner) and Opt3 (self-custodial DilithiumEltoo, flagship)
are the SAME code path — Casey's 2026-06-24 one-path decision.
lsp_models — request/response types (grounded in rest.go / client.ts)
lsp_client — LspClient REST transport over Dio (12 endpoints, LspError)
update_tx_builder — the SWAPPABLE seam: PlaceholderTxBuilder (Opt2) today;
DilithiumEltooBuilder (Opt3) swaps in with zero facade change
soq_lightning — SoqLightning facade (fundAndOpen/openChannel/pay/close/
towers), preserving the live-verified invariants: faucet-cap
clamp, balance conservation, monotonic state advance,
dropped-close resilience
14 unit tests against a stateful in-memory fake LSP (full lifecycle + every
invariant branch + the placeholder/real builder seam). Full package: dart
analyze clean, 18/18 tests green.
Opt2 only — no real on-chain crypto yet; placeholders are visibly placeholders
so nothing downstream mistakes LSP-trusted custody for self-custody.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Proves the Dart LspClient/facade talks to the real stagenet LSP at lsp.soqu.org (info/health/towers). Live run confirms: peer L2SOQ-PEER, eltoo-v1, max_channel_sat 100000000, dual towers 2/2 reachable — matching the TS SDK's live findings. Read-only by design (no faucet: rate-limited + consumes test SOQ). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lets consumers (the SoquShield app) depend on the Lightning layer via package:soqushield_sdk/lightning.dart without pulling the package's native Dilithium FFI / wallet / RPC surface. Lightning is pure Dart over dio. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Start of the Opt3 DilithiumEltooBuilder MVP sprint (per SOQUSHIELD_OPT3_ELTOO_PORT_SCOPE). P0: copied the node-proven golden vectors (onchain_vectors.json, emitted by soq-signer's txbuilder) into the Dart SDK test tree. P1: lib/src/lightning/eltoo/serialization.dart — byte-for-byte port of onchain.ts's byte layer: u8/le16/le32/le64(BigInt)/concat, compactSize, sha256d, hex, the Tx/TxIn/TxOut/OutPoint model, serTxOut (Phase-4 byte-less CTxOut — NO nVisibility/nAssetType), serializeTx (BIP144 witness), and txid. Pinned byte-exact to the node vectors: serializeTxHex == rawTxHex and txid == V.txid, plus varint/le64 boundary checks and a Phase-4 byte-less serTxOut assertion. 8/8 new tests; full SDK suite 25/25; dart analyze clean. Strategy followed: the #1-risk component (the byte-less CTxOut serializer — the recurring root cause) is pinned to a node vector on day one. Next: P2 sighash (APO 0x42/0x41 + BIP143; the vector's sighashHex is the pin). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
lib/src/lightning/eltoo/sighash.dart — byte-for-byte port of channel.ts apoSighash + sighashAll: APO 0x42 (ANYPREVOUTANYSCRIPT, empty scriptField) + 0x41 (ANYPREVOUT, commits scriptCode), EMPTY_OUTPOINT/zeroed prevout-sequence-hashPrevouts-hashSequence, BIP143 SIGHASH_ALL, plus signApoWitness/signAllWitness (sig ‖ hashType) over an injected ML-DSA signer. Pinned byte-exact to node vectors: • APO 0x42 / 0x41 digests ← apo_ctv_vectors.json (b1_dump_vectors, Phase-4 byte-less) • BIP143 SIGHASH_ALL digest ← onchain_vectors.json sighashHex Invariance (channel.test.mjs): 0x42 ignores prevout (rebindable), 0x42≠0x41 (scriptCode commitment), 0x42 commits outputs. 7/7 new tests; full SDK suite green; analyze clean. This is the eLTOO core — the APO-0x42 digest the update TX is signed over. Next: P3 CTV (ctv_hash vector already in apo_ctv_vectors.json). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
lib/src/lightning/eltoo/ctv.dart — byte-for-byte port of channel.ts ctvHash / serTxOutCtv. Two pinned subtleties: serTxOutCtv uses an LE32 script-length prefix (NOT consensus compactSize), and ctvHash is a SINGLE SHA256 (NOT sha256d); scriptSigsHash omitted for segwit. Pinned to apo_ctv_vectors.json ctv_hash; tamper-sensitivity + LE32-length assertions. 3/3 new tests; full SDK suite green; analyze clean. P0-P3 complete: the full consensus-hashing foundation (serialization, APO/BIP143 sighash, CTV) is node-pinned. Next: P4 keyhash 2-of-2 funding (keyhash.test.mjs vectors). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ASH) lib/src/lightning/eltoo/script.dart — OP constants, pushData, scriptNum, p2wsh/p2wshV6, dilithiumWitnessPubKey, p2wshV6Witness (port of channel.ts:52-142). lib/src/lightning/eltoo/keyhash.dart — the SOQ-COV-013 funding suite (port of channel.ts:349-504): dilithiumKeyHash (single SHA256 of the raw 1312-byte key), 1/2-of-2 committed scripts, v6 witnesses, signForKeyhash dispatch, keyhashFunding2of2, partial sign + ORDER-ROBUST combine, the single-operator convenience. Byte-exact construction pins (keyhash = single SHA256, 69-byte witnessScript offsets, v6 funding scriptPubKey, [sigA,pubA,sigB,pubB,ws,trailing] layout, order-invariant combine, wrong-party + mixed-hashType + substitution rejection). 9/9 new tests with deterministic pubkey patterns + a deterministic mock signer; full SDK suite green; analyze clean. NOT pinned here (separate workstream): the node committed_sdk_crossvector byte-match for keys from seeds 0x11/0x22 — needs @noble↔pqcrystals ML-DSA keygen interop + the native FFI (not loadable in pure dart test). Real sig verification rides on that. P0-P4 complete: serialization + APO/BIP143 sighash + CTV + keyhash funding, all node-pinned. Next: P5 eltoo update/settlement scripts + DilithiumEltooBuilder, then P6 stagenet e2e. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
lib/src/lightning/eltoo/eltoo_builder.dart — byte-for-byte port of channel.ts's
DilithiumEltooBuilder. Implements the same UpdateTxBuilder seam PlaceholderTxBuilder satisfies,
so dropping it into SoqLightning(txBuilder: ...) makes payments self-custodial with ZERO
facade/UI change. Per state: build the canonical eLTOO graph (update output re-commits the
state-N script; settlement spends it via the CSV branch paying both balances), sign the update
input with SIGHASH_ANYPREVOUTANYSCRIPT (0x42), return opaque transport hex + the settlement CTV
hash.
Supporting:
- serialization.dart: TxIn.scriptSig + serializeTxLegacy (non-witness, includes scriptSig —
the LSP's opaque update_tx_hex) + txidInternal (the prevout the settlement spends).
- script.dart: eltooUpdateScript (spec-ref; V6 reality = keyhash+CSFS/CTV, flagged).
- lib/eltoo.dart: public entrypoint (import alongside lightning.dart to activate Opt3), kept
separate so the Opt2 facade namespace stays free of the low-level consensus types.
6/6 P5 tests: graph construction (locktime=state+1, v6 output, CSV settlement, 2 balances),
drop-in UpdateTxBuilder, build() emits real hex + a ctv_hash consistent with the derived
settlement, deterministic + balance-sensitive. Full SDK suite green; analyze clean.
⚠️ NOT YET NODE-VALIDATED: the composed primitives are node-pinned (P1–P4), but the tx-graph
assembly is validated on stagenet (P6), not against an offline vector. Do not broadcast builder
output to mainnet until P6 passes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ode-pin
Replaces the dead non-executing eltooUpdateScript (IF/CLTV/CHECKSIG inline-pubkey
spec-ref) with the B1 forms in keyhash.dart:
- eltooUpdateScriptV6 / ...FromKeyhashes: IF <N+1> CLTV DROP keyhash-2of2 /
ELSE <csv> CSV DROP keyhash-2of2 ENDIF (ratchet + settlement execute on V6)
- htlcScriptV6 / ...FromKeyhashes: IF SHA256 <H> EQUALVERIFY keyhash / ELSE
CLTV keyhash ENDIF
- dilithiumKeyhash2of2ScriptFromHashes (32-byte keyhash body, reused)
Rewires DilithiumEltooBuilder.buildUpdateTx to emit the B1 script; refreshes
docstrings (script executes/node-pinned; broadcast witness assembly = step 4).
New test/eltoo/b1_script_test.dart byte-matches the node b1_script_vectors.
Full eltoo suite 34/34, analyze clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…uts) Adds the v6 satisfaction-stack builders for spending the B1 outputs: - eltooUpdateBranchWitness (IF/supersession, truthy selector) - eltooSettlementBranchWitness (ELSE/close, empty selector) - htlcSuccessWitness (preimage + payee, truthy) / htlcTimeoutWitness (payer, empty) Each = [2-of-2 keyhash satisfaction, selector, witnessScript, 0x00||trailingPub] — the exact layout the node accepts (lightning_script_tests eltoo_v6_ratchet_target / htlc_v6_target). Structural test pins selector position/value, script, trailer. eltoo suite 35/35, analyze clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Dart Opt3 eLTOO crypto layer that swaps into the SoqLightning facade via the UpdateTxBuilder seam.
SCRIPT_VERIFY_V6_CONTROLFLOW(soqucoin#12) —eltooUpdateScriptV6/htlcScriptV6(IF/CLTV-ratchet + keyhash-2-of-2) replacing the dead non-executing spec-ref; B1 branch witness assemblers (update/settlement/HTLC success+timeout) matching the node-accepted satisfaction layouts.b1_script_test.dart↔ lightning_script_tests/b1_script_vectors). Eltoo suite 35/35, analyze clean.Pairs with soqucoin#12. Broadcast/stagenet e2e is the remaining (post-flag-activation) step.
🤖 Generated with Claude Code