-
Notifications
You must be signed in to change notification settings - Fork 411
Channel Establishment for V3 Channels #3792
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
588f490
3b1e691
ffddb20
e4465c4
aab2d29
67e394d
41d8529
23de01c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12472,6 +12472,7 @@ where | |
match peer_state.channel_by_id.get_mut(&msg.channel_id) { | ||
Some(chan) => match chan.maybe_handle_error_without_close( | ||
self.chain_hash, &self.fee_estimator, &self.logger, | ||
&self.default_configuration, &peer_state.latest_features, | ||
) { | ||
Ok(Some(OpenChannelMessage::V1(msg))) => { | ||
peer_state.pending_msg_events.push(MessageSendEvent::SendOpenChannel { | ||
|
@@ -15210,13 +15211,16 @@ mod tests { | |
use crate::routing::router::{find_route, PaymentParameters, RouteParameters}; | ||
use crate::sign::EntropySource; | ||
use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; | ||
use crate::util::config::{ChannelConfig, ChannelConfigUpdate, ChannelHandshakeConfigUpdate}; | ||
use crate::util::config::{ | ||
ChannelConfig, ChannelConfigUpdate, ChannelHandshakeConfigUpdate, UserConfig, | ||
}; | ||
use crate::util::errors::APIError; | ||
use crate::util::ser::Writeable; | ||
use crate::util::test_utils; | ||
use bitcoin::secp256k1::ecdh::SharedSecret; | ||
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; | ||
use core::sync::atomic::Ordering; | ||
use lightning_types::features::ChannelTypeFeatures; | ||
|
||
#[test] | ||
#[rustfmt::skip] | ||
|
@@ -16349,23 +16353,103 @@ mod tests { | |
} | ||
|
||
#[test] | ||
#[rustfmt::skip] | ||
fn test_anchors_zero_fee_htlc_tx_fallback() { | ||
fn test_anchors_zero_fee_htlc_tx_downgrade() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Congrats, you touched it, now you get to move it out of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done this in a follow up in #3797 so that move + format can be reviewed separately. |
||
// Tests that if both nodes support anchors, but the remote node does not want to accept | ||
// anchor channels at the moment, an error it sent to the local node such that it can retry | ||
// the channel without the anchors feature. | ||
let mut initiator_cfg = test_default_channel_config(); | ||
initiator_cfg.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; | ||
|
||
let mut receiver_cfg = test_default_channel_config(); | ||
receiver_cfg.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; | ||
receiver_cfg.manually_accept_inbound_channels = true; | ||
|
||
let start_type = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); | ||
let end_type = ChannelTypeFeatures::only_static_remote_key(); | ||
do_test_channel_type_downgrade(initiator_cfg, receiver_cfg, start_type, vec![end_type]); | ||
} | ||
|
||
#[test] | ||
fn test_scid_privacy_downgrade() { | ||
// Tests downgrade from `anchors_zero_fee_htlc_tx` with `option_scid_alias` when the | ||
// remote node advertises the features but does not accept the channel, asserting that | ||
// `option_scid_alias` is the last feature to be downgraded. | ||
let mut initiator_cfg = test_default_channel_config(); | ||
initiator_cfg.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; | ||
initiator_cfg.channel_handshake_config.negotiate_scid_privacy = true; | ||
initiator_cfg.channel_handshake_config.announce_for_forwarding = false; | ||
|
||
let mut receiver_cfg = test_default_channel_config(); | ||
receiver_cfg.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; | ||
receiver_cfg.channel_handshake_config.negotiate_scid_privacy = true; | ||
receiver_cfg.manually_accept_inbound_channels = true; | ||
|
||
let mut start_type = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); | ||
start_type.set_scid_privacy_required(); | ||
let mut with_scid_privacy = ChannelTypeFeatures::only_static_remote_key(); | ||
with_scid_privacy.set_scid_privacy_required(); | ||
let static_remote = ChannelTypeFeatures::only_static_remote_key(); | ||
let downgrade_types = vec![with_scid_privacy, static_remote]; | ||
|
||
do_test_channel_type_downgrade(initiator_cfg, receiver_cfg, start_type, downgrade_types); | ||
} | ||
|
||
#[rustfmt::skip] | ||
fn do_test_channel_type_downgrade(initiator_cfg: UserConfig, acceptor_cfg: UserConfig, | ||
start_type: ChannelTypeFeatures, downgrade_types: Vec<ChannelTypeFeatures>) { | ||
let chanmon_cfgs = create_chanmon_cfgs(2); | ||
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); | ||
let mut anchors_config = test_default_channel_config(); | ||
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.clone()), Some(anchors_config.clone())]); | ||
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(initiator_cfg), Some(acceptor_cfg)]); | ||
let nodes = create_network(2, &node_cfgs, &node_chanmgrs); | ||
let error_message = "Channel force-closed"; | ||
|
||
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 0, None, None).unwrap(); | ||
let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); | ||
assert_eq!(open_channel_msg.common_fields.channel_type.as_ref().unwrap(), &start_type); | ||
|
||
for downgrade_type in downgrade_types { | ||
nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel_msg); | ||
let events = nodes[1].node.get_and_clear_pending_events(); | ||
match events[0] { | ||
Event::OpenChannelRequest { temporary_channel_id, .. } => { | ||
nodes[1].node.force_close_broadcasting_latest_txn(&temporary_channel_id, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap(); | ||
} | ||
_ => panic!("Unexpected event"), | ||
} | ||
|
||
let error_msg = get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()); | ||
nodes[0].node.handle_error(nodes[1].node.get_our_node_id(), &error_msg); | ||
|
||
open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); | ||
let channel_type = open_channel_msg.common_fields.channel_type.as_ref().unwrap(); | ||
assert_eq!(channel_type, &downgrade_type); | ||
|
||
// Since nodes[1] should not have accepted the channel, it should | ||
// not have generated any events. | ||
assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); | ||
} | ||
} | ||
|
||
#[test] | ||
#[rustfmt::skip] | ||
fn test_no_channel_downgrade() { | ||
// Tests that the local node will not retry when a `option_static_remote` channel is | ||
// rejected by a peer that advertises support for the feature. | ||
let initiator_cfg = test_default_channel_config(); | ||
let mut receiver_cfg = test_default_channel_config(); | ||
receiver_cfg.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; | ||
receiver_cfg.manually_accept_inbound_channels = true; | ||
|
||
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, &[Some(initiator_cfg), Some(receiver_cfg)]); | ||
let nodes = create_network(2, &node_cfgs, &node_chanmgrs); | ||
let error_message = "Channel force-closed"; | ||
|
||
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 0, None, None).unwrap(); | ||
let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); | ||
assert!(open_channel_msg.common_fields.channel_type.as_ref().unwrap().supports_anchors_zero_fee_htlc_tx()); | ||
let start_type = ChannelTypeFeatures::only_static_remote_key(); | ||
assert_eq!(open_channel_msg.common_fields.channel_type.as_ref().unwrap(), &start_type); | ||
|
||
nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel_msg); | ||
let events = nodes[1].node.get_and_clear_pending_events(); | ||
|
@@ -16379,12 +16463,10 @@ mod tests { | |
let error_msg = get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()); | ||
nodes[0].node.handle_error(nodes[1].node.get_our_node_id(), &error_msg); | ||
|
||
let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); | ||
assert!(!open_channel_msg.common_fields.channel_type.unwrap().supports_anchors_zero_fee_htlc_tx()); | ||
|
||
// Since nodes[1] should not have accepted the channel, it should | ||
// not have generated any events. | ||
assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); | ||
// Since nodes[0] could not retry the channel with a different type, it should close it. | ||
let chan_closed_events = nodes[0].node.get_and_clear_pending_events(); | ||
assert_eq!(chan_closed_events.len(), 1); | ||
if let Event::ChannelClosed { .. } = chan_closed_events[0] { } else { panic!(); } | ||
} | ||
|
||
#[test] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved this assert up because we should never negotiate a non-zero-htlc-anchor channel, and it's a risk of lost funds if we do.
Couldn't see a historical reason why we only checked it if the channel type was
supports_anchors_zero_fee_htlc_tx
- went back a few commits and couldn't find reasoning. cc @TheBlueMatt