Skip to content

Commit 87d2945

Browse files
TheBlueMattdunxen
authored andcommitted
Move commitment tx fee calculation helpers to chan_utils
These don't really belong in `channel` as they're now used in other parts of the codebase.
1 parent 2962e7f commit 87d2945

File tree

5 files changed

+73
-70
lines changed

5 files changed

+73
-70
lines changed

lightning/src/ln/chan_utils.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,37 @@ impl HTLCClaim {
171171
}
172172
}
173173

174+
#[cfg(not(test))]
175+
const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172;
176+
#[cfg(test)]
177+
pub const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172;
178+
179+
pub(crate) fn commitment_tx_base_weight(channel_type_features: &ChannelTypeFeatures) -> u64 {
180+
const COMMITMENT_TX_BASE_WEIGHT: u64 = 724;
181+
const COMMITMENT_TX_BASE_ANCHOR_WEIGHT: u64 = 1124;
182+
if channel_type_features.supports_anchors_zero_fee_htlc_tx() { COMMITMENT_TX_BASE_ANCHOR_WEIGHT } else { COMMITMENT_TX_BASE_WEIGHT }
183+
}
184+
185+
/// Get the fee cost of a commitment tx with a given number of HTLC outputs.
186+
/// Note that num_htlcs should not include dust HTLCs.
187+
pub(crate) fn commit_tx_fee_sat(feerate_per_kw: u32, num_htlcs: usize, channel_type_features: &ChannelTypeFeatures) -> u64 {
188+
feerate_per_kw as u64 *
189+
(commitment_tx_base_weight(channel_type_features) +
190+
num_htlcs as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC)
191+
/ 1000
192+
}
193+
194+
pub(crate) fn per_outbound_htlc_counterparty_commit_tx_fee_msat(feerate_per_kw: u32, channel_type_features: &ChannelTypeFeatures) -> u64 {
195+
// Note that we need to divide before multiplying to round properly,
196+
// since the lowest denomination of bitcoin on-chain is the satoshi.
197+
let commitment_tx_fee = COMMITMENT_TX_WEIGHT_PER_HTLC * feerate_per_kw as u64 / 1000 * 1000;
198+
if channel_type_features.supports_anchors_zero_fee_htlc_tx() {
199+
commitment_tx_fee + htlc_success_tx_weight(channel_type_features) * feerate_per_kw as u64 / 1000
200+
} else {
201+
commitment_tx_fee
202+
}
203+
}
204+
174205
// Various functions for key derivation and transaction creation for use within channels. Primarily
175206
// used in Channel and ChannelMonitor.
176207

lightning/src/ln/channel.rs

Lines changed: 21 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,14 @@ use crate::ln::msgs::DecodeError;
3232
use crate::ln::script::{self, ShutdownScript};
3333
use crate::ln::channel_state::{ChannelShutdownState, CounterpartyForwardingInfo, InboundHTLCDetails, InboundHTLCStateDetails, OutboundHTLCDetails, OutboundHTLCStateDetails};
3434
use crate::ln::channelmanager::{self, PendingHTLCStatus, HTLCSource, SentHTLCId, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT};
35-
use crate::ln::chan_utils::{CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, htlc_success_tx_weight, htlc_timeout_tx_weight, make_funding_redeemscript, ChannelPublicKeys, CommitmentTransaction, HolderCommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, MAX_HTLCS, get_commitment_transaction_number_obscure_factor, ClosingTransaction};
35+
use crate::ln::chan_utils::{
36+
CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, htlc_success_tx_weight,
37+
htlc_timeout_tx_weight, make_funding_redeemscript, ChannelPublicKeys, CommitmentTransaction,
38+
HolderCommitmentTransaction, ChannelTransactionParameters,
39+
CounterpartyChannelTransactionParameters, MAX_HTLCS,
40+
get_commitment_transaction_number_obscure_factor,
41+
ClosingTransaction, commit_tx_fee_sat, per_outbound_htlc_counterparty_commit_tx_fee_msat,
42+
};
3643
use crate::ln::chan_utils;
3744
use crate::ln::onion_utils::HTLCFailReason;
3845
use crate::chain::BestBlock;
@@ -655,17 +662,6 @@ pub const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;
655662

656663
pub const DEFAULT_MAX_HTLCS: u16 = 50;
657664

658-
pub(crate) fn commitment_tx_base_weight(channel_type_features: &ChannelTypeFeatures) -> u64 {
659-
const COMMITMENT_TX_BASE_WEIGHT: u64 = 724;
660-
const COMMITMENT_TX_BASE_ANCHOR_WEIGHT: u64 = 1124;
661-
if channel_type_features.supports_anchors_zero_fee_htlc_tx() { COMMITMENT_TX_BASE_ANCHOR_WEIGHT } else { COMMITMENT_TX_BASE_WEIGHT }
662-
}
663-
664-
#[cfg(not(test))]
665-
const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172;
666-
#[cfg(test)]
667-
pub const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172;
668-
669665
pub const ANCHOR_OUTPUT_VALUE_SATOSHI: u64 = 330;
670666

671667
/// The percentage of the channel value `holder_max_htlc_value_in_flight_msat` used to be set to,
@@ -1621,7 +1617,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
16211617
0
16221618
};
16231619
let funders_amount_msat = open_channel_fields.funding_satoshis * 1000 - msg_push_msat;
1624-
let commitment_tx_fee = commit_tx_fee_msat(open_channel_fields.commitment_feerate_sat_per_1000_weight, MIN_AFFORDABLE_HTLC_COUNT, &channel_type) / 1000;
1620+
let commitment_tx_fee = commit_tx_fee_sat(open_channel_fields.commitment_feerate_sat_per_1000_weight, MIN_AFFORDABLE_HTLC_COUNT, &channel_type);
16251621
if (funders_amount_msat / 1000).saturating_sub(anchor_outputs_value) < commitment_tx_fee {
16261622
return Err(ChannelError::close(format!("Funding amount ({} sats) can't even pay fee for initial commitment transaction fee of {} sats.", (funders_amount_msat / 1000).saturating_sub(anchor_outputs_value), commitment_tx_fee)));
16271623
}
@@ -1887,7 +1883,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
18871883
let commitment_feerate = fee_estimator.bounded_sat_per_1000_weight(commitment_conf_target);
18881884

18891885
let value_to_self_msat = channel_value_satoshis * 1000 - push_msat;
1890-
let commitment_tx_fee = commit_tx_fee_msat(commitment_feerate, MIN_AFFORDABLE_HTLC_COUNT, &channel_type);
1886+
let commitment_tx_fee = commit_tx_fee_sat(commitment_feerate, MIN_AFFORDABLE_HTLC_COUNT, &channel_type) * 1000;
18911887
if value_to_self_msat.saturating_sub(anchor_outputs_value_msat) < commitment_tx_fee {
18921888
return Err(APIError::APIMisuseError{ err: format!("Funding amount ({}) can't even pay fee for initial commitment transaction fee of {}.", value_to_self_msat / 1000, commitment_tx_fee / 1000) });
18931889
}
@@ -2948,7 +2944,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
29482944
let on_counterparty_tx_nondust_htlcs =
29492945
on_counterparty_tx_accepted_nondust_htlcs + on_counterparty_tx_offered_nondust_htlcs;
29502946
on_counterparty_tx_dust_exposure_msat +=
2951-
commit_tx_fee_msat(excess_feerate, on_counterparty_tx_nondust_htlcs, &self.channel_type);
2947+
commit_tx_fee_sat(excess_feerate, on_counterparty_tx_nondust_htlcs, &self.channel_type) * 1000;
29522948
if !self.channel_type.supports_anchors_zero_fee_htlc_tx() {
29532949
on_counterparty_tx_dust_exposure_msat +=
29542950
on_counterparty_tx_accepted_nondust_htlcs as u64 * htlc_success_tx_weight(&self.channel_type)
@@ -3313,12 +3309,12 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
33133309
}
33143310

33153311
let num_htlcs = included_htlcs + addl_htlcs;
3316-
let res = commit_tx_fee_msat(context.feerate_per_kw, num_htlcs, &context.channel_type);
3312+
let res = commit_tx_fee_sat(context.feerate_per_kw, num_htlcs, &context.channel_type) * 1000;
33173313
#[cfg(any(test, fuzzing))]
33183314
{
33193315
let mut fee = res;
33203316
if fee_spike_buffer_htlc.is_some() {
3321-
fee = commit_tx_fee_msat(context.feerate_per_kw, num_htlcs - 1, &context.channel_type);
3317+
fee = commit_tx_fee_sat(context.feerate_per_kw, num_htlcs - 1, &context.channel_type) * 1000;
33223318
}
33233319
let total_pending_htlcs = context.pending_inbound_htlcs.len() + context.pending_outbound_htlcs.len()
33243320
+ context.holding_cell_htlc_updates.len();
@@ -3404,12 +3400,12 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
34043400
}
34053401

34063402
let num_htlcs = included_htlcs + addl_htlcs;
3407-
let res = commit_tx_fee_msat(context.feerate_per_kw, num_htlcs, &context.channel_type);
3403+
let res = commit_tx_fee_sat(context.feerate_per_kw, num_htlcs, &context.channel_type) * 1000;
34083404
#[cfg(any(test, fuzzing))]
34093405
{
34103406
let mut fee = res;
34113407
if fee_spike_buffer_htlc.is_some() {
3412-
fee = commit_tx_fee_msat(context.feerate_per_kw, num_htlcs - 1, &context.channel_type);
3408+
fee = commit_tx_fee_sat(context.feerate_per_kw, num_htlcs - 1, &context.channel_type) * 1000;
34133409
}
34143410
let total_pending_htlcs = context.pending_inbound_htlcs.len() + context.pending_outbound_htlcs.len();
34153411
let commitment_tx_info = CommitmentTxInfoCached {
@@ -3675,32 +3671,6 @@ fn get_v2_channel_reserve_satoshis(channel_value_satoshis: u64, dust_limit_satos
36753671
cmp::min(channel_value_satoshis, cmp::max(q, dust_limit_satoshis))
36763672
}
36773673

3678-
// Get the fee cost in SATS of a commitment tx with a given number of HTLC outputs.
3679-
// Note that num_htlcs should not include dust HTLCs.
3680-
#[inline]
3681-
fn commit_tx_fee_sat(feerate_per_kw: u32, num_htlcs: usize, channel_type_features: &ChannelTypeFeatures) -> u64 {
3682-
feerate_per_kw as u64 * (commitment_tx_base_weight(channel_type_features) + num_htlcs as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000
3683-
}
3684-
3685-
// Get the fee cost in MSATS of a commitment tx with a given number of HTLC outputs.
3686-
// Note that num_htlcs should not include dust HTLCs.
3687-
pub(crate) fn commit_tx_fee_msat(feerate_per_kw: u32, num_htlcs: usize, channel_type_features: &ChannelTypeFeatures) -> u64 {
3688-
// Note that we need to divide before multiplying to round properly,
3689-
// since the lowest denomination of bitcoin on-chain is the satoshi.
3690-
(commitment_tx_base_weight(channel_type_features) + num_htlcs as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC) * feerate_per_kw as u64 / 1000 * 1000
3691-
}
3692-
3693-
pub(crate) fn per_outbound_htlc_counterparty_commit_tx_fee_msat(feerate_per_kw: u32, channel_type_features: &ChannelTypeFeatures) -> u64 {
3694-
// Note that we need to divide before multiplying to round properly,
3695-
// since the lowest denomination of bitcoin on-chain is the satoshi.
3696-
let commitment_tx_fee = COMMITMENT_TX_WEIGHT_PER_HTLC * feerate_per_kw as u64 / 1000 * 1000;
3697-
if channel_type_features.supports_anchors_zero_fee_htlc_tx() {
3698-
commitment_tx_fee + htlc_success_tx_weight(channel_type_features) * feerate_per_kw as u64 / 1000
3699-
} else {
3700-
commitment_tx_fee
3701-
}
3702-
}
3703-
37043674
/// Context for dual-funded channels.
37053675
#[cfg(any(dual_funding, splicing))]
37063676
pub(super) struct DualFundingChannelContext {
@@ -7395,7 +7365,7 @@ impl<SP: Deref> Channel<SP> where
73957365
&& info.next_holder_htlc_id == self.context.next_holder_htlc_id
73967366
&& info.next_counterparty_htlc_id == self.context.next_counterparty_htlc_id
73977367
&& info.feerate == self.context.feerate_per_kw {
7398-
let actual_fee = commit_tx_fee_msat(self.context.feerate_per_kw, commitment_stats.num_nondust_htlcs, self.context.get_channel_type());
7368+
let actual_fee = commit_tx_fee_sat(self.context.feerate_per_kw, commitment_stats.num_nondust_htlcs, self.context.get_channel_type()) * 1000;
73997369
assert_eq!(actual_fee, info.fee);
74007370
}
74017371
}
@@ -9596,7 +9566,7 @@ mod tests {
95969566
use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint};
95979567
use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
95989568
use crate::ln::channel::InitFeatures;
9599-
use crate::ln::channel::{AwaitingChannelReadyFlags, Channel, ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_msat};
9569+
use crate::ln::channel::{AwaitingChannelReadyFlags, Channel, ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_sat};
96009570
use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS};
96019571
use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures};
96029572
use crate::ln::msgs;
@@ -9819,13 +9789,13 @@ mod tests {
98199789
// the dust limit check.
98209790
let htlc_candidate = HTLCCandidate::new(htlc_amount_msat, HTLCInitiator::LocalOffered);
98219791
let local_commit_tx_fee = node_a_chan.context.next_local_commit_tx_fee_msat(htlc_candidate, None);
9822-
let local_commit_fee_0_htlcs = commit_tx_fee_msat(node_a_chan.context.feerate_per_kw, 0, node_a_chan.context.get_channel_type());
9792+
let local_commit_fee_0_htlcs = commit_tx_fee_sat(node_a_chan.context.feerate_per_kw, 0, node_a_chan.context.get_channel_type()) * 1000;
98239793
assert_eq!(local_commit_tx_fee, local_commit_fee_0_htlcs);
98249794

98259795
// Finally, make sure that when Node A calculates the remote's commitment transaction fees, all
98269796
// of the HTLCs are seen to be above the dust limit.
98279797
node_a_chan.context.channel_transaction_parameters.is_outbound_from_holder = false;
9828-
let remote_commit_fee_3_htlcs = commit_tx_fee_msat(node_a_chan.context.feerate_per_kw, 3, node_a_chan.context.get_channel_type());
9798+
let remote_commit_fee_3_htlcs = commit_tx_fee_sat(node_a_chan.context.feerate_per_kw, 3, node_a_chan.context.get_channel_type()) * 1000;
98299799
let htlc_candidate = HTLCCandidate::new(htlc_amount_msat, HTLCInitiator::LocalOffered);
98309800
let remote_commit_tx_fee = node_a_chan.context.next_remote_commit_tx_fee_msat(htlc_candidate, None);
98319801
assert_eq!(remote_commit_tx_fee, remote_commit_fee_3_htlcs);
@@ -9848,8 +9818,8 @@ mod tests {
98489818
let config = UserConfig::default();
98499819
let mut chan = OutboundV1Channel::<&TestKeysInterface>::new(&fee_est, &&keys_provider, &&keys_provider, node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42, None, &logger).unwrap();
98509820

9851-
let commitment_tx_fee_0_htlcs = commit_tx_fee_msat(chan.context.feerate_per_kw, 0, chan.context.get_channel_type());
9852-
let commitment_tx_fee_1_htlc = commit_tx_fee_msat(chan.context.feerate_per_kw, 1, chan.context.get_channel_type());
9821+
let commitment_tx_fee_0_htlcs = commit_tx_fee_sat(chan.context.feerate_per_kw, 0, chan.context.get_channel_type()) * 1000;
9822+
let commitment_tx_fee_1_htlc = commit_tx_fee_sat(chan.context.feerate_per_kw, 1, chan.context.get_channel_type()) * 1000;
98539823

98549824
// If HTLC_SUCCESS_TX_WEIGHT and HTLC_TIMEOUT_TX_WEIGHT were swapped: then this HTLC would be
98559825
// counted as dust when it shouldn't be.

lightning/src/ln/functional_tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ use crate::chain::transaction::OutPoint;
2020
use crate::sign::{ecdsa::EcdsaChannelSigner, EntropySource, OutputSpender, SignerProvider};
2121
use crate::events::{Event, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentPurpose, ClosureReason, HTLCDestination, PaymentFailureReason};
2222
use crate::ln::types::{ChannelId, PaymentPreimage, PaymentSecret, PaymentHash};
23-
use crate::ln::channel::{commitment_tx_base_weight, COMMITMENT_TX_WEIGHT_PER_HTLC, CONCURRENT_INBOUND_HTLC_FEE_BUFFER, FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE, MIN_AFFORDABLE_HTLC_COUNT, get_holder_selected_channel_reserve_satoshis, OutboundV1Channel, InboundV1Channel, COINBASE_MATURITY, ChannelPhase};
23+
use crate::ln::channel::{CONCURRENT_INBOUND_HTLC_FEE_BUFFER, FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE, MIN_AFFORDABLE_HTLC_COUNT, get_holder_selected_channel_reserve_satoshis, OutboundV1Channel, InboundV1Channel, COINBASE_MATURITY, ChannelPhase};
2424
use crate::ln::channelmanager::{self, PaymentId, RAACommitmentOrder, PaymentSendFailure, RecipientOnionFields, BREAKDOWN_TIMEOUT, ENABLE_GOSSIP_TICKS, DISABLE_GOSSIP_TICKS, MIN_CLTV_EXPIRY_DELTA};
2525
use crate::ln::channel::{DISCONNECT_PEER_AWAITING_RESPONSE_TICKS, ChannelError};
2626
use crate::ln::{chan_utils, onion_utils};
27-
use crate::ln::chan_utils::{OFFERED_HTLC_SCRIPT_WEIGHT, htlc_success_tx_weight, htlc_timeout_tx_weight, HTLCOutputInCommitment};
27+
use crate::ln::chan_utils::{commitment_tx_base_weight, COMMITMENT_TX_WEIGHT_PER_HTLC, OFFERED_HTLC_SCRIPT_WEIGHT, htlc_success_tx_weight, htlc_timeout_tx_weight, HTLCOutputInCommitment};
2828
use crate::routing::gossip::{NetworkGraph, NetworkUpdate};
2929
use crate::routing::router::{Path, PaymentParameters, Route, RouteHop, get_route, RouteParameters};
3030
use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures};

0 commit comments

Comments
 (0)