@@ -2463,13 +2463,46 @@ impl PendingSplice {
2463
2463
}
2464
2464
}
2465
2465
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
+
2466
2486
pub(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))]
2468
2489
DoNothing,
2469
2490
}
2470
2491
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))]
2471
2499
impl_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} => (),
2473
2506
);
2474
2507
2475
2508
/// 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
6158
6191
fn check_splice_contribution_sufficient(
6159
6192
channel_balance: Amount, contribution: &SpliceContribution, is_initiator: bool,
6160
6193
funding_feerate: FeeRate,
6161
- ) -> Result<Amount, ChannelError > {
6194
+ ) -> Result<Amount, String > {
6162
6195
let contribution_amount = contribution.value();
6163
6196
if contribution_amount < SignedAmount::ZERO {
6164
6197
let estimated_fee = Amount::from_sat(estimate_v2_funding_transaction_fee(
@@ -6172,10 +6205,10 @@ fn check_splice_contribution_sufficient(
6172
6205
if channel_balance >= contribution_amount.unsigned_abs() + estimated_fee {
6173
6206
Ok(estimated_fee)
6174
6207
} 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
+ ))
6179
6212
}
6180
6213
} else {
6181
6214
check_v2_funding_inputs_sufficient(
@@ -6242,7 +6275,7 @@ fn estimate_v2_funding_transaction_fee(
6242
6275
fn check_v2_funding_inputs_sufficient(
6243
6276
contribution_amount: i64, funding_inputs: &[FundingTxInput], is_initiator: bool,
6244
6277
is_splice: bool, funding_feerate_sat_per_1000_weight: u32,
6245
- ) -> Result<u64, ChannelError > {
6278
+ ) -> Result<u64, String > {
6246
6279
let estimated_fee = estimate_v2_funding_transaction_fee(
6247
6280
funding_inputs, &[], is_initiator, is_splice, funding_feerate_sat_per_1000_weight,
6248
6281
);
@@ -6265,10 +6298,9 @@ fn check_v2_funding_inputs_sufficient(
6265
6298
6266
6299
let minimal_input_amount_needed = contribution_amount.saturating_add(estimated_fee as i64);
6267
6300
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
+ ))
6272
6304
} else {
6273
6305
Ok(estimated_fee)
6274
6306
}
@@ -11022,9 +11054,13 @@ where
11022
11054
/// - `change_script`: an option change output script. If `None` and needed, one will be
11023
11055
/// generated by `SignerProvider::get_destination_script`.
11024
11056
#[cfg(splicing)]
11025
- pub fn splice_channel(
11057
+ pub fn splice_channel<L: Deref> (
11026
11058
&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
+ {
11028
11064
if self.holder_commitment_point.current_point().is_none() {
11029
11065
return Err(APIError::APIMisuseError {
11030
11066
err: format!(
@@ -11036,7 +11072,7 @@ where
11036
11072
11037
11073
// Check if a splice has been initiated already.
11038
11074
// 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() {
11040
11076
return Err(APIError::APIMisuseError {
11041
11077
err: format!(
11042
11078
"Channel {} cannot be spliced, as it has already a splice pending",
@@ -11054,8 +11090,6 @@ where
11054
11090
});
11055
11091
}
11056
11092
11057
- // TODO(splicing): check for quiescence
11058
-
11059
11093
let our_funding_contribution = contribution.value();
11060
11094
if our_funding_contribution == SignedAmount::ZERO {
11061
11095
return Err(APIError::APIMisuseError {
@@ -11150,8 +11184,50 @@ where
11150
11184
}
11151
11185
}
11152
11186
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
+
11154
11192
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();
11155
11231
let funding_negotiation_context = FundingNegotiationContext {
11156
11232
is_initiator: true,
11157
11233
our_funding_contribution: adjusted_funding_contribution,
@@ -11307,6 +11383,10 @@ where
11307
11383
ES::Target: EntropySource,
11308
11384
L::Target: Logger,
11309
11385
{
11386
+ if !self.context.channel_state.is_quiescent() {
11387
+ return Err(ChannelError::WarnAndDisconnect("Quiescence needed to splice".to_owned()));
11388
+ }
11389
+
11310
11390
let our_funding_contribution = SignedAmount::from_sat(our_funding_contribution_satoshis);
11311
11391
let splice_funding = self.validate_splice_init(msg, our_funding_contribution)?;
11312
11392
@@ -11346,6 +11426,11 @@ where
11346
11426
})?;
11347
11427
debug_assert!(interactive_tx_constructor.take_initiator_first_message().is_none());
11348
11428
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
+
11349
11434
let funding_pubkey = splice_funding.get_holder_pubkeys().funding_pubkey;
11350
11435
11351
11436
self.pending_splice = Some(PendingSplice {
@@ -12094,23 +12179,21 @@ where
12094
12179
);
12095
12180
}
12096
12181
12097
- #[cfg(any(test, fuzzing))]
12182
+ #[cfg(any(splicing, test, fuzzing))]
12098
12183
#[rustfmt::skip]
12099
12184
pub fn propose_quiescence<L: Deref>(
12100
12185
&mut self, logger: &L, action: QuiescentAction,
12101
- ) -> Result<Option<msgs::Stfu>, ChannelError >
12186
+ ) -> Result<Option<msgs::Stfu>, &'static str >
12102
12187
where
12103
12188
L::Target: Logger,
12104
12189
{
12105
12190
log_debug!(logger, "Attempting to initiate quiescence");
12106
12191
12107
12192
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");
12111
12194
}
12112
12195
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" );
12114
12197
}
12115
12198
12116
12199
self.quiescent_action = Some(action);
@@ -12131,7 +12214,7 @@ where
12131
12214
12132
12215
// Assumes we are either awaiting quiescence or our counterparty has requested quiescence.
12133
12216
#[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 >
12135
12218
where
12136
12219
L::Target: Logger,
12137
12220
{
@@ -12145,9 +12228,7 @@ where
12145
12228
if self.context.is_waiting_on_peer_pending_channel_update()
12146
12229
|| self.context.is_monitor_or_signer_pending_channel_update()
12147
12230
{
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")
12151
12232
}
12152
12233
12153
12234
let initiator = if self.context.channel_state.is_remote_stfu_sent() {
@@ -12173,7 +12254,7 @@ where
12173
12254
#[rustfmt::skip]
12174
12255
pub fn stfu<L: Deref>(
12175
12256
&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 {
12177
12258
if self.context.channel_state.is_quiescent() {
12178
12259
return Err(ChannelError::Warn("Channel is already quiescent".to_owned()));
12179
12260
}
@@ -12204,7 +12285,10 @@ where
12204
12285
self.context.channel_state.set_remote_stfu_sent();
12205
12286
12206
12287
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()));
12208
12292
}
12209
12293
12210
12294
// We already sent `stfu` and are now processing theirs. It may be in response to ours, or
@@ -12245,6 +12329,13 @@ where
12245
12329
"Internal Error: Didn't have anything to do after reaching quiescence".to_owned()
12246
12330
));
12247
12331
},
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))]
12248
12339
Some(QuiescentAction::DoNothing) => {
12249
12340
// In quiescence test we want to just hang out here, letting the test manually
12250
12341
// leave quiescence.
@@ -12277,7 +12368,10 @@ where
12277
12368
|| (self.context.channel_state.is_remote_stfu_sent()
12278
12369
&& !self.context.channel_state.is_local_stfu_sent())
12279
12370
{
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()));
12281
12375
}
12282
12376
12283
12377
// We're either:
@@ -16478,8 +16572,8 @@ mod tests {
16478
16572
2000,
16479
16573
);
16480
16574
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.",
16483
16577
);
16484
16578
}
16485
16579
@@ -16514,8 +16608,8 @@ mod tests {
16514
16608
2200,
16515
16609
);
16516
16610
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.",
16519
16613
);
16520
16614
}
16521
16615
0 commit comments