@@ -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