@@ -2443,13 +2443,42 @@ impl PendingSplice {
2443
2443
}
2444
2444
}
2445
2445
2446
+ pub(crate) struct SpliceInstructions {
2447
+ our_funding_contribution_satoshis: i64,
2448
+ our_funding_inputs: Vec<(TxIn, Transaction, Weight)>,
2449
+ change_script: Option<ScriptBuf>,
2450
+ funding_feerate_per_kw: u32,
2451
+ locktime: u32,
2452
+ }
2453
+
2454
+ impl_writeable_tlv_based!(SpliceInstructions, {
2455
+ (1, our_funding_contribution_satoshis, required),
2456
+ (3, our_funding_inputs, required_vec),
2457
+ (5, change_script, option),
2458
+ (7, funding_feerate_per_kw, required),
2459
+ (9, locktime, required),
2460
+ });
2461
+
2446
2462
pub(crate) enum QuiescentAction {
2447
- // TODO: Make this test-only once we have another variant (as some code requires *a* variant).
2463
+ Splice(SpliceInstructions),
2464
+ #[cfg(any(test, fuzzing))]
2448
2465
DoNothing,
2449
2466
}
2450
2467
2468
+ pub(crate) enum StfuResponse {
2469
+ Stfu(msgs::Stfu),
2470
+ #[cfg_attr(not(splicing), allow(unused))]
2471
+ SpliceInit(msgs::SpliceInit),
2472
+ }
2473
+
2474
+ #[cfg(any(test, fuzzing))]
2451
2475
impl_writeable_tlv_based_enum_upgradable!(QuiescentAction,
2452
- (99, DoNothing) => {},
2476
+ (0, DoNothing) => {},
2477
+ {1, Splice} => (),
2478
+ );
2479
+ #[cfg(not(any(test, fuzzing)))]
2480
+ impl_writeable_tlv_based_enum_upgradable!(QuiescentAction,,
2481
+ {1, Splice} => (),
2453
2482
);
2454
2483
2455
2484
/// Wrapper around a [`Transaction`] useful for caching the result of [`Transaction::compute_txid`].
@@ -5926,7 +5955,7 @@ fn estimate_v2_funding_transaction_fee(
5926
5955
fn check_v2_funding_inputs_sufficient(
5927
5956
contribution_amount: i64, funding_inputs: &[(TxIn, Transaction, Weight)], is_initiator: bool,
5928
5957
is_splice: bool, funding_feerate_sat_per_1000_weight: u32,
5929
- ) -> Result<u64, ChannelError > {
5958
+ ) -> Result<u64, String > {
5930
5959
let mut total_input_witness_weight = Weight::from_wu(funding_inputs.iter().map(|(_, _, w)| w.to_wu()).sum());
5931
5960
let mut funding_inputs_len = funding_inputs.len();
5932
5961
if is_initiator && is_splice {
@@ -5941,10 +5970,10 @@ fn check_v2_funding_inputs_sufficient(
5941
5970
if let Some(output) = input.1.output.get(input.0.previous_output.vout as usize) {
5942
5971
total_input_sats = total_input_sats.saturating_add(output.value.to_sat());
5943
5972
} else {
5944
- return Err(ChannelError::Warn( format!(
5973
+ return Err(format!(
5945
5974
"Transaction with txid {} does not have an output with vout of {} corresponding to TxIn at funding_inputs[{}]",
5946
5975
input.1.compute_txid(), input.0.previous_output.vout, idx
5947
- ))) ;
5976
+ ));
5948
5977
}
5949
5978
}
5950
5979
@@ -5961,10 +5990,10 @@ fn check_v2_funding_inputs_sufficient(
5961
5990
5962
5991
let minimal_input_amount_needed = contribution_amount.saturating_add(estimated_fee as i64);
5963
5992
if (total_input_sats as i64) < minimal_input_amount_needed {
5964
- Err(ChannelError::Warn( format!(
5993
+ Err(format!(
5965
5994
"Total input amount {} is lower than needed for contribution {}, considering fees of {}. Need more inputs.",
5966
5995
total_input_sats, contribution_amount, estimated_fee,
5967
- )))
5996
+ ))
5968
5997
} else {
5969
5998
Ok(estimated_fee)
5970
5999
}
@@ -10614,11 +10643,14 @@ where
10614
10643
/// - `change_script`: an option change output script. If `None` and needed, one will be
10615
10644
/// generated by `SignerProvider::get_destination_script`.
10616
10645
#[cfg(splicing)]
10617
- pub fn splice_channel(
10646
+ pub fn splice_channel<L: Deref> (
10618
10647
&mut self, our_funding_contribution_satoshis: i64,
10619
10648
our_funding_inputs: Vec<(TxIn, Transaction, Weight)>, change_script: Option<ScriptBuf>,
10620
- funding_feerate_per_kw: u32, locktime: u32,
10621
- ) -> Result<msgs::SpliceInit, APIError> {
10649
+ funding_feerate_per_kw: u32, locktime: u32, logger: &L,
10650
+ ) -> Result<Option<msgs::Stfu>, APIError>
10651
+ where
10652
+ L::Target: Logger,
10653
+ {
10622
10654
// Check if a splice has been initiated already.
10623
10655
// Note: only a single outstanding splice is supported (per spec)
10624
10656
if self.pending_splice.is_some() {
@@ -10671,11 +10703,44 @@ where
10671
10703
err,
10672
10704
),
10673
10705
})?;
10674
- // Convert inputs
10675
- let mut funding_inputs = Vec::new();
10676
- for (tx_in, tx, _w) in our_funding_inputs.into_iter() {
10677
- let tx16 = TransactionU16LenLimited::new(tx)
10678
- .map_err(|_e| APIError::APIMisuseError { err: format!("Too large transaction") })?;
10706
+
10707
+ // TODO(splicing): Check that transactions aren't too big for the splice_init message here.
10708
+
10709
+ let action = QuiescentAction::Splice(SpliceInstructions {
10710
+ our_funding_contribution_satoshis,
10711
+ our_funding_inputs,
10712
+ change_script,
10713
+ funding_feerate_per_kw,
10714
+ locktime,
10715
+ });
10716
+ self.propose_quiescence(logger, action)
10717
+ .map_err(|e| APIError::APIMisuseError { err: e.to_owned() })
10718
+ }
10719
+
10720
+ #[cfg(splicing)]
10721
+ fn send_splice_init(
10722
+ &mut self, instructions: SpliceInstructions,
10723
+ ) -> Result<msgs::SpliceInit, String> {
10724
+ let SpliceInstructions {
10725
+ our_funding_contribution_satoshis,
10726
+ our_funding_inputs,
10727
+ change_script,
10728
+ funding_feerate_per_kw,
10729
+ locktime,
10730
+ } = instructions;
10731
+
10732
+ // Check that the channel value hasn't changed out from under us.
10733
+ let _fee = check_v2_funding_inputs_sufficient(
10734
+ our_funding_contribution_satoshis,
10735
+ &our_funding_inputs,
10736
+ true,
10737
+ true,
10738
+ funding_feerate_per_kw,
10739
+ )?;
10740
+
10741
+ let mut funding_inputs = Vec::with_capacity(our_funding_inputs.len());
10742
+ for (tx_in, tx, _weight) in our_funding_inputs {
10743
+ let tx16 = TransactionU16LenLimited::new(tx).map_err(|_e| "tx too big".to_owned())?;
10679
10744
funding_inputs.push((tx_in, tx16));
10680
10745
}
10681
10746
@@ -11567,23 +11632,21 @@ where
11567
11632
);
11568
11633
}
11569
11634
11570
- #[cfg(any(test, fuzzing))]
11635
+ #[cfg(any(splicing, test, fuzzing))]
11571
11636
#[rustfmt::skip]
11572
11637
pub fn propose_quiescence<L: Deref>(
11573
11638
&mut self, logger: &L, action: QuiescentAction,
11574
- ) -> Result<Option<msgs::Stfu>, ChannelError >
11639
+ ) -> Result<Option<msgs::Stfu>, &'static str >
11575
11640
where
11576
11641
L::Target: Logger,
11577
11642
{
11578
11643
log_debug!(logger, "Attempting to initiate quiescence");
11579
11644
11580
11645
if !self.context.is_usable() {
11581
- return Err(ChannelError::Ignore(
11582
- "Channel is not in a usable state to propose quiescence".to_owned()
11583
- ));
11646
+ return Err("Channel is not in a usable state to propose quiescence");
11584
11647
}
11585
11648
if self.context.post_quiescence_action.is_some() {
11586
- return Err(ChannelError::Ignore( "Channel is already quiescing".to_owned()) );
11649
+ return Err("Channel is already quiescing");
11587
11650
}
11588
11651
11589
11652
self.context.post_quiescence_action = Some(action);
@@ -11604,7 +11667,7 @@ where
11604
11667
11605
11668
// Assumes we are either awaiting quiescence or our counterparty has requested quiescence.
11606
11669
#[rustfmt::skip]
11607
- pub fn send_stfu<L: Deref>(&mut self, logger: &L) -> Result<msgs::Stfu, ChannelError >
11670
+ pub fn send_stfu<L: Deref>(&mut self, logger: &L) -> Result<msgs::Stfu, &'static str >
11608
11671
where
11609
11672
L::Target: Logger,
11610
11673
{
@@ -11618,9 +11681,7 @@ where
11618
11681
if self.context.is_waiting_on_peer_pending_channel_update()
11619
11682
|| self.context.is_monitor_or_signer_pending_channel_update()
11620
11683
{
11621
- return Err(ChannelError::Ignore(
11622
- "We cannot send `stfu` while state machine is pending".to_owned()
11623
- ));
11684
+ return Err("We cannot send `stfu` while state machine is pending")
11624
11685
}
11625
11686
11626
11687
let initiator = if self.context.channel_state.is_remote_stfu_sent() {
@@ -11646,7 +11707,7 @@ where
11646
11707
#[rustfmt::skip]
11647
11708
pub fn stfu<L: Deref>(
11648
11709
&mut self, msg: &msgs::Stfu, logger: &L
11649
- ) -> Result<Option<msgs::Stfu >, ChannelError> where L::Target: Logger {
11710
+ ) -> Result<Option<StfuResponse >, ChannelError> where L::Target: Logger {
11650
11711
if self.context.channel_state.is_quiescent() {
11651
11712
return Err(ChannelError::Warn("Channel is already quiescent".to_owned()));
11652
11713
}
@@ -11677,7 +11738,10 @@ where
11677
11738
self.context.channel_state.set_remote_stfu_sent();
11678
11739
11679
11740
log_debug!(logger, "Received counterparty stfu proposing quiescence");
11680
- return self.send_stfu(logger).map(|stfu| Some(stfu));
11741
+ return self
11742
+ .send_stfu(logger)
11743
+ .map(|stfu| Some(StfuResponse::Stfu(stfu)))
11744
+ .map_err(|e| ChannelError::Ignore(e.to_owned()));
11681
11745
}
11682
11746
11683
11747
// We already sent `stfu` and are now processing theirs. It may be in response to ours, or
@@ -11718,6 +11782,13 @@ where
11718
11782
"Internal Error: Didn't have anything to do after reaching quiescence".to_owned()
11719
11783
));
11720
11784
},
11785
+ Some(QuiescentAction::Splice(_instructions)) => {
11786
+ #[cfg(splicing)]
11787
+ return self.send_splice_init(_instructions)
11788
+ .map(|splice_init| Some(StfuResponse::SpliceInit(splice_init)))
11789
+ .map_err(|e| ChannelError::Ignore(e.to_owned()));
11790
+ },
11791
+ #[cfg(any(test, fuzzing))]
11721
11792
Some(QuiescentAction::DoNothing) => {
11722
11793
// In quiescence test we want to just hang out here, letting the test manually
11723
11794
// leave quiescence.
@@ -11750,7 +11821,10 @@ where
11750
11821
|| (self.context.channel_state.is_remote_stfu_sent()
11751
11822
&& !self.context.channel_state.is_local_stfu_sent())
11752
11823
{
11753
- return self.send_stfu(logger).map(|stfu| Some(stfu));
11824
+ return self
11825
+ .send_stfu(logger)
11826
+ .map(|stfu| Some(stfu))
11827
+ .map_err(|e| ChannelError::Ignore(e.to_owned()));
11754
11828
}
11755
11829
11756
11830
// We're either:
@@ -15920,8 +15994,8 @@ mod tests {
15920
15994
2000,
15921
15995
);
15922
15996
assert_eq!(
15923
- format!("{:?}", res.err().unwrap() ),
15924
- "Warn: Total input amount 100000 is lower than needed for contribution 220000, considering fees of 1730. Need more inputs.",
15997
+ res.err().unwrap(),
15998
+ "Total input amount 100000 is lower than needed for contribution 220000, considering fees of 1730. Need more inputs.",
15925
15999
);
15926
16000
}
15927
16001
@@ -15956,8 +16030,8 @@ mod tests {
15956
16030
2200,
15957
16031
);
15958
16032
assert_eq!(
15959
- format!("{:?}", res.err().unwrap() ),
15960
- "Warn: Total input amount 300000 is lower than needed for contribution 298032, considering fees of 2495. Need more inputs.",
16033
+ res.err().unwrap(),
16034
+ "Total input amount 300000 is lower than needed for contribution 298032, considering fees of 2495. Need more inputs.",
15961
16035
);
15962
16036
}
15963
16037
0 commit comments