diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index 10e2cd1c7e8..dbe8f40b745 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -3464,9 +3464,11 @@ impl ChannelMonitorImpl { let channel_parameters = &self.onchain_tx_handler.channel_transaction_parameters.as_counterparty_broadcastable(); + let nondust_htlcs = nondust_htlcs.iter_mut().map(|(htlc, _)| htlc).collect(); + CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number, to_broadcaster_value, to_countersignatory_value, broadcaster_funding_key, - countersignatory_funding_key, keys, feerate_per_kw, &mut nondust_htlcs, + countersignatory_funding_key, keys, feerate_per_kw, nondust_htlcs, channel_parameters) } diff --git a/lightning/src/ln/chan_utils.rs b/lightning/src/ln/chan_utils.rs index ae76308f0ce..9e51a863f3b 100644 --- a/lightning/src/ln/chan_utils.rs +++ b/lightning/src/ln/chan_utils.rs @@ -1135,7 +1135,8 @@ impl HolderCommitmentTransaction { for _ in 0..htlcs.len() { counterparty_htlc_sigs.push(dummy_sig); } - let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, 0, 0, dummy_key.clone(), dummy_key.clone(), keys, 0, htlcs, &channel_parameters.as_counterparty_broadcastable()); + let htlc_muts = htlcs.iter_mut().map(|(htlc, _)| htlc).collect(); + let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, 0, 0, dummy_key.clone(), dummy_key.clone(), keys, 0, htlc_muts, &channel_parameters.as_counterparty_broadcastable()); htlcs.sort_by_key(|htlc| htlc.0.transaction_output_index); HolderCommitmentTransaction { inner, @@ -1445,7 +1446,7 @@ impl CommitmentTransaction { /// Only include HTLCs that are above the dust limit for the channel. /// /// This is not exported to bindings users due to the generic though we likely should expose a version without - pub fn new_with_auxiliary_htlc_data(commitment_number: u64, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, broadcaster_funding_key: PublicKey, countersignatory_funding_key: PublicKey, keys: TxCreationKeys, feerate_per_kw: u32, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters) -> CommitmentTransaction { + pub fn new_with_auxiliary_htlc_data(commitment_number: u64, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, broadcaster_funding_key: PublicKey, countersignatory_funding_key: PublicKey, keys: TxCreationKeys, feerate_per_kw: u32, htlcs_with_aux: Vec<&mut HTLCOutputInCommitment>, channel_parameters: &DirectedChannelTransactionParameters) -> CommitmentTransaction { let to_broadcaster_value_sat = Amount::from_sat(to_broadcaster_value_sat); let to_countersignatory_value_sat = Amount::from_sat(to_countersignatory_value_sat); @@ -1482,8 +1483,9 @@ impl CommitmentTransaction { fn internal_rebuild_transaction(&self, keys: &TxCreationKeys, channel_parameters: &DirectedChannelTransactionParameters, broadcaster_funding_key: &PublicKey, countersignatory_funding_key: &PublicKey) -> Result { let (obscured_commitment_transaction_number, txins) = Self::internal_build_inputs(self.commitment_number, channel_parameters); - let mut htlcs_with_aux = self.htlcs.iter().map(|h| (h.clone(), ())).collect(); - let (outputs, _) = Self::internal_build_outputs(keys, self.to_broadcaster_value_sat, self.to_countersignatory_value_sat, &mut htlcs_with_aux, channel_parameters, broadcaster_funding_key, countersignatory_funding_key)?; + let mut htlcs_with_aux: Vec<_> = self.htlcs.iter().map(|h| h.clone()).collect(); + let htlcs_with_aux = htlcs_with_aux.iter_mut().collect(); + let (outputs, _) = Self::internal_build_outputs(keys, self.to_broadcaster_value_sat, self.to_countersignatory_value_sat, htlcs_with_aux, channel_parameters, broadcaster_funding_key, countersignatory_funding_key)?; let transaction = Self::make_transaction(obscured_commitment_transaction_number, txins, outputs); let txid = transaction.compute_txid(); @@ -1507,7 +1509,7 @@ impl CommitmentTransaction { // - initial sorting of outputs / HTLCs in the constructor, in which case T is auxiliary data the // caller needs to have sorted together with the HTLCs so it can keep track of the output index // - building of a bitcoin transaction during a verify() call, in which case T is just () - fn internal_build_outputs(keys: &TxCreationKeys, to_broadcaster_value_sat: Amount, to_countersignatory_value_sat: Amount, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters, broadcaster_funding_key: &PublicKey, countersignatory_funding_key: &PublicKey) -> Result<(Vec, Vec), ()> { + fn internal_build_outputs(keys: &TxCreationKeys, to_broadcaster_value_sat: Amount, to_countersignatory_value_sat: Amount, htlcs_with_aux: Vec<&mut HTLCOutputInCommitment>, channel_parameters: &DirectedChannelTransactionParameters, broadcaster_funding_key: &PublicKey, countersignatory_funding_key: &PublicKey) -> Result<(Vec, Vec), ()> { let countersignatory_pubkeys = channel_parameters.countersignatory_pubkeys(); let contest_delay = channel_parameters.contest_delay(); @@ -1568,7 +1570,7 @@ impl CommitmentTransaction { } let mut htlcs = Vec::with_capacity(htlcs_with_aux.len()); - for (htlc, _) in htlcs_with_aux { + for htlc in htlcs_with_aux { let script = get_htlc_redeemscript(&htlc, &channel_parameters.channel_type_features(), &keys); let txout = TxOut { script_pubkey: script.to_p2wsh(), @@ -1914,7 +1916,7 @@ mod tests { counterparty_funding_pubkey: PublicKey, keys: TxCreationKeys, feerate_per_kw: u32, - htlcs_with_aux: Vec<(HTLCOutputInCommitment, ())>, + htlcs_with_aux: Vec, channel_parameters: ChannelTransactionParameters, counterparty_pubkeys: ChannelPublicKeys, } @@ -1962,7 +1964,7 @@ mod tests { self.holder_funding_pubkey.clone(), self.counterparty_funding_pubkey.clone(), self.keys.clone(), self.feerate_per_kw, - &mut self.htlcs_with_aux, &self.channel_parameters.as_holder_broadcastable() + self.htlcs_with_aux.iter_mut().collect(), &self.channel_parameters.as_holder_broadcastable() ) } } @@ -2008,7 +2010,7 @@ mod tests { // Generate broadcaster output and received and offered HTLC outputs, w/o anchors builder.channel_parameters.channel_type_features = ChannelTypeFeatures::only_static_remote_key(); - builder.htlcs_with_aux = vec![(received_htlc.clone(), ()), (offered_htlc.clone(), ())]; + builder.htlcs_with_aux = vec![received_htlc.clone(), offered_htlc.clone()]; let tx = builder.build(3000, 0); let keys = &builder.keys.clone(); assert_eq!(tx.built.transaction.output.len(), 3); @@ -2021,7 +2023,7 @@ mod tests { // Generate broadcaster output and received and offered HTLC outputs, with anchors builder.channel_parameters.channel_type_features = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); - builder.htlcs_with_aux = vec![(received_htlc.clone(), ()), (offered_htlc.clone(), ())]; + builder.htlcs_with_aux = vec![received_htlc.clone(), offered_htlc.clone()]; let tx = builder.build(3000, 0); assert_eq!(tx.built.transaction.output.len(), 5); assert_eq!(tx.built.transaction.output[2].script_pubkey, get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_p2wsh()); diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 31c12dd2361..4d0ac33923d 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -3288,13 +3288,7 @@ impl ChannelContext where SP::Target: SignerProvider { fn build_commitment_transaction(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool, logger: &L) -> CommitmentStats where L::Target: Logger { - let mut included_dust_htlcs: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::new(); - let num_htlcs = self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len(); - let mut included_non_dust_htlcs: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::with_capacity(num_htlcs); - let broadcaster_dust_limit_satoshis = if local { self.holder_dust_limit_satoshis } else { self.counterparty_dust_limit_satoshis }; - let mut remote_htlc_total_msat = 0; - let mut local_htlc_total_msat = 0; let mut value_to_self_msat_offset = 0; let mut feerate_per_kw = self.feerate_per_kw; @@ -3401,119 +3395,38 @@ impl ChannelContext where SP::Target: SignerProvider { } } } - let mut value_to_self_msat: i64 = self.value_to_self_msat as i64 + value_to_self_msat_offset; + let value_to_self_msat: i64 = self.value_to_self_msat as i64 + value_to_self_msat_offset; - for (htlc, source) in htlcs_in_tx { - if htlc.offered { // "offered HTLC output" - if local { - local_htlc_total_msat += htlc.amount_msat; - } else { - remote_htlc_total_msat += htlc.amount_msat - } - let htlc_in_tx = get_htlc_in_commitment!(htlc, true); - let htlc_tx_fee = if self.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - 0 - } else { - feerate_per_kw as u64 * htlc_timeout_tx_weight(self.get_channel_type()) / 1000 - }; - if htlc.amount_msat / 1000 >= broadcaster_dust_limit_satoshis + htlc_tx_fee { - included_non_dust_htlcs.push((htlc_in_tx, source)); - } else { - included_dust_htlcs.push((htlc_in_tx, source)); - } - } else { - if local { - remote_htlc_total_msat += htlc.amount_msat - } else { - local_htlc_total_msat += htlc.amount_msat; - } - let htlc_in_tx = get_htlc_in_commitment!(htlc, false); - let htlc_tx_fee = if self.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - 0 - } else { - feerate_per_kw as u64 * htlc_success_tx_weight(self.get_channel_type()) / 1000 - }; - if htlc.amount_msat / 1000 >= broadcaster_dust_limit_satoshis + htlc_tx_fee { - included_non_dust_htlcs.push((htlc_in_tx, source)); - } else { - included_dust_htlcs.push((htlc_in_tx, source)); - } - } - } - let mut value_to_remote_msat: i64 = (self.channel_value_satoshis * 1000) as i64 - value_to_self_msat; - value_to_self_msat -= local_htlc_total_msat as i64; - value_to_remote_msat -= remote_htlc_total_msat as i64; + let channel_parameters = if local { self.channel_transaction_parameters.as_holder_broadcastable() } + else { self.channel_transaction_parameters.as_counterparty_broadcastable() }; - #[cfg(debug_assertions)] - { - // Make sure that the to_self/to_remote is always either past the appropriate - // channel_reserve *or* it is making progress towards it. - let mut broadcaster_max_commitment_tx_output = if generated_by_local { - self.holder_max_commitment_tx_output.lock().unwrap() - } else { - self.counterparty_max_commitment_tx_output.lock().unwrap() - }; - debug_assert!(broadcaster_max_commitment_tx_output.0 <= value_to_self_msat as u64 || value_to_self_msat / 1000 >= self.counterparty_selected_channel_reserve_satoshis.unwrap() as i64); - broadcaster_max_commitment_tx_output.0 = cmp::max(broadcaster_max_commitment_tx_output.0, value_to_self_msat as u64); - debug_assert!(broadcaster_max_commitment_tx_output.1 <= value_to_remote_msat as u64 || value_to_remote_msat / 1000 >= self.holder_selected_channel_reserve_satoshis as i64); - broadcaster_max_commitment_tx_output.1 = cmp::max(broadcaster_max_commitment_tx_output.1, value_to_remote_msat as u64); - } - - let total_fee_sat = commit_tx_fee_sat(feerate_per_kw, included_non_dust_htlcs.len(), &self.channel_transaction_parameters.channel_type_features); - let anchors_val = if self.channel_transaction_parameters.channel_type_features.supports_anchors_zero_fee_htlc_tx() { ANCHOR_OUTPUT_VALUE_SATOSHI * 2 } else { 0 } as i64; - let (value_to_self, value_to_remote) = if self.is_outbound() { - (value_to_self_msat / 1000 - anchors_val - total_fee_sat as i64, value_to_remote_msat / 1000) - } else { - (value_to_self_msat / 1000, value_to_remote_msat / 1000 - anchors_val - total_fee_sat as i64) - }; + use crate::sign::tx_builder::SpecTxBuilder; + use crate::sign::tx_builder::TxBuilder; + let tx_builder = SpecTxBuilder {}; + let htlcs = htlcs_in_tx.iter_mut().map(|(htlc, _)| htlc).collect(); - let mut value_to_a = if local { value_to_self } else { value_to_remote }; - let mut value_to_b = if local { value_to_remote } else { value_to_self }; - let (funding_pubkey_a, funding_pubkey_b) = if local { - (self.get_holder_pubkeys().funding_pubkey, self.get_counterparty_pubkeys().funding_pubkey) - } else { - (self.get_counterparty_pubkeys().funding_pubkey, self.get_holder_pubkeys().funding_pubkey) - }; + let (tx, total_fee_sat, num_nondust_htlcs, value_to_self_msat, value_to_remote_msat) = tx_builder.build_commitment_transaction(local, commitment_number, value_to_self_msat, self.channel_value_satoshis, self.is_outbound(), htlcs, &self.secp_ctx, feerate_per_kw, broadcaster_dust_limit_satoshis, keys, &channel_parameters); - if value_to_a >= (broadcaster_dust_limit_satoshis as i64) { - log_trace!(logger, " ...including {} output with value {}", if local { "to_local" } else { "to_remote" }, value_to_a); - } else { - value_to_a = 0; - } - - if value_to_b >= (broadcaster_dust_limit_satoshis as i64) { - log_trace!(logger, " ...including {} output with value {}", if local { "to_remote" } else { "to_local" }, value_to_b); - } else { - value_to_b = 0; - } - - let num_nondust_htlcs = included_non_dust_htlcs.len(); - - let channel_parameters = - if local { self.channel_transaction_parameters.as_holder_broadcastable() } - else { self.channel_transaction_parameters.as_counterparty_broadcastable() }; - let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number, - value_to_a as u64, - value_to_b as u64, - funding_pubkey_a, - funding_pubkey_b, - keys.clone(), - feerate_per_kw, - &mut included_non_dust_htlcs, - &channel_parameters - ); - let mut htlcs_included = included_non_dust_htlcs; // The unwrap is safe, because all non-dust HTLCs have been assigned an output index - htlcs_included.sort_unstable_by_key(|h| h.0.transaction_output_index.unwrap()); - htlcs_included.append(&mut included_dust_htlcs); + let mut trimmed_htlcs = Vec::new(); + let mut htlcs_on_tx = Vec::new(); + for pair in htlcs_in_tx { + if pair.0.transaction_output_index.is_some() { + htlcs_on_tx.push(pair); + } else { + trimmed_htlcs.push(pair); + } + } + htlcs_on_tx.sort_unstable_by_key(|h| h.0.transaction_output_index.unwrap()); + let all_htlcs: Vec<_> = htlcs_on_tx.into_iter().chain(trimmed_htlcs).collect(); CommitmentStats { tx, feerate_per_kw, total_fee_sat, num_nondust_htlcs, - htlcs_included, + htlcs_included: all_htlcs, local_balance_msat: value_to_self_msat as u64, remote_balance_msat: value_to_remote_msat as u64, inbound_htlc_preimages, diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index 66e21d64d54..5a5fb46e20b 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -761,7 +761,7 @@ fn test_update_fee_that_funder_cannot_afford() { let local_chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); let local_chan = local_chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap(); let local_chan_signer = local_chan.get_signer(); - let mut htlcs: Vec<(HTLCOutputInCommitment, ())> = vec![]; + let mut htlcs: Vec = vec![]; let commitment_tx = CommitmentTransaction::new_with_auxiliary_htlc_data( INITIAL_COMMITMENT_NUMBER - 1, push_sats, @@ -769,7 +769,7 @@ fn test_update_fee_that_funder_cannot_afford() { local_funding, remote_funding, commit_tx_keys.clone(), non_buffer_feerate + 4, - &mut htlcs, + htlcs.iter_mut().collect(), &local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable() ); local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(&commitment_tx, Vec::new(), Vec::new(), &secp_ctx).unwrap() @@ -1490,7 +1490,7 @@ fn test_fee_spike_violation_fails_htlc() { // signature for the commitment_signed message. let local_chan_balance = 1313; - let accepted_htlc_info = chan_utils::HTLCOutputInCommitment { + let mut accepted_htlc_info = chan_utils::HTLCOutputInCommitment { offered: false, amount_msat: 3460001, cltv_expiry: htlc_cltv, @@ -1512,7 +1512,7 @@ fn test_fee_spike_violation_fails_htlc() { local_funding, remote_funding, commit_tx_keys.clone(), feerate_per_kw, - &mut vec![(accepted_htlc_info, ())], + vec![&mut accepted_htlc_info], &local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable() ); local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(&commitment_tx, Vec::new(), Vec::new(), &secp_ctx).unwrap() diff --git a/lightning/src/sign/tx_builder.rs b/lightning/src/sign/tx_builder.rs index 6f9d3776f5e..0ef97831014 100644 --- a/lightning/src/sign/tx_builder.rs +++ b/lightning/src/sign/tx_builder.rs @@ -6,7 +6,10 @@ use bitcoin::secp256k1::{self, PublicKey, Secp256k1}; use bitcoin::{Amount, Transaction}; -use crate::ln::chan_utils::{ChannelTransactionParameters, HTLCOutputInCommitment, TxCreationKeys}; +use crate::ln::chan_utils::{ + self, ChannelTransactionParameters, CommitmentTransaction, + DirectedChannelTransactionParameters, HTLCOutputInCommitment, TxCreationKeys, +}; use crate::prelude::*; /// A trait for types that can build commitment transactions, both for the holder, and the counterparty. @@ -15,11 +18,12 @@ pub trait TxBuilder { /// Do not sort `htlcs`; this will be done by the caller as needed. /// This method will be called only after all the channel parameters have been provided via `provide_channel_parameters`. fn build_commitment_transaction( - &self, is_holder_tx: bool, commitment_number: u64, per_commitment_point: &PublicKey, - to_broadcaster_value_sat: Amount, to_countersignatory_value_sat: Amount, - trimmed_value_sat: Amount, htlcs: Vec<&mut HTLCOutputInCommitment>, - secp_ctx: &Secp256k1, - ) -> Transaction; + &self, local: bool, commitment_number: u64, value_to_self_msat: i64, + channel_value_satoshis: u64, is_outbound: bool, + htlcs_in_tx: Vec<&mut HTLCOutputInCommitment>, secp_ctx: &Secp256k1, + feerate_per_kw: u32, broadcaster_dust_limit_satoshis: u64, keys: &TxCreationKeys, + params: &DirectedChannelTransactionParameters, + ) -> (CommitmentTransaction, u64, usize, i64, i64); } /// A type that builds commitment transactions according to the Lightning Specification. @@ -28,11 +32,119 @@ pub struct SpecTxBuilder {} impl TxBuilder for SpecTxBuilder { fn build_commitment_transaction( - &self, is_holder_tx: bool, commitment_number: u64, per_commitment_point: &PublicKey, - to_broadcaster_value_sat: Amount, to_countersignatory_value_sat: Amount, - trimmed_value_sat: Amount, htlcs: Vec<&mut HTLCOutputInCommitment>, - secp_ctx: &Secp256k1, - ) -> Transaction { - todo!(); + &self, local: bool, commitment_number: u64, mut value_to_self_msat: i64, + channel_value_satoshis: u64, is_outbound: bool, + htlcs_in_tx: Vec<&mut HTLCOutputInCommitment>, secp_ctx: &Secp256k1, + feerate_per_kw: u32, broadcaster_dust_limit_satoshis: u64, keys: &TxCreationKeys, + params: &DirectedChannelTransactionParameters, + ) -> (CommitmentTransaction, u64, usize, i64, i64) { + let mut local_htlc_total_msat = 0; + let mut remote_htlc_total_msat = 0; + let mut included_non_dust_htlcs = Vec::new(); + let mut included_dust_htlcs = Vec::new(); + + for htlc in htlcs_in_tx { + if htlc.offered { + // "offered HTLC output" + if local { + local_htlc_total_msat += htlc.amount_msat; + } else { + remote_htlc_total_msat += htlc.amount_msat + } + let htlc_tx_fee = + if params.channel_type_features().supports_anchors_zero_fee_htlc_tx() { + 0 + } else { + feerate_per_kw as u64 + * chan_utils::htlc_timeout_tx_weight(params.channel_type_features()) + / 1000 + }; + if htlc.amount_msat / 1000 >= broadcaster_dust_limit_satoshis + htlc_tx_fee { + included_non_dust_htlcs.push(htlc); + } else { + included_dust_htlcs.push(htlc); + } + } else { + if local { + remote_htlc_total_msat += htlc.amount_msat + } else { + local_htlc_total_msat += htlc.amount_msat; + } + let htlc_tx_fee = + if params.channel_type_features().supports_anchors_zero_fee_htlc_tx() { + 0 + } else { + feerate_per_kw as u64 + * chan_utils::htlc_success_tx_weight(params.channel_type_features()) + / 1000 + }; + if htlc.amount_msat / 1000 >= broadcaster_dust_limit_satoshis + htlc_tx_fee { + included_non_dust_htlcs.push(htlc); + } else { + included_dust_htlcs.push(htlc); + } + } + } + + let mut value_to_remote_msat: i64 = + (channel_value_satoshis * 1000) as i64 - value_to_self_msat; + value_to_self_msat -= local_htlc_total_msat as i64; + value_to_remote_msat -= remote_htlc_total_msat as i64; + + let total_fee_sat = chan_utils::commit_tx_fee_sat( + feerate_per_kw, + included_non_dust_htlcs.len(), + params.channel_type_features(), + ); + let anchors_val = if params.channel_type_features().supports_anchors_zero_fee_htlc_tx() { + crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI * 2 + } else { + 0 + } as i64; + let (value_to_self, value_to_remote) = if is_outbound { + ( + value_to_self_msat / 1000 - anchors_val - total_fee_sat as i64, + value_to_remote_msat / 1000, + ) + } else { + ( + value_to_self_msat / 1000, + value_to_remote_msat / 1000 - anchors_val - total_fee_sat as i64, + ) + }; + + let mut value_to_a = if local { value_to_self } else { value_to_remote }; + let mut value_to_b = if local { value_to_remote } else { value_to_self }; + let (funding_pubkey_a, funding_pubkey_b) = ( + params.broadcaster_pubkeys().funding_pubkey, + params.countersignatory_pubkeys().funding_pubkey, + ); + + if value_to_a >= (broadcaster_dust_limit_satoshis as i64) { + //log_trace!(logger, " ...including {} output with value {}", if local { "to_local" } else { "to_remote" }, value_to_a); + } else { + value_to_a = 0; + } + + if value_to_b >= (broadcaster_dust_limit_satoshis as i64) { + //log_trace!(logger, " ...including {} output with value {}", if local { "to_remote" } else { "to_local" }, value_to_b); + } else { + value_to_b = 0; + } + + let num_nondust_htlcs = included_non_dust_htlcs.len(); + + let tx = CommitmentTransaction::new_with_auxiliary_htlc_data( + commitment_number, + value_to_a as u64, + value_to_b as u64, + funding_pubkey_a, + funding_pubkey_b, + keys.clone(), + feerate_per_kw, + included_non_dust_htlcs, + ¶ms, + ); + (tx, total_fee_sat, num_nondust_htlcs, value_to_self_msat, value_to_remote_msat) } }