Skip to content

Commit 8d20adc

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 8d20adc

File tree

4 files changed

+121
-8
lines changed

4 files changed

+121
-8
lines changed

lightning/src/ln/channel.rs

Lines changed: 29 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 need of this flag is
541+
/// that 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,10 @@ 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+
// The Channel must manually accepted before the FundingCreated is received.
1938+
return Err(ChannelError::Close("FundingCreated message received before the channel was accepted".to_owned()));
1939+
}
19211940
if self.commitment_secrets.get_min_seen_secret() != (1 << 48) ||
19221941
self.cur_counterparty_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER ||
19231942
self.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
@@ -4504,7 +4523,11 @@ impl<Signer: Sign> Channel<Signer> {
45044523
}
45054524
}
45064525

4507-
pub fn get_accept_channel(&self) -> msgs::AcceptChannel {
4526+
pub fn inbound_is_awaiting_accept(&self) -> bool {
4527+
self.inbound_awaiting_accept
4528+
}
4529+
4530+
pub fn get_accept_channel(&mut self) -> msgs::AcceptChannel {
45084531
if self.is_outbound() {
45094532
panic!("Tried to send accept_channel for an outbound channel?");
45104533
}
@@ -4515,6 +4538,8 @@ impl<Signer: Sign> Channel<Signer> {
45154538
panic!("Tried to send an accept_channel for a channel that has already advanced");
45164539
}
45174540

4541+
self.inbound_awaiting_accept = false;
4542+
45184543
let first_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx);
45194544
let keys = self.get_holder_pubkeys();
45204545

@@ -5840,6 +5865,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
58405865
closing_fee_limits: None,
58415866
target_closing_feerate_sats_per_kw,
58425867

5868+
inbound_awaiting_accept: false,
5869+
58435870
funding_tx_confirmed_in,
58445871
funding_tx_confirmation_height,
58455872
short_channel_id,
@@ -6050,7 +6077,7 @@ mod tests {
60506077
// Make sure A's dust limit is as we expect.
60516078
let open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash());
60526079
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();
6080+
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();
60546081

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

lightning/src/ln/channelmanager.rs

Lines changed: 47 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,32 @@ 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+
chain_hash: msg.chain_hash.clone(),
4161+
funding_satoshis: msg.funding_satoshis,
4162+
push_msat: msg.push_msat,
4163+
}
4164+
);
4165+
}
4166+
41254167
entry.insert(channel);
41264168
}
41274169
}

lightning/src/util/config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,9 @@ 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 channel.
309+
/// Default value: false.
310+
pub manually_accept_inbound_channels: bool,
308311
}
309312

310313
impl Default for UserConfig {
@@ -315,6 +318,7 @@ impl Default for UserConfig {
315318
channel_options: ChannelConfig::default(),
316319
accept_forwards_to_priv_channels: false,
317320
accept_inbound_channels: true,
321+
manually_accept_inbound_channels: false,
318322
}
319323
}
320324
}

lightning/src/util/events.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ 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-
32+
use bitcoin::hash_types::{BlockHash};
3333
use io;
3434
use prelude::*;
3535
use core::time::Duration;
@@ -403,6 +403,37 @@ pub enum Event {
403403
/// May contain a closed channel if the HTLC sent along the path was fulfilled on chain.
404404
path: Vec<RouteHop>,
405405
},
406+
/// Indicates a request to open a new channel by a peer.
407+
///
408+
/// The [`ChannelManager::accept_inbound_channel`] function should be called to accept the
409+
/// request. To reject the request, the [`ChannelManager::force_close_channel`] function should
410+
/// be called.
411+
///
412+
/// The event is only triggered when a new open channel request is received and the
413+
/// [`UserConfig::manually_accept_inbound_channels`] config flag is set to true.
414+
///
415+
/// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
416+
/// [`ChannelManager::force_close_channel`]: crate::ln::channelmanager::ChannelManager::force_close_channel
417+
/// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels
418+
OpenChannelRequest {
419+
/// The temporary channel ID of the channel requested to be opened.
420+
///
421+
/// When responding to the request, the `temporary_channel_id` should be passed
422+
/// back to the ChannelManager with [`ChannelManager::accept_inbound_channel`] to accept,
423+
/// or to [`ChannelManager::force_close_channel`] to reject.
424+
///
425+
/// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
426+
/// [`ChannelManager::force_close_channel`]: crate::ln::channelmanager::ChannelManager::force_close_channel
427+
temporary_channel_id: [u8; 32],
428+
/// The node_id of the counterparty requesting to open the channel.
429+
counterparty_node_id: PublicKey,
430+
/// The genesis hash of the blockchain where the channel is requested to be opened.
431+
chain_hash: BlockHash,
432+
/// The channel value of the requested channel.
433+
funding_satoshis: u64,
434+
/// Our starting balance in the channel if the request is accepted, in milli-satoshi.
435+
push_msat: u64,
436+
},
406437
}
407438

408439
impl Writeable for Event {
@@ -515,6 +546,11 @@ impl Writeable for Event {
515546
(2, payment_hash, required),
516547
})
517548
},
549+
&Event::OpenChannelRequest { .. } => {
550+
17u8.write(writer)?;
551+
// We never write the OpenChannelRequest events as, upon disconnection, peers
552+
// drop any channels which have not yet exchanged funding_signed.
553+
},
518554
// Note that, going forward, all new events must only write data inside of
519555
// `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write
520556
// data via `write_tlv_fields`.
@@ -707,6 +743,10 @@ impl MaybeReadable for Event {
707743
};
708744
f()
709745
},
746+
17u8 => {
747+
// Value 17 is used for `Event::OpenChannelRequest`.
748+
Ok(None)
749+
},
710750
// Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue.
711751
// Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt
712752
// reads.

0 commit comments

Comments
 (0)