Skip to content

RSI Support - #181

Merged
martindale merged 63 commits into
masterfrom
feature/rsi
Aug 6, 2026
Merged

RSI Support#181
martindale merged 63 commits into
masterfrom
feature/rsi

Conversation

@martindale

@martindale martindale commented Jun 25, 2026

Copy link
Copy Markdown
Member

Initial sketch of support for RSI through @GoonCitizen.

Summary by CodeRabbit

  • New Features

    • Added Core Lightning JSON-RPC and BOLT12 offer, invoice, payment, and routing support.
    • Added document publishing, blob transfers, sealed content, offer ranking, payments, refunds, and relay workflows.
    • Added contract, sidechain, Beacon federation, and program execution capabilities.
    • Added first-class chat, contract, gossip, and peer message handling.
    • Added multi-seed wallet support and Bitcoin transaction monitoring.
  • Documentation

    • Expanded API, installation, quick-start, Lightning, contracts, sidechain, and simulator documentation.
  • Tests

    • Added broad coverage for document exchange, Lightning, networking, wallets, sidechains, Beacon, and simulator scenarios.

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds native Noise framing and cryptographic primitives, expands Lightning and message APIs, introduces document exchange with sealed content and HTLC settlement, adds federated sidechain and consensus workflows, updates wallet and CLI behavior, and provides a seeded network simulator with Beacon audit reporting.

Changes

Native transport and cryptography

Layer / File(s) Summary
Crypto primitives and Noise transport
src/*, binding.gyp
Adds secure memory, randomness, SHA-2/HMAC/PBKDF2, Noise framing, handshake helpers, and peer send/receive integration.
Lightning RPC and payment helpers
services/lightning.js, functions/lightningBolt12.js, functions/fabricPaymentBech32.js, functions/bolt12Semantics.js
Adds Core Lightning RPC wrappers, BOLT12 classifiers and semantics, Fabric payment encoding, static exports, documentation, and tests.

Protocol and state

Layer / File(s) Summary
Message schemas and routing
constants.js, types/message.js, functions/messageBodyCodec.js, functions/applicationNamespaces.js
Adds first-class chat and peer opcodes, canonical aliases, typed message bodies, and application namespace catalogs.
Consensus and sidechains
types/block.js, types/chain.js, types/beacon.js, functions/sidechainState.js, functions/contractStatechains.js
Adds PoW, federation, and gossip handling; Beacon epoch signing; sidechain persistence, snapshots, journals, and contract namespace sealing.
Wallet and runtime behavior
types/wallet.js, types/environment.js, types/program.js, types/machine.js, types/store.js
Adds multi-seed wallet watching, Bitcoin transaction ingestion, program execution, environment handling, storage hydration, and stricter error propagation.

Document exchange and simulator

Layer / File(s) Summary
Document exchange and CLI
functions/document*, types/peer.js, types/cli.js, functions/cliContracts.js
Adds blob manifests, sealed AES-GCM delivery, offer ranking, relay budgets, Taproot HTLC settlement, catalog inventory, contract-driven CLI commands, purchase sessions, and refunds.
Simulator and audit tooling
tests/simulator/*
Adds seeded network topologies, weighted actions, document-market scenarios, Beacon registry campaigns, audit reports, and smoke coverage.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant Peer
  participant OfferBook
  participant HTLC
  participant Wallet
  CLI->>Peer: requestPeerInventory(kind: documents)
  Peer-->>CLI: inventory response with document offers
  CLI->>OfferBook: ingestInventoryResponse(items)
  OfferBook-->>CLI: ranked offer
  CLI->>HTLC: buildDocumentOfferEscrow(...)
  HTLC-->>CLI: payment address and refund metadata
  Wallet->>Peer: ingest Bitcoin funding or claim transaction
  Peer-->>CLI: ciphertext, key reveal, or settlement event
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the pull request's stated objective of adding RSI support.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/rsi

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codacy-production

codacy-production Bot commented Jun 25, 2026

Copy link
Copy Markdown

Not up to standards ⛔

🔴 Issues 1 high

Alerts:
⚠ 1 issue (≤ 0 issues of at least minor severity)

Results:
1 new issue

Category Results
ErrorProne 1 high

View in Codacy

🟢 Metrics 3354 complexity · 51 duplication

Metric Results
Complexity 3354
Duplication 51

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Security review (synchronize)

Outcome: request changes — 2 High mesh availability findings remain (PoC-confirmed on HEAD 93c78c13).

Current findings

  1. High — P2P_RELAY bit-identical flood vs signer pin — Outers are forwarded unchanged, but P2P_RELAY is omitted from RELAY_AS_IS_*, so the next hop treats the attacker author as a pin mismatch against the honest forwarder and hard-disconnects/bans them (mesh partition).
  2. High — Onion peel misattributes hard misbehavior to the last hop — Still open: peeled inners are handled with TCP origin = last hop; pin/signature/body-hash failures call _applyPeerMisbehavior(..., disconnect: true) and ban the honest relay.

Prior findings validated fixed (not re-reported)

  • Sealed unlock / public payment-hash-as-proof (settlementVerified; autoFulfillDocumentRequests default false)
  • Buyer funding attacker paymentAddress / HTLC offer validation
  • Noise indefinite recv stall + clearing O_NONBLOCK before frame read
  • CWD .FABRIC_SEED injection (allowCwdSeed opt-in)
  • Contract republish allow-list expansion

No Slack destination is configured for this automation; summary is in this review only.

Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

Comment thread types/peer.js Outdated
Comment thread types/peer.js Outdated
Comment thread types/peer.js Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Security review (synchronize @ 1e4d9ffce)

Outcome: request changes — 3 High mesh-availability findings remain (PoC-confirmed).

Current findings

  1. High — P2P_RELAY omitted from RELAY_AS_IS_* — Bit-identical flood of attacker-signed outers fails the next hop’s signer-pin check against the honest forwarder → hard disconnect/ban (mesh partition).
  2. High — peeled SESSION_* still hard-disconnects the last hop813133b69 fixed AMP body-hash/signature/pin/contract-ops attribution via peeledForward, but _punishPeerForSessionKeyViolation still bans the TCP last hop for a laundered bad P2P_SESSION_OPEN/OFFER.
  3. High — peeled relay-nest-exceeded still hard-disconnects the last hop — Nested P2P_RELAY delivered via onion peel still calls _applyPeerMisbehavior(originName, …, disconnect: true) on the honest relay.

Prior findings re-validated (no longer open)

Issue Status
Sealed key unlock via public paymentHash echo Fixed (settlementVerified / authorizeDocumentKeyReveal)
Buyer funding seller-supplied HTLC address Fixed (buyer-bound rebuild)
Native Noise blocking recv DoS Fixed (select + timeout)
CWD .FABRIC_SEED outranking wallet Fixed (allowCwdSeed opt-in)
Contract allow-list republish bypass Fixed (republish ignored)
Onion peel AMP integrity → last-hop disconnect Partially fixed — residuals above

No Slack destination is configured for this automation run; findings are posted only on this PR.

Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

Comment thread types/peer.js Outdated
Comment thread types/peer.js Outdated
Comment thread types/peer.js Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Security review (PR #181)

Request changes — 1 High, 1 Medium remain on onion peel trust boundaries. Prior mesh-partition / peel-disconnect findings are fixed on this tip (P2P_RELAY in RELAY_AS_IS; session-key and nest-cap disconnects gated by peeledForward).

Current findings

  1. High — Valid peeled P2P_SESSION_OFFER / P2P_SESSION_OPEN still rebinds peers / _addressToId for the TCP last hop to the attacker’s key, so the next honest frame from that relay fails signer-pin and is hard-disconnected/banned.
  2. Medium — Peeled P2P_CHAT_MESSAGE and P2P_PEERING_OFFER still apply mesh relay / candidate enqueue under last-hop attribution, so an originator can burn an honest neighbor’s budgets and inject dial targets via onion.

Cleared since last automation pass

  • P2P_RELAY mesh partition (missing RELAY_AS_IS)
  • Peeled session-key / relay-nest-exceeded hard-disconnect of last hop
  • Sealed-document free unlock, buyer HTLC address trust, Noise indefinite recv, CWD seed precedence (not re-opened; still look fixed on HEAD)
Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

Comment thread types/peer.js
Comment thread types/peer.js Outdated
Comment thread types/peer.js

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Security review (synchronize)

Re-validated prior automation findings against 14823568c. The recent onion/relay hardening addresses the earlier high-confidence issues (session rebind on peel, chat/peering mesh side-effects, P2P_RELAY pin ban, payment-hash unlock, CWD seed precedence, Noise stall DoS).

Remaining medium findings: 2 (inline). Same peel-laundering class as the fixed peering/chat paths — P2P_PEER_ALIAS and P2P_PEER_GOSSIP still apply last-hop side-effects.

Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

Comment thread types/peer.js Outdated
Comment thread types/peer.js

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Security review (current)

Prior open findings (P2P_PEER_ALIAS last-hop rebind; peeled P2P_PEER_GOSSIP budget/relay) are addressed in cc253628e / related peel hardening.

Also re-validated as mitigated: sealed-key reveal without settlement, inventory HTLC address spoof, Noise stall DoS, CWD seed precedence, contract allow-list republish, session rebind via peel.

Remaining: 2 medium peel side-effect findings (inline). Onion delivery still attributes some costs/penalties/mesh actions to the honest TCP last hop.

Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

Comment thread types/peer.js Outdated
Comment thread types/peer.js

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Security review (HEAD 4ebeffede)

Prior critical/high items (sealed key unlock without payment, Noise stall DoS, buyer HTLC address trust, CWD seed injection, contract allow-list republish, session/pin hard-disconnect via peel) look fixed on this tip.

Still open: three peel attribution gaps where P2P_FORWARD delivery still treats the honest last hop as the responsible TCP peer for budget, scoring, or dial side-effects.

Severity Issue
High Peeled CONTRACT_PUBLISH hijack penalties apply to the last hop (unbounded −40)
Medium Peeled inners still debit the last hop’s wire-traffic budget
Medium Peeled P2P_PEER_ANNOUNCE still enqueues dial candidates

No critical findings on this pass.

Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

Comment thread types/peer.js Outdated
Comment thread types/peer.js
Comment thread types/peer.js

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Security review (synchronize)

Re-validated prior automation findings against bc5b125. Previously reported critical/high issues (sealed key reveal via public hash echo, buyer HTLC address trust, C Noise stall DoS, contract allow-list bypass, CWD seed precedence, and most onion peel last-hop attribution bugs) appear mitigated in the current tip.

Remaining high-confidence finding: 1 medium (onion peel still debits the TCP last hop’s inbound wire-traffic budget / derank).

No other medium-or-higher issues confirmed in this pass.

Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

Comment thread types/peer.js

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Security review (HEAD 355bec8b9)

Revalidated prior automation findings. Previously reported critical/high issues (sealed key reveal via hash echo, buyer funding of seller-supplied addresses, CWD seed injection, blocking Noise recv DoS, contract republish allow-list bypass, peel hard-disconnect / session rebind / gossip-peering-alias mesh side-effects) appear mitigated on current HEAD.

3 medium findings remain, all onion/P2P_FORWARD peel attribution gaps that can still punish or side-effect the honest last hop. Inline comments below.

No new high/critical issues identified in this pass.

Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

Comment thread types/peer.js
Comment thread types/peer.js
Comment thread types/peer.js Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Security review (current HEAD)

Prior peel-attribution findings (wire-traffic re-debit, CONTRACT_PUBLISH hijack scoring, P2P_PEER_ANNOUNCE dial enqueue) are fixed in this tip (suppressTcpOriginPunish / punishOrigin / local-only announce) and were resolved.

Still open: peel / skipRelayFlood inners of some mesh-gossip types still call relayFrom under the TCP last hop, inconsistent with CONTRACT_PUBLISH / chat / gossip and with SECURITY.md (“only the outermost envelope is mesh-flooded”).

Findings

  1. High — peeled / relay-unwrapped CONTRACT_MESSAGE still mesh-relays
  2. Medium — same for CONTRACT_PROPOSAL
  3. Medium — same for BitcoinBlock

No Slack destination is configured for this automation; assessment is on the PR only.

Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

Comment thread types/peer.js Outdated
Comment thread types/peer.js Outdated
Comment thread types/peer.js Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Security review (HEAD 65eca838e)

Prior peel / skipRelayFlood findings for CONTRACT_MESSAGE, CONTRACT_PROPOSAL, and BitcoinBlock are fixed (and covered by tests/peer.onion.forward.js). Re-validated as still mitigated: sealed-key hash-echo unlock, buyer HTLC address trust, C Noise stall DoS, CWD .FABRIC_SEED injection, contract allow-list / session rebind hard-disconnect via peel.

Still open: DocumentRequest handling never receives peel / skipRelayFlood / relayedAsIs opts, so it still violates outermost-only flood and can misdeliver content to the TCP last hop.

Findings

  1. High — peeled DocumentRequest fulfills (or queues for fulfill) to the TCP last hop
  2. Medium — peeled / P2P_RELAY-unwrapped DocumentRequest still mesh-relays when the document is not held

No Slack destination is configured for this automation; assessment is on the PR only.

Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

Comment thread types/peer.js
Comment thread types/peer.js

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Security review of 77c06e34 (vs 8d4426be).

Prior automation findings revalidated as fixed: sealed key reveal no longer treats public paymentHashHex as settlement proof; buyer HTLC rebuild/validate rejects seller-supplied addresses; Noise frame I/O uses timeouts and keeps O_NONBLOCK; onion peel / foreign P2P_RELAY local-observe (meshDeliveryContext) no longer hard-disconnects or debit-budgets the last hop; CWD .FABRIC_SEED is opt-in; republish no longer expands the contract patch allow-list.

Open finding: 1 High — first-wire CONTRACT_PUBLISH still grants patch rights to the AMP signer, so a content-identical front-run elevates an attacker into _contractPatchAllowList and allows unauthorized CONTRACT_MESSAGE ops. PoC-confirmed on this tip.

No other medium+ issues with a clear remote attack path remained after validation.

Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

Comment thread types/peer.js Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Security review (HEAD b373f998)

Outcome: 1 High finding remains.

Prior automation findings were re-validated against current HEAD and are addressed (sealed unlock requires settlementVerified, HTLC buy rebuilds/validates P2TR, Noise I/O has timeouts, CWD seed is opt-in, peel/RELAY local-observe gates, contract publish front-run authz).

Current finding

  1. High — Junk DocumentContentKeyReveal burns cooperative key delivery (first-writer-wins on public paymentHashHex before open succeeds).

No other medium+ issues with a confirmed attacker→sink path were left after validation.

Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

Comment thread types/peer.js Outdated
if (!docId) return null;
const pay = obj.paymentHashHex != null ? String(obj.paymentHashHex).toLowerCase() : '';
const key = obj.keyHex != null ? String(obj.keyHex).toLowerCase() : '';
return `keyreveal:${docId}:${pay || key}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High — logical key uses public payment hash, enabling reveal slot theft.

paymentHashHex is advertised in sealed inventory (SHA256(K)). Dedup prefers that public value over keyHex, so any peer can claim keyreveal:<docId>:<pay> with a random non-matching keyHex.

Impact: first junk frame permanently occupies the slot (cache up to 10k); the seller’s real reveal is dropped as a duplicate. Claim only after successful open, or bind the key to verified seller identity / key material that proves hash preimage.

Comment thread types/peer.js Outdated
Comment on lines +2849 to +2850
const claimReveal = this._claimLogicalRegistrationOrPunish(
'DocumentContentKeyReveal', reveal, signerPubkeyHex, punishOrigin);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High — claim-before-open DoS on paid sealed delivery.

Logical registration runs before openSealedDelivery / seller binding. A Noise-authenticated peer (or onion path) can send a signed junk DocumentContentKeyReveal with public documentId + paymentHashHex and a wrong keyHex; open fails but the claim sticks, and later valid reveals are ignored.

On private-relay routes, the reverse-forward below also relays that junk before validation. Buyer is stuck until HTLC timeout/claim-preimage fallback.

Fix: claim only after successful open (or unclaim on failure); reject/forward only when paymentHashHexFromKey(keyHex) matches.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security review (synchronize @ 4d35921)

Prior automation findings re-validated on HEAD — all fixed: CWD .FABRIC_SEED opt-in (allowCwdSeed), contract/chat bit-identical relay + wire-hash dedup, sealed unlock requiring settlementVerified, buyer HTLC rebuild/validateInventoryHtlcOffer, DocumentContentKeyReveal well-formedness + post-open claim, and clearing of indefinite blocking recv.

Open finding: 1 High — Noise framed I/O uses a per-select 30s budget with no overall handshake/frame deadline, so a slowloris peer can hold connections_rwlock across accept/handshake (and block writers during established reads) for hours by dripping bytes. Details in inline comments.

No other medium+ issues confirmed in the latest delta.

Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

Comment thread src/noise.c
Comment on lines +59 to +80
/* Blocking read of exactly n bytes (fails closed on timeout / stall). */
static ssize_t noise_read_all(int fd, uint8_t *p, size_t n)
{
size_t off = 0;
while (off < n)
{
int ready = noise_wait_fd(fd, 0, FABRIC_NOISE_IO_TIMEOUT_MS);
if (ready == 0)
{
errno = ETIMEDOUT;
return -1;
}
if (ready < 0)
return -1;
ssize_t r = recv(fd, p + off, n - off, 0);
if (r < 0 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
continue;
if (r <= 0)
return r;
off += (size_t)r;
}
return (ssize_t)off;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High — unauthenticated slowloris DoS via per-wait I/O timeout.

noise_read_all resets a 30s select() budget on every partial recv. Combined with fabric_noise_read_frame accepting attacker-chosen lengths up to the out-cap (4096 during handshake; up to FABRIC_NOISE_MAX_FRAME_BYTES on established reads), a peer can advertise a large L and drip 1 byte every ~29s so one frame occupies the caller for hours. There is no overall handshake/frame deadline.

Impact: Accept path calls this while holding connections_rwlock for writing (src/peer.c ~1770), so one TCP client can block accepts/disconnects/connects for extended periods. Add a monotonic overall I/O budget (and/or release the wrlock around handshake).

Comment thread src/peer.c
// Perform handshake as responder (accepted socket already non-blocking)
memcpy(conn->remote_pubkey, remote_pubkey + (33 - 32), 32);
if (noise_perform_xx_handshake(client_sock, 0, peer->app_protocol, peer->private_key, conn->remote_pubkey, &conn->send_cipher, &conn->recv_cipher) != 0)
if (noise_perform_xx_handshake(client_sock, 0, peer->app_protocol, NULL, conn->remote_pubkey, &conn->send_cipher, &conn->recv_cipher) != 0)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High — exclusive connection lock held across Noise handshake I/O.

After pubkey exchange, noise_perform_xx_handshake() runs under connections_rwlock (wrlock acquired earlier in this accept path). Because handshake frame reads use the per-select timeout in src/noise.c (no overall deadline), a slowloris client that starts the responder READ_MESSAGE phase can pin this write lock far beyond 30s and stall all connection-table mutations.

Impact: Unauthenticated remote availability loss for native fabricd peering. Perform the handshake off the wrlock (slot reserved / state machine), or enforce a hard total handshake time budget before unlock.

@martindale martindale changed the title WIP: RSI Support RSI Support Aug 6, 2026
@martindale
martindale merged commit 214909a into master Aug 6, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant