feat(lightning): fund-safety hardening and protocol completion#92
Closed
coreyphillips wants to merge 6 commits into
Closed
feat(lightning): fund-safety hardening and protocol completion#92coreyphillips wants to merge 6 commits into
coreyphillips wants to merge 6 commits into
Conversation
Implement a full Lightning node on top of beignet's on-chain wallet: Noise transport, channel state machine, on-chain monitoring, gossip and routing, invoices, and onion payments, plus a CLI/HTTP daemon and AI-agent tooling. Protocol coverage: - BOLT 1/8: Noise transport, init, peer management - BOLT 2: channel open/close, HTLC lifecycle, channel reestablish - BOLT 3: key derivation, commitment & HTLC txs, anchor outputs - BOLT 4: Sphinx onion, payment forwarding, failure handling - BOLT 5: force-close, output resolution, sweeps, penalty txs - BOLT 7: gossip sync, network graph, pathfinding, mission control - BOLT 11: invoice encode/decode/sign - Extensions: dual funding (v2), splicing, zero-conf, keysend, quiescence, SCID aliases, rapid gossip sync Anchor channels are the default channel type, made force-close-safe by wallet-funded fee bumping: zero-fee second-level HTLC txs get a wallet fee input attached, and commitments are CPFP-bumped via the local anchor output. Both paths validated end-to-end against LND on regtest. Adds a CLI/HTTP daemon (OpenAPI spec, webhooks, payment queue, rate limiting) and AI-agent ergonomics (liquidity/fee advisors, structured logs, mainnet-readiness checks). Tested: 2,740 lightning + 720 CLI unit tests, plus interop suites against LND, CLN, and Eclair.
… test coverage Startup reliability (mainnet): - electrum: de-dupe concurrent connectToElectrum() calls via a shared in-flight promise, so racing startup connects no longer clobber rn-electrum-client's shared global socket and emit a spurious "Unable to connect to Electrum server." - electrum-backend: listUnspent() fails fast when disconnected instead of probing a not-yet-open socket (which logged a raw "Connection to server lost" stack trace from the client library). - beignet-node: defer fallback-fund recovery until Electrum is actually connected; clean the wait timer up on shutdown. - lightning-node: emit node:ready as soon as a channel reaches NORMAL, so waitForReady() no longer spuriously times out when a single stored peer is offline/slow to reconnect. Test coverage: - BOLT 3/4/8/11 conformance vectors and tests under tests/lightning/conformance. - HTLC-claim crypto tests and a mempool interop test for on-chain claims. - chain-resolver, htlc-safety and socks5 test additions. Accompanying channel/commitment/onion/serialization hardening across the chain, channel and transport modules.
BOLT 7 requires channel_update and node_announcement timestamps to be greater than zero but does not specify handling for violations. Reject zero-timestamp messages in decodeChannelUpdateMessage and decodeNodeAnnouncementMessage so they never reach the network graph, matching the parse-time fix LND shipped in v0.20.1-beta for the zero-timestamp gossip DoS class. Also wrap the channel_announcement/node_announcement/channel_update gossip handlers in try/catch so a malformed or rejected message is dropped silently instead of propagating up through the peer message dispatcher (which is not itself guarded). Adds regression tests for both decoders. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Apply eslint --fix to resolve the 45 pre-existing prettier/prettier errors flagged by the PR lint check. Formatting-only changes; no logic affected. `lint:check` now exits clean (0 errors, warnings only). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adversarial fund-safety fixes (loss-of-funds hardening against an untrusted peer and an on-chain adversary), each with regression tests: - Classify a revoked commitment that shares our local commitment index as a breach via script-based ownership disambiguation, so it is penalized instead of being mistaken for our own commitment and left unpunished. - Claim a received HTLC on-chain when the preimage is learned after the peer force-closes with their current commitment, preventing loss of a forwarded HTLC to the peer's timeout path. - Persist isLessor/leaseExpiry so a lessor's lease-locked commitment rebuilds byte-identically after a restart and stays broadcastable (with a serialize, restore, rebuild byte-parity invariant test). - Resolve a live, urgency-bumped force-close feerate from the fee estimator at every force-close entry point instead of a hardcoded rate. - Re-fee-bump stuck anchor second-level HTLC transactions so a post-broadcast fee spike cannot strand the HTLC race. - Reject a liquidity-ads lease unless the seller funds at least the requested amount. - Recover from reorgs: retain output watches after a spend and re-broadcast our penalty or HTLC-success if a reorg evicts it. - Enforce low-S (BIP146) on the remote commitment and HTLC signatures we place in transactions we broadcast. - Reject the invalid script-enforced-lease plus simple-taproot channel-type combination at negotiation (they are mutually exclusive commitment types). Also lands the accumulated Lightning feature work on this branch: simple taproot channels (BOLT 3/5 scripts and MuSig2 co-signing), hold invoices and async payments, dual funding with liquidity ads (bLIP-0051), BOLT 12 offers, and route blinding, with substantially expanded test coverage. Verification: full non-interop lightning suite 2916 passing, BOLT conformance 42 passing, tsc clean.
The initial anchor commitment CPFP was one-shot, so a fee spike after the force-close broadcast could pin the commitment and block every second-level HTLC claim (each spends a commitment output). ChannelManager now retains each anchor force-close CPFP and the node re-issues it at the current live feerate every few blocks, while the commitment is still unconfirmed, until it confirms. Full non-interop lightning suite 2919 passing, BOLT conformance 42 passing, tsc clean.
Collaborator
Author
|
Closing: this should target the coreyphillips/beignet fork, not the upstream. Re-opening there. |
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.
Summary
This branch adds a from-scratch, BOLT-compliant Lightning Network implementation under
src/lightning/, and this update lands a round of adversarial fund-safety hardening on top of the accumulated feature work.Fund-safety fixes
Each is a loss-of-funds hardening against an untrusted peer and an on-chain adversary, and ships with a regression test:
to_localscripts, so the breach is routed to the penalty path.isLessor/leaseExpiryare now serialized, so a lessor's lease-locked commitment rebuilds byte-identically after a restart and its cached remote signature stays valid. Covered by a serialize/restore/rebuild byte-parity invariant test.Two additional audited surfaces (cooperative-close output validation and inbound
update_feebounds) were reviewed and found already safe; no changes were required there.Feature scope on this branch
Simple taproot channels (BOLT 3/5 scripts plus MuSig2 co-signing), hold invoices and async payments, dual funding with liquidity ads (bLIP-0051), BOLT 12 offers, and route blinding.
Testing
tsc --noEmit: clean.