Skip to content

Commit 68b16e2

Browse files
committed
Define a method for determining the max HTLCs rather than a const
Once we support zero-fee commitment transactions, we will no longer have a constant number of maximum HTLCs in-flight per channel but rather it will depend on the channel type. Here we prepare for this by removing the `MAX_HTLCS` constant and replacing it with a function.
1 parent 8527258 commit 68b16e2

File tree

5 files changed

+45
-31
lines changed

5 files changed

+45
-31
lines changed

lightning/src/ln/chan_utils.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,14 @@ use super::channel_keys::{DelayedPaymentBasepoint, DelayedPaymentKey, HtlcKey, H
5252
#[allow(unused_imports)]
5353
use crate::prelude::*;
5454

55-
/// Maximum number of one-way in-flight HTLC (protocol-level value).
56-
pub const MAX_HTLCS: u16 = 483;
55+
/// Maximum number of in-flight HTLCs in each direction allowed by the lightning protocol.
56+
///
57+
/// 483 for non-zero-fee-commitment channels and 114 for zero-fee-commitment channels.
58+
///
59+
/// Actual maximums can be set equal to or below this value by each channel participant.
60+
pub fn max_htlcs(_channel_type: &ChannelTypeFeatures) -> u16 {
61+
483
62+
}
5763
/// The weight of a BIP141 witnessScript for a BOLT3's "offered HTLC output" on a commitment transaction, non-anchor variant.
5864
pub const OFFERED_HTLC_SCRIPT_WEIGHT: usize = 133;
5965
/// The weight of a BIP141 witnessScript for a BOLT3's "offered HTLC output" on a commitment transaction, anchor variant.

lightning/src/ln/channel.rs

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use crate::ln::chan_utils::{
4343
CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, htlc_success_tx_weight,
4444
htlc_timeout_tx_weight, ChannelPublicKeys, CommitmentTransaction,
4545
HolderCommitmentTransaction, ChannelTransactionParameters,
46-
CounterpartyChannelTransactionParameters, MAX_HTLCS,
46+
CounterpartyChannelTransactionParameters, max_htlcs,
4747
get_commitment_transaction_number_obscure_factor,
4848
ClosingTransaction, commit_tx_fee_sat,
4949
};
@@ -2457,8 +2457,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
24572457
if open_channel_fields.max_accepted_htlcs < 1 {
24582458
return Err(ChannelError::close("0 max_accepted_htlcs makes for a useless channel".to_owned()));
24592459
}
2460-
if open_channel_fields.max_accepted_htlcs > MAX_HTLCS {
2461-
return Err(ChannelError::close(format!("max_accepted_htlcs was {}. It must not be larger than {}", open_channel_fields.max_accepted_htlcs, MAX_HTLCS)));
2460+
if open_channel_fields.max_accepted_htlcs > max_htlcs(&channel_type) {
2461+
return Err(ChannelError::close(format!("max_accepted_htlcs was {}. It must not be larger than {}", open_channel_fields.max_accepted_htlcs, max_htlcs(&channel_type))));
24622462
}
24632463

24642464
// Now check against optional parameters as set by config...
@@ -2686,7 +2686,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
26862686
counterparty_htlc_minimum_msat: open_channel_fields.htlc_minimum_msat,
26872687
holder_htlc_minimum_msat: if config.channel_handshake_config.our_htlc_minimum_msat == 0 { 1 } else { config.channel_handshake_config.our_htlc_minimum_msat },
26882688
counterparty_max_accepted_htlcs: open_channel_fields.max_accepted_htlcs,
2689-
holder_max_accepted_htlcs: cmp::min(config.channel_handshake_config.our_max_accepted_htlcs, MAX_HTLCS),
2689+
holder_max_accepted_htlcs: cmp::min(config.channel_handshake_config.our_max_accepted_htlcs, max_htlcs(&channel_type)),
26902690
minimum_depth,
26912691

26922692
counterparty_forwarding_info: None,
@@ -2923,7 +2923,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
29232923
counterparty_htlc_minimum_msat: 0,
29242924
holder_htlc_minimum_msat: if config.channel_handshake_config.our_htlc_minimum_msat == 0 { 1 } else { config.channel_handshake_config.our_htlc_minimum_msat },
29252925
counterparty_max_accepted_htlcs: 0,
2926-
holder_max_accepted_htlcs: cmp::min(config.channel_handshake_config.our_max_accepted_htlcs, MAX_HTLCS),
2926+
holder_max_accepted_htlcs: cmp::min(config.channel_handshake_config.our_max_accepted_htlcs, max_htlcs(&channel_type)),
29272927
minimum_depth: None, // Filled in in accept_channel
29282928

29292929
counterparty_forwarding_info: None,
@@ -3183,6 +3183,22 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
31833183
if !matches!(self.channel_state, ChannelState::NegotiatingFunding(flags) if flags == NegotiatingFundingFlags::OUR_INIT_SENT) {
31843184
return Err(ChannelError::close("Got an accept_channel message at a strange time".to_owned()));
31853185
}
3186+
3187+
if let Some(ty) = &common_fields.channel_type {
3188+
if *ty != self.channel_type {
3189+
return Err(ChannelError::close("Channel Type in accept_channel didn't match the one sent in open_channel.".to_owned()));
3190+
}
3191+
} else if their_features.supports_channel_type() {
3192+
// Assume they've accepted the channel type as they said they understand it.
3193+
} else {
3194+
let channel_type = ChannelTypeFeatures::from_init(&their_features);
3195+
if channel_type != ChannelTypeFeatures::only_static_remote_key() {
3196+
return Err(ChannelError::close("Only static_remote_key is supported for non-negotiated channel types".to_owned()));
3197+
}
3198+
self.channel_type = channel_type.clone();
3199+
funding.channel_transaction_parameters.channel_type_features = channel_type;
3200+
}
3201+
31863202
if common_fields.dust_limit_satoshis > 21000000 * 100000000 {
31873203
return Err(ChannelError::close(format!("Peer never wants payout outputs? dust_limit_satoshis was {}", common_fields.dust_limit_satoshis)));
31883204
}
@@ -3207,8 +3223,10 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
32073223
if common_fields.max_accepted_htlcs < 1 {
32083224
return Err(ChannelError::close("0 max_accepted_htlcs makes for a useless channel".to_owned()));
32093225
}
3210-
if common_fields.max_accepted_htlcs > MAX_HTLCS {
3211-
return Err(ChannelError::close(format!("max_accepted_htlcs was {}. It must not be larger than {}", common_fields.max_accepted_htlcs, MAX_HTLCS)));
3226+
3227+
let channel_type = &funding.channel_transaction_parameters.channel_type_features;
3228+
if common_fields.max_accepted_htlcs > max_htlcs(channel_type) {
3229+
return Err(ChannelError::close(format!("max_accepted_htlcs was {}. It must not be larger than {}", common_fields.max_accepted_htlcs, max_htlcs(channel_type))));
32123230
}
32133231

32143232
// Now check against optional parameters as set by config...
@@ -3234,21 +3252,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
32343252
return Err(ChannelError::close(format!("We consider the minimum depth to be unreasonably large. Expected minimum: ({}). Actual: ({})", peer_limits.max_minimum_depth, common_fields.minimum_depth)));
32353253
}
32363254

3237-
if let Some(ty) = &common_fields.channel_type {
3238-
if *ty != self.channel_type {
3239-
return Err(ChannelError::close("Channel Type in accept_channel didn't match the one sent in open_channel.".to_owned()));
3240-
}
3241-
} else if their_features.supports_channel_type() {
3242-
// Assume they've accepted the channel type as they said they understand it.
3243-
} else {
3244-
let channel_type = ChannelTypeFeatures::from_init(&their_features);
3245-
if channel_type != ChannelTypeFeatures::only_static_remote_key() {
3246-
return Err(ChannelError::close("Only static_remote_key is supported for non-negotiated channel types".to_owned()));
3247-
}
3248-
self.channel_type = channel_type.clone();
3249-
funding.channel_transaction_parameters.channel_type_features = channel_type;
3250-
}
3251-
32523255
let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() {
32533256
match &common_fields.shutdown_scriptpubkey {
32543257
&Some(ref script) => {

lightning/src/ln/functional_tests.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10609,8 +10609,9 @@ pub fn test_nondust_htlc_excess_fees_are_dust() {
1060910609
config.channel_config.max_dust_htlc_exposure =
1061010610
MaxDustHTLCExposure::FeeRateMultiplier(10_000);
1061110611
// Make sure the HTLC limits don't get in the way
10612-
config.channel_handshake_limits.min_max_accepted_htlcs = chan_utils::MAX_HTLCS;
10613-
config.channel_handshake_config.our_max_accepted_htlcs = chan_utils::MAX_HTLCS;
10612+
let chan_ty = ChannelTypeFeatures::only_static_remote_key();
10613+
config.channel_handshake_limits.min_max_accepted_htlcs = chan_utils::max_htlcs(&chan_ty);
10614+
config.channel_handshake_config.our_max_accepted_htlcs = chan_utils::max_htlcs(&chan_ty);
1061410615
config.channel_handshake_config.our_htlc_minimum_msat = 1;
1061510616
config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 100;
1061610617

@@ -10651,7 +10652,7 @@ pub fn test_nondust_htlc_excess_fees_are_dust() {
1065110652
let commitment_tx_per_htlc_cost =
1065210653
htlc_success_tx_weight(&ChannelTypeFeatures::empty()) * EXCESS_FEERATE as u64;
1065310654
let max_htlcs_remaining = dust_limit * 2 / commitment_tx_per_htlc_cost;
10654-
assert!(max_htlcs_remaining < chan_utils::MAX_HTLCS.into(),
10655+
assert!(max_htlcs_remaining < chan_utils::max_htlcs(&chan_ty).into(),
1065510656
"We should be able to fill our dust limit without too many HTLCs");
1065610657
for i in 0..max_htlcs_remaining + 1 {
1065710658
assert_ne!(i, max_htlcs_remaining);

lightning/src/util/anchor_channel_reserves.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ use crate::chain::chainmonitor::ChainMonitor;
2525
use crate::chain::chainmonitor::Persist;
2626
use crate::chain::Filter;
2727
use crate::events::bump_transaction::Utxo;
28-
use crate::ln::chan_utils::MAX_HTLCS;
28+
use crate::ln::chan_utils::max_htlcs;
2929
use crate::ln::channelmanager::AChannelManager;
3030
use crate::prelude::new_hash_set;
3131
use crate::sign::ecdsa::EcdsaChannelSigner;
32+
use crate::types::features::ChannelTypeFeatures;
3233
use crate::util::logger::Logger;
3334
use bitcoin::constants::WITNESS_SCALE_FACTOR;
3435
use bitcoin::Amount;
@@ -178,7 +179,8 @@ impl Default for AnchorChannelReserveContext {
178179
fn get_reserve_per_channel_with_input(
179180
context: &AnchorChannelReserveContext, initial_input_weight: Weight,
180181
) -> Amount {
181-
let expected_accepted_htlcs = min(context.expected_accepted_htlcs, MAX_HTLCS) as u64;
182+
let max_max_htlcs = max_htlcs(&ChannelTypeFeatures::only_static_remote_key());
183+
let expected_accepted_htlcs = min(context.expected_accepted_htlcs, max_max_htlcs) as u64;
182184
let weight = Weight::from_wu(
183185
COMMITMENT_TRANSACTION_BASE_WEIGHT +
184186
// Reserves are calculated in terms of accepted HTLCs, as their timeout defines the urgency of

lightning/src/util/config.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,10 @@ pub struct ChannelHandshakeConfig {
193193
///
194194
/// Default value: `50`
195195
///
196-
/// Maximum value: `483` (Any values larger will be treated as `483`. This is the BOLT #2 spec
197-
/// limit on `max_accepted_htlcs`.)
196+
/// Maximum value: depends on channel type, see docs on [`max_htlcs`] (any values over the
197+
/// maximum will be silently reduced to the maximum).
198+
///
199+
/// [`max_htlcs`]: crate::ln::chan_utils::max_htlcs
198200
pub our_max_accepted_htlcs: u16,
199201
}
200202

0 commit comments

Comments
 (0)