counterparty_htlc_minimum_msat: msg.htlc_minimum_msat,
holder_htlc_minimum_msat: if config.own_channel_config.our_htlc_minimum_msat == 0 { 1 } else { config.own_channel_config.our_htlc_minimum_msat },
counterparty_max_accepted_htlcs: msg.max_accepted_htlcs,
- minimum_depth: Some(config.own_channel_config.minimum_depth),
+ minimum_depth: Some(cmp::max(config.own_channel_config.minimum_depth, 1)),
counterparty_forwarding_info: None,
self.inbound_awaiting_accept
}
+ /// Sets this channel to accepting 0conf, must be done before `get_accept_channel`
+ pub fn set_0conf(&mut self) {
+ assert!(self.inbound_awaiting_accept);
+ self.minimum_depth = Some(0);
+ }
+
/// Marks an inbound channel as accepted and generates a [`msgs::AcceptChannel`] message which
/// should be sent back to the counterparty node.
///
}
}
- /// Called to accept a request to open a channel after [`Event::OpenChannelRequest`] has been
- /// triggered.
+ /// Accepts a request to open a channel after a [`Event::OpenChannelRequest`].
///
/// The `temporary_channel_id` parameter indicates which inbound channel should be accepted,
/// and the `counterparty_node_id` parameter is the id of the peer which has requested to open
/// the channel.
///
- /// For inbound channels, the `user_channel_id` parameter will be provided back in
+ /// The `user_channel_id` parameter will be provided back in
/// [`Event::ChannelClosed::user_channel_id`] to allow tracking of which events correspond
- /// with which `accept_inbound_channel` call.
+ /// with which `accept_inbound_channel`/`accept_inbound_channel_from_trusted_peer_0conf` call.
///
/// [`Event::OpenChannelRequest`]: events::Event::OpenChannelRequest
/// [`Event::ChannelClosed::user_channel_id`]: events::Event::ChannelClosed::user_channel_id
pub fn accept_inbound_channel(&self, temporary_channel_id: &[u8; 32], counterparty_node_id: &PublicKey, user_channel_id: u64) -> Result<(), APIError> {
+ self.do_accept_inbound_channel(temporary_channel_id, counterparty_node_id, false, user_channel_id)
+ }
+
+ /// Accepts a request to open a channel after a [`events::Event::OpenChannelRequest`], treating
+ /// it as confirmed immediately.
+ ///
+ /// The `user_channel_id` parameter will be provided back in
+ /// [`Event::ChannelClosed::user_channel_id`] to allow tracking of which events correspond
+ /// with which `accept_inbound_channel`/`accept_inbound_channel_from_trusted_peer_0conf` call.
+ ///
+ /// Unlike [`ChannelManager::accept_inbound_channel`], this method accepts the incoming channel
+ /// and (if the counterparty agrees), enables forwarding of payments immediately.
+ ///
+ /// This fully trusts that the counterparty has honestly and correctly constructed the funding
+ /// transaction and blindly assumes that it will eventually confirm.
+ ///
+ /// If it does not confirm before we decide to close the channel, or if the funding transaction
+ /// does not pay to the correct script the correct amount, *you will lose funds*.
+ ///
+ /// [`Event::OpenChannelRequest`]: events::Event::OpenChannelRequest
+ /// [`Event::ChannelClosed::user_channel_id`]: events::Event::ChannelClosed::user_channel_id
+ pub fn accept_inbound_channel_from_trusted_peer_0conf(&self, temporary_channel_id: &[u8; 32], counterparty_node_id: &PublicKey, user_channel_id: u64) -> Result<(), APIError> {
+ self.do_accept_inbound_channel(temporary_channel_id, counterparty_node_id, true, user_channel_id)
+ }
+
+ fn do_accept_inbound_channel(&self, temporary_channel_id: &[u8; 32], counterparty_node_id: &PublicKey, accept_0conf: bool, user_channel_id: u64) -> Result<(), APIError> {
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
let mut channel_state_lock = self.channel_state.lock().unwrap();
if *counterparty_node_id != channel.get().get_counterparty_node_id() {
return Err(APIError::APIMisuseError { err: "The passed counterparty_node_id doesn't match the channel's counterparty node_id".to_owned() });
}
+ if accept_0conf { channel.get_mut().set_0conf(); }
channel_state.pending_msg_events.push(events::MessageSendEvent::SendAcceptChannel {
node_id: channel.get().get_counterparty_node_id(),
msg: channel.get_mut().accept_inbound_channel(user_channel_id),
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
- let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+ let mut chan_config = test_default_channel_config();
+ chan_config.manually_accept_inbound_channels = true;
+
+ let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(chan_config)]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None).unwrap();
let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_channel);
+ let events = nodes[1].node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ match events[0] {
+ Event::OpenChannelRequest { temporary_channel_id, .. } => {
+ nodes[1].node.accept_inbound_channel_from_trusted_peer_0conf(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 0).unwrap();
+ },
+ _ => panic!("Unexpected event"),
+ };
+
let mut accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
- accept_channel.minimum_depth = 0;
+ assert_eq!(accept_channel.minimum_depth, 0);
nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_channel);
let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42);
/// Applied only for inbound channels (see ChannelHandshakeLimits::max_minimum_depth for the
/// equivalent limit applied to outbound channels).
///
+ /// A lower-bound of 1 is applied, requiring all channels to have a confirmed commitment
+ /// transaction before operation. If you wish to accept channels with zero confirmations, see
+ /// [`UserConfig::manually_accept_inbound_channels`] and
+ /// [`ChannelManager::accept_inbound_channel_from_trusted_peer_0conf`].
+ ///
/// Default value: 6.
+ ///
+ /// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
+ /// [`ChannelManager::accept_inbound_channel_from_trusted_peer_0conf`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel_from_trusted_peer_0conf
pub minimum_depth: u32,
/// Set to the number of blocks we require our counterparty to wait to claim their money (ie
/// the number of blocks we have to punish our counterparty if they broadcast a revoked