Skip to content

Commit 927c5af

Browse files
jkczyzclaude
andcommitted
Derive SpliceFundingFailed inputs from FundingContribution
Replace the maybe_create_splice_funding_failed! macro and splice_funding_failed_for method with a unified splice_funding_failed_for! macro that derives contributed inputs and outputs from the FundingContribution rather than extracting them from the negotiation state. Callers pass ident parameters for which PendingSplice filtering methods to use: contributed_inputs/contributed_outputs when the current round's contribution has been popped or was never pushed, and prior_contributed_inputs/prior_contributed_outputs for the read-only persistence path where the contribution is cloned instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent eaaf326 commit 927c5af

1 file changed

Lines changed: 66 additions & 73 deletions

File tree

lightning/src/ln/channel.rs

Lines changed: 66 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -6740,48 +6740,29 @@ pub struct SpliceFundingFailed {
67406740
pub contribution: Option<FundingContribution>,
67416741
}
67426742

6743-
macro_rules! maybe_create_splice_funding_failed {
6744-
($funded_channel: expr, $pending_splice: expr, $pending_splice_ref: expr, $get: ident, $contributed_inputs_and_outputs: ident) => {{
6745-
$pending_splice
6746-
.and_then(|pending_splice| pending_splice.funding_negotiation.$get())
6747-
.and_then(|funding_negotiation| {
6748-
let is_initiator = funding_negotiation.is_initiator();
6749-
6750-
let (mut contributed_inputs, mut contributed_outputs) = match funding_negotiation {
6751-
FundingNegotiation::AwaitingAck { context, .. } => {
6752-
context.$contributed_inputs_and_outputs()
6753-
},
6754-
FundingNegotiation::ConstructingTransaction {
6755-
interactive_tx_constructor,
6756-
..
6757-
} => interactive_tx_constructor.$contributed_inputs_and_outputs(),
6758-
FundingNegotiation::AwaitingSignatures { .. } => $funded_channel
6759-
.context
6760-
.interactive_tx_signing_session
6761-
.$get()
6762-
.expect("We have a pending splice awaiting signatures")
6763-
.$contributed_inputs_and_outputs(),
6764-
};
6765-
6766-
if let Some(pending_splice) = $pending_splice_ref {
6767-
for input in pending_splice.prior_contributed_inputs() {
6768-
contributed_inputs.retain(|i| *i != input);
6769-
}
6770-
for output in pending_splice.prior_contributed_outputs() {
6771-
contributed_outputs.retain(|o| o.script_pubkey != output.script_pubkey);
6772-
}
6773-
}
6774-
6775-
if !is_initiator && contributed_inputs.is_empty() && contributed_outputs.is_empty()
6776-
{
6777-
return None;
6778-
}
6779-
6780-
let contribution =
6781-
$pending_splice_ref.and_then(|ps| ps.contributions.last().cloned());
6782-
6783-
Some(SpliceFundingFailed { contributed_inputs, contributed_outputs, contribution })
6784-
})
6743+
macro_rules! splice_funding_failed_for {
6744+
($self: expr, $is_initiator: expr, $contribution: expr,
6745+
$contributed_inputs: ident, $contributed_outputs: ident) => {{
6746+
let contribution = $contribution;
6747+
let existing_inputs =
6748+
$self.pending_splice.as_ref().into_iter().flat_map(|ps| ps.$contributed_inputs());
6749+
let existing_outputs =
6750+
$self.pending_splice.as_ref().into_iter().flat_map(|ps| ps.$contributed_outputs());
6751+
let filtered =
6752+
contribution.clone().into_unique_contributions(existing_inputs, existing_outputs);
6753+
match filtered {
6754+
None if !$is_initiator => None,
6755+
None => Some(SpliceFundingFailed {
6756+
contributed_inputs: vec![],
6757+
contributed_outputs: vec![],
6758+
contribution: Some(contribution),
6759+
}),
6760+
Some((contributed_inputs, contributed_outputs)) => Some(SpliceFundingFailed {
6761+
contributed_inputs,
6762+
contributed_outputs,
6763+
contribution: Some(contribution),
6764+
}),
6765+
}
67856766
}};
67866767
}
67876768

@@ -6811,21 +6792,16 @@ where
68116792
/// Builds a [`SpliceFundingFailed`] from a contribution, filtering out inputs/outputs
68126793
/// that are still committed to a prior splice round.
68136794
fn splice_funding_failed_for(&self, contribution: FundingContribution) -> SpliceFundingFailed {
6814-
let cloned_contribution = contribution.clone();
6815-
let (mut inputs, mut outputs) = contribution.into_contributed_inputs_and_outputs();
6816-
if let Some(ref pending_splice) = self.pending_splice {
6817-
for input in pending_splice.contributed_inputs() {
6818-
inputs.retain(|i| *i != input);
6819-
}
6820-
for output in pending_splice.contributed_outputs() {
6821-
outputs.retain(|o| o.script_pubkey != output.script_pubkey);
6822-
}
6823-
}
6824-
SpliceFundingFailed {
6825-
contributed_inputs: inputs,
6826-
contributed_outputs: outputs,
6827-
contribution: Some(cloned_contribution),
6828-
}
6795+
// The contribution was never pushed to `contributions`, so `contributed_inputs()` and
6796+
// `contributed_outputs()` return only prior rounds' entries for filtering.
6797+
splice_funding_failed_for!(
6798+
self,
6799+
true,
6800+
contribution,
6801+
contributed_inputs,
6802+
contributed_outputs
6803+
)
6804+
.expect("is_initiator is true so this always returns Some")
68296805
}
68306806

68316807
fn quiescent_action_into_error(&self, action: QuiescentAction) -> QuiescentError {
@@ -6969,21 +6945,19 @@ where
69696945
);
69706946
}
69716947

6972-
let splice_funding_failed = maybe_create_splice_funding_failed!(
6973-
self,
6974-
self.pending_splice.as_mut(),
6975-
self.pending_splice.as_ref(),
6976-
take,
6977-
into_contributed_inputs_and_outputs
6978-
);
6979-
6980-
// Pop the current round's contribution, if any (acceptors may not have one). This
6981-
// must happen after `maybe_create_splice_funding_failed` for correct filtering.
6948+
// Take the funding negotiation and pop the current round's contribution, if any
6949+
// (acceptors may not have one).
69826950
let pending_splice = self
69836951
.pending_splice
69846952
.as_mut()
69856953
.expect("reset_pending_splice_state requires pending_splice");
6986-
if let Some(contribution) = pending_splice.contributions.pop() {
6954+
let is_initiator = pending_splice
6955+
.funding_negotiation
6956+
.take()
6957+
.map(|negotiation| negotiation.is_initiator())
6958+
.unwrap_or(false);
6959+
let contribution = pending_splice.contributions.pop();
6960+
if let Some(ref contribution) = contribution {
69876961
debug_assert!(
69886962
pending_splice
69896963
.last_funding_feerate_sat_per_1000_weight
@@ -6993,6 +6967,18 @@ where
69936967
);
69946968
}
69956969

6970+
// After pop, `contributed_inputs()` / `contributed_outputs()` return only prior
6971+
// rounds for filtering.
6972+
let splice_funding_failed = contribution.and_then(|contribution| {
6973+
splice_funding_failed_for!(
6974+
self,
6975+
is_initiator,
6976+
contribution,
6977+
contributed_inputs,
6978+
contributed_outputs
6979+
)
6980+
});
6981+
69966982
if self.pending_funding().is_empty() {
69976983
self.pending_splice.take();
69986984
}
@@ -7010,12 +6996,19 @@ where
70106996
return None;
70116997
}
70126998

7013-
maybe_create_splice_funding_failed!(
6999+
let pending_splice = self.pending_splice.as_ref()?;
7000+
let is_initiator = pending_splice
7001+
.funding_negotiation
7002+
.as_ref()
7003+
.map(|negotiation| negotiation.is_initiator())
7004+
.unwrap_or(false);
7005+
let contribution = pending_splice.contributions.last().cloned()?;
7006+
splice_funding_failed_for!(
70147007
self,
7015-
self.pending_splice.as_ref(),
7016-
self.pending_splice.as_ref(),
7017-
as_ref,
7018-
to_contributed_inputs_and_outputs
7008+
is_initiator,
7009+
contribution,
7010+
prior_contributed_inputs,
7011+
prior_contributed_outputs
70197012
)
70207013
}
70217014

0 commit comments

Comments
 (0)