Skip to content

Commit c8ae2e7

Browse files
Support manual signaling of channel readiness
1 parent 2d213a4 commit c8ae2e7

File tree

4 files changed

+145
-15
lines changed

4 files changed

+145
-15
lines changed

lightning/src/ln/channel.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4968,10 +4968,11 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
49684968
self.channel_update_status = status;
49694969
}
49704970

4971-
fn check_get_channel_ready(&mut self, height: u32) -> Option<msgs::ChannelReady> {
4971+
pub fn check_get_channel_ready(&mut self, height: u32) -> Option<msgs::ChannelReady> {
49724972
// Called:
49734973
// * always when a new block/transactions are confirmed with the new height
49744974
// * when funding is signed with a height of 0
4975+
// * when user calls ChannelManager::signal_channel_readiness
49754976
if self.funding_tx_confirmation_height == 0 && self.minimum_depth != Some(0) {
49764977
return None;
49774978
}

lightning/src/ln/channelmanager.rs

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,20 +1451,30 @@ macro_rules! remove_channel {
14511451

14521452
macro_rules! send_channel_ready {
14531453
($self: ident, $pending_msg_events: expr, $channel: expr, $channel_ready_msg: expr) => {{
1454-
$pending_msg_events.push(events::MessageSendEvent::SendChannelReady {
1455-
node_id: $channel.get_counterparty_node_id(),
1456-
msg: $channel_ready_msg,
1457-
});
1458-
// Note that we may send a `channel_ready` multiple times for a channel if we reconnect, so
1459-
// we allow collisions, but we shouldn't ever be updating the channel ID pointed to.
1460-
let mut short_to_chan_info = $self.short_to_chan_info.write().unwrap();
1461-
let outbound_alias_insert = short_to_chan_info.insert($channel.outbound_scid_alias(), ($channel.get_counterparty_node_id(), $channel.channel_id()));
1462-
assert!(outbound_alias_insert.is_none() || outbound_alias_insert.unwrap() == ($channel.get_counterparty_node_id(), $channel.channel_id()),
1463-
"SCIDs should never collide - ensure you weren't behind the chain tip by a full month when creating channels");
1464-
if let Some(real_scid) = $channel.get_short_channel_id() {
1465-
let scid_insert = short_to_chan_info.insert(real_scid, ($channel.get_counterparty_node_id(), $channel.channel_id()));
1466-
assert!(scid_insert.is_none() || scid_insert.unwrap() == ($channel.get_counterparty_node_id(), $channel.channel_id()),
1454+
if $self.default_configuration.manually_signal_channel_ready {
1455+
let mut pending_events = $self.pending_events.lock().unwrap();
1456+
pending_events.push(events::Event::PendingChannelReady {
1457+
channel_id: $channel.channel_id(),
1458+
user_channel_id: $channel.get_user_id(),
1459+
counterparty_node_id: $channel.get_counterparty_node_id(),
1460+
funding_txid: $channel.get_funding_txo().unwrap().txid,
1461+
});
1462+
} else {
1463+
$pending_msg_events.push(events::MessageSendEvent::SendChannelReady {
1464+
node_id: $channel.get_counterparty_node_id(),
1465+
msg: $channel_ready_msg,
1466+
});
1467+
// Note that we may send a `channel_ready` multiple times for a channel if we reconnect, so
1468+
// we allow collisions, but we shouldn't ever be updating the channel ID pointed to.
1469+
let mut short_to_chan_info = $self.short_to_chan_info.write().unwrap();
1470+
let outbound_alias_insert = short_to_chan_info.insert($channel.outbound_scid_alias(), ($channel.get_counterparty_node_id(), $channel.channel_id()));
1471+
assert!(outbound_alias_insert.is_none() || outbound_alias_insert.unwrap() == ($channel.get_counterparty_node_id(), $channel.channel_id()),
14671472
"SCIDs should never collide - ensure you weren't behind the chain tip by a full month when creating channels");
1473+
if let Some(real_scid) = $channel.get_short_channel_id() {
1474+
let scid_insert = short_to_chan_info.insert(real_scid, ($channel.get_counterparty_node_id(), $channel.channel_id()));
1475+
assert!(scid_insert.is_none() || scid_insert.unwrap() == ($channel.get_counterparty_node_id(), $channel.channel_id()),
1476+
"SCIDs should never collide - ensure you weren't behind the chain tip by a full month when creating channels");
1477+
}
14681478
}
14691479
}}
14701480
}
@@ -4354,6 +4364,38 @@ where
43544364
Ok(())
43554365
}
43564366

4367+
/// Signals channel readiness after a [`Event::PendingChannelReady`].
4368+
///
4369+
/// The `channel_id` parameter indicates which channel should signal readiness,
4370+
/// and the `counterparty_node_id` parameter is the id of the peer the channel is with.
4371+
///
4372+
/// [`Event::PendingChannelReady`]: events::Event::PendingChannelReady
4373+
pub fn signal_channel_readiness(&self, channel_id: &[u8; 32], counterparty_node_id: &PublicKey) -> Result<(), APIError> {
4374+
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
4375+
4376+
let per_peer_state = self.per_peer_state.read().unwrap();
4377+
let peer_state_mutex = per_peer_state.get(counterparty_node_id)
4378+
.ok_or_else(|| APIError::ChannelUnavailable { err: format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id) })?;
4379+
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
4380+
let peer_state = &mut *peer_state_lock;
4381+
let pending_msg_events = &mut peer_state.pending_msg_events;
4382+
match peer_state.channel_by_id.entry(channel_id.clone()) {
4383+
hash_map::Entry::Occupied(mut channel) => {
4384+
let best_block_height = self.best_block.read().unwrap().height();
4385+
let channel = channel.get_mut();
4386+
match channel.check_get_channel_ready(best_block_height) {
4387+
Some(channel_ready) => send_channel_ready!(self, pending_msg_events, channel, channel_ready),
4388+
None => return Err(APIError::APIMisuseError { err: "The channel isn't currently in a state where we can signal readiness.".to_owned() })
4389+
}
4390+
}
4391+
hash_map::Entry::Vacant(_) => {
4392+
return Err(APIError::ChannelUnavailable { err: format!("Channel with id {} not found for the passed counterparty node_id {}", log_bytes!(*channel_id), counterparty_node_id) });
4393+
}
4394+
}
4395+
4396+
Ok(())
4397+
}
4398+
43574399
/// Gets the number of peers which match the given filter and do not have any funded, outbound,
43584400
/// or 0-conf channels.
43594401
///

lightning/src/util/config.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,17 @@ pub struct UserConfig {
538538
/// [`ChannelManager::get_intercept_scid`]: crate::ln::channelmanager::ChannelManager::get_intercept_scid
539539
/// [`Event::HTLCIntercepted`]: crate::util::events::Event::HTLCIntercepted
540540
pub accept_intercept_htlcs: bool,
541+
/// If this is set to true, the user needs to manually signal readiness for an inbound channel.
542+
///
543+
/// When set to true, [`Event::PendingChannelReady`] will be triggered once LDK has seen sufficient
544+
/// confirmations of the funding transaction. In that case, a [`msgs::ChannelReady`] message will not be
545+
/// sent to the counterparty node unless the user explicitly chooses to signal readiness.
546+
///
547+
/// Default value: false.
548+
///
549+
/// [`Event::PendingChannelReady`]: crate::util::events::Event::PendingChannelReady
550+
/// [`msgs::ChannelReady`]: crate::ln::msgs::ChannelReady
551+
pub manually_signal_channel_ready: bool,
541552
}
542553

543554
impl Default for UserConfig {
@@ -550,6 +561,7 @@ impl Default for UserConfig {
550561
accept_inbound_channels: true,
551562
manually_accept_inbound_channels: false,
552563
accept_intercept_htlcs: false,
564+
manually_signal_channel_ready: false,
553565
}
554566
}
555567
}

lightning/src/util/events.rs

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use crate::util::errors::APIError;
2727
use crate::util::ser::{BigSize, FixedLengthReader, Writeable, Writer, MaybeReadable, Readable, RequiredWrapper, UpgradableRequired, WithoutLength};
2828
use crate::routing::router::{RouteHop, RouteParameters};
2929

30-
use bitcoin::{PackedLockTime, Transaction};
30+
use bitcoin::{PackedLockTime, Transaction, Txid};
3131
#[cfg(anchors)]
3232
use bitcoin::{OutPoint, Txid, TxIn, TxOut, Witness};
3333
use bitcoin::blockdata::script::Script;
@@ -817,6 +817,50 @@ pub enum Event {
817817
/// transaction.
818818
claim_from_onchain_tx: bool,
819819
},
820+
/// Indicates a channel has received sufficient confirmations and LDK is ready to send [`msgs::ChannelReady`].
821+
///
822+
/// To signal readiness, call [`ChannelManager::signal_channel_readiness`]. To reject the
823+
/// request, call [`ChannelManager::force_close_without_broadcasting_txn`].
824+
///
825+
/// The event is only triggered when the [`UserConfig::manually_signal_channel_ready`]
826+
/// config flag is set to true.
827+
///
828+
/// [`ChannelManager::signal_channel_readiness`]: crate::ln::channelmanager::ChannelManager::signal_channel_readiness
829+
/// [`ChannelManager::force_close_without_broadcasting_txn`]: crate::ln::channelmanager::ChannelManager::force_close_without_broadcasting_txn
830+
/// [`UserConfig::manually_signal_channel_ready`]: crate::util::config::UserConfig::manually_signal_channel_ready
831+
/// [`msgs::ChannelReady`]: crate::ln::msgs::ChannelReady
832+
PendingChannelReady {
833+
/// The channel ID of the channel.
834+
///
835+
/// When responding to the request, the `channel_id` should be passed
836+
/// back to the ChannelManager through [`ChannelManager::signal_channel_readiness`] to signal,
837+
/// or through [`ChannelManager::force_close_without_broadcasting_txn`] to reject.
838+
///
839+
/// [`ChannelManager::signal_channel_readiness`]: crate::ln::channelmanager::ChannelManager::signal_channel_readiness
840+
/// [`ChannelManager::force_close_without_broadcasting_txn`]: crate::ln::channelmanager::ChannelManager::force_close_without_broadcasting_txn
841+
channel_id: [u8; 32],
842+
/// The `user_channel_id` value passed in to [`ChannelManager::create_channel`] for outbound
843+
/// channels, or to [`ChannelManager::accept_inbound_channel`] for inbound channels if
844+
/// [`UserConfig::manually_accept_inbound_channels`] config flag is set to true. Otherwise
845+
/// `user_channel_id` will be randomized for an inbound channel.
846+
///
847+
/// [`ChannelManager::create_channel`]: crate::ln::channelmanager::ChannelManager::create_channel
848+
/// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
849+
/// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels
850+
user_channel_id: u128,
851+
/// The node_id of the counterparty requesting to open the channel.
852+
///
853+
/// When responding to the request, the `counterparty_node_id` should be passed
854+
/// back to the `ChannelManager` through [`ChannelManager::signal_channel_readiness`] to
855+
/// signal readiness, or through [`ChannelManager::force_close_without_broadcasting_txn`] to reject the
856+
/// request.
857+
///
858+
/// [`ChannelManager::signal_channel_readiness`]: crate::ln::channelmanager::ChannelManager::signal_channel_readiness
859+
/// [`ChannelManager::force_close_without_broadcasting_txn`]: crate::ln::channelmanager::ChannelManager::force_close_without_broadcasting_txn
860+
counterparty_node_id: PublicKey,
861+
/// The txid of the funding transaction.
862+
funding_txid: Txid,
863+
},
820864
/// Used to indicate that a channel with the given `channel_id` is ready to
821865
/// be used. This event is emitted either when the funding transaction has been confirmed
822866
/// on-chain, or, in case of a 0conf channel, when both parties have confirmed the channel
@@ -1136,6 +1180,15 @@ impl Writeable for Event {
11361180
(6, channel_type, required),
11371181
});
11381182
},
1183+
&Event::PendingChannelReady { ref channel_id, ref user_channel_id, ref counterparty_node_id, ref funding_txid } => {
1184+
31u8.write(writer)?;
1185+
write_tlv_fields!(writer, {
1186+
(0, channel_id, required),
1187+
(2, user_channel_id, required),
1188+
(4, counterparty_node_id, required),
1189+
(6, funding_txid, required)
1190+
});
1191+
},
11391192
// Note that, going forward, all new events must only write data inside of
11401193
// `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write
11411194
// data via `write_tlv_fields`.
@@ -1471,6 +1524,28 @@ impl MaybeReadable for Event {
14711524
};
14721525
f()
14731526
},
1527+
31u8 => {
1528+
let f = || {
1529+
let mut channel_id = [0; 32];
1530+
let mut user_channel_id: u128 = 0;
1531+
let mut counterparty_node_id = RequiredWrapper(None);
1532+
let mut funding_txid = RequiredWrapper(None);
1533+
read_tlv_fields!(reader, {
1534+
(0, channel_id, required),
1535+
(2, user_channel_id, required),
1536+
(4, counterparty_node_id, required),
1537+
(6, funding_txid, required),
1538+
});
1539+
1540+
Ok(Some(Event::PendingChannelReady {
1541+
channel_id,
1542+
user_channel_id,
1543+
counterparty_node_id: counterparty_node_id.0.unwrap(),
1544+
funding_txid: funding_txid.0.unwrap()
1545+
}))
1546+
};
1547+
f()
1548+
},
14741549
// Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue.
14751550
// Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt
14761551
// reads.

0 commit comments

Comments
 (0)