Skip to content

Commit 3e57ec4

Browse files
committed
Use struct instead of enum for SpliceContribution
When adding support for mixed splice-in and splice-out, the contribution amount will need to be computed based on the splice-in and splice-out values. Rather than add a third variant to SpliceContribution, which could have an invalid contribution amount, use a more general struct that can represent splice-in, splice-out, and mixed. Constructors are provided for the typical splice-in and splice-out case whereas support for the mixed case will be added in an independent change.
1 parent de384ff commit 3e57ec4

File tree

4 files changed

+152
-200
lines changed

4 files changed

+152
-200
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 24 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1860,11 +1860,8 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
18601860

18611861
0xa0 => {
18621862
let input = FundingTxInput::new_p2wpkh(coinbase_tx.clone(), 0).unwrap();
1863-
let contribution = SpliceContribution::SpliceIn {
1864-
value: Amount::from_sat(10_000),
1865-
inputs: vec![input],
1866-
change_script: None,
1867-
};
1863+
let contribution =
1864+
SpliceContribution::splice_in(Amount::from_sat(10_000), vec![input], None);
18681865
let funding_feerate_sat_per_kw = fee_est_a.ret_val.load(atomic::Ordering::Acquire);
18691866
if let Err(e) = nodes[0].splice_channel(
18701867
&chan_a_id,
@@ -1882,11 +1879,8 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
18821879
},
18831880
0xa1 => {
18841881
let input = FundingTxInput::new_p2wpkh(coinbase_tx.clone(), 1).unwrap();
1885-
let contribution = SpliceContribution::SpliceIn {
1886-
value: Amount::from_sat(10_000),
1887-
inputs: vec![input],
1888-
change_script: None,
1889-
};
1882+
let contribution =
1883+
SpliceContribution::splice_in(Amount::from_sat(10_000), vec![input], None);
18901884
let funding_feerate_sat_per_kw = fee_est_b.ret_val.load(atomic::Ordering::Acquire);
18911885
if let Err(e) = nodes[1].splice_channel(
18921886
&chan_a_id,
@@ -1904,11 +1898,8 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
19041898
},
19051899
0xa2 => {
19061900
let input = FundingTxInput::new_p2wpkh(coinbase_tx.clone(), 0).unwrap();
1907-
let contribution = SpliceContribution::SpliceIn {
1908-
value: Amount::from_sat(10_000),
1909-
inputs: vec![input],
1910-
change_script: None,
1911-
};
1901+
let contribution =
1902+
SpliceContribution::splice_in(Amount::from_sat(10_000), vec![input], None);
19121903
let funding_feerate_sat_per_kw = fee_est_b.ret_val.load(atomic::Ordering::Acquire);
19131904
if let Err(e) = nodes[1].splice_channel(
19141905
&chan_b_id,
@@ -1926,11 +1917,8 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
19261917
},
19271918
0xa3 => {
19281919
let input = FundingTxInput::new_p2wpkh(coinbase_tx.clone(), 1).unwrap();
1929-
let contribution = SpliceContribution::SpliceIn {
1930-
value: Amount::from_sat(10_000),
1931-
inputs: vec![input],
1932-
change_script: None,
1933-
};
1920+
let contribution =
1921+
SpliceContribution::splice_in(Amount::from_sat(10_000), vec![input], None);
19341922
let funding_feerate_sat_per_kw = fee_est_c.ret_val.load(atomic::Ordering::Acquire);
19351923
if let Err(e) = nodes[2].splice_channel(
19361924
&chan_b_id,
@@ -1958,12 +1946,10 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
19581946
.map(|chan| chan.outbound_capacity_msat)
19591947
.unwrap();
19601948
if outbound_capacity_msat >= 20_000_000 {
1961-
let contribution = SpliceContribution::SpliceOut {
1962-
outputs: vec![TxOut {
1963-
value: Amount::from_sat(MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS),
1964-
script_pubkey: coinbase_tx.output[0].script_pubkey.clone(),
1965-
}],
1966-
};
1949+
let contribution = SpliceContribution::splice_out(vec![TxOut {
1950+
value: Amount::from_sat(MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS),
1951+
script_pubkey: coinbase_tx.output[0].script_pubkey.clone(),
1952+
}]);
19671953
let funding_feerate_sat_per_kw =
19681954
fee_est_a.ret_val.load(atomic::Ordering::Acquire);
19691955
if let Err(e) = nodes[0].splice_channel(
@@ -1989,12 +1975,10 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
19891975
.map(|chan| chan.outbound_capacity_msat)
19901976
.unwrap();
19911977
if outbound_capacity_msat >= 20_000_000 {
1992-
let contribution = SpliceContribution::SpliceOut {
1993-
outputs: vec![TxOut {
1994-
value: Amount::from_sat(MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS),
1995-
script_pubkey: coinbase_tx.output[1].script_pubkey.clone(),
1996-
}],
1997-
};
1978+
let contribution = SpliceContribution::splice_out(vec![TxOut {
1979+
value: Amount::from_sat(MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS),
1980+
script_pubkey: coinbase_tx.output[1].script_pubkey.clone(),
1981+
}]);
19981982
let funding_feerate_sat_per_kw =
19991983
fee_est_b.ret_val.load(atomic::Ordering::Acquire);
20001984
if let Err(e) = nodes[1].splice_channel(
@@ -2020,12 +2004,10 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
20202004
.map(|chan| chan.outbound_capacity_msat)
20212005
.unwrap();
20222006
if outbound_capacity_msat >= 20_000_000 {
2023-
let contribution = SpliceContribution::SpliceOut {
2024-
outputs: vec![TxOut {
2025-
value: Amount::from_sat(MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS),
2026-
script_pubkey: coinbase_tx.output[1].script_pubkey.clone(),
2027-
}],
2028-
};
2007+
let contribution = SpliceContribution::splice_out(vec![TxOut {
2008+
value: Amount::from_sat(MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS),
2009+
script_pubkey: coinbase_tx.output[1].script_pubkey.clone(),
2010+
}]);
20292011
let funding_feerate_sat_per_kw =
20302012
fee_est_b.ret_val.load(atomic::Ordering::Acquire);
20312013
if let Err(e) = nodes[1].splice_channel(
@@ -2051,12 +2033,10 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
20512033
.map(|chan| chan.outbound_capacity_msat)
20522034
.unwrap();
20532035
if outbound_capacity_msat >= 20_000_000 {
2054-
let contribution = SpliceContribution::SpliceOut {
2055-
outputs: vec![TxOut {
2056-
value: Amount::from_sat(MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS),
2057-
script_pubkey: coinbase_tx.output[2].script_pubkey.clone(),
2058-
}],
2059-
};
2036+
let contribution = SpliceContribution::splice_out(vec![TxOut {
2037+
value: Amount::from_sat(MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS),
2038+
script_pubkey: coinbase_tx.output[2].script_pubkey.clone(),
2039+
}]);
20602040
let funding_feerate_sat_per_kw =
20612041
fee_est_c.ret_val.load(atomic::Ordering::Acquire);
20622042
if let Err(e) = nodes[2].splice_channel(

lightning-tests/src/upgrade_downgrade_tests.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -441,12 +441,10 @@ fn do_test_0_1_htlc_forward_after_splice(fail_htlc: bool) {
441441
reconnect_b_c_args.send_announcement_sigs = (true, true);
442442
reconnect_nodes(reconnect_b_c_args);
443443

444-
let contribution = SpliceContribution::SpliceOut {
445-
outputs: vec![TxOut {
446-
value: Amount::from_sat(1_000),
447-
script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(),
448-
}],
449-
};
444+
let contribution = SpliceContribution::splice_out(vec![TxOut {
445+
value: Amount::from_sat(1_000),
446+
script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(),
447+
}]);
450448
let splice_tx = splice_channel(&nodes[0], &nodes[1], ChannelId(chan_id_bytes_a), contribution);
451449
for node in nodes.iter() {
452450
mine_transaction(node, &splice_tx);

lightning/src/ln/funding.rs

Lines changed: 43 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -20,69 +20,62 @@ use crate::sign::{P2TR_KEY_PATH_WITNESS_WEIGHT, P2WPKH_WITNESS_WEIGHT};
2020

2121
/// The components of a splice's funding transaction that are contributed by one party.
2222
#[derive(Debug, Clone)]
23-
pub enum SpliceContribution {
24-
/// When funds are added to a channel.
25-
SpliceIn {
26-
/// The amount to contribute to the splice.
27-
value: Amount,
28-
29-
/// The inputs included in the splice's funding transaction to meet the contributed amount
30-
/// plus fees. Any excess amount will be sent to a change output.
31-
inputs: Vec<FundingTxInput>,
32-
33-
/// An optional change output script. This will be used if needed or, when not set,
34-
/// generated using [`SignerProvider::get_destination_script`].
35-
///
36-
/// [`SignerProvider::get_destination_script`]: crate::sign::SignerProvider::get_destination_script
37-
change_script: Option<ScriptBuf>,
38-
},
39-
/// When funds are removed from a channel.
40-
SpliceOut {
41-
/// The outputs to include in the splice's funding transaction. The total value of all
42-
/// outputs plus fees will be the amount that is removed.
43-
outputs: Vec<TxOut>,
44-
},
23+
pub struct SpliceContribution {
24+
/// The amount to contribute to the splice.
25+
value: SignedAmount,
26+
27+
/// The inputs included in the splice's funding transaction to meet the contributed amount
28+
/// plus fees. Any excess amount will be sent to a change output.
29+
inputs: Vec<FundingTxInput>,
30+
31+
/// The outputs to include in the splice's funding transaction. The total value of all
32+
/// outputs plus fees will be the amount that is removed.
33+
outputs: Vec<TxOut>,
34+
35+
/// An optional change output script. This will be used if needed or, when not set,
36+
/// generated using [`SignerProvider::get_destination_script`].
37+
///
38+
/// [`SignerProvider::get_destination_script`]: crate::sign::SignerProvider::get_destination_script
39+
change_script: Option<ScriptBuf>,
4540
}
4641

4742
impl SpliceContribution {
43+
/// Creates a contribution for when funds are only added to a channel.
44+
pub fn splice_in(
45+
value: Amount, inputs: Vec<FundingTxInput>, change_script: Option<ScriptBuf>,
46+
) -> Self {
47+
let value_added = value.to_signed().unwrap_or(SignedAmount::MAX);
48+
49+
Self { value: value_added, inputs, outputs: vec![], change_script }
50+
}
51+
52+
/// Creates a contribution for when funds are only removed from a channel.
53+
pub fn splice_out(outputs: Vec<TxOut>) -> Self {
54+
let value_removed = outputs
55+
.iter()
56+
.map(|txout| txout.value)
57+
.sum::<Amount>()
58+
.to_signed()
59+
.unwrap_or(SignedAmount::MAX);
60+
61+
Self { value: -value_removed, inputs: vec![], outputs, change_script: None }
62+
}
63+
4864
pub(super) fn value(&self) -> SignedAmount {
49-
match self {
50-
SpliceContribution::SpliceIn { value, .. } => {
51-
value.to_signed().unwrap_or(SignedAmount::MAX)
52-
},
53-
SpliceContribution::SpliceOut { outputs } => {
54-
let value_removed = outputs
55-
.iter()
56-
.map(|txout| txout.value)
57-
.sum::<Amount>()
58-
.to_signed()
59-
.unwrap_or(SignedAmount::MAX);
60-
-value_removed
61-
},
62-
}
65+
self.value
6366
}
6467

6568
pub(super) fn inputs(&self) -> &[FundingTxInput] {
66-
match self {
67-
SpliceContribution::SpliceIn { inputs, .. } => &inputs[..],
68-
SpliceContribution::SpliceOut { .. } => &[],
69-
}
69+
&self.inputs[..]
7070
}
7171

7272
pub(super) fn outputs(&self) -> &[TxOut] {
73-
match self {
74-
SpliceContribution::SpliceIn { .. } => &[],
75-
SpliceContribution::SpliceOut { outputs } => &outputs[..],
76-
}
73+
&self.outputs[..]
7774
}
7875

7976
pub(super) fn into_tx_parts(self) -> (Vec<FundingTxInput>, Vec<TxOut>, Option<ScriptBuf>) {
80-
match self {
81-
SpliceContribution::SpliceIn { inputs, change_script, .. } => {
82-
(inputs, vec![], change_script)
83-
},
84-
SpliceContribution::SpliceOut { outputs } => (vec![], outputs, None),
85-
}
77+
let SpliceContribution { value: _, inputs, outputs, change_script } = self;
78+
(inputs, outputs, change_script)
8679
}
8780
}
8881

0 commit comments

Comments
 (0)