@@ -2463,13 +2463,46 @@ impl PendingSplice {
24632463 }
24642464}
24652465
2466+ pub(crate) struct SpliceInstructions {
2467+ adjusted_funding_contribution: SignedAmount,
2468+ our_funding_inputs: Vec<FundingTxInput>,
2469+ our_funding_outputs: Vec<TxOut>,
2470+ change_script: Option<ScriptBuf>,
2471+ funding_feerate_per_kw: u32,
2472+ locktime: u32,
2473+ original_funding_txo: OutPoint,
2474+ }
2475+
2476+ impl_writeable_tlv_based!(SpliceInstructions, {
2477+ (1, adjusted_funding_contribution, required),
2478+ (3, our_funding_inputs, required_vec),
2479+ (5, our_funding_outputs, required_vec),
2480+ (7, change_script, option),
2481+ (9, funding_feerate_per_kw, required),
2482+ (11, locktime, required),
2483+ (13, original_funding_txo, required),
2484+ });
2485+
24662486pub(crate) enum QuiescentAction {
2467- // TODO: Make this test-only once we have another variant (as some code requires *a* variant).
2487+ Splice(SpliceInstructions),
2488+ #[cfg(any(test, fuzzing))]
24682489 DoNothing,
24692490}
24702491
2492+ pub(crate) enum StfuResponse {
2493+ Stfu(msgs::Stfu),
2494+ #[cfg_attr(not(splicing), allow(unused))]
2495+ SpliceInit(msgs::SpliceInit),
2496+ }
2497+
2498+ #[cfg(any(test, fuzzing))]
24712499impl_writeable_tlv_based_enum_upgradable!(QuiescentAction,
2472- (99, DoNothing) => {},
2500+ (0, DoNothing) => {},
2501+ {1, Splice} => (),
2502+ );
2503+ #[cfg(not(any(test, fuzzing)))]
2504+ impl_writeable_tlv_based_enum_upgradable!(QuiescentAction,,
2505+ {1, Splice} => (),
24732506);
24742507
24752508/// Wrapper around a [`Transaction`] useful for caching the result of [`Transaction::compute_txid`].
@@ -6158,7 +6191,7 @@ fn get_v2_channel_reserve_satoshis(channel_value_satoshis: u64, dust_limit_satos
61586191fn check_splice_contribution_sufficient(
61596192 channel_balance: Amount, contribution: &SpliceContribution, is_initiator: bool,
61606193 funding_feerate: FeeRate,
6161- ) -> Result<Amount, ChannelError > {
6194+ ) -> Result<Amount, String > {
61626195 let contribution_amount = contribution.value();
61636196 if contribution_amount < SignedAmount::ZERO {
61646197 let estimated_fee = Amount::from_sat(estimate_v2_funding_transaction_fee(
@@ -6172,10 +6205,10 @@ fn check_splice_contribution_sufficient(
61726205 if channel_balance >= contribution_amount.unsigned_abs() + estimated_fee {
61736206 Ok(estimated_fee)
61746207 } else {
6175- Err(ChannelError::Warn( format!(
6176- "Available channel balance {} is lower than needed for splicing out {}, considering fees of {}",
6177- channel_balance, contribution_amount.unsigned_abs(), estimated_fee ,
6178- )))
6208+ Err(format!(
6209+ "Available channel balance {channel_balance } is lower than needed for splicing out {}, considering fees of {estimated_fee }",
6210+ contribution_amount.unsigned_abs(),
6211+ ))
61796212 }
61806213 } else {
61816214 check_v2_funding_inputs_sufficient(
@@ -6242,7 +6275,7 @@ fn estimate_v2_funding_transaction_fee(
62426275fn check_v2_funding_inputs_sufficient(
62436276 contribution_amount: i64, funding_inputs: &[FundingTxInput], is_initiator: bool,
62446277 is_splice: bool, funding_feerate_sat_per_1000_weight: u32,
6245- ) -> Result<u64, ChannelError > {
6278+ ) -> Result<u64, String > {
62466279 let estimated_fee = estimate_v2_funding_transaction_fee(
62476280 funding_inputs, &[], is_initiator, is_splice, funding_feerate_sat_per_1000_weight,
62486281 );
@@ -6265,10 +6298,9 @@ fn check_v2_funding_inputs_sufficient(
62656298
62666299 let minimal_input_amount_needed = contribution_amount.saturating_add(estimated_fee as i64);
62676300 if (total_input_sats as i64) < minimal_input_amount_needed {
6268- Err(ChannelError::Warn(format!(
6269- "Total input amount {} is lower than needed for contribution {}, considering fees of {}. Need more inputs.",
6270- total_input_sats, contribution_amount, estimated_fee,
6271- )))
6301+ Err(format!(
6302+ "Total input amount {total_input_sats} is lower than needed for contribution {contribution_amount}, considering fees of {estimated_fee}. Need more inputs.",
6303+ ))
62726304 } else {
62736305 Ok(estimated_fee)
62746306 }
@@ -11022,9 +11054,13 @@ where
1102211054 /// - `change_script`: an option change output script. If `None` and needed, one will be
1102311055 /// generated by `SignerProvider::get_destination_script`.
1102411056 #[cfg(splicing)]
11025- pub fn splice_channel(
11057+ pub fn splice_channel<L: Deref> (
1102611058 &mut self, contribution: SpliceContribution, funding_feerate_per_kw: u32, locktime: u32,
11027- ) -> Result<msgs::SpliceInit, APIError> {
11059+ logger: &L,
11060+ ) -> Result<Option<msgs::Stfu>, APIError>
11061+ where
11062+ L::Target: Logger,
11063+ {
1102811064 if self.holder_commitment_point.current_point().is_none() {
1102911065 return Err(APIError::APIMisuseError {
1103011066 err: format!(
@@ -11036,7 +11072,7 @@ where
1103611072
1103711073 // Check if a splice has been initiated already.
1103811074 // Note: only a single outstanding splice is supported (per spec)
11039- if self.pending_splice.is_some() {
11075+ if self.pending_splice.is_some() || self.quiescent_action.is_some() {
1104011076 return Err(APIError::APIMisuseError {
1104111077 err: format!(
1104211078 "Channel {} cannot be spliced, as it has already a splice pending",
@@ -11054,8 +11090,6 @@ where
1105411090 });
1105511091 }
1105611092
11057- // TODO(splicing): check for quiescence
11058-
1105911093 let our_funding_contribution = contribution.value();
1106011094 if our_funding_contribution == SignedAmount::ZERO {
1106111095 return Err(APIError::APIMisuseError {
@@ -11150,8 +11184,50 @@ where
1115011184 }
1115111185 }
1115211186
11153- let prev_funding_input = self.funding.to_splice_funding_input();
11187+ let original_funding_txo = self.funding.get_funding_txo().ok_or_else(|| {
11188+ debug_assert!(false);
11189+ APIError::APIMisuseError { err: "Channel isn't yet fully funded".to_owned() }
11190+ })?;
11191+
1115411192 let (our_funding_inputs, our_funding_outputs, change_script) = contribution.into_tx_parts();
11193+
11194+ let action = QuiescentAction::Splice(SpliceInstructions {
11195+ adjusted_funding_contribution,
11196+ our_funding_inputs,
11197+ our_funding_outputs,
11198+ change_script,
11199+ funding_feerate_per_kw,
11200+ locktime,
11201+ original_funding_txo,
11202+ });
11203+ self.propose_quiescence(logger, action)
11204+ .map_err(|e| APIError::APIMisuseError { err: e.to_owned() })
11205+ }
11206+
11207+ #[cfg(splicing)]
11208+ fn send_splice_init(
11209+ &mut self, instructions: SpliceInstructions,
11210+ ) -> Result<msgs::SpliceInit, String> {
11211+ let SpliceInstructions {
11212+ adjusted_funding_contribution,
11213+ our_funding_inputs,
11214+ our_funding_outputs,
11215+ change_script,
11216+ funding_feerate_per_kw,
11217+ locktime,
11218+ original_funding_txo,
11219+ } = instructions;
11220+
11221+ // Check if a splice has been initiated already.
11222+ // Note: only a single outstanding splice is supported (per spec)
11223+ if self.pending_splice.is_some() {
11224+ return Err(format!(
11225+ "Channel {} cannot be spliced, as it has already a splice pending",
11226+ self.context.channel_id(),
11227+ ));
11228+ }
11229+
11230+ let prev_funding_input = self.funding.to_splice_funding_input();
1115511231 let funding_negotiation_context = FundingNegotiationContext {
1115611232 is_initiator: true,
1115711233 our_funding_contribution: adjusted_funding_contribution,
@@ -11307,6 +11383,10 @@ where
1130711383 ES::Target: EntropySource,
1130811384 L::Target: Logger,
1130911385 {
11386+ if !self.context.channel_state.is_quiescent() {
11387+ return Err(ChannelError::WarnAndDisconnect("Quiescence needed to splice".to_owned()));
11388+ }
11389+
1131011390 let our_funding_contribution = SignedAmount::from_sat(our_funding_contribution_satoshis);
1131111391 let splice_funding = self.validate_splice_init(msg, our_funding_contribution)?;
1131211392
@@ -11346,6 +11426,11 @@ where
1134611426 })?;
1134711427 debug_assert!(interactive_tx_constructor.take_initiator_first_message().is_none());
1134811428
11429+ // TODO(splicing): if quiescent_action is set, integrate what the user wants to do into the
11430+ // counterparty-initiated splice. For always-on nodes this probably isn't a useful
11431+ // optimization, but for often-offline nodes it may be, as we may connect and immediately
11432+ // go into splicing from both sides.
11433+
1134911434 let funding_pubkey = splice_funding.get_holder_pubkeys().funding_pubkey;
1135011435
1135111436 self.pending_splice = Some(PendingSplice {
@@ -12094,23 +12179,21 @@ where
1209412179 );
1209512180 }
1209612181
12097- #[cfg(any(test, fuzzing))]
12182+ #[cfg(any(splicing, test, fuzzing))]
1209812183 #[rustfmt::skip]
1209912184 pub fn propose_quiescence<L: Deref>(
1210012185 &mut self, logger: &L, action: QuiescentAction,
12101- ) -> Result<Option<msgs::Stfu>, ChannelError >
12186+ ) -> Result<Option<msgs::Stfu>, &'static str >
1210212187 where
1210312188 L::Target: Logger,
1210412189 {
1210512190 log_debug!(logger, "Attempting to initiate quiescence");
1210612191
1210712192 if !self.context.is_usable() {
12108- return Err(ChannelError::Ignore(
12109- "Channel is not in a usable state to propose quiescence".to_owned()
12110- ));
12193+ return Err("Channel is not in a usable state to propose quiescence");
1211112194 }
1211212195 if self.quiescent_action.is_some() {
12113- return Err(ChannelError::Ignore( "Channel is already quiescing".to_owned()) );
12196+ return Err("Channel already has a pending quiescent action and cannot start another" );
1211412197 }
1211512198
1211612199 self.quiescent_action = Some(action);
@@ -12131,7 +12214,7 @@ where
1213112214
1213212215 // Assumes we are either awaiting quiescence or our counterparty has requested quiescence.
1213312216 #[rustfmt::skip]
12134- pub fn send_stfu<L: Deref>(&mut self, logger: &L) -> Result<msgs::Stfu, ChannelError >
12217+ pub fn send_stfu<L: Deref>(&mut self, logger: &L) -> Result<msgs::Stfu, &'static str >
1213512218 where
1213612219 L::Target: Logger,
1213712220 {
@@ -12145,9 +12228,7 @@ where
1214512228 if self.context.is_waiting_on_peer_pending_channel_update()
1214612229 || self.context.is_monitor_or_signer_pending_channel_update()
1214712230 {
12148- return Err(ChannelError::Ignore(
12149- "We cannot send `stfu` while state machine is pending".to_owned()
12150- ));
12231+ return Err("We cannot send `stfu` while state machine is pending")
1215112232 }
1215212233
1215312234 let initiator = if self.context.channel_state.is_remote_stfu_sent() {
@@ -12173,7 +12254,7 @@ where
1217312254 #[rustfmt::skip]
1217412255 pub fn stfu<L: Deref>(
1217512256 &mut self, msg: &msgs::Stfu, logger: &L
12176- ) -> Result<Option<msgs::Stfu >, ChannelError> where L::Target: Logger {
12257+ ) -> Result<Option<StfuResponse >, ChannelError> where L::Target: Logger {
1217712258 if self.context.channel_state.is_quiescent() {
1217812259 return Err(ChannelError::Warn("Channel is already quiescent".to_owned()));
1217912260 }
@@ -12204,7 +12285,10 @@ where
1220412285 self.context.channel_state.set_remote_stfu_sent();
1220512286
1220612287 log_debug!(logger, "Received counterparty stfu proposing quiescence");
12207- return self.send_stfu(logger).map(|stfu| Some(stfu));
12288+ return self
12289+ .send_stfu(logger)
12290+ .map(|stfu| Some(StfuResponse::Stfu(stfu)))
12291+ .map_err(|e| ChannelError::Ignore(e.to_owned()));
1220812292 }
1220912293
1221012294 // We already sent `stfu` and are now processing theirs. It may be in response to ours, or
@@ -12245,6 +12329,13 @@ where
1224512329 "Internal Error: Didn't have anything to do after reaching quiescence".to_owned()
1224612330 ));
1224712331 },
12332+ Some(QuiescentAction::Splice(_instructions)) => {
12333+ #[cfg(splicing)]
12334+ return self.send_splice_init(_instructions)
12335+ .map(|splice_init| Some(StfuResponse::SpliceInit(splice_init)))
12336+ .map_err(|e| ChannelError::WarnAndDisconnect(e.to_owned()));
12337+ },
12338+ #[cfg(any(test, fuzzing))]
1224812339 Some(QuiescentAction::DoNothing) => {
1224912340 // In quiescence test we want to just hang out here, letting the test manually
1225012341 // leave quiescence.
@@ -12277,7 +12368,10 @@ where
1227712368 || (self.context.channel_state.is_remote_stfu_sent()
1227812369 && !self.context.channel_state.is_local_stfu_sent())
1227912370 {
12280- return self.send_stfu(logger).map(|stfu| Some(stfu));
12371+ return self
12372+ .send_stfu(logger)
12373+ .map(|stfu| Some(stfu))
12374+ .map_err(|e| ChannelError::Ignore(e.to_owned()));
1228112375 }
1228212376
1228312377 // We're either:
@@ -16478,8 +16572,8 @@ mod tests {
1647816572 2000,
1647916573 );
1648016574 assert_eq!(
16481- format!("{:?}", res.err().unwrap() ),
16482- "Warn: Total input amount 100000 is lower than needed for contribution 220000, considering fees of 1746. Need more inputs.",
16575+ res.err().unwrap(),
16576+ "Total input amount 100000 is lower than needed for contribution 220000, considering fees of 1746. Need more inputs.",
1648316577 );
1648416578 }
1648516579
@@ -16514,8 +16608,8 @@ mod tests {
1651416608 2200,
1651516609 );
1651616610 assert_eq!(
16517- format!("{:?}", res.err().unwrap() ),
16518- "Warn: Total input amount 300000 is lower than needed for contribution 298032, considering fees of 2522. Need more inputs.",
16611+ res.err().unwrap(),
16612+ "Total input amount 300000 is lower than needed for contribution 298032, considering fees of 2522. Need more inputs.",
1651916613 );
1652016614 }
1652116615
0 commit comments