Wipe splice state upon failed interactive funding construction - #4120

Merged
jkczyz merged 1 commit into
lightningdevkit:mainfrom
wpaulino:reset-splice-state
Oct 1, 2025
Merged

Wipe splice state upon failed interactive funding construction#4120
jkczyz merged 1 commit into
lightningdevkit:mainfrom
wpaulino:reset-splice-state

Conversation

@wpaulino

Copy link
Copy Markdown
Contributor

An interactive funding construction can be considered failed upon a disconnect or a tx_abort message. So far, we've consumed the InteractiveTxConstructor in the latter case, but not the former. Additionally, we may have splice-specific state that needs to be consumed as well to allow us to negotiate another splice later on.

This commit ensures that we properly consume all splice and interactive funding state whenever possible upon a disconnect or tx_abort.

The interactive funding state is safe to consume as long as we have either yet to reach AwaitingSignatures, or we have but tx_signatures has not been sent/received.

The splice state is safe to consume as long as we don't have a pending FundingNegotiation::AwaitingSignatures with a tx_signatures sent/received and we don't have any negotiated candidates. Note that until splice RBF is supported, it is not currently possible to have any negotiated candidates with a pending interactive funding transaction.

@wpaulinowpaulino added this to the 0.2 milestone Sep 24, 2025
@wpaulinowpaulino self-assigned this Sep 24, 2025
@ldk-reviews-bot

ldk-reviews-bot commented Sep 24, 2025

Copy link
Copy Markdown

👋 Thanks for assigning @TheBlueMatt 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.

@codecov

codecovBot commented Sep 24, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.14815% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.68%. Comparing base (3e21ba3) to head (6d2b110).
⚠️ Report is 82 commits behind head on main.

Files with missing linesPatch %Lines
lightning/src/ln/channel.rs60.00%30 Missing and 2 partials ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #4120 +/- ##
==========================================
- Coverage 88.72% 88.68% -0.04% 
==========================================
Files 177 180 +3 Lines 133404 135148 +1744 Branches 133404 135148 +1744 ==========================================
+ Hits 118365 119860 +1495 - Misses 12325 12523 +198 - Partials 2714 2765 +51 
FlagCoverage Δ
fuzzing21.79% <33.75%> (+0.05%)⬆️
tests88.52% <88.14%> (-0.04%)⬇️

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.

Comment threadlightning/src/ln/channel.rs Outdated
Comment on lines +6766 to +6767
signing_session.holder_tx_signatures().is_some()
|| signing_session.has_received_tx_signatures()

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.

Does it matter if we received their signatures if we haven't sent ours? Or is it because if they sent theirs then they would not have reset their state?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

You're supposed to remember the channel as soon as one side has sent tx_signatures, because you can't be sure the other side didn't just sign and broadcast without sending their own.

Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
@ldk-reviews-bot

Copy link
Copy Markdown

👋 The first review has been submitted!

Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer.

Comment threadlightning/src/ln/channel.rs Outdated
.pending_splice
.as_mut()
.and_then(|pending_splice| pending_splice.funding_negotiation.take());
if funded_channel.should_reset_pending_splice_funding_negotiation() {

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.

Looks like we aren't calling fail_interactive_tx_negotiation when failing to handle a splice_ack. #4077 updates fail_interactive_tx_negotiation to take a NegotiationError, which it uses to construct a SpliceFundingFailed struct.

For FundingNegotiation::ConstructingTransaction, the NegotiationError is formed by copying the inputs from the InteractiveTxConstructor. For FundingNegotiation::AwaitingAck when handling splice_ack, we'd need to do something similar?

Either way we are cloning the inputs just to later take the FundingNegotiation here. Maybe that is ok for now? Any thoughts on a better way of doing this?

@jkczyzjkczyzSep 25, 2025

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.

Hmmm... so we are also already take'ing the FundingNegotiation in one place in splice_ack handling (when FundingNegotiation::into_interactive_tx_constructor fails), but not earlier when validating the splice_ack message.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

We shouldn't need to call fail_interactive_tx_negotiation whenever we fail handling a message by sending a warning and disconnecting.

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.

Ah, so failing to process a splice_ack would just disconnect, and the peer could re-send it after reconnecting. Do we eventually timeout quiescence somewhere?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Quiescence is also implicitly terminated upon disconnection, but we do have a timeout enforced at should_disconnect_peer_awaiting_response.

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.

Oh, so we'd need to produce a SpliceFailed event in some other way? I'm thinking when we are in FundingNegotiation::AwaitingAck and fail processing the splice_ack.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah sounds like that logic might need to live in the disconnection handler, since we'll need to emit an event anyway if a peer disconnects mid-splice negotiation for whatever reason.

Comment threadlightning/src/ln/channel.rs Outdated
jkczyz
jkczyz previously approved these changes Sep 26, 2025
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
TheBlueMatt
TheBlueMatt previously approved these changes Sep 26, 2025
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
An interactive funding construction can be considered failed upon a
disconnect or a `tx_abort` message. So far, we've consumed the
`InteractiveTxConstructor` in the latter case, but not the former.
Additionally, we may have splice-specific state that needs to be
consumed as well to allow us to negotiate another splice later on.
This commit ensures that we properly consume all splice and interactive
funding state whenever possible upon a disconnect or `tx_abort`.
The interactive funding state is safe to consume as long as we have
either yet to reach `AwaitingSignatures`, or we have but `tx_signatures`
has not been sent/received. In all of these cases, we also make sure to
clear the quiescent state flag such that we're able to resume processing
updates on the channel.
The splice state is safe to consume as long as we don't have a pending
`FundingNegotiation::AwaitingSignatures` with a `tx_signatures`
sent/received and we don't have any negotiated candidates. Note that
until splice RBF is supported, it is not currently possible to have any
negotiated candidates with a pending interactive funding transaction.
@jkczyz
jkczyz merged commit cfe2a1e into lightningdevkit:mainOct 1, 2025
25 checks passed
@wpaulino
wpaulino deleted the reset-splice-state branch October 1, 2025 07:57
Sign up for freeto 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

@wpaulino@ldk-reviews-bot@TheBlueMatt@jkczyz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Wipe splice state upon failed interactive funding construction - #4120

Merged
jkczyz merged 1 commit into
lightningdevkit:mainfrom
wpaulino:reset-splice-state
Oct 1, 2025
Merged

Wipe splice state upon failed interactive funding construction#4120
jkczyz merged 1 commit into
lightningdevkit:mainfrom
wpaulino:reset-splice-state

Conversation

@wpaulino

Copy link
Copy Markdown
Contributor

An interactive funding construction can be considered failed upon a disconnect or a tx_abort message. So far, we've consumed the InteractiveTxConstructor in the latter case, but not the former. Additionally, we may have splice-specific state that needs to be consumed as well to allow us to negotiate another splice later on.

This commit ensures that we properly consume all splice and interactive funding state whenever possible upon a disconnect or tx_abort.

The interactive funding state is safe to consume as long as we have either yet to reach AwaitingSignatures, or we have but tx_signatures has not been sent/received.

The splice state is safe to consume as long as we don't have a pending FundingNegotiation::AwaitingSignatures with a tx_signatures sent/received and we don't have any negotiated candidates. Note that until splice RBF is supported, it is not currently possible to have any negotiated candidates with a pending interactive funding transaction.

@wpaulinowpaulino added this to the 0.2 milestone Sep 24, 2025
@wpaulinowpaulino self-assigned this Sep 24, 2025
@ldk-reviews-bot

ldk-reviews-bot commented Sep 24, 2025

Copy link
Copy Markdown

👋 Thanks for assigning @TheBlueMatt 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.

@codecov

codecovBot commented Sep 24, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.14815% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.68%. Comparing base (3e21ba3) to head (6d2b110).
⚠️ Report is 82 commits behind head on main.

Files with missing linesPatch %Lines
lightning/src/ln/channel.rs60.00%30 Missing and 2 partials ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #4120 +/- ##
==========================================
- Coverage 88.72% 88.68% -0.04% 
==========================================
Files 177 180 +3 Lines 133404 135148 +1744 Branches 133404 135148 +1744 ==========================================
+ Hits 118365 119860 +1495 - Misses 12325 12523 +198 - Partials 2714 2765 +51 
FlagCoverage Δ
fuzzing21.79% <33.75%> (+0.05%)⬆️
tests88.52% <88.14%> (-0.04%)⬇️

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.

Comment threadlightning/src/ln/channel.rs Outdated
Comment on lines +6766 to +6767
signing_session.holder_tx_signatures().is_some()
|| signing_session.has_received_tx_signatures()

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.

Does it matter if we received their signatures if we haven't sent ours? Or is it because if they sent theirs then they would not have reset their state?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

You're supposed to remember the channel as soon as one side has sent tx_signatures, because you can't be sure the other side didn't just sign and broadcast without sending their own.

Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
@ldk-reviews-bot

Copy link
Copy Markdown

👋 The first review has been submitted!

Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer.

Comment threadlightning/src/ln/channel.rs Outdated
.pending_splice
.as_mut()
.and_then(|pending_splice| pending_splice.funding_negotiation.take());
if funded_channel.should_reset_pending_splice_funding_negotiation() {

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.

Looks like we aren't calling fail_interactive_tx_negotiation when failing to handle a splice_ack. #4077 updates fail_interactive_tx_negotiation to take a NegotiationError, which it uses to construct a SpliceFundingFailed struct.

For FundingNegotiation::ConstructingTransaction, the NegotiationError is formed by copying the inputs from the InteractiveTxConstructor. For FundingNegotiation::AwaitingAck when handling splice_ack, we'd need to do something similar?

Either way we are cloning the inputs just to later take the FundingNegotiation here. Maybe that is ok for now? Any thoughts on a better way of doing this?

@jkczyzjkczyzSep 25, 2025

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.

Hmmm... so we are also already take'ing the FundingNegotiation in one place in splice_ack handling (when FundingNegotiation::into_interactive_tx_constructor fails), but not earlier when validating the splice_ack message.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

We shouldn't need to call fail_interactive_tx_negotiation whenever we fail handling a message by sending a warning and disconnecting.

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.

Ah, so failing to process a splice_ack would just disconnect, and the peer could re-send it after reconnecting. Do we eventually timeout quiescence somewhere?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Quiescence is also implicitly terminated upon disconnection, but we do have a timeout enforced at should_disconnect_peer_awaiting_response.

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.

Oh, so we'd need to produce a SpliceFailed event in some other way? I'm thinking when we are in FundingNegotiation::AwaitingAck and fail processing the splice_ack.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah sounds like that logic might need to live in the disconnection handler, since we'll need to emit an event anyway if a peer disconnects mid-splice negotiation for whatever reason.

Comment threadlightning/src/ln/channel.rs Outdated
jkczyz
jkczyz previously approved these changes Sep 26, 2025
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
TheBlueMatt
TheBlueMatt previously approved these changes Sep 26, 2025
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
An interactive funding construction can be considered failed upon a
disconnect or a `tx_abort` message. So far, we've consumed the
`InteractiveTxConstructor` in the latter case, but not the former.
Additionally, we may have splice-specific state that needs to be
consumed as well to allow us to negotiate another splice later on.
This commit ensures that we properly consume all splice and interactive
funding state whenever possible upon a disconnect or `tx_abort`.
The interactive funding state is safe to consume as long as we have
either yet to reach `AwaitingSignatures`, or we have but `tx_signatures`
has not been sent/received. In all of these cases, we also make sure to
clear the quiescent state flag such that we're able to resume processing
updates on the channel.
The splice state is safe to consume as long as we don't have a pending
`FundingNegotiation::AwaitingSignatures` with a `tx_signatures`
sent/received and we don't have any negotiated candidates. Note that
until splice RBF is supported, it is not currently possible to have any
negotiated candidates with a pending interactive funding transaction.
@jkczyz
jkczyz merged commit cfe2a1e into lightningdevkit:mainOct 1, 2025
25 checks passed
@wpaulino
wpaulino deleted the reset-splice-state branch October 1, 2025 07:57
Sign up for freeto 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

@wpaulino@ldk-reviews-bot@TheBlueMatt@jkczyz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Wipe splice state upon failed interactive funding construction - #4120

Merged
jkczyz merged 1 commit into
lightningdevkit:mainfrom
wpaulino:reset-splice-state
Oct 1, 2025
Merged

Wipe splice state upon failed interactive funding construction#4120
jkczyz merged 1 commit into
lightningdevkit:mainfrom
wpaulino:reset-splice-state

Conversation

@wpaulino

Copy link
Copy Markdown
Contributor

An interactive funding construction can be considered failed upon a disconnect or a tx_abort message. So far, we've consumed the InteractiveTxConstructor in the latter case, but not the former. Additionally, we may have splice-specific state that needs to be consumed as well to allow us to negotiate another splice later on.

This commit ensures that we properly consume all splice and interactive funding state whenever possible upon a disconnect or tx_abort.

The interactive funding state is safe to consume as long as we have either yet to reach AwaitingSignatures, or we have but tx_signatures has not been sent/received.

The splice state is safe to consume as long as we don't have a pending FundingNegotiation::AwaitingSignatures with a tx_signatures sent/received and we don't have any negotiated candidates. Note that until splice RBF is supported, it is not currently possible to have any negotiated candidates with a pending interactive funding transaction.

@wpaulinowpaulino added this to the 0.2 milestone Sep 24, 2025
@wpaulinowpaulino self-assigned this Sep 24, 2025
@ldk-reviews-bot

ldk-reviews-bot commented Sep 24, 2025

Copy link
Copy Markdown

👋 Thanks for assigning @TheBlueMatt 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.

@codecov

codecovBot commented Sep 24, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.14815% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.68%. Comparing base (3e21ba3) to head (6d2b110).
⚠️ Report is 82 commits behind head on main.

Files with missing linesPatch %Lines
lightning/src/ln/channel.rs60.00%30 Missing and 2 partials ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #4120 +/- ##
==========================================
- Coverage 88.72% 88.68% -0.04% 
==========================================
Files 177 180 +3 Lines 133404 135148 +1744 Branches 133404 135148 +1744 ==========================================
+ Hits 118365 119860 +1495 - Misses 12325 12523 +198 - Partials 2714 2765 +51 
FlagCoverage Δ
fuzzing21.79% <33.75%> (+0.05%)⬆️
tests88.52% <88.14%> (-0.04%)⬇️

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.

Comment threadlightning/src/ln/channel.rs Outdated
Comment on lines +6766 to +6767
signing_session.holder_tx_signatures().is_some()
|| signing_session.has_received_tx_signatures()

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.

Does it matter if we received their signatures if we haven't sent ours? Or is it because if they sent theirs then they would not have reset their state?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

You're supposed to remember the channel as soon as one side has sent tx_signatures, because you can't be sure the other side didn't just sign and broadcast without sending their own.

Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
@ldk-reviews-bot

Copy link
Copy Markdown

👋 The first review has been submitted!

Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer.

Comment threadlightning/src/ln/channel.rs Outdated
.pending_splice
.as_mut()
.and_then(|pending_splice| pending_splice.funding_negotiation.take());
if funded_channel.should_reset_pending_splice_funding_negotiation() {

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.

Looks like we aren't calling fail_interactive_tx_negotiation when failing to handle a splice_ack. #4077 updates fail_interactive_tx_negotiation to take a NegotiationError, which it uses to construct a SpliceFundingFailed struct.

For FundingNegotiation::ConstructingTransaction, the NegotiationError is formed by copying the inputs from the InteractiveTxConstructor. For FundingNegotiation::AwaitingAck when handling splice_ack, we'd need to do something similar?

Either way we are cloning the inputs just to later take the FundingNegotiation here. Maybe that is ok for now? Any thoughts on a better way of doing this?

@jkczyzjkczyzSep 25, 2025

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.

Hmmm... so we are also already take'ing the FundingNegotiation in one place in splice_ack handling (when FundingNegotiation::into_interactive_tx_constructor fails), but not earlier when validating the splice_ack message.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

We shouldn't need to call fail_interactive_tx_negotiation whenever we fail handling a message by sending a warning and disconnecting.

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.

Ah, so failing to process a splice_ack would just disconnect, and the peer could re-send it after reconnecting. Do we eventually timeout quiescence somewhere?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Quiescence is also implicitly terminated upon disconnection, but we do have a timeout enforced at should_disconnect_peer_awaiting_response.

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.

Oh, so we'd need to produce a SpliceFailed event in some other way? I'm thinking when we are in FundingNegotiation::AwaitingAck and fail processing the splice_ack.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah sounds like that logic might need to live in the disconnection handler, since we'll need to emit an event anyway if a peer disconnects mid-splice negotiation for whatever reason.

Comment threadlightning/src/ln/channel.rs Outdated
jkczyz
jkczyz previously approved these changes Sep 26, 2025
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
TheBlueMatt
TheBlueMatt previously approved these changes Sep 26, 2025
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
An interactive funding construction can be considered failed upon a
disconnect or a `tx_abort` message. So far, we've consumed the
`InteractiveTxConstructor` in the latter case, but not the former.
Additionally, we may have splice-specific state that needs to be
consumed as well to allow us to negotiate another splice later on.
This commit ensures that we properly consume all splice and interactive
funding state whenever possible upon a disconnect or `tx_abort`.
The interactive funding state is safe to consume as long as we have
either yet to reach `AwaitingSignatures`, or we have but `tx_signatures`
has not been sent/received. In all of these cases, we also make sure to
clear the quiescent state flag such that we're able to resume processing
updates on the channel.
The splice state is safe to consume as long as we don't have a pending
`FundingNegotiation::AwaitingSignatures` with a `tx_signatures`
sent/received and we don't have any negotiated candidates. Note that
until splice RBF is supported, it is not currently possible to have any
negotiated candidates with a pending interactive funding transaction.
@jkczyz
jkczyz merged commit cfe2a1e into lightningdevkit:mainOct 1, 2025
25 checks passed
@wpaulino
wpaulino deleted the reset-splice-state branch October 1, 2025 07:57
Sign up for freeto 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

@wpaulino@ldk-reviews-bot@TheBlueMatt@jkczyz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Wipe splice state upon failed interactive funding construction - #4120

Merged
jkczyz merged 1 commit into
lightningdevkit:mainfrom
wpaulino:reset-splice-state
Oct 1, 2025
Merged

Wipe splice state upon failed interactive funding construction#4120
jkczyz merged 1 commit into
lightningdevkit:mainfrom
wpaulino:reset-splice-state

Conversation

@wpaulino

Copy link
Copy Markdown
Contributor

An interactive funding construction can be considered failed upon a disconnect or a tx_abort message. So far, we've consumed the InteractiveTxConstructor in the latter case, but not the former. Additionally, we may have splice-specific state that needs to be consumed as well to allow us to negotiate another splice later on.

This commit ensures that we properly consume all splice and interactive funding state whenever possible upon a disconnect or tx_abort.

The interactive funding state is safe to consume as long as we have either yet to reach AwaitingSignatures, or we have but tx_signatures has not been sent/received.

The splice state is safe to consume as long as we don't have a pending FundingNegotiation::AwaitingSignatures with a tx_signatures sent/received and we don't have any negotiated candidates. Note that until splice RBF is supported, it is not currently possible to have any negotiated candidates with a pending interactive funding transaction.

@wpaulinowpaulino added this to the 0.2 milestone Sep 24, 2025
@wpaulinowpaulino self-assigned this Sep 24, 2025
@ldk-reviews-bot

ldk-reviews-bot commented Sep 24, 2025

Copy link
Copy Markdown

👋 Thanks for assigning @TheBlueMatt 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.

@codecov

codecovBot commented Sep 24, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.14815% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.68%. Comparing base (3e21ba3) to head (6d2b110).
⚠️ Report is 82 commits behind head on main.

Files with missing linesPatch %Lines
lightning/src/ln/channel.rs60.00%30 Missing and 2 partials ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #4120 +/- ##
==========================================
- Coverage 88.72% 88.68% -0.04% 
==========================================
Files 177 180 +3 Lines 133404 135148 +1744 Branches 133404 135148 +1744 ==========================================
+ Hits 118365 119860 +1495 - Misses 12325 12523 +198 - Partials 2714 2765 +51 
FlagCoverage Δ
fuzzing21.79% <33.75%> (+0.05%)⬆️
tests88.52% <88.14%> (-0.04%)⬇️

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.

Comment threadlightning/src/ln/channel.rs Outdated
Comment on lines +6766 to +6767
signing_session.holder_tx_signatures().is_some()
|| signing_session.has_received_tx_signatures()

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.

Does it matter if we received their signatures if we haven't sent ours? Or is it because if they sent theirs then they would not have reset their state?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

You're supposed to remember the channel as soon as one side has sent tx_signatures, because you can't be sure the other side didn't just sign and broadcast without sending their own.

Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
@ldk-reviews-bot

Copy link
Copy Markdown

👋 The first review has been submitted!

Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer.

Comment threadlightning/src/ln/channel.rs Outdated
.pending_splice
.as_mut()
.and_then(|pending_splice| pending_splice.funding_negotiation.take());
if funded_channel.should_reset_pending_splice_funding_negotiation() {

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.

Looks like we aren't calling fail_interactive_tx_negotiation when failing to handle a splice_ack. #4077 updates fail_interactive_tx_negotiation to take a NegotiationError, which it uses to construct a SpliceFundingFailed struct.

For FundingNegotiation::ConstructingTransaction, the NegotiationError is formed by copying the inputs from the InteractiveTxConstructor. For FundingNegotiation::AwaitingAck when handling splice_ack, we'd need to do something similar?

Either way we are cloning the inputs just to later take the FundingNegotiation here. Maybe that is ok for now? Any thoughts on a better way of doing this?

@jkczyzjkczyzSep 25, 2025

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.

Hmmm... so we are also already take'ing the FundingNegotiation in one place in splice_ack handling (when FundingNegotiation::into_interactive_tx_constructor fails), but not earlier when validating the splice_ack message.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

We shouldn't need to call fail_interactive_tx_negotiation whenever we fail handling a message by sending a warning and disconnecting.

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.

Ah, so failing to process a splice_ack would just disconnect, and the peer could re-send it after reconnecting. Do we eventually timeout quiescence somewhere?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Quiescence is also implicitly terminated upon disconnection, but we do have a timeout enforced at should_disconnect_peer_awaiting_response.

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.

Oh, so we'd need to produce a SpliceFailed event in some other way? I'm thinking when we are in FundingNegotiation::AwaitingAck and fail processing the splice_ack.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah sounds like that logic might need to live in the disconnection handler, since we'll need to emit an event anyway if a peer disconnects mid-splice negotiation for whatever reason.

Comment threadlightning/src/ln/channel.rs Outdated
jkczyz
jkczyz previously approved these changes Sep 26, 2025
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
TheBlueMatt
TheBlueMatt previously approved these changes Sep 26, 2025
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
An interactive funding construction can be considered failed upon a
disconnect or a `tx_abort` message. So far, we've consumed the
`InteractiveTxConstructor` in the latter case, but not the former.
Additionally, we may have splice-specific state that needs to be
consumed as well to allow us to negotiate another splice later on.
This commit ensures that we properly consume all splice and interactive
funding state whenever possible upon a disconnect or `tx_abort`.
The interactive funding state is safe to consume as long as we have
either yet to reach `AwaitingSignatures`, or we have but `tx_signatures`
has not been sent/received. In all of these cases, we also make sure to
clear the quiescent state flag such that we're able to resume processing
updates on the channel.
The splice state is safe to consume as long as we don't have a pending
`FundingNegotiation::AwaitingSignatures` with a `tx_signatures`
sent/received and we don't have any negotiated candidates. Note that
until splice RBF is supported, it is not currently possible to have any
negotiated candidates with a pending interactive funding transaction.
@jkczyz
jkczyz merged commit cfe2a1e into lightningdevkit:mainOct 1, 2025
25 checks passed
@wpaulino
wpaulino deleted the reset-splice-state branch October 1, 2025 07:57
Sign up for freeto 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

@wpaulino@ldk-reviews-bot@TheBlueMatt@jkczyz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Wipe splice state upon failed interactive funding construction - #4120

Merged
jkczyz merged 1 commit into
lightningdevkit:mainfrom
wpaulino:reset-splice-state
Oct 1, 2025
Merged

Wipe splice state upon failed interactive funding construction#4120
jkczyz merged 1 commit into
lightningdevkit:mainfrom
wpaulino:reset-splice-state

Conversation

@wpaulino

Copy link
Copy Markdown
Contributor

An interactive funding construction can be considered failed upon a disconnect or a tx_abort message. So far, we've consumed the InteractiveTxConstructor in the latter case, but not the former. Additionally, we may have splice-specific state that needs to be consumed as well to allow us to negotiate another splice later on.

This commit ensures that we properly consume all splice and interactive funding state whenever possible upon a disconnect or tx_abort.

The interactive funding state is safe to consume as long as we have either yet to reach AwaitingSignatures, or we have but tx_signatures has not been sent/received.

The splice state is safe to consume as long as we don't have a pending FundingNegotiation::AwaitingSignatures with a tx_signatures sent/received and we don't have any negotiated candidates. Note that until splice RBF is supported, it is not currently possible to have any negotiated candidates with a pending interactive funding transaction.

@wpaulinowpaulino added this to the 0.2 milestone Sep 24, 2025
@wpaulinowpaulino self-assigned this Sep 24, 2025
@ldk-reviews-bot

ldk-reviews-bot commented Sep 24, 2025

Copy link
Copy Markdown

👋 Thanks for assigning @TheBlueMatt 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.

@codecov

codecovBot commented Sep 24, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.14815% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.68%. Comparing base (3e21ba3) to head (6d2b110).
⚠️ Report is 82 commits behind head on main.

Files with missing linesPatch %Lines
lightning/src/ln/channel.rs60.00%30 Missing and 2 partials ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #4120 +/- ##
==========================================
- Coverage 88.72% 88.68% -0.04% 
==========================================
Files 177 180 +3 Lines 133404 135148 +1744 Branches 133404 135148 +1744 ==========================================
+ Hits 118365 119860 +1495 - Misses 12325 12523 +198 - Partials 2714 2765 +51 
FlagCoverage Δ
fuzzing21.79% <33.75%> (+0.05%)⬆️
tests88.52% <88.14%> (-0.04%)⬇️

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.

Comment threadlightning/src/ln/channel.rs Outdated
Comment on lines +6766 to +6767
signing_session.holder_tx_signatures().is_some()
|| signing_session.has_received_tx_signatures()

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.

Does it matter if we received their signatures if we haven't sent ours? Or is it because if they sent theirs then they would not have reset their state?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

You're supposed to remember the channel as soon as one side has sent tx_signatures, because you can't be sure the other side didn't just sign and broadcast without sending their own.

Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
@ldk-reviews-bot

Copy link
Copy Markdown

👋 The first review has been submitted!

Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer.

Comment threadlightning/src/ln/channel.rs Outdated
.pending_splice
.as_mut()
.and_then(|pending_splice| pending_splice.funding_negotiation.take());
if funded_channel.should_reset_pending_splice_funding_negotiation() {

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.

Looks like we aren't calling fail_interactive_tx_negotiation when failing to handle a splice_ack. #4077 updates fail_interactive_tx_negotiation to take a NegotiationError, which it uses to construct a SpliceFundingFailed struct.

For FundingNegotiation::ConstructingTransaction, the NegotiationError is formed by copying the inputs from the InteractiveTxConstructor. For FundingNegotiation::AwaitingAck when handling splice_ack, we'd need to do something similar?

Either way we are cloning the inputs just to later take the FundingNegotiation here. Maybe that is ok for now? Any thoughts on a better way of doing this?

@jkczyzjkczyzSep 25, 2025

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.

Hmmm... so we are also already take'ing the FundingNegotiation in one place in splice_ack handling (when FundingNegotiation::into_interactive_tx_constructor fails), but not earlier when validating the splice_ack message.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

We shouldn't need to call fail_interactive_tx_negotiation whenever we fail handling a message by sending a warning and disconnecting.

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.

Ah, so failing to process a splice_ack would just disconnect, and the peer could re-send it after reconnecting. Do we eventually timeout quiescence somewhere?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Quiescence is also implicitly terminated upon disconnection, but we do have a timeout enforced at should_disconnect_peer_awaiting_response.

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.

Oh, so we'd need to produce a SpliceFailed event in some other way? I'm thinking when we are in FundingNegotiation::AwaitingAck and fail processing the splice_ack.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah sounds like that logic might need to live in the disconnection handler, since we'll need to emit an event anyway if a peer disconnects mid-splice negotiation for whatever reason.

Comment threadlightning/src/ln/channel.rs Outdated
jkczyz
jkczyz previously approved these changes Sep 26, 2025
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
TheBlueMatt
TheBlueMatt previously approved these changes Sep 26, 2025
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
An interactive funding construction can be considered failed upon a
disconnect or a `tx_abort` message. So far, we've consumed the
`InteractiveTxConstructor` in the latter case, but not the former.
Additionally, we may have splice-specific state that needs to be
consumed as well to allow us to negotiate another splice later on.
This commit ensures that we properly consume all splice and interactive
funding state whenever possible upon a disconnect or `tx_abort`.
The interactive funding state is safe to consume as long as we have
either yet to reach `AwaitingSignatures`, or we have but `tx_signatures`
has not been sent/received. In all of these cases, we also make sure to
clear the quiescent state flag such that we're able to resume processing
updates on the channel.
The splice state is safe to consume as long as we don't have a pending
`FundingNegotiation::AwaitingSignatures` with a `tx_signatures`
sent/received and we don't have any negotiated candidates. Note that
until splice RBF is supported, it is not currently possible to have any
negotiated candidates with a pending interactive funding transaction.
@jkczyz
jkczyz merged commit cfe2a1e into lightningdevkit:mainOct 1, 2025
25 checks passed
@wpaulino
wpaulino deleted the reset-splice-state branch October 1, 2025 07:57
Sign up for freeto 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

@wpaulino@ldk-reviews-bot@TheBlueMatt@jkczyz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Wipe splice state upon failed interactive funding construction - #4120

Merged
jkczyz merged 1 commit into
lightningdevkit:mainfrom
wpaulino:reset-splice-state
Oct 1, 2025
Merged

Wipe splice state upon failed interactive funding construction#4120
jkczyz merged 1 commit into
lightningdevkit:mainfrom
wpaulino:reset-splice-state

Conversation

@wpaulino

Copy link
Copy Markdown
Contributor

An interactive funding construction can be considered failed upon a disconnect or a tx_abort message. So far, we've consumed the InteractiveTxConstructor in the latter case, but not the former. Additionally, we may have splice-specific state that needs to be consumed as well to allow us to negotiate another splice later on.

This commit ensures that we properly consume all splice and interactive funding state whenever possible upon a disconnect or tx_abort.

The interactive funding state is safe to consume as long as we have either yet to reach AwaitingSignatures, or we have but tx_signatures has not been sent/received.

The splice state is safe to consume as long as we don't have a pending FundingNegotiation::AwaitingSignatures with a tx_signatures sent/received and we don't have any negotiated candidates. Note that until splice RBF is supported, it is not currently possible to have any negotiated candidates with a pending interactive funding transaction.

@wpaulinowpaulino added this to the 0.2 milestone Sep 24, 2025
@wpaulinowpaulino self-assigned this Sep 24, 2025
@ldk-reviews-bot

ldk-reviews-bot commented Sep 24, 2025

Copy link
Copy Markdown

👋 Thanks for assigning @TheBlueMatt 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.

@codecov

codecovBot commented Sep 24, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.14815% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.68%. Comparing base (3e21ba3) to head (6d2b110).
⚠️ Report is 82 commits behind head on main.

Files with missing linesPatch %Lines
lightning/src/ln/channel.rs60.00%30 Missing and 2 partials ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #4120 +/- ##
==========================================
- Coverage 88.72% 88.68% -0.04% 
==========================================
Files 177 180 +3 Lines 133404 135148 +1744 Branches 133404 135148 +1744 ==========================================
+ Hits 118365 119860 +1495 - Misses 12325 12523 +198 - Partials 2714 2765 +51 
FlagCoverage Δ
fuzzing21.79% <33.75%> (+0.05%)⬆️
tests88.52% <88.14%> (-0.04%)⬇️

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.

Comment threadlightning/src/ln/channel.rs Outdated
Comment on lines +6766 to +6767
signing_session.holder_tx_signatures().is_some()
|| signing_session.has_received_tx_signatures()

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.

Does it matter if we received their signatures if we haven't sent ours? Or is it because if they sent theirs then they would not have reset their state?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

You're supposed to remember the channel as soon as one side has sent tx_signatures, because you can't be sure the other side didn't just sign and broadcast without sending their own.

Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
@ldk-reviews-bot

Copy link
Copy Markdown

👋 The first review has been submitted!

Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer.

Comment threadlightning/src/ln/channel.rs Outdated
.pending_splice
.as_mut()
.and_then(|pending_splice| pending_splice.funding_negotiation.take());
if funded_channel.should_reset_pending_splice_funding_negotiation() {

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.

Looks like we aren't calling fail_interactive_tx_negotiation when failing to handle a splice_ack. #4077 updates fail_interactive_tx_negotiation to take a NegotiationError, which it uses to construct a SpliceFundingFailed struct.

For FundingNegotiation::ConstructingTransaction, the NegotiationError is formed by copying the inputs from the InteractiveTxConstructor. For FundingNegotiation::AwaitingAck when handling splice_ack, we'd need to do something similar?

Either way we are cloning the inputs just to later take the FundingNegotiation here. Maybe that is ok for now? Any thoughts on a better way of doing this?

@jkczyzjkczyzSep 25, 2025

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.

Hmmm... so we are also already take'ing the FundingNegotiation in one place in splice_ack handling (when FundingNegotiation::into_interactive_tx_constructor fails), but not earlier when validating the splice_ack message.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

We shouldn't need to call fail_interactive_tx_negotiation whenever we fail handling a message by sending a warning and disconnecting.

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.

Ah, so failing to process a splice_ack would just disconnect, and the peer could re-send it after reconnecting. Do we eventually timeout quiescence somewhere?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Quiescence is also implicitly terminated upon disconnection, but we do have a timeout enforced at should_disconnect_peer_awaiting_response.

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.

Oh, so we'd need to produce a SpliceFailed event in some other way? I'm thinking when we are in FundingNegotiation::AwaitingAck and fail processing the splice_ack.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah sounds like that logic might need to live in the disconnection handler, since we'll need to emit an event anyway if a peer disconnects mid-splice negotiation for whatever reason.

Comment threadlightning/src/ln/channel.rs Outdated
jkczyz
jkczyz previously approved these changes Sep 26, 2025
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
TheBlueMatt
TheBlueMatt previously approved these changes Sep 26, 2025
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
An interactive funding construction can be considered failed upon a
disconnect or a `tx_abort` message. So far, we've consumed the
`InteractiveTxConstructor` in the latter case, but not the former.
Additionally, we may have splice-specific state that needs to be
consumed as well to allow us to negotiate another splice later on.
This commit ensures that we properly consume all splice and interactive
funding state whenever possible upon a disconnect or `tx_abort`.
The interactive funding state is safe to consume as long as we have
either yet to reach `AwaitingSignatures`, or we have but `tx_signatures`
has not been sent/received. In all of these cases, we also make sure to
clear the quiescent state flag such that we're able to resume processing
updates on the channel.
The splice state is safe to consume as long as we don't have a pending
`FundingNegotiation::AwaitingSignatures` with a `tx_signatures`
sent/received and we don't have any negotiated candidates. Note that
until splice RBF is supported, it is not currently possible to have any
negotiated candidates with a pending interactive funding transaction.
@jkczyz
jkczyz merged commit cfe2a1e into lightningdevkit:mainOct 1, 2025
25 checks passed
@wpaulino
wpaulino deleted the reset-splice-state branch October 1, 2025 07:57
Sign up for freeto 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

@wpaulino@ldk-reviews-bot@TheBlueMatt@jkczyz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Wipe splice state upon failed interactive funding construction - #4120

Merged
jkczyz merged 1 commit into
lightningdevkit:mainfrom
wpaulino:reset-splice-state
Oct 1, 2025
Merged

Wipe splice state upon failed interactive funding construction#4120
jkczyz merged 1 commit into
lightningdevkit:mainfrom
wpaulino:reset-splice-state

Conversation

@wpaulino

Copy link
Copy Markdown
Contributor

An interactive funding construction can be considered failed upon a disconnect or a tx_abort message. So far, we've consumed the InteractiveTxConstructor in the latter case, but not the former. Additionally, we may have splice-specific state that needs to be consumed as well to allow us to negotiate another splice later on.

This commit ensures that we properly consume all splice and interactive funding state whenever possible upon a disconnect or tx_abort.

The interactive funding state is safe to consume as long as we have either yet to reach AwaitingSignatures, or we have but tx_signatures has not been sent/received.

The splice state is safe to consume as long as we don't have a pending FundingNegotiation::AwaitingSignatures with a tx_signatures sent/received and we don't have any negotiated candidates. Note that until splice RBF is supported, it is not currently possible to have any negotiated candidates with a pending interactive funding transaction.

@wpaulinowpaulino added this to the 0.2 milestone Sep 24, 2025
@wpaulinowpaulino self-assigned this Sep 24, 2025
@ldk-reviews-bot

ldk-reviews-bot commented Sep 24, 2025

Copy link
Copy Markdown

👋 Thanks for assigning @TheBlueMatt 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.

@codecov

codecovBot commented Sep 24, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.14815% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.68%. Comparing base (3e21ba3) to head (6d2b110).
⚠️ Report is 82 commits behind head on main.

Files with missing linesPatch %Lines
lightning/src/ln/channel.rs60.00%30 Missing and 2 partials ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #4120 +/- ##
==========================================
- Coverage 88.72% 88.68% -0.04% 
==========================================
Files 177 180 +3 Lines 133404 135148 +1744 Branches 133404 135148 +1744 ==========================================
+ Hits 118365 119860 +1495 - Misses 12325 12523 +198 - Partials 2714 2765 +51 
FlagCoverage Δ
fuzzing21.79% <33.75%> (+0.05%)⬆️
tests88.52% <88.14%> (-0.04%)⬇️

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.

Comment threadlightning/src/ln/channel.rs Outdated
Comment on lines +6766 to +6767
signing_session.holder_tx_signatures().is_some()
|| signing_session.has_received_tx_signatures()

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.

Does it matter if we received their signatures if we haven't sent ours? Or is it because if they sent theirs then they would not have reset their state?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

You're supposed to remember the channel as soon as one side has sent tx_signatures, because you can't be sure the other side didn't just sign and broadcast without sending their own.

Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
@ldk-reviews-bot

Copy link
Copy Markdown

👋 The first review has been submitted!

Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer.

Comment threadlightning/src/ln/channel.rs Outdated
.pending_splice
.as_mut()
.and_then(|pending_splice| pending_splice.funding_negotiation.take());
if funded_channel.should_reset_pending_splice_funding_negotiation() {

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.

Looks like we aren't calling fail_interactive_tx_negotiation when failing to handle a splice_ack. #4077 updates fail_interactive_tx_negotiation to take a NegotiationError, which it uses to construct a SpliceFundingFailed struct.

For FundingNegotiation::ConstructingTransaction, the NegotiationError is formed by copying the inputs from the InteractiveTxConstructor. For FundingNegotiation::AwaitingAck when handling splice_ack, we'd need to do something similar?

Either way we are cloning the inputs just to later take the FundingNegotiation here. Maybe that is ok for now? Any thoughts on a better way of doing this?

@jkczyzjkczyzSep 25, 2025

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.

Hmmm... so we are also already take'ing the FundingNegotiation in one place in splice_ack handling (when FundingNegotiation::into_interactive_tx_constructor fails), but not earlier when validating the splice_ack message.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

We shouldn't need to call fail_interactive_tx_negotiation whenever we fail handling a message by sending a warning and disconnecting.

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.

Ah, so failing to process a splice_ack would just disconnect, and the peer could re-send it after reconnecting. Do we eventually timeout quiescence somewhere?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Quiescence is also implicitly terminated upon disconnection, but we do have a timeout enforced at should_disconnect_peer_awaiting_response.

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.

Oh, so we'd need to produce a SpliceFailed event in some other way? I'm thinking when we are in FundingNegotiation::AwaitingAck and fail processing the splice_ack.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah sounds like that logic might need to live in the disconnection handler, since we'll need to emit an event anyway if a peer disconnects mid-splice negotiation for whatever reason.

Comment threadlightning/src/ln/channel.rs Outdated
jkczyz
jkczyz previously approved these changes Sep 26, 2025
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
TheBlueMatt
TheBlueMatt previously approved these changes Sep 26, 2025
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
An interactive funding construction can be considered failed upon a
disconnect or a `tx_abort` message. So far, we've consumed the
`InteractiveTxConstructor` in the latter case, but not the former.
Additionally, we may have splice-specific state that needs to be
consumed as well to allow us to negotiate another splice later on.
This commit ensures that we properly consume all splice and interactive
funding state whenever possible upon a disconnect or `tx_abort`.
The interactive funding state is safe to consume as long as we have
either yet to reach `AwaitingSignatures`, or we have but `tx_signatures`
has not been sent/received. In all of these cases, we also make sure to
clear the quiescent state flag such that we're able to resume processing
updates on the channel.
The splice state is safe to consume as long as we don't have a pending
`FundingNegotiation::AwaitingSignatures` with a `tx_signatures`
sent/received and we don't have any negotiated candidates. Note that
until splice RBF is supported, it is not currently possible to have any
negotiated candidates with a pending interactive funding transaction.
@jkczyz
jkczyz merged commit cfe2a1e into lightningdevkit:mainOct 1, 2025
25 checks passed
@wpaulino
wpaulino deleted the reset-splice-state branch October 1, 2025 07:57
Sign up for freeto 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

@wpaulino@ldk-reviews-bot@TheBlueMatt@jkczyz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Wipe splice state upon failed interactive funding construction - #4120

Merged
jkczyz merged 1 commit into
lightningdevkit:mainfrom
wpaulino:reset-splice-state
Oct 1, 2025
Merged

Wipe splice state upon failed interactive funding construction#4120
jkczyz merged 1 commit into
lightningdevkit:mainfrom
wpaulino:reset-splice-state

Conversation

@wpaulino

Copy link
Copy Markdown
Contributor

An interactive funding construction can be considered failed upon a disconnect or a tx_abort message. So far, we've consumed the InteractiveTxConstructor in the latter case, but not the former. Additionally, we may have splice-specific state that needs to be consumed as well to allow us to negotiate another splice later on.

This commit ensures that we properly consume all splice and interactive funding state whenever possible upon a disconnect or tx_abort.

The interactive funding state is safe to consume as long as we have either yet to reach AwaitingSignatures, or we have but tx_signatures has not been sent/received.

The splice state is safe to consume as long as we don't have a pending FundingNegotiation::AwaitingSignatures with a tx_signatures sent/received and we don't have any negotiated candidates. Note that until splice RBF is supported, it is not currently possible to have any negotiated candidates with a pending interactive funding transaction.

@wpaulinowpaulino added this to the 0.2 milestone Sep 24, 2025
@wpaulinowpaulino self-assigned this Sep 24, 2025
@ldk-reviews-bot

ldk-reviews-bot commented Sep 24, 2025

Copy link
Copy Markdown

👋 Thanks for assigning @TheBlueMatt 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.

@codecov

codecovBot commented Sep 24, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.14815% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.68%. Comparing base (3e21ba3) to head (6d2b110).
⚠️ Report is 82 commits behind head on main.

Files with missing linesPatch %Lines
lightning/src/ln/channel.rs60.00%30 Missing and 2 partials ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #4120 +/- ##
==========================================
- Coverage 88.72% 88.68% -0.04% 
==========================================
Files 177 180 +3 Lines 133404 135148 +1744 Branches 133404 135148 +1744 ==========================================
+ Hits 118365 119860 +1495 - Misses 12325 12523 +198 - Partials 2714 2765 +51 
FlagCoverage Δ
fuzzing21.79% <33.75%> (+0.05%)⬆️
tests88.52% <88.14%> (-0.04%)⬇️

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.

Comment threadlightning/src/ln/channel.rs Outdated
Comment on lines +6766 to +6767
signing_session.holder_tx_signatures().is_some()
|| signing_session.has_received_tx_signatures()

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.

Does it matter if we received their signatures if we haven't sent ours? Or is it because if they sent theirs then they would not have reset their state?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

You're supposed to remember the channel as soon as one side has sent tx_signatures, because you can't be sure the other side didn't just sign and broadcast without sending their own.

Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
@ldk-reviews-bot

Copy link
Copy Markdown

👋 The first review has been submitted!

Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer.

Comment threadlightning/src/ln/channel.rs Outdated
.pending_splice
.as_mut()
.and_then(|pending_splice| pending_splice.funding_negotiation.take());
if funded_channel.should_reset_pending_splice_funding_negotiation() {

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.

Looks like we aren't calling fail_interactive_tx_negotiation when failing to handle a splice_ack. #4077 updates fail_interactive_tx_negotiation to take a NegotiationError, which it uses to construct a SpliceFundingFailed struct.

For FundingNegotiation::ConstructingTransaction, the NegotiationError is formed by copying the inputs from the InteractiveTxConstructor. For FundingNegotiation::AwaitingAck when handling splice_ack, we'd need to do something similar?

Either way we are cloning the inputs just to later take the FundingNegotiation here. Maybe that is ok for now? Any thoughts on a better way of doing this?

@jkczyzjkczyzSep 25, 2025

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.

Hmmm... so we are also already take'ing the FundingNegotiation in one place in splice_ack handling (when FundingNegotiation::into_interactive_tx_constructor fails), but not earlier when validating the splice_ack message.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

We shouldn't need to call fail_interactive_tx_negotiation whenever we fail handling a message by sending a warning and disconnecting.

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.

Ah, so failing to process a splice_ack would just disconnect, and the peer could re-send it after reconnecting. Do we eventually timeout quiescence somewhere?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Quiescence is also implicitly terminated upon disconnection, but we do have a timeout enforced at should_disconnect_peer_awaiting_response.

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.

Oh, so we'd need to produce a SpliceFailed event in some other way? I'm thinking when we are in FundingNegotiation::AwaitingAck and fail processing the splice_ack.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah sounds like that logic might need to live in the disconnection handler, since we'll need to emit an event anyway if a peer disconnects mid-splice negotiation for whatever reason.

Comment threadlightning/src/ln/channel.rs Outdated
jkczyz
jkczyz previously approved these changes Sep 26, 2025
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
TheBlueMatt
TheBlueMatt previously approved these changes Sep 26, 2025
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
Comment threadlightning/src/ln/channel.rs Outdated
An interactive funding construction can be considered failed upon a
disconnect or a `tx_abort` message. So far, we've consumed the
`InteractiveTxConstructor` in the latter case, but not the former.
Additionally, we may have splice-specific state that needs to be
consumed as well to allow us to negotiate another splice later on.
This commit ensures that we properly consume all splice and interactive
funding state whenever possible upon a disconnect or `tx_abort`.
The interactive funding state is safe to consume as long as we have
either yet to reach `AwaitingSignatures`, or we have but `tx_signatures`
has not been sent/received. In all of these cases, we also make sure to
clear the quiescent state flag such that we're able to resume processing
updates on the channel.
The splice state is safe to consume as long as we don't have a pending
`FundingNegotiation::AwaitingSignatures` with a `tx_signatures`
sent/received and we don't have any negotiated candidates. Note that
until splice RBF is supported, it is not currently possible to have any
negotiated candidates with a pending interactive funding transaction.
@jkczyz
jkczyz merged commit cfe2a1e into lightningdevkit:mainOct 1, 2025
25 checks passed
@wpaulino
wpaulino deleted the reset-splice-state branch October 1, 2025 07:57
Sign up for freeto 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

@wpaulino@ldk-reviews-bot@TheBlueMatt@jkczyz