Skip to content

[WIP]: LSP support - #1623

Open
chenyukang wants to merge 117 commits into
nervosnetwork:developfrom
chenyukang:lsp-support
Open

chenyukang wants to merge 117 commits into
nervosnetwork:developfrom
chenyukang:lsp-support

Conversation

@chenyukang

@chenyukang chenyukang commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

To resolve #1571
Implementation of #1625

@chenyukang chenyukang changed the title [WI]: LSP support [WIP]: LSP support Aug 11, 2026
chenyukang and others added 26 commits August 30, 2026 00:24
# Conflicts:
#	crates/fiber-lib/src/fiber/network.rs
Read cold tenant signing status without activating its runtime and reject tenant-provided settlement secrets.

Resolve watchtower TLC signing keys from the verified TLC identity and original derivation index, reject missing or conflicting keys, and recover stale signing requests.

Consolidate signer regression tests and include the LSP SDK in WASM linting. Validated with 141 related nextest tests, make clippy, and cargo fmt.
…rt test suites

- Enforce strict signature invariant checks with assert_not_awaiting_signature
- Streamline handle_signer_notification with validate_and_apply_signer_notification
- Eliminate runtime continuation tail flags and replace ChannelSignerBuffers with PendingMessages
- Add duplicate CommitmentSigned idempotency handling by resending cached RevokeAndAck
- Replay cached AnnouncementSignatures when receiving peer signatures while already in ChannelReady
- Fix channel re-establishment and closing signature handling in ShuttingDown state
- Add comprehensive external signer restart test suites covering all 6 ChannelSigningTransitions for both Tenant and Signer restarts
…reuse

- Enforce next_material presence for state-advancing transitions in apply_next_signer_material
- Validate completeness of next_commitment_point, next_commitment_nonce, and next_revocation_nonce
- Guard against cross-purpose nonce collisions and cross-slot nonce reuse (fail-closed)
- Ensure transactional atomicity: only insert public material into core once all checks pass
- Add requires_next_signer_material to ChannelSignatureRequest
- Add comprehensive unit and integration tests covering missing/partial material, nonce collisions, and idempotency
…Ack signature

When awaiting an external signature for SendRevokeAndAck, remote_commitment_number is not yet incremented and last_revoke_ack_msg is not generated. If the remote peer restarts and sends ReestablishChannel during this window, processing it prematurely leads to misaligned commitment numbers, corrupted MuSig2 nonces, or unexpected RevokeAndAck errors triggering a force close.

- Prioritize is_awaiting_signature in handle_peer_message, queuing incoming ReestablishChannel and deferring outgoing reestablish
- Send deferred ReestablishChannel in handle_signer_notification after external signature completion before draining queued messages
- Add assertion in handle_reestablish_channel_message preventing execution while awaiting signature
- Add reproduction and edge-case regression tests in channel.rs
…ate replayed TLCs

When a peer disconnects or restarts while an external signature is awaiting completion:
- Purge stale pending peer messages in mark_reestablishing_offline, mark_watching_chain_offline, and on_peer_reconnected to prevent old session messages from polluting the new connection
- Unify pending_reestablish_send and pending message purging into on_peer_reconnected as the single source of truth for reconnection state transitions
- Handle AddTlc and RemoveTlc idempotently to accommodate peer replay during channel reestablishment (resend_tlcs_on_reestablish) without failing on expected next TLC ID checks
- Add reproduction and regression tests verifying pending message purging and duplicate TLC handling across peer restarts
… raw wire messages while reestablishing

- In RestoreOfflineChannel, defer sending ReestablishChannel and set pending_reestablish_send when channel.signing_context.is_awaiting_signature() is true.
- In finish_send_revoke_and_ack and finish_send_commitment_signed, suppress raw wire message sending while reestablishing == true so messages are not dropped by reestablishing peers.
- In handle_signer_notification, ensure send_reestablish_message is only triggered when peer is not Offline, allowing on_peer_reconnected to cleanly drive reestablishment when connection is ready.
- Add tests for cold tenant restart while awaiting SendRevokeAndAck and SendCommitmentSigned.
…ure requests

Replace the single-slot WatchtowerExternalState with multi-request
pending_requests and signed_signatures maps to prevent concurrent TLC
settlement signature requests from overwriting one another.

Maintain the unified WatchtowerSigner and WatchtowerSignerState
abstractions across the watchtower actor, RPC handler, and store
interfaces, with verified TDD reproduction test coverage.
Preserve hosted FiberActor routing and external signing while integrating shutdown settlement recovery. Resolve tenant watch snapshots from the host store and adapt reconciliation fixtures with signer and namespace regression coverage.
Derive local commitment points and public nonces on demand instead of publishing and persisting every signing round. Drop legacy local caches on restore while preserving pending requests and idempotency receipts. Keep external signer validation and material history unchanged.

Cover bounded local material state, restart with legacy caches, pending signature and receipt restoration, and unchanged external material requirements.
Problem:
a7a4307 made a ChannelReady public channel reply to every received
AnnouncementSignatures with its own cached signatures. Reestablishment
already proactively replays those signatures, so two ready peers keep
replying to one another. Each duplicate also rebuilds/broadcasts the
channel announcement and update. The resulting ingress flood trips peer
admission limits and disconnects an otherwise recovered session, making
legacy recovery, repeated restarts, MPP retries and list_peers tests fail.

Fix:
Treat AnnouncementSignatures as an idempotent no-op once a public channel
is ChannelReady, before mutating announcement state or broadcasting gossip.
Keep the public-channel check and the AwaitingChannelReady path, as well
as proactive cached-signature replay during funding/reestablishment. This
still lets a ready peer recover the other side's missing announcement,
without responding to that peer's replay indefinitely. No wire-format,
persisted-schema or admission-limit changes are needed.

Regression coverage:
- Replay signatures repeatedly into a ready public channel and assert no
  outgoing messages, no gossip broadcasts and no persisted-state changes.
- Reestablish asymmetric Ready/AwaitingChannelReady peers after a lost
  announcement; check cached replay restores readiness and then stops.
- Strengthen external announcement-signing restart coverage to check both
  peers recover and the exact cached remote signature is restored.

Both new regression tests fail on the unmodified implementation. The
focused 40-test run, including all five previously failing tests, passes
with this fix.

Validation:
- make test: default storage 1552 passed / 9 skipped; SQLite 1550 passed /
  9 skipped; fiber-types 27 passed.
- make clippy: all features/targets, SQLite, fiber-types and wasm32 pass.
- cargo fmt --all -- --check, changed-file typos and git diff --check pass.
The public-channel restart fixture checked get_channel_signing_status for
SignChannelAnnouncement, then called try_sign_pending, which queried the
status a second time. If the first response was NoSignatureRequired and
the announcement request arrived before the second query, the helper
signed the very request the test meant to leave pending. The channel
became ready, so setup waited for a consumed checkpoint until its 30s
timeout. CI run 35158563757 shows this exact sequence.

Pass the already-observed ChannelSigningStatus into the signing helper.
The public setup now checks and acts on one snapshot; the unconstrained
recovery/private-channel callers still query once before signing. Do not
change production code, RPCs, timeout budgets or retry counts.

Add a deterministic regression that presents a stale idle snapshot while
a real announcement signature is pending. Assert that the signer store,
complete signing request and absent local announcement signature remain
unchanged, then explicitly sign the observed request and recover both
peers. The regression fails with the old re-query behavior.

Validation with CI trace logging and RUST_TEST_THREADS=2:
- All 19 external signer restart tests pass with default storage and
  SQLite.
- Repeat the signer restart, tenant restart and new announcement snapshot
  tests 20 times each: all 60 executions pass without timeout.
- Nextest reports intermittent non-failing leaky-test warnings in default
  storage runs; SQLite reports none. These warnings are not suppressed.
- make clippy passes, including SQLite and wasm32; fmt, changed-file typos
  and git diff --check also pass.
@chenyukang
chenyukang marked this pull request as ready for review September 17, 2026 02:13
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.

Running fiber on Android mobile: 24/7 availability and watchtower delegation

3 participants