@@ -13,8 +13,8 @@ use bitcoin::consensus::encode;
1313use bitcoin::constants::ChainHash;
1414use bitcoin::script::{Builder, Script, ScriptBuf, WScriptHash};
1515use bitcoin::sighash::EcdsaSighashType;
16- use bitcoin::transaction::{Transaction, TxIn, TxOut};
17- use bitcoin::{Weight, Witness} ;
16+ use bitcoin::transaction::{Transaction, TxOut};
17+ use bitcoin::Witness;
1818
1919use bitcoin::hash_types::{BlockHash, Txid};
2020use bitcoin::hashes::sha256::Hash as Sha256;
@@ -26,7 +26,7 @@ use bitcoin::secp256k1::{ecdsa::Signature, Secp256k1};
2626use bitcoin::secp256k1::{PublicKey, SecretKey};
2727#[cfg(splicing)]
2828use bitcoin::Sequence;
29- use bitcoin::{secp256k1, sighash};
29+ use bitcoin::{secp256k1, sighash, TxIn };
3030
3131use crate::chain::chaininterface::{
3232 fee_for_weight, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator,
@@ -37,18 +37,15 @@ use crate::chain::channelmonitor::{
3737};
3838use crate::chain::transaction::{OutPoint, TransactionData};
3939use crate::chain::BestBlock;
40- use crate::events::bump_transaction::BASE_INPUT_WEIGHT;
41- #[cfg(splicing)]
42- use crate::events::bump_transaction::EMPTY_SCRIPT_SIG_WEIGHT;
40+ use crate::events::bump_transaction::{BASE_INPUT_WEIGHT, EMPTY_SCRIPT_SIG_WEIGHT};
4341use crate::events::ClosureReason;
4442use crate::ln::chan_utils;
45- #[cfg(splicing)]
46- use crate::ln::chan_utils::FUNDING_TRANSACTION_WITNESS_WEIGHT;
4743use crate::ln::chan_utils::{
4844 get_commitment_transaction_number_obscure_factor, max_htlcs, second_stage_tx_fees_sat,
4945 selected_commitment_sat_per_1000_weight, ChannelPublicKeys, ChannelTransactionParameters,
5046 ClosingTransaction, CommitmentTransaction, CounterpartyChannelTransactionParameters,
5147 CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HolderCommitmentTransaction,
48+ FUNDING_TRANSACTION_WITNESS_WEIGHT,
5249};
5350use crate::ln::channel_state::{
5451 ChannelShutdownState, CounterpartyForwardingInfo, InboundHTLCDetails, InboundHTLCStateDetails,
@@ -59,6 +56,7 @@ use crate::ln::channelmanager::{
5956 PaymentClaimDetails, PendingHTLCInfo, PendingHTLCStatus, RAACommitmentOrder, SentHTLCId,
6057 BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA,
6158};
59+ use crate::ln::funding::FundingTxInput;
6260#[cfg(splicing)]
6361use crate::ln::interactivetxs::{
6462 calculate_change_output_value, AbortReason, InteractiveTxMessageSend,
@@ -5880,21 +5878,18 @@ fn get_v2_channel_reserve_satoshis(channel_value_satoshis: u64, dust_limit_satos
58805878}
58815879
58825880/// Estimate our part of the fee of the new funding transaction.
5883- /// input_count: Number of contributed inputs.
5884- /// input_satisfaction_weight: The satisfaction weight for contributed inputs.
58855881#[allow(dead_code)] // TODO(dual_funding): TODO(splicing): Remove allow once used.
58865882#[rustfmt::skip]
58875883fn estimate_v2_funding_transaction_fee(
5888- is_initiator: bool, input_count: usize, input_satisfaction_weight: Weight ,
5884+ funding_inputs: &[FundingTxInput], is_initiator: bool, is_splice: bool ,
58895885 funding_feerate_sat_per_1000_weight: u32,
58905886) -> u64 {
5891- // Inputs
5892- let mut weight = (input_count as u64) * BASE_INPUT_WEIGHT;
5887+ let mut weight: u64 = funding_inputs
5888+ .iter()
5889+ .map(|input| BASE_INPUT_WEIGHT.saturating_add(input.utxo.satisfaction_weight))
5890+ .fold(0, |total_weight, input_weight| total_weight.saturating_add(input_weight));
58935891
5894- // Witnesses
5895- weight = weight.saturating_add(input_satisfaction_weight.to_wu());
5896-
5897- // If we are the initiator, we must pay for weight of all common fields in the funding transaction.
5892+ // The initiator pays for all common fields and the shared output in the funding transaction.
58985893 if is_initiator {
58995894 weight = weight
59005895 .saturating_add(TX_COMMON_FIELDS_WEIGHT)
@@ -5903,7 +5898,15 @@ fn estimate_v2_funding_transaction_fee(
59035898 // to calculate the contributed weight, so we use an all-zero hash.
59045899 .saturating_add(get_output_weight(&ScriptBuf::new_p2wsh(
59055900 &WScriptHash::from_raw_hash(Hash::all_zeros())
5906- )).to_wu())
5901+ )).to_wu());
5902+
5903+ // The splice initiator pays for the input spending the previous funding output.
5904+ if is_splice {
5905+ weight = weight
5906+ .saturating_add(BASE_INPUT_WEIGHT)
5907+ .saturating_add(EMPTY_SCRIPT_SIG_WEIGHT)
5908+ .saturating_add(FUNDING_TRANSACTION_WITNESS_WEIGHT);
5909+ }
59075910 }
59085911
59095912 fee_for_weight(funding_feerate_sat_per_1000_weight, weight)
@@ -5918,29 +5921,16 @@ fn estimate_v2_funding_transaction_fee(
59185921#[cfg(splicing)]
59195922#[rustfmt::skip]
59205923fn check_v2_funding_inputs_sufficient(
5921- contribution_amount: i64, funding_inputs: &[(TxIn, Transaction, Weight) ], is_initiator: bool,
5924+ contribution_amount: i64, funding_inputs: &[FundingTxInput ], is_initiator: bool,
59225925 is_splice: bool, funding_feerate_sat_per_1000_weight: u32,
59235926) -> Result<u64, ChannelError> {
5924- let mut total_input_satisfaction_weight = Weight::from_wu(funding_inputs.iter().map(|(_, _, w)| w.to_wu()).sum());
5925- let mut funding_inputs_len = funding_inputs.len();
5926- if is_initiator && is_splice {
5927- // consider the weight of the input and witness needed for spending the old funding transaction
5928- funding_inputs_len += 1;
5929- total_input_satisfaction_weight +=
5930- Weight::from_wu(EMPTY_SCRIPT_SIG_WEIGHT + FUNDING_TRANSACTION_WITNESS_WEIGHT);
5931- }
5932- let estimated_fee = estimate_v2_funding_transaction_fee(is_initiator, funding_inputs_len, total_input_satisfaction_weight, funding_feerate_sat_per_1000_weight);
5927+ let estimated_fee = estimate_v2_funding_transaction_fee(
5928+ funding_inputs, is_initiator, is_splice, funding_feerate_sat_per_1000_weight,
5929+ );
59335930
59345931 let mut total_input_sats = 0u64;
5935- for (idx, input) in funding_inputs.iter().enumerate() {
5936- if let Some(output) = input.1.output.get(input.0.previous_output.vout as usize) {
5937- total_input_sats = total_input_sats.saturating_add(output.value.to_sat());
5938- } else {
5939- return Err(ChannelError::Warn(format!(
5940- "Transaction with txid {} does not have an output with vout of {} corresponding to TxIn at funding_inputs[{}]",
5941- input.1.compute_txid(), input.0.previous_output.vout, idx
5942- )));
5943- }
5932+ for FundingTxInput { utxo, .. } in funding_inputs.iter() {
5933+ total_input_sats = total_input_sats.saturating_add(utxo.output.value.to_sat());
59445934 }
59455935
59465936 // If the inputs are enough to cover intended contribution amount, with fees even when
@@ -5982,7 +5972,7 @@ pub(super) struct FundingNegotiationContext {
59825972 pub shared_funding_input: Option<SharedOwnedInput>,
59835973 /// The funding inputs we will be contributing to the channel.
59845974 #[allow(dead_code)] // TODO(dual_funding): Remove once contribution to V2 channels is enabled.
5985- pub our_funding_inputs: Vec<(TxIn, Transaction, Weight) >,
5975+ pub our_funding_inputs: Vec<FundingTxInput >,
59865976 /// The change output script. This will be used if needed or -- if not set -- generated using
59875977 /// `SignerProvider::get_destination_script`.
59885978 #[allow(dead_code)] // TODO(splicing): Remove once splicing is enabled.
@@ -6054,8 +6044,13 @@ impl FundingNegotiationContext {
60546044 }
60556045 }
60566046
6057- let funding_inputs =
6058- self.our_funding_inputs.into_iter().map(|(txin, tx, _)| (txin, tx)).collect();
6047+ let funding_inputs = self
6048+ .our_funding_inputs
6049+ .into_iter()
6050+ .map(|FundingTxInput { utxo, sequence, prevtx }| {
6051+ (TxIn { previous_output: utxo.outpoint, sequence, ..Default::default() }, prevtx)
6052+ })
6053+ .collect();
60596054
60606055 let constructor_args = InteractiveTxConstructorArgs {
60616056 entropy_source,
@@ -10608,9 +10603,8 @@ where
1060810603 /// generated by `SignerProvider::get_destination_script`.
1060910604 #[cfg(splicing)]
1061010605 pub fn splice_channel(
10611- &mut self, our_funding_contribution_satoshis: i64,
10612- our_funding_inputs: Vec<(TxIn, Transaction, Weight)>, change_script: Option<ScriptBuf>,
10613- funding_feerate_per_kw: u32, locktime: u32,
10606+ &mut self, our_funding_contribution_satoshis: i64, our_funding_inputs: Vec<FundingTxInput>,
10607+ change_script: Option<ScriptBuf>, funding_feerate_per_kw: u32, locktime: u32,
1061410608 ) -> Result<msgs::SpliceInit, APIError> {
1061510609 // Check if a splice has been initiated already.
1061610610 // Note: only a single outstanding splice is supported (per spec)
@@ -10676,21 +10670,22 @@ where
1067610670 ),
1067710671 })?;
1067810672
10679- for (txin, tx, _) in our_funding_inputs.iter() {
10673+ for FundingTxInput { utxo, prevtx, .. } in our_funding_inputs.iter() {
1068010674 const MESSAGE_TEMPLATE: msgs::TxAddInput = msgs::TxAddInput {
1068110675 channel_id: ChannelId([0; 32]),
1068210676 serial_id: 0,
1068310677 prevtx: None,
1068410678 prevtx_out: 0,
1068510679 sequence: 0,
10680+ // Mutually exclusive with prevtx, which is accounted for below.
1068610681 shared_input_txid: None,
1068710682 };
10688- let message_len = MESSAGE_TEMPLATE.serialized_length() + tx .serialized_length();
10683+ let message_len = MESSAGE_TEMPLATE.serialized_length() + prevtx .serialized_length();
1068910684 if message_len > LN_MAX_MSG_LEN {
1069010685 return Err(APIError::APIMisuseError {
1069110686 err: format!(
1069210687 "Funding input references a prevtx that is too large for tx_add_input: {}",
10693- txin.previous_output ,
10688+ utxo.outpoint ,
1069410689 ),
1069510690 });
1069610691 }
@@ -12472,7 +12467,7 @@ where
1247212467 pub fn new_outbound<ES: Deref, F: Deref, L: Deref>(
1247312468 fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP,
1247412469 counterparty_node_id: PublicKey, their_features: &InitFeatures, funding_satoshis: u64,
12475- funding_inputs: Vec<(TxIn, Transaction, Weight) >, user_id: u128, config: &UserConfig,
12470+ funding_inputs: Vec<FundingTxInput >, user_id: u128, config: &UserConfig,
1247612471 current_chain_height: u32, outbound_scid_alias: u64, funding_confirmation_target: ConfirmationTarget,
1247712472 logger: L,
1247812473 ) -> Result<Self, APIError>
@@ -12686,8 +12681,12 @@ where
1268612681 value: Amount::from_sat(funding.get_value_satoshis()),
1268712682 script_pubkey: funding.get_funding_redeemscript().to_p2wsh(),
1268812683 };
12689- let inputs_to_contribute =
12690- our_funding_inputs.into_iter().map(|(txin, tx, _)| (txin, tx)).collect();
12684+ let inputs_to_contribute = our_funding_inputs
12685+ .into_iter()
12686+ .map(|FundingTxInput { utxo, sequence, prevtx }| {
12687+ (TxIn { previous_output: utxo.outpoint, sequence, ..Default::default() }, prevtx)
12688+ })
12689+ .collect();
1269112690
1269212691 let interactive_tx_constructor = Some(InteractiveTxConstructor::new(
1269312692 InteractiveTxConstructorArgs {
@@ -14124,6 +14123,7 @@ mod tests {
1412414123 };
1412514124 use crate::ln::channel_keys::{RevocationBasepoint, RevocationKey};
1412614125 use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
14126+ use crate::ln::funding::FundingTxInput;
1412714127 use crate::ln::msgs;
1412814128 use crate::ln::msgs::{ChannelUpdate, UnsignedChannelUpdate, MAX_VALUE_MSAT};
1412914129 use crate::ln::onion_utils::{AttributionData, LocalHTLCFailureReason};
@@ -14155,12 +14155,8 @@ mod tests {
1415514155 use bitcoin::secp256k1::ffi::Signature as FFISignature;
1415614156 use bitcoin::secp256k1::{ecdsa::Signature, Secp256k1};
1415714157 use bitcoin::secp256k1::{PublicKey, SecretKey};
14158- #[cfg(splicing)]
14159- use bitcoin::transaction::TxIn;
1416014158 use bitcoin::transaction::{Transaction, TxOut, Version};
14161- #[cfg(splicing)]
14162- use bitcoin::Weight;
14163- use bitcoin::{WitnessProgram, WitnessVersion};
14159+ use bitcoin::{ScriptBuf, WPubkeyHash, WitnessProgram, WitnessVersion};
1416414160 use std::cmp;
1416514161
1416614162 #[test]
@@ -15866,54 +15862,65 @@ mod tests {
1586615862 #[rustfmt::skip]
1586715863 fn test_estimate_v2_funding_transaction_fee() {
1586815864 use crate::ln::channel::estimate_v2_funding_transaction_fee;
15869- use bitcoin::Weight;
1587015865
15871- // 2 inputs with weight 300, initiator, 2000 sat/kw feerate
15866+ let one_input = [funding_input_sats(1_000)];
15867+ let two_inputs = [funding_input_sats(1_000), funding_input_sats(1_000)];
15868+
15869+ // 2 inputs, initiator, 2000 sat/kw feerate
1587215870 assert_eq!(
15873- estimate_v2_funding_transaction_fee(true, 2, Weight::from_wu(300) , 2000),
15874- 1668
15871+ estimate_v2_funding_transaction_fee(&two_inputs, true, false , 2000),
15872+ 1520,
1587515873 );
1587615874
1587715875 // higher feerate
1587815876 assert_eq!(
15879- estimate_v2_funding_transaction_fee(true, 2, Weight::from_wu(300) , 3000),
15880- 2502
15877+ estimate_v2_funding_transaction_fee(&two_inputs, true, false , 3000),
15878+ 2280,
1588115879 );
1588215880
1588315881 // only 1 input
1588415882 assert_eq!(
15885- estimate_v2_funding_transaction_fee(true, 1, Weight::from_wu(300) , 2000),
15886- 1348
15883+ estimate_v2_funding_transaction_fee(&one_input, true, false , 2000),
15884+ 974,
1588715885 );
1588815886
15889- // 0 input weight
15887+ // 0 inputs
1589015888 assert_eq!(
15891- estimate_v2_funding_transaction_fee(true, 1, Weight::from_wu(0) , 2000),
15892- 748
15889+ estimate_v2_funding_transaction_fee(&[], true, false , 2000),
15890+ 428,
1589315891 );
1589415892
1589515893 // not initiator
1589615894 assert_eq!(
15897- estimate_v2_funding_transaction_fee(false, 1, Weight::from_wu(0), 2000),
15898- 320
15895+ estimate_v2_funding_transaction_fee(&[], false, false, 2000),
15896+ 0,
15897+ );
15898+
15899+ // splice initiator
15900+ assert_eq!(
15901+ estimate_v2_funding_transaction_fee(&one_input, true, true, 2000),
15902+ 1746,
15903+ );
15904+
15905+ // splice acceptor
15906+ assert_eq!(
15907+ estimate_v2_funding_transaction_fee(&one_input, false, true, 2000),
15908+ 546,
1589915909 );
1590015910 }
1590115911
15902- #[cfg(splicing)]
1590315912 #[rustfmt::skip]
15904- fn funding_input_sats(input_value_sats: u64) -> (TxIn, Transaction, Weight) {
15905- use crate::sign::P2WPKH_WITNESS_WEIGHT;
15906-
15907- let input_1_prev_out = TxOut { value: Amount::from_sat(input_value_sats), script_pubkey: bitcoin::ScriptBuf::default() };
15908- let input_1_prev_tx = Transaction {
15909- input: vec![], output: vec![input_1_prev_out],
15910- version: Version::TWO, lock_time: bitcoin::absolute::LockTime::ZERO,
15913+ fn funding_input_sats(input_value_sats: u64) -> FundingTxInput {
15914+ let prevout = TxOut {
15915+ value: Amount::from_sat(input_value_sats),
15916+ script_pubkey: ScriptBuf::new_p2wpkh(&WPubkeyHash::all_zeros()),
1591115917 };
15912- let input_1_txin = TxIn {
15913- previous_output: bitcoin::OutPoint { txid: input_1_prev_tx.compute_txid(), vout: 0 } ,
15914- ..Default::default()
15918+ let prevtx = Transaction {
15919+ input: vec![], output: vec![prevout] ,
15920+ version: Version::TWO, lock_time: bitcoin::absolute::LockTime::ZERO,
1591515921 };
15916- (input_1_txin, input_1_prev_tx, Weight::from_wu(P2WPKH_WITNESS_WEIGHT))
15922+
15923+ FundingTxInput::new_p2wpkh(prevtx, 0).unwrap()
1591715924 }
1591815925
1591915926 #[cfg(splicing)]
@@ -15934,7 +15941,7 @@ mod tests {
1593415941 true,
1593515942 2000,
1593615943 ).unwrap(),
15937- 2276 ,
15944+ 2292 ,
1593815945 );
1593915946
1594015947 // negative case, inputs clearly insufficient
@@ -15950,13 +15957,13 @@ mod tests {
1595015957 );
1595115958 assert_eq!(
1595215959 format!("{:?}", res.err().unwrap()),
15953- "Warn: Total input amount 100000 is lower than needed for contribution 220000, considering fees of 1738 . Need more inputs.",
15960+ "Warn: Total input amount 100000 is lower than needed for contribution 220000, considering fees of 1746 . Need more inputs.",
1595415961 );
1595515962 }
1595615963
1595715964 // barely covers
1595815965 {
15959- let expected_fee: u64 = 2276 ;
15966+ let expected_fee: u64 = 2292 ;
1596015967 assert_eq!(
1596115968 check_v2_funding_inputs_sufficient(
1596215969 (300_000 - expected_fee - 20) as i64,
@@ -15986,13 +15993,13 @@ mod tests {
1598615993 );
1598715994 assert_eq!(
1598815995 format!("{:?}", res.err().unwrap()),
15989- "Warn: Total input amount 300000 is lower than needed for contribution 298032, considering fees of 2504 . Need more inputs.",
15996+ "Warn: Total input amount 300000 is lower than needed for contribution 298032, considering fees of 2522 . Need more inputs.",
1599015997 );
1599115998 }
1599215999
1599316000 // barely covers, less fees (no extra weight, no init)
1599416001 {
15995- let expected_fee: u64 = 1076 ;
16002+ let expected_fee: u64 = 1092 ;
1599616003 assert_eq!(
1599716004 check_v2_funding_inputs_sufficient(
1599816005 (300_000 - expected_fee - 20) as i64,
0 commit comments