@@ -11950,31 +11950,33 @@ where
1195011950 });
1195111951 }
1195211952
11953- let (min_rbf_feerate, prior_contribution) =
11954- if let Ok(min_rbf_feerate) = self.can_initiate_rbf() {
11955- // A previous splice was negotiated but not yet locked. The user's splice
11956- // will be an RBF, so provide the minimum RBF feerate and prior contribution.
11957- let prior = self.build_prior_contribution();
11958- (Some(min_rbf_feerate), prior)
11959- } else if let Some(negotiation) = self
11960- .pending_splice
11961- .as_ref()
11962- .and_then(|pending_splice| pending_splice.funding_negotiation.as_ref())
11963- {
11964- // A splice is currently being negotiated.
11965- // - If the negotiation succeeds, the user's splice will need to satisfy the RBF
11966- // feerate requirement. Derive the minimum RBF feerate from the negotiation's
11967- // feerate so the user can choose an appropriate feerate.
11968- // - If the negotiation fails (e.g., tx_abort), the splice will proceed as a fresh
11969- // splice instead.
11970- let prev_feerate = negotiation.funding_feerate_sat_per_1000_weight();
11971- let min_feerate_kwu = ((prev_feerate as u64) * 25).div_ceil(24);
11972- (Some(FeeRate::from_sat_per_kwu(min_feerate_kwu)), None)
11973- } else {
11974- // No RBF feerate to derive — either a fresh splice or a pending splice that
11975- // can't be RBF'd (e.g., splice_locked already exchanged).
11976- (None, None)
11977- };
11953+ let (min_rbf_feerate, prior_contribution) = if self.is_rbf_compatible().is_err() {
11954+ // Channel can never RBF (e.g., zero-conf).
11955+ (None, None)
11956+ } else if let Ok(min_rbf_feerate) = self.can_initiate_rbf() {
11957+ // A previous splice was negotiated but not yet locked. The user's splice
11958+ // will be an RBF, so provide the minimum RBF feerate and prior contribution.
11959+ let prior = self.build_prior_contribution();
11960+ (Some(min_rbf_feerate), prior)
11961+ } else if let Some(negotiation) = self
11962+ .pending_splice
11963+ .as_ref()
11964+ .and_then(|pending_splice| pending_splice.funding_negotiation.as_ref())
11965+ {
11966+ // A splice is currently being negotiated.
11967+ // - If the negotiation succeeds, the user's splice will need to satisfy the RBF
11968+ // feerate requirement. Derive the minimum RBF feerate from the negotiation's
11969+ // feerate so the user can choose an appropriate feerate.
11970+ // - If the negotiation fails (e.g., tx_abort), the splice will proceed as a fresh
11971+ // splice instead.
11972+ let prev_feerate = negotiation.funding_feerate_sat_per_1000_weight();
11973+ let min_feerate_kwu = ((prev_feerate as u64) * 25).div_ceil(24);
11974+ (Some(FeeRate::from_sat_per_kwu(min_feerate_kwu)), None)
11975+ } else {
11976+ // No RBF feerate to derive — either a fresh splice or a pending splice that
11977+ // can't be RBF'd (e.g., splice_locked already exchanged).
11978+ (None, None)
11979+ };
1197811980
1197911981 let funding_txo = self.funding.get_funding_txo().expect("funding_txo should be set");
1198011982 let previous_utxo =
@@ -12000,13 +12002,19 @@ where
1200012002 Some(PriorContribution::new(prior.clone(), holder_balance))
1200112003 }
1200212004
12003- fn can_initiate_rbf(&self) -> Result<FeeRate, String> {
12005+ /// Returns whether this channel can ever RBF, independent of splice state.
12006+ fn is_rbf_compatible(&self) -> Result<(), String> {
1200412007 if self.context.minimum_depth(&self.funding) == Some(0) {
1200512008 return Err(format!(
12006- "Channel {} has option_zeroconf, cannot RBF splice ",
12009+ "Channel {} has option_zeroconf, cannot RBF",
1200712010 self.context.channel_id(),
1200812011 ));
1200912012 }
12013+ Ok(())
12014+ }
12015+
12016+ fn can_initiate_rbf(&self) -> Result<FeeRate, String> {
12017+ self.is_rbf_compatible()?;
1201012018
1201112019 let pending_splice = match &self.pending_splice {
1201212020 Some(pending_splice) => pending_splice,
@@ -12586,12 +12594,7 @@ where
1258612594 return Err(ChannelError::WarnAndDisconnect("Quiescence needed for RBF".to_owned()));
1258712595 }
1258812596
12589- if self.context.minimum_depth(&self.funding) == Some(0) {
12590- return Err(ChannelError::WarnAndDisconnect(format!(
12591- "Channel {} has option_zeroconf, cannot RBF splice",
12592- self.context.channel_id(),
12593- )));
12594- }
12597+ self.is_rbf_compatible().map_err(|msg| ChannelError::WarnAndDisconnect(msg))?;
1259512598
1259612599 let pending_splice = match &self.pending_splice {
1259712600 Some(pending_splice) => pending_splice,
0 commit comments