Skip to content

Commit 8f3fe98

Browse files
committed
Limit the number of pending un-funded inbound channel
Because we store some (not large, but not zero) state per-peer, it's useful to limit the number of peers we have connected, at least with some buffer. Much more importantly, each channel has a relatively large cost, especially around the `ChannelMonitor`s we have to build for each. Thus, here, we limit the number of channels per-peer which aren't (yet) on-chain, as well as limit the number of (inbound) peers which don't have a (funded-on-chain) channel. Fixes #1889
1 parent 49cb089 commit 8f3fe98

File tree

1 file changed

+44
-3
lines changed

1 file changed

+44
-3
lines changed

lightning/src/ln/channelmanager.rs

+44-3
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,15 @@ pub(crate) const MPP_TIMEOUT_TICKS: u8 = 3;
924924
/// [`OutboundPayments::remove_stale_resolved_payments`].
925925
pub(crate) const IDEMPOTENCY_TIMEOUT_TICKS: u8 = 7;
926926

927+
/// The maximum number of unfunded channels we can have per-peer before we start rejecting new
928+
/// (inbound) ones. The number of peers without funded channels is limited separately in
929+
/// [`MAX_NO_CHANNEL_PEERS`].
930+
const MAX_UNFUNDED_CHANS_PER_PEER: usize = 4;
931+
932+
/// The maximum number of peers which we do not have a (funded) channel with. Once we reach this
933+
/// many peers we reject new (inbound) connections.
934+
const MAX_NO_CHANNEL_PEERS: usize = 50;
935+
927936
/// Information needed for constructing an invoice route hint for this channel.
928937
#[derive(Clone, Debug, PartialEq)]
929938
pub struct CounterpartyForwardingInfo {
@@ -4262,9 +4271,23 @@ where
42624271
}
42634272
let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
42644273
let peer_state = &mut *peer_state_lock;
4274+
4275+
let mut unfunded_channels = 0;
4276+
let best_block_height = self.best_block.read().unwrap().height();
4277+
for (_, chan) in peer_state.channel_by_id.iter() {
4278+
if chan.get_funding_tx_confirmations(best_block_height) == 0 {
4279+
unfunded_channels += 1;
4280+
}
4281+
}
4282+
if unfunded_channels > MAX_UNFUNDED_CHANS_PER_PEER {
4283+
return Err(MsgHandleErrInternal::send_err_msg_no_close(
4284+
format!("Refusing more than {} unfunded channels.", MAX_UNFUNDED_CHANS_PER_PEER),
4285+
msg.temporary_channel_id.clone()));
4286+
}
4287+
42654288
let mut channel = match Channel::new_from_req(&self.fee_estimator, &self.entropy_source, &self.signer_provider,
4266-
counterparty_node_id.clone(), &self.channel_type_features(), &peer_state.latest_features, msg, user_channel_id, &self.default_configuration,
4267-
self.best_block.read().unwrap().height(), &self.logger, outbound_scid_alias)
4289+
counterparty_node_id.clone(), &self.channel_type_features(), &peer_state.latest_features, msg, user_channel_id,
4290+
&self.default_configuration, best_block_height, &self.logger, outbound_scid_alias)
42684291
{
42694292
Err(e) => {
42704293
self.outbound_scid_aliases.lock().unwrap().remove(&outbound_scid_alias);
@@ -6207,7 +6230,7 @@ where
62076230
}
62086231
}
62096232

6210-
fn peer_connected(&self, counterparty_node_id: &PublicKey, init_msg: &msgs::Init, _inbound: bool) -> Result<(), ()> {
6233+
fn peer_connected(&self, counterparty_node_id: &PublicKey, init_msg: &msgs::Init, inbound: bool) -> Result<(), ()> {
62116234
if !init_msg.features.supports_static_remote_key() {
62126235
log_debug!(self.logger, "Peer {} does not support static remote key, disconnecting with no_connection_possible", log_pubkey!(counterparty_node_id));
62136236
return Err(());
@@ -6217,6 +6240,24 @@ where
62176240

62186241
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
62196242

6243+
let mut peers_with_unfunded_channels = 0;
6244+
let best_block_height = self.best_block.read().unwrap().height();
6245+
{
6246+
let peer_state_lock = self.per_peer_state.read().unwrap();
6247+
for (_, peer) in peer_state_lock.iter() {
6248+
let mut has_funded_channels = false;
6249+
for (_, chan) in peer.lock().unwrap().channel_by_id.iter() {
6250+
if chan.get_funding_tx_confirmations(best_block_height) != 0 {
6251+
has_funded_channels = true;
6252+
}
6253+
}
6254+
if !has_funded_channels { peers_with_unfunded_channels += 1 }
6255+
}
6256+
}
6257+
if inbound && peers_with_unfunded_channels > MAX_NO_CHANNEL_PEERS {
6258+
return Err(());
6259+
}
6260+
62206261
{
62216262
let mut peer_state_lock = self.per_peer_state.write().unwrap();
62226263
match peer_state_lock.entry(counterparty_node_id.clone()) {

0 commit comments

Comments
 (0)