Skip to content

Commit f38f2d5

Browse files
Add option accept or reject channel requests
Add new new config flag, which when set to true allows the node operator to accept or reject new channel requests.
1 parent 1a24dcc commit f38f2d5

File tree

4 files changed

+127
-8
lines changed

4 files changed

+127
-8
lines changed

lightning/src/ln/channel.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,17 @@ pub(super) struct Channel<Signer: Sign> {
536536
#[cfg(not(test))]
537537
closing_fee_limits: Option<(u64, u64)>,
538538

539+
/// Flag that ensures that the `get_accept_channel` function must be called before the
540+
/// `funding_created` function is executed successfully. The reason for this flag is that
541+
/// when the util::config::UserConfig.manually_accept_inbound_channels is set to true,
542+
/// inbound channels are required to be manually accepted by the node operator before the
543+
/// `SendAcceptChannel` message is created and sent out. The `get_accept_channel` function is
544+
/// called during that process.
545+
/// A counterparty node could theoretically send a `FundingCreated` message before the node
546+
/// operator has accepted the inbound channel. That would would execute the `funding_created`
547+
/// function before the `get_accept_channel` function, and should therefore be rejected.
548+
inbound_awaiting_accept: bool,
549+
539550
/// The hash of the block in which the funding transaction was included.
540551
funding_tx_confirmed_in: Option<BlockHash>,
541552
funding_tx_confirmation_height: u32,
@@ -833,6 +844,8 @@ impl<Signer: Sign> Channel<Signer> {
833844
closing_fee_limits: None,
834845
target_closing_feerate_sats_per_kw: None,
835846

847+
inbound_awaiting_accept: false,
848+
836849
funding_tx_confirmed_in: None,
837850
funding_tx_confirmation_height: 0,
838851
short_channel_id: None,
@@ -1130,6 +1143,8 @@ impl<Signer: Sign> Channel<Signer> {
11301143
closing_fee_limits: None,
11311144
target_closing_feerate_sats_per_kw: None,
11321145

1146+
inbound_awaiting_accept: true,
1147+
11331148
funding_tx_confirmed_in: None,
11341149
funding_tx_confirmation_height: 0,
11351150
short_channel_id: None,
@@ -1918,6 +1933,9 @@ impl<Signer: Sign> Channel<Signer> {
19181933
// channel.
19191934
return Err(ChannelError::Close("Received funding_created after we got the channel!".to_owned()));
19201935
}
1936+
if self.inbound_awaiting_accept {
1937+
return Err(ChannelError::Close("FundingCreated message received before the channel was accepted".to_owned()));
1938+
}
19211939
if self.commitment_secrets.get_min_seen_secret() != (1 << 48) ||
19221940
self.cur_counterparty_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER ||
19231941
self.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
@@ -4504,7 +4522,11 @@ impl<Signer: Sign> Channel<Signer> {
45044522
}
45054523
}
45064524

4507-
pub fn get_accept_channel(&self) -> msgs::AcceptChannel {
4525+
pub fn inbound_is_awaiting_accept(&self) -> bool {
4526+
self.inbound_awaiting_accept
4527+
}
4528+
4529+
pub fn get_accept_channel(&mut self) -> msgs::AcceptChannel {
45084530
if self.is_outbound() {
45094531
panic!("Tried to send accept_channel for an outbound channel?");
45104532
}
@@ -4515,6 +4537,8 @@ impl<Signer: Sign> Channel<Signer> {
45154537
panic!("Tried to send an accept_channel for a channel that has already advanced");
45164538
}
45174539

4540+
self.inbound_awaiting_accept = false;
4541+
45184542
let first_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx);
45194543
let keys = self.get_holder_pubkeys();
45204544

@@ -5840,6 +5864,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
58405864
closing_fee_limits: None,
58415865
target_closing_feerate_sats_per_kw,
58425866

5867+
inbound_awaiting_accept: false,
5868+
58435869
funding_tx_confirmed_in,
58445870
funding_tx_confirmation_height,
58455871
short_channel_id,
@@ -6050,7 +6076,7 @@ mod tests {
60506076
// Make sure A's dust limit is as we expect.
60516077
let open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash());
60526078
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
6053-
let node_b_chan = Channel::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger).unwrap();
6079+
let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger).unwrap();
60546080

60556081
// Node B --> Node A: accept channel, explicitly setting B's dust limit.
60566082
let mut accept_channel_msg = node_b_chan.get_accept_channel();

lightning/src/ln/channelmanager.rs

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4101,6 +4101,34 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
41014101
}
41024102
}
41034103

4104+
/// Called to accept a request to open a channel after the
4105+
/// [`events::Event::OpenChannelRequest`] has been triggered.
4106+
///
4107+
/// The `temporary_channel_id` parameter indicates which inbound channel should be accepted.
4108+
///
4109+
/// [`events::Event::OpenChannelRequest`]: crate::util::events::Event::OpenChannelRequest
4110+
pub fn accept_inbound_channel(&self, temporary_channel_id: &[u8; 32]) -> Result<(), APIError> {
4111+
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
4112+
4113+
let mut channel_state_lock = self.channel_state.lock().unwrap();
4114+
let channel_state = &mut *channel_state_lock;
4115+
match channel_state.by_id.entry(temporary_channel_id.clone()) {
4116+
hash_map::Entry::Occupied(mut channel) => {
4117+
if !channel.get().inbound_is_awaiting_accept() {
4118+
return Err(APIError::APIMisuseError { err: "The channel isn't currently awaiting to be accepted.".to_owned() });
4119+
}
4120+
channel_state.pending_msg_events.push(events::MessageSendEvent::SendAcceptChannel {
4121+
node_id: channel.get().get_counterparty_node_id(),
4122+
msg: channel.get_mut().get_accept_channel(),
4123+
});
4124+
}
4125+
hash_map::Entry::Vacant(_) => {
4126+
return Err(APIError::ChannelUnavailable { err: "Can't accept a channel that doesn't exist".to_owned() });
4127+
}
4128+
}
4129+
Ok(())
4130+
}
4131+
41044132
fn internal_open_channel(&self, counterparty_node_id: &PublicKey, their_features: InitFeatures, msg: &msgs::OpenChannel) -> Result<(), MsgHandleErrInternal> {
41054133
if msg.chain_hash != self.genesis_hash {
41064134
return Err(MsgHandleErrInternal::send_err_msg_no_close("Unknown genesis block hash".to_owned(), msg.temporary_channel_id.clone()));
@@ -4110,18 +4138,31 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
41104138
return Err(MsgHandleErrInternal::send_err_msg_no_close("No inbound channels accepted".to_owned(), msg.temporary_channel_id.clone()));
41114139
}
41124140

4113-
let channel = Channel::new_from_req(&self.fee_estimator, &self.keys_manager, counterparty_node_id.clone(),
4141+
let mut channel = Channel::new_from_req(&self.fee_estimator, &self.keys_manager, counterparty_node_id.clone(),
41144142
&their_features, msg, 0, &self.default_configuration, self.best_block.read().unwrap().height(), &self.logger)
41154143
.map_err(|e| MsgHandleErrInternal::from_chan_no_close(e, msg.temporary_channel_id))?;
41164144
let mut channel_state_lock = self.channel_state.lock().unwrap();
41174145
let channel_state = &mut *channel_state_lock;
41184146
match channel_state.by_id.entry(channel.channel_id()) {
41194147
hash_map::Entry::Occupied(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("temporary_channel_id collision!".to_owned(), msg.temporary_channel_id.clone())),
41204148
hash_map::Entry::Vacant(entry) => {
4121-
channel_state.pending_msg_events.push(events::MessageSendEvent::SendAcceptChannel {
4122-
node_id: counterparty_node_id.clone(),
4123-
msg: channel.get_accept_channel(),
4124-
});
4149+
if !self.default_configuration.manually_accept_inbound_channels {
4150+
channel_state.pending_msg_events.push(events::MessageSendEvent::SendAcceptChannel {
4151+
node_id: counterparty_node_id.clone(),
4152+
msg: channel.get_accept_channel(),
4153+
});
4154+
} else {
4155+
let mut pending_events = self.pending_events.lock().unwrap();
4156+
pending_events.push(
4157+
events::Event::OpenChannelRequest {
4158+
temporary_channel_id: msg.temporary_channel_id.clone(),
4159+
counterparty_node_id: counterparty_node_id.clone(),
4160+
funding_satoshis: msg.funding_satoshis,
4161+
push_msat: msg.push_msat,
4162+
}
4163+
);
4164+
}
4165+
41254166
entry.insert(channel);
41264167
}
41274168
}

lightning/src/util/config.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,20 @@ pub struct UserConfig {
305305
/// If this is set to false, we do not accept inbound requests to open a new channel.
306306
/// Default value: true.
307307
pub accept_inbound_channels: bool,
308+
/// If this is set to true, the user needs to manually accept inbound requests to open a new
309+
/// channel.
310+
///
311+
/// When set to true, the [`Event::OpenChannelRequest`] event will be triggered once a request
312+
/// to open a new inbound channel is received through a [`msgs::OpenChannel`] message. In that
313+
/// case, a [`msgs::AcceptChannel`] message will not be sent back to the counterparty node
314+
/// unless the user explicitly chooses to accept the request.
315+
///
316+
/// Default value: false.
317+
///
318+
/// [`Event::OpenChannelRequest`]: crate::util::events::Event::OpenChannelRequest
319+
/// [`msgs::OpenChannel`]: crate::ln::msgs::OpenChannel
320+
/// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel
321+
pub manually_accept_inbound_channels: bool,
308322
}
309323

310324
impl Default for UserConfig {
@@ -315,6 +329,7 @@ impl Default for UserConfig {
315329
channel_options: ChannelConfig::default(),
316330
accept_forwards_to_priv_channels: false,
317331
accept_inbound_channels: true,
332+
manually_accept_inbound_channels: false,
318333
}
319334
}
320335
}

lightning/src/util/events.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ use bitcoin::blockdata::script::Script;
2929
use bitcoin::hashes::Hash;
3030
use bitcoin::hashes::sha256::Hash as Sha256;
3131
use bitcoin::secp256k1::key::PublicKey;
32-
3332
use io;
3433
use prelude::*;
3534
use core::time::Duration;
@@ -403,6 +402,35 @@ pub enum Event {
403402
/// May contain a closed channel if the HTLC sent along the path was fulfilled on chain.
404403
path: Vec<RouteHop>,
405404
},
405+
/// Indicates a request to open a new channel by a peer.
406+
///
407+
/// The [`ChannelManager::accept_inbound_channel`] function should be called to accept the
408+
/// request. To reject the request, the [`ChannelManager::force_close_channel`] function should
409+
/// be called.
410+
///
411+
/// The event is only triggered when a new open channel request is received and the
412+
/// [`UserConfig::manually_accept_inbound_channels`] config flag is set to true.
413+
///
414+
/// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
415+
/// [`ChannelManager::force_close_channel`]: crate::ln::channelmanager::ChannelManager::force_close_channel
416+
/// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels
417+
OpenChannelRequest {
418+
/// The temporary channel ID of the channel requested to be opened.
419+
///
420+
/// When responding to the request, the `temporary_channel_id` should be passed
421+
/// back to the ChannelManager with [`ChannelManager::accept_inbound_channel`] to accept,
422+
/// or to [`ChannelManager::force_close_channel`] to reject.
423+
///
424+
/// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
425+
/// [`ChannelManager::force_close_channel`]: crate::ln::channelmanager::ChannelManager::force_close_channel
426+
temporary_channel_id: [u8; 32],
427+
/// The node_id of the counterparty requesting to open the channel.
428+
counterparty_node_id: PublicKey,
429+
/// The channel value of the requested channel.
430+
funding_satoshis: u64,
431+
/// Our starting balance in the channel if the request is accepted, in milli-satoshi.
432+
push_msat: u64,
433+
},
406434
}
407435

408436
impl Writeable for Event {
@@ -515,6 +543,11 @@ impl Writeable for Event {
515543
(2, payment_hash, required),
516544
})
517545
},
546+
&Event::OpenChannelRequest { .. } => {
547+
17u8.write(writer)?;
548+
// We never write the OpenChannelRequest events as, upon disconnection, peers
549+
// drop any channels which have not yet exchanged funding_signed.
550+
},
518551
// Note that, going forward, all new events must only write data inside of
519552
// `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write
520553
// data via `write_tlv_fields`.
@@ -707,6 +740,10 @@ impl MaybeReadable for Event {
707740
};
708741
f()
709742
},
743+
17u8 => {
744+
// Value 17 is used for `Event::OpenChannelRequest`.
745+
Ok(None)
746+
},
710747
// Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue.
711748
// Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt
712749
// reads.

0 commit comments

Comments
 (0)