Skip to content

Commit 3c13abe

Browse files
committed
Implement ZeroConf channel type.
1 parent ce7b0b4 commit 3c13abe

File tree

4 files changed

+61
-11
lines changed

4 files changed

+61
-11
lines changed

lightning/src/ln/channel.rs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,16 +1081,23 @@ impl<Signer: Sign> Channel<Signer> {
10811081
if channel_type.supports_any_optional_bits() {
10821082
return Err(ChannelError::Close("Channel Type field contained optional bits - this is not allowed".to_owned()));
10831083
}
1084-
// We currently only allow two channel types, so write it all out here - we allow
1084+
// We currently only allow three channel types, so write it all out here - we allow
10851085
// `only_static_remote_key` in all contexts, and further allow
1086-
// `static_remote_key|scid_privacy` if the channel is not publicly announced.
1087-
let mut allowed_type = ChannelTypeFeatures::only_static_remote_key();
1088-
if *channel_type != allowed_type {
1089-
allowed_type.set_scid_privacy_required();
1090-
if *channel_type != allowed_type {
1086+
// `static_remote_key | scid_privacy` or `static_remote_key | zero_conf`, if the channel
1087+
// is not publicly announced.
1088+
if *channel_type != ChannelTypeFeatures::only_static_remote_key() {
1089+
let mut static_remote_key_with_privacy_type = ChannelTypeFeatures::only_static_remote_key();
1090+
static_remote_key_with_privacy_type.set_scid_privacy_required();
1091+
1092+
let mut static_remote_key_with_zero_conf_type = ChannelTypeFeatures::only_static_remote_key();
1093+
static_remote_key_with_zero_conf_type.set_zero_conf_required();
1094+
1095+
if *channel_type != static_remote_key_with_privacy_type &&
1096+
*channel_type != static_remote_key_with_zero_conf_type {
10911097
return Err(ChannelError::Close("Channel Type was not understood".to_owned()));
10921098
}
1093-
if announced_channel {
1099+
1100+
if *channel_type == static_remote_key_with_privacy_type && announced_channel {
10941101
return Err(ChannelError::Close("SCID Alias/Privacy Channel Type cannot be set on a public channel".to_owned()));
10951102
}
10961103
}
@@ -6407,7 +6414,7 @@ mod tests {
64076414
use ln::channelmanager::{HTLCSource, PaymentId};
64086415
use ln::channel::{Channel, InboundHTLCOutput, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator};
64096416
use ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS};
6410-
use ln::features::InitFeatures;
6417+
use ln::features::{InitFeatures, ChannelTypeFeatures};
64116418
use ln::msgs::{ChannelUpdate, DataLossProtect, DecodeError, OptionalField, UnsignedChannelUpdate};
64126419
use ln::script::ShutdownScript;
64136420
use ln::chan_utils;
@@ -7722,4 +7729,27 @@ mod tests {
77227729
assert_eq!(chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_secret, &base_secret).unwrap(),
77237730
SecretKey::from_slice(&hex::decode("d09ffff62ddb2297ab000cc85bcb4283fdeb6aa052affbc9dddcf33b61078110").unwrap()[..]).unwrap());
77247731
}
7732+
7733+
#[test]
7734+
fn test_zero_conf_channel_type_support() {
7735+
let feeest = TestFeeEstimator{fee_est: 15000};
7736+
let secp_ctx = Secp256k1::new();
7737+
let seed = [42; 32];
7738+
let network = Network::Testnet;
7739+
let keys_provider = test_utils::TestKeysInterface::new(&seed, network);
7740+
let logger = test_utils::TestLogger::new();
7741+
7742+
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
7743+
let config = UserConfig::default();
7744+
let node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
7745+
7746+
let mut channel_type_features = ChannelTypeFeatures::only_static_remote_key();
7747+
channel_type_features.set_zero_conf_required();
7748+
7749+
let mut open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash());
7750+
open_channel_msg.channel_type = Some(channel_type_features);
7751+
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
7752+
let res = Channel::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger, 42);
7753+
assert!(res.is_ok());
7754+
}
77257755
}

lightning/src/ln/channelmanager.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4200,7 +4200,11 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
42004200
if *counterparty_node_id != channel.get().get_counterparty_node_id() {
42014201
return Err(APIError::APIMisuseError { err: "The passed counterparty_node_id doesn't match the channel's counterparty node_id".to_owned() });
42024202
}
4203-
if accept_0conf { channel.get_mut().set_0conf(); }
4203+
if accept_0conf {
4204+
channel.get_mut().set_0conf();
4205+
} else if channel.get().get_channel_type().requires_zero_conf() {
4206+
return Err(APIError::APIMisuseError { err: "This channel requires 0conf. Please use accept_inbound_channel_from_trusted_peer_0conf to accept.".to_owned() });
4207+
}
42044208
channel_state.pending_msg_events.push(events::MessageSendEvent::SendAcceptChannel {
42054209
node_id: channel.get().get_counterparty_node_id(),
42064210
msg: channel.get_mut().accept_inbound_channel(user_channel_id),
@@ -4242,6 +4246,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
42424246
},
42434247
hash_map::Entry::Vacant(entry) => {
42444248
if !self.default_configuration.manually_accept_inbound_channels {
4249+
if channel.get_channel_type().requires_zero_conf() {
4250+
return Err(MsgHandleErrInternal::send_err_msg_no_close("No zero confirmation channels accepted".to_owned(), msg.temporary_channel_id.clone()));
4251+
}
42454252
channel_state.pending_msg_events.push(events::MessageSendEvent::SendAcceptChannel {
42464253
node_id: counterparty_node_id.clone(),
42474254
msg: channel.accept_inbound_channel(0),

lightning/src/ln/features.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ mod sealed {
217217
// Byte 4
218218
,
219219
// Byte 5
220-
SCIDPrivacy,
220+
SCIDPrivacy | ZeroConf,
221221
],
222222
optional_features: [
223223
// Byte 0
@@ -402,7 +402,9 @@ mod sealed {
402402
define_feature!(47, SCIDPrivacy, [InitContext, NodeContext, ChannelTypeContext],
403403
"Feature flags for only forwarding with SCID aliasing. Called `option_scid_alias` in the BOLTs",
404404
set_scid_privacy_optional, set_scid_privacy_required, supports_scid_privacy, requires_scid_privacy);
405-
405+
define_feature!(51, ZeroConf, [ChannelTypeContext],
406+
"Feature flags for accepting channels with zero confirmations. Called `option_zeroconf` in the BOLTs",
407+
set_zero_conf_optional, set_zero_conf_required, supports_zero_conf, requires_zero_conf);
406408
define_feature!(55, Keysend, [NodeContext],
407409
"Feature flags for keysend payments.", set_keysend_optional, set_keysend_required,
408410
supports_keysend, requires_keysend);
@@ -852,14 +854,19 @@ mod tests {
852854

853855
assert!(InitFeatures::known().supports_scid_privacy());
854856
assert!(NodeFeatures::known().supports_scid_privacy());
857+
assert!(ChannelTypeFeatures::known().supports_scid_privacy());
855858
assert!(!InitFeatures::known().requires_scid_privacy());
856859
assert!(!NodeFeatures::known().requires_scid_privacy());
860+
assert!(ChannelTypeFeatures::known().requires_scid_privacy());
857861

858862
assert!(InitFeatures::known().supports_wumbo());
859863
assert!(NodeFeatures::known().supports_wumbo());
860864
assert!(!InitFeatures::known().requires_wumbo());
861865
assert!(!NodeFeatures::known().requires_wumbo());
862866

867+
assert!(!ChannelTypeFeatures::known().supports_zero_conf());
868+
assert!(!ChannelTypeFeatures::known().requires_zero_conf());
869+
863870
let mut init_features = InitFeatures::known();
864871
assert!(init_features.initial_routing_sync());
865872
init_features.clear_initial_routing_sync();

lightning/src/util/events.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,12 @@ pub enum Event {
466466
/// the resulting [`ChannelManager`] will not be readable by versions of LDK prior to
467467
/// 0.0.106.
468468
///
469+
/// Furthermore, note that if [`ChannelTypeFeatures::supports_zero_conf`] returns true on this type,
470+
/// the resulting [`ChannelManager`] will not be readable by versions of LDK prior to
471+
/// 0.0.107. Channels setting this type also need to get manually accepted via
472+
/// [`crate::ln::channelmanager::ChannelManager::accept_inbound_channel_from_trusted_peer_0conf`],
473+
/// or will be rejected otherwise.
474+
///
469475
/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
470476
channel_type: ChannelTypeFeatures,
471477
},

0 commit comments

Comments
 (0)