Skip to content

Commit 50d1260

Browse files
authored
Merge pull request #1860 from wpaulino/open-channel-anchors-support
Support opening anchor channels and test end-to-end unilateral close
2 parents ad40573 + 660165c commit 50d1260

9 files changed

+525
-74
lines changed

lightning/src/ln/channel.rs

+239-52
Large diffs are not rendered by default.

lightning/src/ln/channelmanager.rs

+47-3
Original file line numberDiff line numberDiff line change
@@ -4196,7 +4196,7 @@ where
41964196
let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
41974197
let peer_state = &mut *peer_state_lock;
41984198
let mut channel = match Channel::new_from_req(&self.fee_estimator, &self.entropy_source, &self.signer_provider,
4199-
counterparty_node_id.clone(), &peer_state.latest_features, msg, user_channel_id, &self.default_configuration,
4199+
counterparty_node_id.clone(), &self.channel_type_features(), &peer_state.latest_features, msg, user_channel_id, &self.default_configuration,
42004200
self.best_block.read().unwrap().height(), &self.logger, outbound_scid_alias)
42014201
{
42024202
Err(e) => {
@@ -6267,7 +6267,7 @@ pub(crate) fn provided_channel_features(config: &UserConfig) -> ChannelFeatures
62676267
/// Fetches the set of [`ChannelTypeFeatures`] flags which are provided by or required by
62686268
/// [`ChannelManager`].
62696269
pub(crate) fn provided_channel_type_features(config: &UserConfig) -> ChannelTypeFeatures {
6270-
ChannelTypeFeatures::from_counterparty_init(&provided_init_features(config))
6270+
ChannelTypeFeatures::from_init(&provided_init_features(config))
62716271
}
62726272

62736273
/// Fetches the set of [`InitFeatures`] flags which are provided by or required by
@@ -6288,6 +6288,12 @@ pub fn provided_init_features(_config: &UserConfig) -> InitFeatures {
62886288
features.set_channel_type_optional();
62896289
features.set_scid_privacy_optional();
62906290
features.set_zero_conf_optional();
6291+
#[cfg(anchors)]
6292+
{ // Attributes are not allowed on if expressions on our current MSRV of 1.41.
6293+
if _config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx {
6294+
features.set_anchors_zero_fee_htlc_tx_optional();
6295+
}
6296+
}
62916297
features
62926298
}
62936299

@@ -7027,7 +7033,9 @@ where
70277033
let mut short_to_chan_info = HashMap::with_capacity(cmp::min(channel_count as usize, 128));
70287034
let mut channel_closures = Vec::new();
70297035
for _ in 0..channel_count {
7030-
let mut channel: Channel<<SP::Target as SignerProvider>::Signer> = Channel::read(reader, (&args.entropy_source, &args.signer_provider, best_block_height))?;
7036+
let mut channel: Channel<<SP::Target as SignerProvider>::Signer> = Channel::read(reader, (
7037+
&args.entropy_source, &args.signer_provider, best_block_height, &provided_channel_type_features(&args.default_config)
7038+
))?;
70317039
let funding_txo = channel.get_funding_txo().ok_or(DecodeError::InvalidValue)?;
70327040
funding_txo_set.insert(funding_txo.clone());
70337041
if let Some(ref mut monitor) = args.channel_monitors.get_mut(&funding_txo) {
@@ -8311,6 +8319,42 @@ mod tests {
83118319

83128320
nodes[1].node.handle_update_fee(&unkown_public_key, &update_fee_msg);
83138321
}
8322+
8323+
#[cfg(anchors)]
8324+
#[test]
8325+
fn test_anchors_zero_fee_htlc_tx_fallback() {
8326+
// Tests that if both nodes support anchors, but the remote node does not want to accept
8327+
// anchor channels at the moment, an error it sent to the local node such that it can retry
8328+
// the channel without the anchors feature.
8329+
let chanmon_cfgs = create_chanmon_cfgs(2);
8330+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
8331+
let mut anchors_config = test_default_channel_config();
8332+
anchors_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
8333+
anchors_config.manually_accept_inbound_channels = true;
8334+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(anchors_config.clone()), Some(anchors_config.clone())]);
8335+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
8336+
8337+
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 0, None).unwrap();
8338+
let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
8339+
assert!(open_channel_msg.channel_type.as_ref().unwrap().supports_anchors_zero_fee_htlc_tx());
8340+
8341+
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg);
8342+
let events = nodes[1].node.get_and_clear_pending_events();
8343+
match events[0] {
8344+
Event::OpenChannelRequest { temporary_channel_id, .. } => {
8345+
nodes[1].node.force_close_broadcasting_latest_txn(&temporary_channel_id, &nodes[0].node.get_our_node_id()).unwrap();
8346+
}
8347+
_ => panic!("Unexpected event"),
8348+
}
8349+
8350+
let error_msg = get_err_msg!(nodes[1], nodes[0].node.get_our_node_id());
8351+
nodes[0].node.handle_error(&nodes[1].node.get_our_node_id(), &error_msg);
8352+
8353+
let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
8354+
assert!(!open_channel_msg.channel_type.unwrap().supports_anchors_zero_fee_htlc_tx());
8355+
8356+
check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed);
8357+
}
83148358
}
83158359

83168360
#[cfg(all(any(test, feature = "_test_utils"), feature = "_bench_unstable"))]

lightning/src/ln/features.rs

+47-9
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@
5252
//! (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md) for more information).
5353
//! - `Keysend` - send funds to a node without an invoice
5454
//! (see the [`Keysend` feature assignment proposal](https://github.com/lightning/bolts/issues/605#issuecomment-606679798) for more information).
55+
//! - `AnchorsZeroFeeHtlcTx` - requires/supports that commitment transactions include anchor outputs
56+
//! and HTLC transactions are pre-signed with zero fee (see
57+
//! [BOLT-3](https://github.com/lightning/bolts/blob/master/03-transactions.md) for more
58+
//! information).
5559
//!
5660
//! [BOLT #9]: https://github.com/lightning/bolts/blob/master/09-features.md
5761
//! [messages]: crate::ln::msgs
@@ -122,7 +126,7 @@ mod sealed {
122126
// Byte 1
123127
VariableLengthOnion | StaticRemoteKey | PaymentSecret,
124128
// Byte 2
125-
BasicMPP | Wumbo,
129+
BasicMPP | Wumbo | AnchorsZeroFeeHtlcTx,
126130
// Byte 3
127131
ShutdownAnySegwit,
128132
// Byte 4
@@ -138,7 +142,7 @@ mod sealed {
138142
// Byte 1
139143
VariableLengthOnion | StaticRemoteKey | PaymentSecret,
140144
// Byte 2
141-
BasicMPP | Wumbo,
145+
BasicMPP | Wumbo | AnchorsZeroFeeHtlcTx,
142146
// Byte 3
143147
ShutdownAnySegwit,
144148
// Byte 4
@@ -176,7 +180,7 @@ mod sealed {
176180
// Byte 1
177181
StaticRemoteKey,
178182
// Byte 2
179-
,
183+
AnchorsZeroFeeHtlcTx,
180184
// Byte 3
181185
,
182186
// Byte 4
@@ -357,6 +361,9 @@ mod sealed {
357361
define_feature!(19, Wumbo, [InitContext, NodeContext],
358362
"Feature flags for `option_support_large_channel` (aka wumbo channels).", set_wumbo_optional, set_wumbo_required,
359363
supports_wumbo, requires_wumbo);
364+
define_feature!(23, AnchorsZeroFeeHtlcTx, [InitContext, NodeContext, ChannelTypeContext],
365+
"Feature flags for `option_anchors_zero_fee_htlc_tx`.", set_anchors_zero_fee_htlc_tx_optional,
366+
set_anchors_zero_fee_htlc_tx_required, supports_anchors_zero_fee_htlc_tx, requires_anchors_zero_fee_htlc_tx);
360367
define_feature!(27, ShutdownAnySegwit, [InitContext, NodeContext],
361368
"Feature flags for `opt_shutdown_anysegwit`.", set_shutdown_any_segwit_optional,
362369
set_shutdown_any_segwit_required, supports_shutdown_anysegwit, requires_shutdown_anysegwit);
@@ -505,10 +512,10 @@ impl InvoiceFeatures {
505512
}
506513

507514
impl ChannelTypeFeatures {
508-
/// Constructs the implicit channel type based on the common supported types between us and our
509-
/// counterparty
510-
pub(crate) fn from_counterparty_init(counterparty_init: &InitFeatures) -> Self {
511-
let mut ret = counterparty_init.to_context_internal();
515+
// Maps the relevant `InitFeatures` to `ChannelTypeFeatures`. Any unknown features to
516+
// `ChannelTypeFeatures` are not included in the result.
517+
pub(crate) fn from_init(init: &InitFeatures) -> Self {
518+
let mut ret = init.to_context_internal();
512519
// ChannelTypeFeatures must only contain required bits, so we OR the required forms of all
513520
// optional bits and then AND out the optional ones.
514521
for byte in ret.flags.iter_mut() {
@@ -678,6 +685,24 @@ impl<T: sealed::Context> Features<T> {
678685
(byte & unknown_features) != 0
679686
})
680687
}
688+
689+
// Returns true if the features within `self` are a subset of the features within `other`.
690+
pub(crate) fn is_subset(&self, other: &Self) -> bool {
691+
for (idx, byte) in self.flags.iter().enumerate() {
692+
if let Some(other_byte) = other.flags.get(idx) {
693+
if byte & other_byte != *byte {
694+
// `self` has bits set that `other` doesn't.
695+
return false;
696+
}
697+
} else {
698+
if *byte > 0 {
699+
// `self` has a non-zero byte that `other` doesn't.
700+
return false;
701+
}
702+
}
703+
}
704+
true
705+
}
681706
}
682707

683708
impl<T: sealed::UpfrontShutdownScript> Features<T> {
@@ -704,6 +729,18 @@ impl<T: sealed::Wumbo> Features<T> {
704729
}
705730
}
706731

732+
impl<T: sealed::SCIDPrivacy> Features<T> {
733+
pub(crate) fn clear_scid_privacy(&mut self) {
734+
<T as sealed::SCIDPrivacy>::clear_bits(&mut self.flags);
735+
}
736+
}
737+
738+
impl<T: sealed::AnchorsZeroFeeHtlcTx> Features<T> {
739+
pub(crate) fn clear_anchors_zero_fee_htlc_tx(&mut self) {
740+
<T as sealed::AnchorsZeroFeeHtlcTx>::clear_bits(&mut self.flags);
741+
}
742+
}
743+
707744
#[cfg(test)]
708745
impl<T: sealed::UnknownFeature> Features<T> {
709746
pub(crate) fn unknown() -> Self {
@@ -808,6 +845,7 @@ mod tests {
808845
init_features.set_channel_type_optional();
809846
init_features.set_scid_privacy_optional();
810847
init_features.set_zero_conf_optional();
848+
init_features.set_anchors_zero_fee_htlc_tx_optional();
811849

812850
assert!(init_features.initial_routing_sync());
813851
assert!(!init_features.supports_upfront_shutdown_script());
@@ -826,7 +864,7 @@ mod tests {
826864
assert_eq!(node_features.flags.len(), 7);
827865
assert_eq!(node_features.flags[0], 0b00000010);
828866
assert_eq!(node_features.flags[1], 0b01010001);
829-
assert_eq!(node_features.flags[2], 0b00001010);
867+
assert_eq!(node_features.flags[2], 0b10001010);
830868
assert_eq!(node_features.flags[3], 0b00001000);
831869
assert_eq!(node_features.flags[4], 0b10000000);
832870
assert_eq!(node_features.flags[5], 0b10100000);
@@ -917,7 +955,7 @@ mod tests {
917955
// required-StaticRemoteKey ChannelTypeFeatures.
918956
let mut init_features = InitFeatures::empty();
919957
init_features.set_static_remote_key_optional();
920-
let converted_features = ChannelTypeFeatures::from_counterparty_init(&init_features);
958+
let converted_features = ChannelTypeFeatures::from_init(&init_features);
921959
assert_eq!(converted_features, ChannelTypeFeatures::only_static_remote_key());
922960
assert!(!converted_features.supports_any_optional_bits());
923961
assert!(converted_features.requires_static_remote_key());

lightning/src/ln/functional_test_utils.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,22 @@ pub fn confirm_transaction<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &Tran
6161
connect_blocks(node, CHAN_CONFIRM_DEPTH - 1);
6262
scid
6363
}
64-
/// Mine a signle block containing the given transaction
64+
/// Mine a single block containing the given transaction
6565
pub fn mine_transaction<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &Transaction) {
6666
let height = node.best_block_info().1 + 1;
6767
confirm_transaction_at(node, tx, height);
6868
}
69+
/// Mine a single block containing the given transactions
70+
pub fn mine_transactions<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, txn: &[&Transaction]) {
71+
let height = node.best_block_info().1 + 1;
72+
confirm_transactions_at(node, txn, height);
73+
}
6974
/// Mine the given transaction at the given height, mining blocks as required to build to that
7075
/// height
7176
///
7277
/// Returns the SCID a channel confirmed in the given transaction will have, assuming the funding
7378
/// output is the 1st output in the transaction.
74-
pub fn confirm_transaction_at<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &Transaction, conf_height: u32) -> u64 {
79+
pub fn confirm_transactions_at<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, txn: &[&Transaction], conf_height: u32) -> u64 {
7580
let first_connect_height = node.best_block_info().1 + 1;
7681
assert!(first_connect_height <= conf_height);
7782
if conf_height > first_connect_height {
@@ -84,10 +89,15 @@ pub fn confirm_transaction_at<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &T
8489
for _ in 0..*node.network_chan_count.borrow() { // Make sure we don't end up with channels at the same short id by offsetting by chan_count
8590
block.txdata.push(Transaction { version: 0, lock_time: PackedLockTime::ZERO, input: Vec::new(), output: Vec::new() });
8691
}
87-
block.txdata.push(tx.clone());
92+
for tx in txn {
93+
block.txdata.push((*tx).clone());
94+
}
8895
connect_block(node, &block);
8996
scid_utils::scid_from_parts(conf_height as u64, block.txdata.len() as u64 - 1, 0).unwrap()
9097
}
98+
pub fn confirm_transaction_at<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &Transaction, conf_height: u32) -> u64 {
99+
confirm_transactions_at(node, &[tx], conf_height)
100+
}
91101

92102
/// The possible ways we may notify a ChannelManager of a new block
93103
#[derive(Clone, Copy, Debug, PartialEq)]

lightning/src/ln/functional_tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6861,7 +6861,7 @@ fn test_user_configurable_csv_delay() {
68616861
let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id());
68626862
open_channel.to_self_delay = 200;
68636863
if let Err(error) = Channel::new_from_req(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }),
6864-
&nodes[0].keys_manager, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &nodes[1].node.init_features(), &open_channel, 0,
6864+
&nodes[0].keys_manager, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &nodes[0].node.channel_type_features(), &nodes[1].node.init_features(), &open_channel, 0,
68656865
&low_our_to_self_config, 0, &nodes[0].logger, 42)
68666866
{
68676867
match error {
@@ -6893,7 +6893,7 @@ fn test_user_configurable_csv_delay() {
68936893
let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id());
68946894
open_channel.to_self_delay = 200;
68956895
if let Err(error) = Channel::new_from_req(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }),
6896-
&nodes[0].keys_manager, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &nodes[1].node.init_features(), &open_channel, 0,
6896+
&nodes[0].keys_manager, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &nodes[0].node.channel_type_features(), &nodes[1].node.init_features(), &open_channel, 0,
68976897
&high_their_to_self_config, 0, &nodes[0].logger, 42)
68986898
{
68996899
match error {

0 commit comments

Comments
 (0)