Skip to content

Commit bc90c80

Browse files
committed
Allow deserialization of new Channels before we've seen a block
Previously, if we have a live ChannelManager (that has seen blocks) and we open a new Channel, if we serialize that ChannelManager before a new block comes in, we'll fail to deserialize it. This is the result of an overly-ambigious last_block_connected check which would see 0s for the new channel but the previous block for the ChannelManager as a whole. We add a new test which catches this error as well as hopefully getting some test coverage for other similar issues in the future.
1 parent 899fc9e commit bc90c80

File tree

2 files changed

+107
-1
lines changed

2 files changed

+107
-1
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3310,7 +3310,11 @@ impl<'a, R : ::std::io::Read, ChanSigner: ChannelKeys + Readable<R>, M: Deref> R
33103310
let mut short_to_id = HashMap::with_capacity(cmp::min(channel_count as usize, 128));
33113311
for _ in 0..channel_count {
33123312
let mut channel: Channel<ChanSigner> = ReadableArgs::read(reader, args.logger.clone())?;
3313-
if channel.last_block_connected != last_block_hash {
3313+
// A channel which was added after we'd seen some blocks, but which wasn't around long
3314+
// enough to see some blocks itself prior to serialization may still have its
3315+
// last_block_connected set to 0s while we have something else. This is explicitly
3316+
// allowed.
3317+
if channel.last_block_connected != Default::default() && channel.last_block_connected != last_block_hash {
33143318
return Err(DecodeError::InvalidValue);
33153319
}
33163320

lightning/src/ln/functional_tests.rs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,108 @@ fn test_1_conf_open() {
413413
}
414414
}
415415

416+
fn do_test_sanity_on_in_flight_opens(steps: u8) {
417+
// Previously, we had issues deserializing channels when we hadn't connected the first block
418+
// after creation. To catch that and similar issues, we lean on the Node::drop impl to test
419+
// serialization round-trips and simply do steps towards opening a channel and then drop the
420+
// Node objects.
421+
//
422+
// steps with the high bit set connects some blocks on the ChannelManagers directly before
423+
// starting, and the low 4 bits (0-7) select at what point we should exit with 8 indicating
424+
// that we should run all the way through channel confirmation.
425+
426+
let node_cfgs = create_node_cfgs(2);
427+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
428+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
429+
430+
if steps & 0b1000_0000 != 0{
431+
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
432+
nodes[0].block_notifier.block_connected_checked(&header, 1, &Vec::new(), &[0; 0]);
433+
nodes[1].block_notifier.block_connected_checked(&header, 1, &Vec::new(), &[0; 0]);
434+
}
435+
436+
if steps & 0x0f == 0 { return; }
437+
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42).unwrap();
438+
let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
439+
440+
if steps & 0x0f == 1 { return; }
441+
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::supported(), &open_channel);
442+
let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
443+
444+
if steps & 0x0f == 2 { return; }
445+
nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::supported(), &accept_channel);
446+
447+
let (temporary_channel_id, tx, funding_output) = create_funding_transaction(&nodes[0], 100000, 42);
448+
449+
if steps & 0x0f == 3 { return; }
450+
{
451+
nodes[0].node.funding_transaction_generated(&temporary_channel_id, funding_output);
452+
let mut added_monitors = nodes[0].chan_monitor.added_monitors.lock().unwrap();
453+
assert_eq!(added_monitors.len(), 1);
454+
assert_eq!(added_monitors[0].0, funding_output);
455+
added_monitors.clear();
456+
}
457+
let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
458+
459+
if steps & 0x0f == 4 { return; }
460+
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created);
461+
{
462+
let mut added_monitors = nodes[1].chan_monitor.added_monitors.lock().unwrap();
463+
assert_eq!(added_monitors.len(), 1);
464+
assert_eq!(added_monitors[0].0, funding_output);
465+
added_monitors.clear();
466+
}
467+
let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
468+
469+
if steps & 0x0f == 5 { return; }
470+
nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed);
471+
{
472+
let mut added_monitors = nodes[0].chan_monitor.added_monitors.lock().unwrap();
473+
assert_eq!(added_monitors.len(), 1);
474+
assert_eq!(added_monitors[0].0, funding_output);
475+
added_monitors.clear();
476+
}
477+
478+
let events_4 = nodes[0].node.get_and_clear_pending_events();
479+
assert_eq!(events_4.len(), 1);
480+
match events_4[0] {
481+
Event::FundingBroadcastSafe { ref funding_txo, user_channel_id } => {
482+
assert_eq!(user_channel_id, 42);
483+
assert_eq!(*funding_txo, funding_output);
484+
},
485+
_ => panic!("Unexpected event"),
486+
};
487+
488+
if steps & 0x0f == 6 { return; }
489+
create_chan_between_nodes_with_value_confirm_first(&nodes[0], &nodes[1], &tx);
490+
491+
if steps & 0x0f == 7 { return; }
492+
confirm_transaction(&nodes[0].block_notifier, &nodes[0].chain_monitor, &tx, tx.version);
493+
create_chan_between_nodes_with_value_confirm_second(&nodes[1], &nodes[0]);
494+
}
495+
496+
#[test]
497+
fn test_sanity_on_in_flight_opens() {
498+
do_test_sanity_on_in_flight_opens(0);
499+
do_test_sanity_on_in_flight_opens(0 | 0b1000_0000);
500+
do_test_sanity_on_in_flight_opens(1);
501+
do_test_sanity_on_in_flight_opens(1 | 0b1000_0000);
502+
do_test_sanity_on_in_flight_opens(2);
503+
do_test_sanity_on_in_flight_opens(2 | 0b1000_0000);
504+
do_test_sanity_on_in_flight_opens(3);
505+
do_test_sanity_on_in_flight_opens(3 | 0b1000_0000);
506+
do_test_sanity_on_in_flight_opens(4);
507+
do_test_sanity_on_in_flight_opens(4 | 0b1000_0000);
508+
do_test_sanity_on_in_flight_opens(5);
509+
do_test_sanity_on_in_flight_opens(5 | 0b1000_0000);
510+
do_test_sanity_on_in_flight_opens(6);
511+
do_test_sanity_on_in_flight_opens(6 | 0b1000_0000);
512+
do_test_sanity_on_in_flight_opens(7);
513+
do_test_sanity_on_in_flight_opens(7 | 0b1000_0000);
514+
do_test_sanity_on_in_flight_opens(8);
515+
do_test_sanity_on_in_flight_opens(8 | 0b1000_0000);
516+
}
517+
416518
#[test]
417519
fn test_update_fee_vanilla() {
418520
let node_cfgs = create_node_cfgs(2);

0 commit comments

Comments
 (0)