Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 102 additions & 28 deletions fuzz/src/chanmon_consistency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -863,9 +863,15 @@ fn assert_action_timeout_awaiting_response(action: &msgs::ErrorAction) {
));
}

pub enum ChanType {
Legacy,
KeyedAnchors,
ZeroFeeCommitments,
}

#[inline]
pub fn do_test<Out: Output + MaybeSend + MaybeSync>(
data: &[u8], underlying_out: Out, anchors: bool,
data: &[u8], underlying_out: Out, chan_type: ChanType,
) {
let out = SearchingOutput::new(underlying_out);
let broadcast_a = Arc::new(TestBroadcaster { txn_broadcasted: RefCell::new(Vec::new()) });
Expand Down Expand Up @@ -926,8 +932,19 @@ pub fn do_test<Out: Output + MaybeSend + MaybeSync>(
config.channel_config.forwarding_fee_proportional_millionths = 0;
config.channel_handshake_config.announce_for_forwarding = true;
config.reject_inbound_splices = false;
if !anchors {
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = false;
match chan_type {
ChanType::Legacy => {
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = false;
config.channel_handshake_config.negotiate_anchor_zero_fee_commitments = false;
},
ChanType::KeyedAnchors => {
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
config.channel_handshake_config.negotiate_anchor_zero_fee_commitments = false;
},
ChanType::ZeroFeeCommitments => {
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = false;
config.channel_handshake_config.negotiate_anchor_zero_fee_commitments = true;
},
}
let network = Network::Bitcoin;
let best_block_timestamp = genesis_block(network).header.time;
Expand Down Expand Up @@ -978,8 +995,19 @@ pub fn do_test<Out: Output + MaybeSend + MaybeSync>(
config.channel_config.forwarding_fee_proportional_millionths = 0;
config.channel_handshake_config.announce_for_forwarding = true;
config.reject_inbound_splices = false;
if !anchors {
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = false;
match chan_type {
ChanType::Legacy => {
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = false;
config.channel_handshake_config.negotiate_anchor_zero_fee_commitments = false;
},
ChanType::KeyedAnchors => {
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
config.channel_handshake_config.negotiate_anchor_zero_fee_commitments = false;
},
ChanType::ZeroFeeCommitments => {
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = false;
config.channel_handshake_config.negotiate_anchor_zero_fee_commitments = true;
},
}

let mut monitors = new_hash_map();
Expand Down Expand Up @@ -1078,8 +1106,23 @@ pub fn do_test<Out: Output + MaybeSend + MaybeSync>(
}};
}
macro_rules! make_channel {
($source: expr, $dest: expr, $source_monitor: expr, $dest_monitor: expr, $dest_keys_manager: expr, $chan_id: expr) => {{
$source.create_channel($dest.get_our_node_id(), 100_000, 42, 0, None, None).unwrap();
($source: expr, $dest: expr, $source_monitor: expr, $dest_monitor: expr, $dest_keys_manager: expr, $chan_id: expr, $trusted_open: expr, $trusted_accept: expr) => {{
if $trusted_open {
$source
.create_channel_to_trusted_peer_0reserve(
$dest.get_our_node_id(),
100_000,
42,
0,
None,
None,
)
.unwrap();
} else {
$source
.create_channel($dest.get_our_node_id(), 100_000, 42, 0, None, None)
.unwrap();
}
let open_channel = {
let events = $source.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
Expand All @@ -1104,14 +1147,27 @@ pub fn do_test<Out: Output + MaybeSend + MaybeSync>(
random_bytes
.copy_from_slice(&$dest_keys_manager.get_secure_random_bytes()[..16]);
let user_channel_id = u128::from_be_bytes(random_bytes);
$dest
.accept_inbound_channel(
temporary_channel_id,
counterparty_node_id,
user_channel_id,
None,
)
.unwrap();
if $trusted_accept {
$dest
.accept_inbound_channel_from_trusted_peer(
temporary_channel_id,
counterparty_node_id,
user_channel_id,
false,
true,
None,
)
.unwrap();
} else {
$dest
.accept_inbound_channel(
temporary_channel_id,
counterparty_node_id,
user_channel_id,
None,
)
.unwrap();
}
} else {
panic!("Wrong event type");
}
Expand Down Expand Up @@ -1287,12 +1343,16 @@ pub fn do_test<Out: Output + MaybeSend + MaybeSync>(
// Fuzz mode uses XOR-based hashing (all bytes XOR to one byte), and
// versions 0-5 cause collisions between A-B and B-C channel pairs
// (e.g., A-B with Version(1) collides with B-C with Version(3)).
make_channel!(nodes[0], nodes[1], monitor_a, monitor_b, keys_manager_b, 1);
make_channel!(nodes[0], nodes[1], monitor_a, monitor_b, keys_manager_b, 2);
make_channel!(nodes[0], nodes[1], monitor_a, monitor_b, keys_manager_b, 3);
make_channel!(nodes[1], nodes[2], monitor_b, monitor_c, keys_manager_c, 4);
make_channel!(nodes[1], nodes[2], monitor_b, monitor_c, keys_manager_c, 5);
make_channel!(nodes[1], nodes[2], monitor_b, monitor_c, keys_manager_c, 6);
// A-B: channel 2 A and B have 0-reserve (trusted open + trusted accept),
// channel 3 A has 0-reserve (trusted accept)
make_channel!(nodes[0], nodes[1], monitor_a, monitor_b, keys_manager_b, 1, false, false);
make_channel!(nodes[0], nodes[1], monitor_a, monitor_b, keys_manager_b, 2, true, true);
make_channel!(nodes[0], nodes[1], monitor_a, monitor_b, keys_manager_b, 3, false, true);
// B-C: channel 4 B has 0-reserve (via trusted accept),
// channel 5 C has 0-reserve (via trusted open)
make_channel!(nodes[1], nodes[2], monitor_b, monitor_c, keys_manager_c, 4, false, true);
make_channel!(nodes[1], nodes[2], monitor_b, monitor_c, keys_manager_c, 5, true, false);
make_channel!(nodes[1], nodes[2], monitor_b, monitor_c, keys_manager_c, 6, false, false);

// Wipe the transactions-broadcasted set to make sure we don't broadcast any transactions
// during normal operation in `test_return`.
Expand Down Expand Up @@ -2301,7 +2361,7 @@ pub fn do_test<Out: Output + MaybeSend + MaybeSync>(

0x80 => {
let mut max_feerate = last_htlc_clear_fee_a;
if !anchors {
if matches!(chan_type, ChanType::Legacy) {
max_feerate *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
}
if fee_est_a.ret_val.fetch_add(250, atomic::Ordering::AcqRel) + 250 > max_feerate {
Expand All @@ -2316,7 +2376,7 @@ pub fn do_test<Out: Output + MaybeSend + MaybeSync>(

0x84 => {
let mut max_feerate = last_htlc_clear_fee_b;
if !anchors {
if matches!(chan_type, ChanType::Legacy) {
max_feerate *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
}
if fee_est_b.ret_val.fetch_add(250, atomic::Ordering::AcqRel) + 250 > max_feerate {
Expand All @@ -2331,7 +2391,7 @@ pub fn do_test<Out: Output + MaybeSend + MaybeSync>(

0x88 => {
let mut max_feerate = last_htlc_clear_fee_c;
if !anchors {
if matches!(chan_type, ChanType::Legacy) {
max_feerate *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
}
if fee_est_c.ret_val.fetch_add(250, atomic::Ordering::AcqRel) + 250 > max_feerate {
Expand Down Expand Up @@ -2783,12 +2843,26 @@ impl<O: Output> SearchingOutput<O> {
}

pub fn chanmon_consistency_test<Out: Output + MaybeSend + MaybeSync>(data: &[u8], out: Out) {
do_test(data, out.clone(), false);
do_test(data, out, true);
do_test(data, out.clone(), ChanType::Legacy);
do_test(data, out.clone(), ChanType::KeyedAnchors);
do_test(data, out, ChanType::ZeroFeeCommitments);
}

#[no_mangle]
pub extern "C" fn chanmon_consistency_run(data: *const u8, datalen: usize) {
do_test(unsafe { std::slice::from_raw_parts(data, datalen) }, test_logger::DevNull {}, false);
do_test(unsafe { std::slice::from_raw_parts(data, datalen) }, test_logger::DevNull {}, true);
do_test(
unsafe { std::slice::from_raw_parts(data, datalen) },
test_logger::DevNull {},
ChanType::Legacy,
);
do_test(
unsafe { std::slice::from_raw_parts(data, datalen) },
test_logger::DevNull {},
ChanType::KeyedAnchors,
);
do_test(
unsafe { std::slice::from_raw_parts(data, datalen) },
test_logger::DevNull {},
ChanType::ZeroFeeCommitments,
);
}
4 changes: 3 additions & 1 deletion lightning-liquidity/tests/lsps2_integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1513,10 +1513,12 @@ fn create_channel_with_manual_broadcast(
Event::OpenChannelRequest { temporary_channel_id, .. } => {
client_node
.node
.accept_inbound_channel_from_trusted_peer_0conf(
.accept_inbound_channel_from_trusted_peer(
&temporary_channel_id,
&service_node_id,
user_channel_id,
true,
false,
None,
)
.unwrap();
Expand Down
2 changes: 1 addition & 1 deletion lightning/src/events/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1643,7 +1643,7 @@ pub enum Event {
/// Furthermore, note that if [`ChannelTypeFeatures::supports_zero_conf`] returns true on this type,
/// the resulting [`ChannelManager`] will not be readable by versions of LDK prior to
/// 0.0.107. Channels setting this type also need to get manually accepted via
/// [`crate::ln::channelmanager::ChannelManager::accept_inbound_channel_from_trusted_peer_0conf`],
/// [`crate::ln::channelmanager::ChannelManager::accept_inbound_channel_from_trusted_peer`],
/// or will be rejected otherwise.
///
/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
Expand Down
8 changes: 6 additions & 2 deletions lightning/src/ln/async_signer_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ fn do_test_open_channel(zero_conf: bool) {
Event::OpenChannelRequest { temporary_channel_id, .. } => {
nodes[1]
.node
.accept_inbound_channel_from_trusted_peer_0conf(
.accept_inbound_channel_from_trusted_peer(
temporary_channel_id,
&node_a_id,
0,
true,
false,
None,
)
.expect("Unable to accept inbound zero-conf channel");
Expand Down Expand Up @@ -383,10 +385,12 @@ fn do_test_funding_signed_0conf(signer_ops: Vec<SignerOp>) {
Event::OpenChannelRequest { temporary_channel_id, .. } => {
nodes[1]
.node
.accept_inbound_channel_from_trusted_peer_0conf(
.accept_inbound_channel_from_trusted_peer(
temporary_channel_id,
&node_a_id,
0,
true,
false,
None,
)
.expect("Unable to accept inbound zero-conf channel");
Expand Down
8 changes: 6 additions & 2 deletions lightning/src/ln/chanmon_update_fail_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3235,7 +3235,9 @@ fn do_test_outbound_reload_without_init_mon(use_0conf: bool) {
if use_0conf {
nodes[1]
.node
.accept_inbound_channel_from_trusted_peer_0conf(&chan_id, &node_a_id, 0, None)
.accept_inbound_channel_from_trusted_peer(
&chan_id, &node_a_id, 0, true, false, None,
)
.unwrap();
} else {
nodes[1].node.accept_inbound_channel(&chan_id, &node_a_id, 0, None).unwrap();
Expand Down Expand Up @@ -3344,7 +3346,9 @@ fn do_test_inbound_reload_without_init_mon(use_0conf: bool, lock_commitment: boo
if use_0conf {
nodes[1]
.node
.accept_inbound_channel_from_trusted_peer_0conf(&chan_id, &node_a_id, 0, None)
.accept_inbound_channel_from_trusted_peer(
&chan_id, &node_a_id, 0, true, false, None,
)
.unwrap();
} else {
nodes[1].node.accept_inbound_channel(&chan_id, &node_a_id, 0, None).unwrap();
Expand Down
Loading
Loading