Skip to content

Commit

Permalink
Require inbound channels with anchor outputs to be accepted manually
Browse files Browse the repository at this point in the history
Since the use of channels with anchor outputs requires a reserve of
onchain funds to handle channel force closures, it would be
irresponsible to allow a node to accept inbound channel without first
consulting such reserves. To allow users to do so, we require such
channels be manually accepted.
  • Loading branch information
wpaulino committed Jun 23, 2023
1 parent 054dd70 commit ed14d0e
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 2 deletions.
52 changes: 50 additions & 2 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5103,9 +5103,13 @@ where
return Err(MsgHandleErrInternal::send_err_msg_no_close("temporary_channel_id collision for the same peer!".to_owned(), msg.temporary_channel_id.clone()))
} else {
if !self.default_configuration.manually_accept_inbound_channels {
if channel.context.get_channel_type().requires_zero_conf() {
let channel_type = channel.context.get_channel_type();
if channel_type.requires_zero_conf() {
return Err(MsgHandleErrInternal::send_err_msg_no_close("No zero confirmation channels accepted".to_owned(), msg.temporary_channel_id.clone()));
}
if channel_type.requires_anchors_zero_fee_htlc_tx() {
return Err(MsgHandleErrInternal::send_err_msg_no_close("No channels with anchor outputs accepted".to_owned(), msg.temporary_channel_id.clone()));
}
peer_state.pending_msg_events.push(events::MessageSendEvent::SendAcceptChannel {
node_id: counterparty_node_id.clone(),
msg: channel.accept_inbound_channel(user_channel_id),
Expand Down Expand Up @@ -8732,7 +8736,7 @@ mod tests {
use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
use crate::ln::channelmanager::{inbound_payment, PaymentId, PaymentSendFailure, RecipientOnionFields, InterceptId};
use crate::ln::functional_test_utils::*;
use crate::ln::msgs;
use crate::ln::msgs::{self, ErrorAction};
use crate::ln::msgs::ChannelMessageHandler;
use crate::routing::router::{PaymentParameters, RouteParameters, find_route};
use crate::util::errors::APIError;
Expand Down Expand Up @@ -9728,6 +9732,50 @@ mod tests {
sender_intended_amt_msat - extra_fee_msat, 42, None, true, Some(extra_fee_msat)).is_ok());
}

#[test]
fn test_inbound_anchors_manual_acceptance() {
// Tests that we properly limit inbound channels when we have the manual-channel-acceptance
// flag set and (sometimes) accept channels as 0conf.
let mut anchors_cfg = test_default_channel_config();
anchors_cfg.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;

let mut anchors_manual_accept_cfg = anchors_cfg.clone();
anchors_manual_accept_cfg.manually_accept_inbound_channels = true;

let chanmon_cfgs = create_chanmon_cfgs(3);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs,
&[Some(anchors_cfg.clone()), Some(anchors_cfg.clone()), Some(anchors_manual_accept_cfg.clone())]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);

nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None).unwrap();
let open_channel_msg = 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(), &open_channel_msg);
assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
let msg_events = nodes[1].node.get_and_clear_pending_msg_events();
match &msg_events[0] {
MessageSendEvent::HandleError { node_id, action } => {
assert_eq!(*node_id, nodes[0].node.get_our_node_id());
match action {
ErrorAction::SendErrorMessage { msg } =>
assert_eq!(msg.data, "No channels with anchor outputs accepted".to_owned()),
_ => panic!("Unexpected error action"),
}
}
_ => panic!("Unexpected event"),
}

nodes[2].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg);
let events = nodes[2].node.get_and_clear_pending_events();
match events[0] {
Event::OpenChannelRequest { temporary_channel_id, .. } =>
nodes[2].node.accept_inbound_channel(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 23).unwrap(),
_ => panic!("Unexpected event"),
}
get_event_msg!(nodes[2], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
}

#[test]
fn test_anchors_zero_fee_htlc_tx_fallback() {
// Tests that if both nodes support anchors, but the remote node does not want to accept
Expand Down
3 changes: 3 additions & 0 deletions lightning/src/ln/monitor_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1721,6 +1721,7 @@ fn do_test_monitor_rebroadcast_pending_claims(anchors: bool) {
let mut config = test_default_channel_config();
if anchors {
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
config.manually_accept_inbound_channels = true;
}
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config), Some(config)]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
Expand Down Expand Up @@ -1870,6 +1871,7 @@ fn test_yield_anchors_events() {
let mut anchors_config = UserConfig::default();
anchors_config.channel_handshake_config.announced_channel = true;
anchors_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
anchors_config.manually_accept_inbound_channels = true;
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(anchors_config), Some(anchors_config)]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);

Expand Down Expand Up @@ -2002,6 +2004,7 @@ fn test_anchors_aggregated_revoked_htlc_tx() {
let mut anchors_config = UserConfig::default();
anchors_config.channel_handshake_config.announced_channel = true;
anchors_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
anchors_config.manually_accept_inbound_channels = true;
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(anchors_config), Some(anchors_config)]);

let bob_persister: test_utils::TestPersister;
Expand Down
4 changes: 4 additions & 0 deletions lightning/src/util/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ pub struct ChannelHandshakeConfig {
/// channels. This feature requires having a reserve of onchain funds readily available to bump
/// transactions in the event of a channel force close to avoid the possibility of losing funds.
///
/// Note that if you wish accept inbound channels with anchor outputs, you must enable
/// [`UserConfig::manually_accept_inbound_channels`] and manually accept them with
/// [`ChannelManager::accept_inbound_channel`].
///
/// If this option is set, channels may be created that will not be readable by LDK versions
/// prior to 0.0.116, causing [`ChannelManager`]'s read method to return a
/// [`DecodeError::InvalidValue`].
Expand Down

0 comments on commit ed14d0e

Please sign in to comment.