Skip to content

Commit 957df6c

Browse files
committed
Replace funding input tuple with struct
The funding inputs used for splicing and v2 channel establishment are passed as a tuple of txin, prevtx, and witness weight. Add a struct so that the items included can be better documented.
1 parent 98c5e18 commit 957df6c

File tree

5 files changed

+88
-54
lines changed

5 files changed

+88
-54
lines changed

lightning/src/ln/channel.rs

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use bitcoin::consensus::encode;
1313
use bitcoin::constants::ChainHash;
1414
use bitcoin::script::{Builder, Script, ScriptBuf, WScriptHash};
1515
use bitcoin::sighash::EcdsaSighashType;
16-
use bitcoin::transaction::{Transaction, TxIn, TxOut};
16+
use bitcoin::transaction::{Transaction, TxOut};
1717
use bitcoin::{Weight, Witness};
1818

1919
use bitcoin::hash_types::{BlockHash, Txid};
@@ -24,9 +24,9 @@ use bitcoin::hashes::Hash;
2424
use bitcoin::secp256k1::constants::PUBLIC_KEY_SIZE;
2525
use bitcoin::secp256k1::{ecdsa::Signature, Secp256k1};
2626
use bitcoin::secp256k1::{PublicKey, SecretKey};
27-
#[cfg(splicing)]
28-
use bitcoin::Sequence;
2927
use bitcoin::{secp256k1, sighash};
28+
#[cfg(splicing)]
29+
use bitcoin::{Sequence, TxIn};
3030

3131
use crate::chain::chaininterface::{
3232
fee_for_weight, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator,
@@ -53,7 +53,7 @@ use crate::ln::channel_state::{
5353
OutboundHTLCDetails, OutboundHTLCStateDetails,
5454
};
5555
use crate::ln::channelmanager::{
56-
self, FundingConfirmedMessage, HTLCFailureMsg, HTLCSource, OpenChannelMessage,
56+
self, FundingConfirmedMessage, FundingTxInput, HTLCFailureMsg, HTLCSource, OpenChannelMessage,
5757
PaymentClaimDetails, PendingHTLCInfo, PendingHTLCStatus, RAACommitmentOrder, SentHTLCId,
5858
BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA,
5959
};
@@ -5915,10 +5915,11 @@ fn estimate_v2_funding_transaction_fee(
59155915
#[cfg(splicing)]
59165916
#[rustfmt::skip]
59175917
fn check_v2_funding_inputs_sufficient(
5918-
contribution_amount: i64, funding_inputs: &[(TxIn, Transaction, Weight)], is_initiator: bool,
5918+
contribution_amount: i64, funding_inputs: &[FundingTxInput], is_initiator: bool,
59195919
is_splice: bool, funding_feerate_sat_per_1000_weight: u32,
59205920
) -> Result<u64, ChannelError> {
5921-
let mut total_input_witness_weight = Weight::from_wu(funding_inputs.iter().map(|(_, _, w)| w.to_wu()).sum());
5921+
let mut total_input_witness_weight =
5922+
funding_inputs.iter().map(|FundingTxInput { witness_weight, .. }| witness_weight).sum();
59225923
let mut funding_inputs_len = funding_inputs.len();
59235924
if is_initiator && is_splice {
59245925
// consider the weight of the input and witness needed for spending the old funding transaction
@@ -5928,13 +5929,13 @@ fn check_v2_funding_inputs_sufficient(
59285929
let estimated_fee = estimate_v2_funding_transaction_fee(is_initiator, funding_inputs_len, total_input_witness_weight, funding_feerate_sat_per_1000_weight);
59295930

59305931
let mut total_input_sats = 0u64;
5931-
for (idx, input) in funding_inputs.iter().enumerate() {
5932-
if let Some(output) = input.1.output.get(input.0.previous_output.vout as usize) {
5932+
for (idx, FundingTxInput { txin, prevtx, .. }) in funding_inputs.iter().enumerate() {
5933+
if let Some(output) = prevtx.output.get(txin.previous_output.vout as usize) {
59335934
total_input_sats = total_input_sats.saturating_add(output.value.to_sat());
59345935
} else {
59355936
return Err(ChannelError::Warn(format!(
59365937
"Transaction with txid {} does not have an output with vout of {} corresponding to TxIn at funding_inputs[{}]",
5937-
input.1.compute_txid(), input.0.previous_output.vout, idx
5938+
prevtx.compute_txid(), txin.previous_output.vout, idx
59385939
)));
59395940
}
59405941
}
@@ -5978,7 +5979,7 @@ pub(super) struct FundingNegotiationContext {
59785979
pub shared_funding_input: Option<SharedOwnedInput>,
59795980
/// The funding inputs we will be contributing to the channel.
59805981
#[allow(dead_code)] // TODO(dual_funding): Remove once contribution to V2 channels is enabled.
5981-
pub our_funding_inputs: Vec<(TxIn, Transaction, Weight)>,
5982+
pub our_funding_inputs: Vec<FundingTxInput>,
59825983
/// The change output script. This will be used if needed or -- if not set -- generated using
59835984
/// `SignerProvider::get_destination_script`.
59845985
#[allow(dead_code)] // TODO(splicing): Remove once splicing is enabled.
@@ -6050,8 +6051,11 @@ impl FundingNegotiationContext {
60506051
}
60516052
}
60526053

6053-
let funding_inputs =
6054-
self.our_funding_inputs.into_iter().map(|(txin, tx, _)| (txin, tx)).collect();
6054+
let funding_inputs = self
6055+
.our_funding_inputs
6056+
.into_iter()
6057+
.map(|FundingTxInput { txin, prevtx, .. }| (txin, prevtx))
6058+
.collect();
60556059

60566060
let constructor_args = InteractiveTxConstructorArgs {
60576061
entropy_source,
@@ -10604,9 +10608,8 @@ where
1060410608
/// generated by `SignerProvider::get_destination_script`.
1060510609
#[cfg(splicing)]
1060610610
pub fn splice_channel(
10607-
&mut self, our_funding_contribution_satoshis: i64,
10608-
our_funding_inputs: Vec<(TxIn, Transaction, Weight)>, change_script: Option<ScriptBuf>,
10609-
funding_feerate_per_kw: u32, locktime: u32,
10611+
&mut self, our_funding_contribution_satoshis: i64, our_funding_inputs: Vec<FundingTxInput>,
10612+
change_script: Option<ScriptBuf>, funding_feerate_per_kw: u32, locktime: u32,
1061010613
) -> Result<msgs::SpliceInit, APIError> {
1061110614
// Check if a splice has been initiated already.
1061210615
// Note: only a single outstanding splice is supported (per spec)
@@ -10672,7 +10675,7 @@ where
1067210675
),
1067310676
})?;
1067410677

10675-
for (txin, tx, _) in our_funding_inputs.iter() {
10678+
for FundingTxInput { txin, prevtx, .. } in our_funding_inputs.iter() {
1067610679
const MESSAGE_TEMPLATE: msgs::TxAddInput = msgs::TxAddInput {
1067710680
channel_id: ChannelId([0; 32]),
1067810681
serial_id: 0,
@@ -10681,7 +10684,7 @@ where
1068110684
sequence: 0,
1068210685
shared_input_txid: None,
1068310686
};
10684-
let message_len = MESSAGE_TEMPLATE.serialized_length() + tx.serialized_length();
10687+
let message_len = MESSAGE_TEMPLATE.serialized_length() + prevtx.serialized_length();
1068510688
if message_len > LN_MAX_MSG_LEN {
1068610689
return Err(APIError::APIMisuseError {
1068710690
err: format!(
@@ -12466,7 +12469,7 @@ where
1246612469
pub fn new_outbound<ES: Deref, F: Deref, L: Deref>(
1246712470
fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP,
1246812471
counterparty_node_id: PublicKey, their_features: &InitFeatures, funding_satoshis: u64,
12469-
funding_inputs: Vec<(TxIn, Transaction, Weight)>, user_id: u128, config: &UserConfig,
12472+
funding_inputs: Vec<FundingTxInput>, user_id: u128, config: &UserConfig,
1247012473
current_chain_height: u32, outbound_scid_alias: u64, funding_confirmation_target: ConfirmationTarget,
1247112474
logger: L,
1247212475
) -> Result<Self, APIError>
@@ -12680,8 +12683,10 @@ where
1268012683
value: Amount::from_sat(funding.get_value_satoshis()),
1268112684
script_pubkey: funding.get_funding_redeemscript().to_p2wsh(),
1268212685
};
12683-
let inputs_to_contribute =
12684-
our_funding_inputs.into_iter().map(|(txin, tx, _)| (txin, tx)).collect();
12686+
let inputs_to_contribute = our_funding_inputs
12687+
.into_iter()
12688+
.map(|FundingTxInput { txin, prevtx, .. }| (txin, prevtx))
12689+
.collect();
1268512690

1268612691
let interactive_tx_constructor = Some(InteractiveTxConstructor::new(
1268712692
InteractiveTxConstructorArgs {
@@ -14117,6 +14122,8 @@ mod tests {
1411714122
TOTAL_BITCOIN_SUPPLY_SATOSHIS,
1411814123
};
1411914124
use crate::ln::channel_keys::{RevocationBasepoint, RevocationKey};
14125+
#[cfg(splicing)]
14126+
use crate::ln::channelmanager::FundingTxInput;
1412014127
use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
1412114128
use crate::ln::msgs;
1412214129
use crate::ln::msgs::{ChannelUpdate, UnsignedChannelUpdate, MAX_VALUE_MSAT};
@@ -14153,7 +14160,7 @@ mod tests {
1415314160
use bitcoin::transaction::TxIn;
1415414161
use bitcoin::transaction::{Transaction, TxOut, Version};
1415514162
#[cfg(splicing)]
14156-
use bitcoin::Weight;
14163+
use bitcoin::{ScriptBuf, Weight};
1415714164
use bitcoin::{WitnessProgram, WitnessVersion};
1415814165
use std::cmp;
1415914166

@@ -15895,19 +15902,21 @@ mod tests {
1589515902

1589615903
#[cfg(splicing)]
1589715904
#[rustfmt::skip]
15898-
fn funding_input_sats(input_value_sats: u64) -> (TxIn, Transaction, Weight) {
15905+
fn funding_input_sats(input_value_sats: u64) -> FundingTxInput {
1589915906
use crate::sign::P2WPKH_WITNESS_WEIGHT;
1590015907

15901-
let input_1_prev_out = TxOut { value: Amount::from_sat(input_value_sats), script_pubkey: bitcoin::ScriptBuf::default() };
15902-
let input_1_prev_tx = Transaction {
15903-
input: vec![], output: vec![input_1_prev_out],
15908+
let prevout = TxOut { value: Amount::from_sat(input_value_sats), script_pubkey: ScriptBuf::default() };
15909+
let prevtx = Transaction {
15910+
input: vec![], output: vec![prevout],
1590415911
version: Version::TWO, lock_time: bitcoin::absolute::LockTime::ZERO,
1590515912
};
15906-
let input_1_txin = TxIn {
15907-
previous_output: bitcoin::OutPoint { txid: input_1_prev_tx.compute_txid(), vout: 0 },
15913+
let txin = TxIn {
15914+
previous_output: bitcoin::OutPoint { txid: prevtx.compute_txid(), vout: 0 },
1590815915
..Default::default()
1590915916
};
15910-
(input_1_txin, input_1_prev_tx, Weight::from_wu(P2WPKH_WITNESS_WEIGHT))
15917+
let witness_weight = Weight::from_wu(P2WPKH_WITNESS_WEIGHT);
15918+
15919+
FundingTxInput { txin, prevtx, witness_weight }
1591115920
}
1591215921

1591315922
#[cfg(splicing)]

lightning/src/ln/channelmanager.rs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ use bitcoin::hashes::{Hash, HashEngine, HmacEngine};
3030

3131
use bitcoin::secp256k1::Secp256k1;
3232
use bitcoin::secp256k1::{PublicKey, SecretKey};
33-
use bitcoin::{secp256k1, Sequence, SignedAmount};
3433
#[cfg(splicing)]
35-
use bitcoin::{ScriptBuf, TxIn, Weight};
34+
use bitcoin::ScriptBuf;
35+
use bitcoin::{secp256k1, Sequence, SignedAmount, TxIn, Weight};
3636

3737
use crate::blinded_path::message::MessageForwardNode;
3838
use crate::blinded_path::message::{AsyncPaymentsContext, OffersContext};
@@ -200,6 +200,26 @@ pub use crate::ln::outbound_payment::{
200200
};
201201
use crate::ln::script::ShutdownScript;
202202

203+
/// An input to contribute to a channel's funding transaction either when using the v2 channel
204+
/// establishment protocol or when splicing.
205+
#[derive(Clone)]
206+
pub struct FundingTxInput {
207+
/// An input for the funding transaction used to cover the channel contributions.
208+
pub txin: TxIn,
209+
210+
/// The transaction containing the unspent [`TxOut`] referenced by [`txin`].
211+
///
212+
/// [`TxOut`]: bitcoin::TxOut
213+
/// [`txin`]: Self::txin
214+
pub prevtx: Transaction,
215+
216+
/// The weight of the witness that is needed to spend the [`TxOut`] referenced by [`txin`].
217+
///
218+
/// [`TxOut`]: bitcoin::TxOut
219+
/// [`txin`]: Self::txin
220+
pub witness_weight: Weight,
221+
}
222+
203223
// We hold various information about HTLC relay in the HTLC objects in Channel itself:
204224
//
205225
// Upon receipt of an HTLC from a peer, we'll give it a PendingHTLCStatus indicating if it should
@@ -4459,7 +4479,7 @@ where
44594479
#[rustfmt::skip]
44604480
pub fn splice_channel(
44614481
&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, our_funding_contribution_satoshis: i64,
4462-
our_funding_inputs: Vec<(TxIn, Transaction, Weight)>, change_script: Option<ScriptBuf>,
4482+
our_funding_inputs: Vec<FundingTxInput>, change_script: Option<ScriptBuf>,
44634483
funding_feerate_per_kw: u32, locktime: Option<u32>,
44644484
) -> Result<(), APIError> {
44654485
let mut res = Ok(());
@@ -4480,9 +4500,8 @@ where
44804500
#[cfg(splicing)]
44814501
fn internal_splice_channel(
44824502
&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey,
4483-
our_funding_contribution_satoshis: i64,
4484-
our_funding_inputs: Vec<(TxIn, Transaction, Weight)>, change_script: Option<ScriptBuf>,
4485-
funding_feerate_per_kw: u32, locktime: Option<u32>,
4503+
our_funding_contribution_satoshis: i64, our_funding_inputs: Vec<FundingTxInput>,
4504+
change_script: Option<ScriptBuf>, funding_feerate_per_kw: u32, locktime: Option<u32>,
44864505
) -> Result<(), APIError> {
44874506
let per_peer_state = self.per_peer_state.read().unwrap();
44884507

lightning/src/ln/dual_funding_tests.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use {
1818
},
1919
crate::ln::channel::PendingV2Channel,
2020
crate::ln::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint, RevocationBasepoint},
21+
crate::ln::channelmanager::FundingTxInput,
2122
crate::ln::functional_test_utils::*,
2223
crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, MessageSendEvent},
2324
crate::ln::msgs::{CommitmentSigned, TxAddInput, TxAddOutput, TxComplete, TxSignatures},
@@ -82,12 +83,13 @@ fn do_test_v2_channel_establishment(session: V2ChannelEstablishmentTestSession)
8283
&RevocationBasepoint::from(open_channel_v2_msg.common_fields.revocation_basepoint),
8384
);
8485

86+
let FundingTxInput { txin, prevtx, .. } = &initiator_funding_inputs[0];
8587
let tx_add_input_msg = TxAddInput {
8688
channel_id,
8789
serial_id: 2, // Even serial_id from initiator.
88-
prevtx: Some(initiator_funding_inputs[0].1.clone()),
90+
prevtx: Some(prevtx.clone()),
8991
prevtx_out: 0,
90-
sequence: initiator_funding_inputs[0].0.sequence.0,
92+
sequence: txin.sequence.0,
9193
shared_input_txid: None,
9294
};
9395
let input_value = tx_add_input_msg.prevtx.as_ref().unwrap().output

lightning/src/ln/functional_test_utils.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ use crate::events::{
2323
};
2424
use crate::ln::chan_utils::{commitment_tx_base_weight, COMMITMENT_TX_WEIGHT_PER_HTLC};
2525
use crate::ln::channelmanager::{
26-
AChannelManager, ChainParameters, ChannelManager, ChannelManagerReadArgs, PaymentId,
27-
RAACommitmentOrder, RecipientOnionFields, MIN_CLTV_EXPIRY_DELTA,
26+
AChannelManager, ChainParameters, ChannelManager, ChannelManagerReadArgs, FundingTxInput,
27+
PaymentId, RAACommitmentOrder, RecipientOnionFields, MIN_CLTV_EXPIRY_DELTA,
2828
};
2929
use crate::ln::msgs;
3030
use crate::ln::msgs::{
@@ -1440,7 +1440,7 @@ fn internal_create_funding_transaction<'a, 'b, 'c>(
14401440
/// Return the inputs (with prev tx), and the total witness weight for these inputs
14411441
pub fn create_dual_funding_utxos_with_prev_txs(
14421442
node: &Node<'_, '_, '_>, utxo_values_in_satoshis: &[u64],
1443-
) -> Vec<(TxIn, Transaction, Weight)> {
1443+
) -> Vec<FundingTxInput> {
14441444
// Ensure we have unique transactions per node by using the locktime.
14451445
let tx = Transaction {
14461446
version: TxVersion::TWO,
@@ -1462,17 +1462,17 @@ pub fn create_dual_funding_utxos_with_prev_txs(
14621462

14631463
let mut inputs = vec![];
14641464
for i in 0..utxo_values_in_satoshis.len() {
1465-
inputs.push((
1466-
TxIn {
1465+
inputs.push(FundingTxInput {
1466+
txin: TxIn {
14671467
previous_output: OutPoint { txid: tx.compute_txid(), index: i as u16 }
14681468
.into_bitcoin_outpoint(),
14691469
script_sig: ScriptBuf::new(),
14701470
sequence: Sequence::ZERO,
14711471
witness: Witness::new(),
14721472
},
1473-
tx.clone(),
1474-
Weight::from_wu(P2WPKH_WITNESS_WEIGHT),
1475-
));
1473+
prevtx: tx.clone(),
1474+
witness_weight: Weight::from_wu(P2WPKH_WITNESS_WEIGHT),
1475+
});
14761476
}
14771477

14781478
inputs

lightning/src/ln/interactivetxs.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use crate::chain::chaininterface::fee_for_weight;
2828
use crate::events::bump_transaction::{BASE_INPUT_WEIGHT, EMPTY_SCRIPT_SIG_WEIGHT};
2929
use crate::ln::chan_utils::FUNDING_TRANSACTION_WITNESS_WEIGHT;
3030
use crate::ln::channel::{FundingNegotiationContext, TOTAL_BITCOIN_SUPPLY_SATOSHIS};
31+
use crate::ln::channelmanager::FundingTxInput;
3132
use crate::ln::msgs;
3233
use crate::ln::msgs::{MessageSendEvent, SerialId, TxSignatures};
3334
use crate::ln::types::ChannelId;
@@ -2075,17 +2076,18 @@ pub(super) fn calculate_change_output_value(
20752076

20762077
let mut total_input_satoshis = 0u64;
20772078
let mut our_funding_inputs_weight = 0u64;
2078-
for (txin, tx, _) in context.our_funding_inputs.iter() {
2079-
let txid = tx.compute_txid();
2079+
for FundingTxInput { txin, prevtx, witness_weight } in context.our_funding_inputs.iter() {
2080+
let txid = prevtx.compute_txid();
20802081
if txin.previous_output.txid != txid {
20812082
return Err(AbortReason::PrevTxOutInvalid);
20822083
}
2083-
let output = tx
2084+
let output = prevtx
20842085
.output
20852086
.get(txin.previous_output.vout as usize)
20862087
.ok_or(AbortReason::PrevTxOutInvalid)?;
20872088
total_input_satoshis = total_input_satoshis.saturating_add(output.value.to_sat());
2088-
let weight = estimate_input_weight(output).to_wu();
2089+
2090+
let weight = BASE_INPUT_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT + witness_weight.to_wu();
20892091
our_funding_inputs_weight = our_funding_inputs_weight.saturating_add(weight);
20902092
}
20912093

@@ -2128,6 +2130,7 @@ pub(super) fn calculate_change_output_value(
21282130
mod tests {
21292131
use crate::chain::chaininterface::{fee_for_weight, FEERATE_FLOOR_SATS_PER_KW};
21302132
use crate::ln::channel::{FundingNegotiationContext, TOTAL_BITCOIN_SUPPLY_SATOSHIS};
2133+
use crate::ln::channelmanager::FundingTxInput;
21312134
use crate::ln::interactivetxs::{
21322135
calculate_change_output_value, generate_holder_serial_id, AbortReason,
21332136
HandleTxCompleteValue, InteractiveTxConstructor, InteractiveTxConstructorArgs,
@@ -2155,7 +2158,8 @@ mod tests {
21552158
use super::{
21562159
get_output_weight, AddingRole, ConstructedTransaction, InteractiveTxOutput,
21572160
InteractiveTxSigningSession, NegotiatedTxInput, OutputOwned, P2TR_INPUT_WEIGHT_LOWER_BOUND,
2158-
P2WPKH_INPUT_WEIGHT_LOWER_BOUND, P2WSH_INPUT_WEIGHT_LOWER_BOUND, TX_COMMON_FIELDS_WEIGHT,
2161+
P2WPKH_INPUT_WEIGHT_LOWER_BOUND, P2WPKH_WITNESS_WEIGHT, P2WSH_INPUT_WEIGHT_LOWER_BOUND,
2162+
TX_COMMON_FIELDS_WEIGHT,
21592163
};
21602164

21612165
const TEST_FEERATE_SATS_PER_KW: u32 = FEERATE_FLOOR_SATS_PER_KW * 10;
@@ -3147,23 +3151,23 @@ mod tests {
31473151
let inputs = input_prevouts
31483152
.iter()
31493153
.map(|txout| {
3150-
let tx = Transaction {
3154+
let prevtx = Transaction {
31513155
input: Vec::new(),
31523156
output: vec![(*txout).clone()],
31533157
lock_time: AbsoluteLockTime::ZERO,
31543158
version: Version::TWO,
31553159
};
3156-
let txid = tx.compute_txid();
3160+
let txid = prevtx.compute_txid();
31573161
let txin = TxIn {
31583162
previous_output: OutPoint { txid, vout: 0 },
31593163
script_sig: ScriptBuf::new(),
31603164
sequence: Sequence::ZERO,
31613165
witness: Witness::new(),
31623166
};
3163-
let weight = Weight::ZERO;
3164-
(txin, tx, weight)
3167+
let witness_weight = Weight::from_wu(P2WPKH_WITNESS_WEIGHT);
3168+
FundingTxInput { txin, prevtx, witness_weight }
31653169
})
3166-
.collect::<Vec<(TxIn, Transaction, Weight)>>();
3170+
.collect();
31673171
let our_contributed = 110_000;
31683172
let txout = TxOut { value: Amount::from_sat(10_000), script_pubkey: ScriptBuf::new() };
31693173
let outputs = vec![txout];

0 commit comments

Comments
 (0)