Skip to content

Add splice cleanup invariants#4699

Open
joostjager wants to merge 2 commits into
lightningdevkit:mainfrom
joostjager:splice-assert
Open

Add splice cleanup invariants#4699
joostjager wants to merge 2 commits into
lightningdevkit:mainfrom
joostjager:splice-assert

Conversation

@joostjager

Copy link
Copy Markdown
Contributor

After tx_abort or SpliceNegotiationFailed, probe splice_channel to ensure stale queued or active negotiation state does not remain.

This lets the chanmon consistency harness catch recoverability gaps where an aborted or failed splice still blocks a fresh attempt.

@ldk-reviews-bot

ldk-reviews-bot commented Jun 16, 2026

Copy link
Copy Markdown

👋 Thanks for assigning @wpaulino as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@joostjager joostjager requested a review from wpaulino June 16, 2026 08:50
Comment thread fuzz/src/chanmon_consistency.rs Outdated
@ldk-claude-review-bot

ldk-claude-review-bot commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

No new issues found.

Both issues I raised in the prior pass are resolved by this revision:

  • fuzz/src/chanmon_consistency.rs:2226 (resolved) — the helper no longer .unwrap()s; it now matches Err(ChannelUnavailable) with "No such channel_id" / "No such peer" prefixes and returns, avoiding the spurious panic when the channel was already removed during close cleanup. I verified those prefixes match the actual APIError::no_such_peer / no_such_channel_for_peer messages, so the trailing Err(e) => panic! arm is unreachable for the only two errors splice_probe_state can produce.
  • fuzz/src/chanmon_consistency.rs:2921 (resolved) — the tx_abort branch now checks both "waiting to be negotiated" and "currently being negotiated", mirroring the failure branch.

Additional verification this pass:

  • ChannelManager::splice_channel / Channel::splice_channel are read-only probes (no persistence guard, as_funded()), safe to call in the harness.
  • quiescent_action (→ QueuedAction) can only originate from a real splice here — the fuzz target never calls maybe_propose_quiescence — so the invariant won't fire spuriously.

Standing cross-cutting notes (non-blocking, already raised previously, not re-posted): the err.contains(...) assertions are fragile coupling to human-readable error text and the splice_channel string probe is now largely redundant with assert_no_stale_splice_negotiation.

After tx_abort or SpliceNegotiationFailed, probe splice_channel
to ensure stale queued or active negotiation state does not remain.

This lets the chanmon consistency harness catch recoverability gaps
where an aborted or failed splice still blocks a fresh attempt.
@joostjager

Copy link
Copy Markdown
Contributor Author

Claude's cross-cutting notes might be worth addressing in a follow up #4699 (comment)

Comment thread fuzz/src/chanmon_consistency.rs Outdated
Expose a fuzz-only read-only splice state probe so chanmon
consistency can check cleanup paths that the public splice API does
not fully surface. Use it after tx_abort and splice failure events to
catch queued or active negotiation state on either side while allowing
already-negotiated pending splice state.

Treat missing peers or channels as clean probe results. Close-related
cleanup events may be handled after the channel has already been
removed.
let dest_idx = log_peer_message(node_idx, node_id, nodes, out, "tx_abort");
nodes[dest_idx].handle_tx_abort(source_node_id, msg);
if let Err(APIError::APIMisuseError { ref err }) =
nodes[dest_idx].node.splice_channel(&msg.channel_id, &source_node_id)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is a bit brittle at the moment because it's possible for a queued splice to exist prior to processing this event. It seems the new fuzz-only probe is all we need now if we extend assert_no_stale_splice_negotiation to also consider SpliceProbeState::QueuedAction.

@wpaulino

Copy link
Copy Markdown
Contributor

Can we make #4687 fit the use case here instead?

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.

4 participants