@@ -56,6 +56,7 @@ use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBounde
56
56
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS};
57
57
use crate::chain::transaction::{OutPoint, TransactionData};
58
58
use crate::sign::ecdsa::EcdsaChannelSigner;
59
+ use crate::sign::tx_builder::{SpecTxBuilder, TxBuilder};
59
60
use crate::sign::{EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient};
60
61
use crate::events::{ClosureReason, Event};
61
62
use crate::events::bump_transaction::BASE_INPUT_WEIGHT;
@@ -265,24 +266,6 @@ struct InboundHTLCOutput {
265
266
state: InboundHTLCState,
266
267
}
267
268
268
- impl InboundHTLCOutput {
269
- fn is_dust(&self, local: bool, feerate_per_kw: u32, broadcaster_dust_limit_sat: u64, features: &ChannelTypeFeatures) -> bool {
270
- let htlc_tx_fee_sat = if features.supports_anchors_zero_fee_htlc_tx() {
271
- 0
272
- } else {
273
- let htlc_tx_weight = if !local {
274
- // this is an offered htlc
275
- htlc_timeout_tx_weight(features)
276
- } else {
277
- htlc_success_tx_weight(features)
278
- };
279
- // As required by the spec, round down
280
- feerate_per_kw as u64 * htlc_tx_weight / 1000
281
- };
282
- self.amount_msat / 1000 < broadcaster_dust_limit_sat + htlc_tx_fee_sat
283
- }
284
- }
285
-
286
269
#[cfg_attr(test, derive(Clone, Debug, PartialEq))]
287
270
enum OutboundHTLCState {
288
271
/// Added by us and included in a commitment_signed (if we were AwaitingRemoteRevoke when we
@@ -405,24 +388,6 @@ struct OutboundHTLCOutput {
405
388
send_timestamp: Option<Duration>,
406
389
}
407
390
408
- impl OutboundHTLCOutput {
409
- fn is_dust(&self, local: bool, feerate_per_kw: u32, broadcaster_dust_limit_sat: u64, features: &ChannelTypeFeatures) -> bool {
410
- let htlc_tx_fee_sat = if features.supports_anchors_zero_fee_htlc_tx() {
411
- 0
412
- } else {
413
- let htlc_tx_weight = if local {
414
- // this is an offered htlc
415
- htlc_timeout_tx_weight(features)
416
- } else {
417
- htlc_success_tx_weight(features)
418
- };
419
- // As required by the spec, round down
420
- feerate_per_kw as u64 * htlc_tx_weight / 1000
421
- };
422
- self.amount_msat / 1000 < broadcaster_dust_limit_sat + htlc_tx_fee_sat
423
- }
424
- }
425
-
426
391
/// See AwaitingRemoteRevoke ChannelState for more info
427
392
#[cfg_attr(test, derive(Clone, Debug, PartialEq))]
428
393
enum HTLCUpdateAwaitingACK {
@@ -985,13 +950,13 @@ struct CommitmentData<'a> {
985
950
}
986
951
987
952
/// A struct gathering stats on a commitment transaction, either local or remote.
988
- struct CommitmentStats {
989
- feerate_per_kw: u32, // the feerate of the commitment transaction
990
- total_fee_sat: u64, // the total fee included in the transaction
991
- total_anchors_sat: u64, // the sum of the anchors' amounts
992
- broadcaster_dust_limit_sat: u64 , // the broadcaster's dust limit
993
- local_balance_before_fee_anchors_msat: u64, // local balance before fees and anchors *not* considering dust limits
994
- remote_balance_before_fee_anchors_msat: u64, // remote balance before fees and anchors *not* considering dust limits
953
+ #[derive(Debug, PartialEq)]
954
+ pub(crate) struct CommitmentStats {
955
+ pub(crate) total_fee_sat: u64, // the total fee included in the transaction
956
+ pub(crate) total_anchors_sat: u64, // the sum of the anchors' amounts
957
+ pub(crate) nondust_htlc_count: usize , // the number of non- dust HTLCs at that commitment
958
+ pub(crate) local_balance_before_fee_anchors_msat: u64, // local balance before fees and anchors *not* considering dust limits
959
+ pub(crate) remote_balance_before_fee_anchors_msat: u64, // remote balance before fees and anchors *not* considering dust limits
995
960
}
996
961
997
962
/// Used when calculating whether we or the remote can afford an additional HTLC.
@@ -3850,16 +3815,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3850
3815
})
3851
3816
}
3852
3817
3853
- /// Builds stats on a potential commitment transaction build, without actually building the
3854
- /// commitment transaction. See `build_commitment_transaction` for further docs.
3855
- #[inline]
3856
- fn build_commitment_stats(&self, funding: &FundingScope, local: bool, generated_by_local: bool) -> CommitmentStats {
3857
- let broadcaster_dust_limit_sat = if local { self.holder_dust_limit_satoshis } else { self.counterparty_dust_limit_satoshis };
3858
- let mut non_dust_htlc_count = 0;
3859
- let mut remote_htlc_total_msat = 0;
3860
- let mut local_htlc_total_msat = 0;
3861
- let mut value_to_self_msat_offset = 0;
3862
-
3818
+ fn get_commitment_feerate(&self, funding: &FundingScope, generated_by_local: bool) -> u32 {
3863
3819
let mut feerate_per_kw = self.feerate_per_kw;
3864
3820
if let Some((feerate, update_state)) = self.pending_update_fee {
3865
3821
if match update_state {
@@ -3872,13 +3828,36 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3872
3828
feerate_per_kw = feerate;
3873
3829
}
3874
3830
}
3831
+ feerate_per_kw
3832
+ }
3833
+
3834
+ /// Builds stats at a particular commitment, without building the full
3835
+ /// commitment transaction. See `build_commitment_transaction` for further docs.
3836
+ #[inline]
3837
+ #[allow(dead_code)]
3838
+ fn build_commitment_stats(&self, funding: &FundingScope, local: bool, generated_by_local: bool) -> CommitmentStats {
3839
+ let broadcaster_dust_limit_sat = if local { self.holder_dust_limit_satoshis } else { self.counterparty_dust_limit_satoshis };
3840
+ let feerate_per_kw = self.get_commitment_feerate(funding, generated_by_local);
3841
+
3842
+ let num_htlcs = self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len();
3843
+ let mut htlcs_included = Vec::with_capacity(num_htlcs);
3844
+ let mut value_to_self_msat_offset = 0;
3845
+
3846
+ macro_rules! get_htlc_in_commitment {
3847
+ ($htlc: expr, $offered: expr) => {
3848
+ HTLCOutputInCommitment {
3849
+ offered: $offered,
3850
+ amount_msat: $htlc.amount_msat,
3851
+ cltv_expiry: $htlc.cltv_expiry,
3852
+ payment_hash: $htlc.payment_hash,
3853
+ transaction_output_index: None
3854
+ }
3855
+ }
3856
+ }
3875
3857
3876
3858
for htlc in self.pending_inbound_htlcs.iter() {
3877
3859
if htlc.state.included_in_commitment(generated_by_local) {
3878
- if !htlc.is_dust(local, feerate_per_kw, broadcaster_dust_limit_sat, funding.get_channel_type()) {
3879
- non_dust_htlc_count += 1;
3880
- }
3881
- remote_htlc_total_msat += htlc.amount_msat;
3860
+ htlcs_included.push(get_htlc_in_commitment!(htlc, !local));
3882
3861
} else {
3883
3862
if htlc.state.preimage().is_some() {
3884
3863
value_to_self_msat_offset += htlc.amount_msat as i64;
@@ -3888,10 +3867,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3888
3867
3889
3868
for htlc in self.pending_outbound_htlcs.iter() {
3890
3869
if htlc.state.included_in_commitment(generated_by_local) {
3891
- if !htlc.is_dust(local, feerate_per_kw, broadcaster_dust_limit_sat, funding.get_channel_type()) {
3892
- non_dust_htlc_count += 1;
3893
- }
3894
- local_htlc_total_msat += htlc.amount_msat;
3870
+ htlcs_included.push(get_htlc_in_commitment!(htlc, local));
3895
3871
} else {
3896
3872
if htlc.state.preimage().is_some() {
3897
3873
value_to_self_msat_offset -= htlc.amount_msat as i64;
@@ -3901,15 +3877,21 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3901
3877
3902
3878
// # Panics
3903
3879
//
3904
- // While we expect `value_to_self_msat_offset` to be negative in some cases, the value going
3905
- // to each party MUST be 0 or positive, even if all HTLCs pending in the commitment clear by
3906
- // failure.
3880
+ // While we expect `value_to_self_msat_offset` to be negative in some cases, the local
3881
+ // balance MUST remain greater than or equal to 0.
3907
3882
3908
3883
// TODO: When MSRV >= 1.66.0, use u64::checked_add_signed
3909
- let mut value_to_self_msat = (funding.value_to_self_msat as i64 + value_to_self_msat_offset).try_into().unwrap();
3910
- let mut value_to_remote_msat = (funding.get_value_satoshis() * 1000).checked_sub(value_to_self_msat).unwrap();
3911
- value_to_self_msat = value_to_self_msat.checked_sub(local_htlc_total_msat).unwrap();
3912
- value_to_remote_msat = value_to_remote_msat.checked_sub(remote_htlc_total_msat).unwrap();
3884
+ let value_to_self_with_offset_msat = (funding.value_to_self_msat as i64 + value_to_self_msat_offset).try_into().unwrap();
3885
+
3886
+ let stats = TxBuilder::build_commitment_stats(
3887
+ &SpecTxBuilder {},
3888
+ local,
3889
+ &funding.channel_transaction_parameters,
3890
+ value_to_self_with_offset_msat,
3891
+ &htlcs_included,
3892
+ feerate_per_kw,
3893
+ broadcaster_dust_limit_sat,
3894
+ );
3913
3895
3914
3896
#[cfg(debug_assertions)]
3915
3897
{
@@ -3920,23 +3902,13 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3920
3902
} else {
3921
3903
funding.counterparty_max_commitment_tx_output.lock().unwrap()
3922
3904
};
3923
- debug_assert!(broadcaster_max_commitment_tx_output.0 <= value_to_self_msat || value_to_self_msat / 1000 >= funding.counterparty_selected_channel_reserve_satoshis.unwrap());
3924
- broadcaster_max_commitment_tx_output.0 = cmp::max(broadcaster_max_commitment_tx_output.0, value_to_self_msat );
3925
- debug_assert!(broadcaster_max_commitment_tx_output.1 <= value_to_remote_msat || value_to_remote_msat / 1000 >= funding.holder_selected_channel_reserve_satoshis);
3926
- broadcaster_max_commitment_tx_output.1 = cmp::max(broadcaster_max_commitment_tx_output.1, value_to_remote_msat );
3905
+ debug_assert!(broadcaster_max_commitment_tx_output.0 <= stats.local_balance_before_fee_anchors_msat || stats.local_balance_before_fee_anchors_msat / 1000 >= funding.counterparty_selected_channel_reserve_satoshis.unwrap());
3906
+ broadcaster_max_commitment_tx_output.0 = cmp::max(broadcaster_max_commitment_tx_output.0, stats.local_balance_before_fee_anchors_msat );
3907
+ debug_assert!(broadcaster_max_commitment_tx_output.1 <= stats.remote_balance_before_fee_anchors_msat || stats.remote_balance_before_fee_anchors_msat / 1000 >= funding.holder_selected_channel_reserve_satoshis);
3908
+ broadcaster_max_commitment_tx_output.1 = cmp::max(broadcaster_max_commitment_tx_output.1, stats.remote_balance_before_fee_anchors_msat );
3927
3909
}
3928
3910
3929
- let total_fee_sat = commit_tx_fee_sat(feerate_per_kw, non_dust_htlc_count, &funding.channel_transaction_parameters.channel_type_features);
3930
- let total_anchors_sat = if funding.channel_transaction_parameters.channel_type_features.supports_anchors_zero_fee_htlc_tx() { ANCHOR_OUTPUT_VALUE_SATOSHI * 2 } else { 0 };
3931
-
3932
- CommitmentStats {
3933
- feerate_per_kw,
3934
- total_fee_sat,
3935
- total_anchors_sat,
3936
- broadcaster_dust_limit_sat,
3937
- local_balance_before_fee_anchors_msat: value_to_self_msat,
3938
- remote_balance_before_fee_anchors_msat: value_to_remote_msat,
3939
- }
3911
+ stats
3940
3912
}
3941
3913
3942
3914
/// Transaction nomenclature is somewhat confusing here as there are many different cases - a
@@ -3956,19 +3928,12 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3956
3928
fn build_commitment_transaction<L: Deref>(&self, funding: &FundingScope, commitment_number: u64, per_commitment_point: &PublicKey, local: bool, generated_by_local: bool, logger: &L) -> CommitmentData
3957
3929
where L::Target: Logger
3958
3930
{
3959
- let stats = self.build_commitment_stats(funding, local, generated_by_local);
3960
- let CommitmentStats {
3961
- feerate_per_kw,
3962
- total_fee_sat,
3963
- total_anchors_sat,
3964
- broadcaster_dust_limit_sat,
3965
- local_balance_before_fee_anchors_msat,
3966
- remote_balance_before_fee_anchors_msat
3967
- } = stats;
3931
+ let broadcaster_dust_limit_sat = if local { self.holder_dust_limit_satoshis } else { self.counterparty_dust_limit_satoshis };
3932
+ let feerate_per_kw = self.get_commitment_feerate(funding, generated_by_local);
3968
3933
3969
3934
let num_htlcs = self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len();
3970
3935
let mut htlcs_included: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::with_capacity(num_htlcs);
3971
- let mut nondust_htlcs: Vec<HTLCOutputInCommitment> = Vec::with_capacity(num_htlcs) ;
3936
+ let mut value_to_self_msat_offset = 0 ;
3972
3937
3973
3938
log_trace!(logger, "Building commitment transaction number {} (really {} xor {}) for channel {} for {}, generated by {} with fee {}...",
3974
3939
commitment_number, (INITIAL_COMMITMENT_NUMBER - commitment_number),
@@ -3991,13 +3956,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3991
3956
macro_rules! add_htlc_output {
3992
3957
($htlc: expr, $outbound: expr, $source: expr) => {
3993
3958
let htlc_in_tx = get_htlc_in_commitment!($htlc, $outbound == local);
3994
- htlcs_included.push((htlc_in_tx.clone(), $source));
3995
- if $htlc.is_dust(local, feerate_per_kw, broadcaster_dust_limit_sat, funding.get_channel_type()) {
3996
- log_trace!(logger, " ...including {} {} dust HTLC {} (hash {}) with value {} due to dust limit", if $outbound { "outbound" } else { "inbound" }, $htlc.state, $htlc.htlc_id, $htlc.payment_hash, $htlc.amount_msat);
3997
- } else {
3998
- log_trace!(logger, " ...including {} {} HTLC {} (hash {}) with value {}", if $outbound { "outbound" } else { "inbound" }, $htlc.state, $htlc.htlc_id, $htlc.payment_hash, $htlc.amount_msat);
3999
- nondust_htlcs.push(htlc_in_tx);
4000
- }
3959
+ htlcs_included.push((htlc_in_tx, $source));
4001
3960
}
4002
3961
}
4003
3962
@@ -4006,11 +3965,13 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
4006
3965
4007
3966
for htlc in self.pending_inbound_htlcs.iter() {
4008
3967
if htlc.state.included_in_commitment(generated_by_local) {
3968
+ log_trace!(logger, " ...including inbound {} HTLC {} (hash {}) with value {}", htlc.state, htlc.htlc_id, htlc.payment_hash, htlc.amount_msat);
4009
3969
add_htlc_output!(htlc, false, None);
4010
3970
} else {
4011
3971
log_trace!(logger, " ...not including inbound HTLC {} (hash {}) with value {} due to state ({})", htlc.htlc_id, htlc.payment_hash, htlc.amount_msat, htlc.state);
4012
3972
if let Some(preimage) = htlc.state.preimage() {
4013
3973
inbound_htlc_preimages.push(preimage);
3974
+ value_to_self_msat_offset += htlc.amount_msat as i64;
4014
3975
}
4015
3976
}
4016
3977
};
@@ -4020,53 +3981,38 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
4020
3981
outbound_htlc_preimages.push(preimage);
4021
3982
}
4022
3983
if htlc.state.included_in_commitment(generated_by_local) {
3984
+ log_trace!(logger, " ...including outbound {} HTLC {} (hash {}) with value {}", htlc.state, htlc.htlc_id, htlc.payment_hash, htlc.amount_msat);
4023
3985
add_htlc_output!(htlc, true, Some(&htlc.source));
4024
3986
} else {
4025
3987
log_trace!(logger, " ...not including outbound HTLC {} (hash {}) with value {} due to state ({})", htlc.htlc_id, htlc.payment_hash, htlc.amount_msat, htlc.state);
3988
+ if htlc.state.preimage().is_some() {
3989
+ value_to_self_msat_offset -= htlc.amount_msat as i64;
3990
+ }
4026
3991
}
4027
3992
};
4028
3993
4029
- // We MUST use saturating subs here, as the funder's balance is not guaranteed to be greater
4030
- // than or equal to the sum of `total_fee_sat` and `total_anchors_sat`.
3994
+ // # Panics
4031
3995
//
4032
- // This is because when the remote party sends an `update_fee` message, we build the new
4033
- // commitment transaction *before* checking whether the remote party's balance is enough to
4034
- // cover the total fee and the anchors.
4035
-
4036
- let (value_to_self, value_to_remote) = if funding.is_outbound() {
4037
- ((local_balance_before_fee_anchors_msat / 1000).saturating_sub(total_anchors_sat).saturating_sub(total_fee_sat), remote_balance_before_fee_anchors_msat / 1000)
4038
- } else {
4039
- (local_balance_before_fee_anchors_msat / 1000, (remote_balance_before_fee_anchors_msat / 1000).saturating_sub(total_anchors_sat).saturating_sub(total_fee_sat))
4040
- };
4041
-
4042
- let mut to_broadcaster_value_sat = if local { value_to_self } else { value_to_remote };
4043
- let mut to_countersignatory_value_sat = if local { value_to_remote } else { value_to_self };
4044
-
4045
- if to_broadcaster_value_sat >= broadcaster_dust_limit_sat {
4046
- log_trace!(logger, " ...including {} output with value {}", if local { "to_local" } else { "to_remote" }, to_broadcaster_value_sat);
4047
- } else {
4048
- to_broadcaster_value_sat = 0;
4049
- }
3996
+ // While we expect `value_to_self_msat_offset` to be negative in some cases, the local
3997
+ // balance MUST remain greater than or equal to 0.
4050
3998
4051
- if to_countersignatory_value_sat >= broadcaster_dust_limit_sat {
4052
- log_trace!(logger, " ...including {} output with value {}", if local { "to_remote" } else { "to_local" }, to_countersignatory_value_sat);
4053
- } else {
4054
- to_countersignatory_value_sat = 0;
4055
- }
3999
+ // TODO: When MSRV >= 1.66.0, use u64::checked_add_signed
4000
+ let value_to_self_with_offset_msat = (funding.value_to_self_msat as i64 + value_to_self_msat_offset).try_into().unwrap();
4056
4001
4057
- let channel_parameters =
4058
- if local { funding.channel_transaction_parameters.as_holder_broadcastable() }
4059
- else { funding.channel_transaction_parameters.as_counterparty_broadcastable() };
4060
- let tx = CommitmentTransaction::new(
4002
+ let (tx, stats) = TxBuilder::build_commitment_transaction(
4003
+ &SpecTxBuilder {},
4004
+ local,
4061
4005
commitment_number,
4062
4006
per_commitment_point,
4063
- to_broadcaster_value_sat,
4064
- to_countersignatory_value_sat,
4065
- feerate_per_kw,
4066
- nondust_htlcs,
4067
- &channel_parameters,
4007
+ &funding.channel_transaction_parameters,
4068
4008
&self.secp_ctx,
4009
+ value_to_self_with_offset_msat,
4010
+ htlcs_included.iter().map(|(htlc, _source)| htlc).cloned().collect(),
4011
+ feerate_per_kw,
4012
+ broadcaster_dust_limit_sat,
4013
+ logger,
4069
4014
);
4015
+ debug_assert_eq!(stats, self.build_commitment_stats(funding, local, generated_by_local));
4070
4016
4071
4017
// This populates the HTLC-source table with the indices from the HTLCs in the commitment
4072
4018
// transaction.
@@ -6659,13 +6605,10 @@ impl<SP: Deref> FundedChannel<SP> where
6659
6605
// Before proposing a feerate update, check that we can actually afford the new fee.
6660
6606
let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
6661
6607
let htlc_stats = self.context.get_pending_htlc_stats(&self.funding, Some(feerate_per_kw), dust_exposure_limiting_feerate);
6662
- let commitment_data = self.context.build_commitment_transaction(
6663
- &self.funding, self.holder_commitment_point.transaction_number(),
6664
- &self.holder_commitment_point.current_point(), true, true, logger,
6665
- );
6666
- let buffer_fee_msat = commit_tx_fee_sat(feerate_per_kw, commitment_data.tx.nondust_htlcs().len() + htlc_stats.on_holder_tx_outbound_holding_cell_htlcs_count as usize + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, self.funding.get_channel_type()) * 1000;
6667
- let holder_balance_msat = commitment_data.stats.local_balance_before_fee_anchors_msat - htlc_stats.outbound_holding_cell_msat;
6668
- if holder_balance_msat < buffer_fee_msat + self.funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 {
6608
+ let stats = self.context.build_commitment_stats(&self.funding, true, true);
6609
+ let buffer_fee_msat = commit_tx_fee_sat(feerate_per_kw, stats.nondust_htlc_count + htlc_stats.on_holder_tx_outbound_holding_cell_htlcs_count as usize + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, self.funding.get_channel_type()) * 1000;
6610
+ let holder_balance_msat = stats.local_balance_before_fee_anchors_msat - htlc_stats.outbound_holding_cell_msat;
6611
+ if holder_balance_msat < buffer_fee_msat + self.funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 {
6669
6612
//TODO: auto-close after a number of failures?
6670
6613
log_debug!(logger, "Cannot afford to send new feerate at {}", feerate_per_kw);
6671
6614
return None;
0 commit comments