Skip to content

Drop QuiescentError::with_negotiation_failure_reason#4608

Open
jkczyz wants to merge 3 commits intolightningdevkit:mainfrom
jkczyz:2026-05-splice-rbf-fail-event-follow-ups
Open

Drop QuiescentError::with_negotiation_failure_reason#4608
jkczyz wants to merge 3 commits intolightningdevkit:mainfrom
jkczyz:2026-05-splice-rbf-fail-event-follow-ups

Conversation

@jkczyz
Copy link
Copy Markdown
Contributor

@jkczyz jkczyz commented May 8, 2026

Drops QuiescentError::with_negotiation_failure_reason as a follow-up to #4514. The placeholder Unknown reason it overrode was a footgun — sites that forgot to chain it could leak Unknown into Event::SpliceNegotiationFailed, and the pattern wired splice-specific reason vocabulary into the generic QuiescentAction machinery. Each error-return site in propose_quiescence now picks its reason at construction. funding_contributed's pending-quiescent-action check is also made exhaustive on QuiescentAction, so a future variant produces a compile error there.

Also includes two minor doc clarifications from the #4514 review: the relationship between Event::SpliceNegotiationFailed::contribution and Event::DiscardFunding, and the script_pubkey-only matching in FundingContribution::into_unique_contributions.

@ldk-reviews-bot
Copy link
Copy Markdown

ldk-reviews-bot commented May 8, 2026

👋 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.

@jkczyz jkczyz requested a review from TheBlueMatt May 8, 2026 17:09
@ldk-claude-review-bot
Copy link
Copy Markdown
Collaborator

ldk-claude-review-bot commented May 8, 2026

The debug_assert!(false, ...) pattern is widely used in this codebase (34 occurrences in channel.rs alone), so the new usage is consistent.

I've now re-reviewed every hunk in the diff:

  1. events/mod.rs: Documentation-only addition explaining the overlap between SpliceNegotiationFailed::contribution and DiscardFunding. Accurate.

  2. channel.rs (removal of with_negotiation_failure_reason and quiescent_action_into_error): Clean removal with functionality properly inlined at call sites.

  3. channel.rs (abandon_quiescent_action): Simplified to match QuiescentAction directly. Correct.

  4. channel.rs (funding_contributed): Now exhaustive on QuiescentAction. The unreachable!() for test-only DoNothing is appropriate since funding_contributed should never be called with that action.

  5. channel.rs (propose_quiescence): Two error paths inline QuiescentError construction with correct reasons. The debug_assert!(false) + Unknown fallback for the "already has pending action" path is consistent with codebase conventions.

  6. funding.rs: Documentation-only addition accurately describing into_unique_contributions behavior.

  7. splicing_tests.rs: Comment update from removed method name to current method name.

No issues found.

///
/// Outputs are compared by `script_pubkey` alone (not full `TxOut`), since values may
/// differ between rounds (e.g., a change output adjusted for a new feerate). As a
/// consequence, multiple contribution outputs sharing a `script_pubkey` are all
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.

Just noting that this won't be allowed anymore after #4575

Comment thread lightning/src/ln/channel.rs Outdated
// Only the test-only DoNothing action is expected here; production callers must
// short-circuit before reaching this branch.
#[cfg(any(test, fuzzing, feature = "_test_utils"))]
let is_allowed = matches!(action, QuiescentAction::DoNothing);
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.

Not a huge deal, but why does this need to be allowed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There are some tests calling maybe_propose_quiescence with it.

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.

Sorry I meant why do we need to allow another DoNothing after one is already pending? Removing this doesn't seem to cause any test failures, is it a fuzzing thing?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ah... I may have mistakenly thought quiescence_tests was checking this. But indeed that doesn't seem to be the case.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 8, 2026

Codecov Report

❌ Patch coverage is 66.66667% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.12%. Comparing base (75ac90a) to head (b2b0d43).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
lightning/src/ln/channel.rs 66.66% 10 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4608      +/-   ##
==========================================
- Coverage   86.12%   86.12%   -0.01%     
==========================================
  Files         157      157              
  Lines      108824   108822       -2     
  Branches   108824   108822       -2     
==========================================
- Hits        93727    93719       -8     
- Misses      12480    12486       +6     
  Partials     2617     2617              
Flag Coverage Δ
tests 86.12% <66.66%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

jkczyz and others added 3 commits May 8, 2026 14:12
QuiescentError::FailSplice was built with a placeholder
NegotiationFailureReason::Unknown and expected callers to chain a
with_negotiation_failure_reason builder. Sites that forgot the chain
leaked Unknown into Event::SpliceNegotiationFailed, and the pattern
forced splice-specific reason vocabulary into the generic
QuiescentAction helper.

Each call site in propose_quiescence now picks the reason at
construction. The pending-quiescent-action branch is unreachable, so
it asserts unconditionally; the match retains arms for both action
variants so release builds return a sensible error if the invariant
is violated. abandon_quiescent_action returns SpliceFundingFailed
directly without round-tripping through QuiescentError, since the
reason was always discarded there.

Make funding_contributed's pending-quiescent-action check exhaustive
on QuiescentAction. A future variant produces a compile error here
and at the matching arm in propose_quiescence, forcing the author to
decide how it interacts with funding contribution.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The contribution returned in Event::SpliceNegotiationFailed may include
inputs and outputs already committed to a prior negotiated (but not yet
locked) splice transaction. Those overlapping items are intentionally
omitted from the preceding Event::DiscardFunding to avoid prompting the
user to reclaim UTXOs that are still in use elsewhere. The relationship
was documented on the internal SpliceFundingFailed fields but lost when
they were made private; surface it on the public event field doc.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The function compares outputs by script_pubkey alone, not full TxOut,
so any contribution output sharing a script with an existing output is
filtered regardless of value. This is intentional — a change output's
value may shift between rounds (e.g., for a new feerate) and should
still match. But the consequence isn't obvious: multiple contribution
outputs sharing a script are all filtered together when any existing
output uses that script. Document it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jkczyz jkczyz force-pushed the 2026-05-splice-rbf-fail-event-follow-ups branch from b61f231 to b2b0d43 Compare May 8, 2026 19:13
@jkczyz jkczyz requested a review from wpaulino May 8, 2026 19:14
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