Skip to content

Commit 1c9df02

Browse files
authored
Merge pull request #2566 from G8XSU/check-best-block-2538
Verify channel-monitor processes blocks with skipped best_block
2 parents 8de8861 + d926be2 commit 1c9df02

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

lightning/src/ln/functional_tests.rs

+67
Original file line numberDiff line numberDiff line change
@@ -4093,6 +4093,73 @@ fn test_channel_ready_without_best_block_updated() {
40934093
nodes[1].node.handle_channel_ready(&nodes[0].node.get_our_node_id(), &as_channel_ready);
40944094
}
40954095

4096+
#[test]
4097+
fn test_channel_monitor_skipping_block_when_channel_manager_is_leading() {
4098+
let chanmon_cfgs = create_chanmon_cfgs(2);
4099+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
4100+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
4101+
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
4102+
4103+
// Let channel_manager get ahead of chain_monitor by 1 block.
4104+
// This is to emulate race-condition where newly added channel_monitor skips processing 1 block,
4105+
// in case where client calls block_connect on channel_manager first and then on chain_monitor.
4106+
let height_1 = nodes[0].best_block_info().1 + 1;
4107+
let mut block_1 = create_dummy_block(nodes[0].best_block_hash(), height_1, Vec::new());
4108+
4109+
nodes[0].blocks.lock().unwrap().push((block_1.clone(), height_1));
4110+
nodes[0].node.block_connected(&block_1, height_1);
4111+
4112+
// Create channel, and it gets added to chain_monitor in funding_created.
4113+
let funding_tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 1_000_000, 0);
4114+
4115+
// Now, newly added channel_monitor in chain_monitor hasn't processed block_1,
4116+
// but it's best_block is block_1, since that was populated by channel_manager, and channel_manager
4117+
// was running ahead of chain_monitor at the time of funding_created.
4118+
// Later on, subsequent blocks are connected to both channel_manager and chain_monitor.
4119+
// Hence, this channel's channel_monitor skipped block_1, directly tries to process subsequent blocks.
4120+
confirm_transaction_at(&nodes[0], &funding_tx, nodes[0].best_block_info().1 + 1);
4121+
connect_blocks(&nodes[0], CHAN_CONFIRM_DEPTH);
4122+
4123+
// Ensure nodes[0] generates a channel_ready after the transactions_confirmed
4124+
let as_channel_ready = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, nodes[1].node.get_our_node_id());
4125+
nodes[1].node.handle_channel_ready(&nodes[0].node.get_our_node_id(), &as_channel_ready);
4126+
}
4127+
4128+
#[test]
4129+
fn test_channel_monitor_skipping_block_when_channel_manager_is_lagging() {
4130+
let chanmon_cfgs = create_chanmon_cfgs(2);
4131+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
4132+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
4133+
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
4134+
4135+
// Let chain_monitor get ahead of channel_manager by 1 block.
4136+
// This is to emulate race-condition where newly added channel_monitor skips processing 1 block,
4137+
// in case where client calls block_connect on chain_monitor first and then on channel_manager.
4138+
let height_1 = nodes[0].best_block_info().1 + 1;
4139+
let mut block_1 = create_dummy_block(nodes[0].best_block_hash(), height_1, Vec::new());
4140+
4141+
nodes[0].blocks.lock().unwrap().push((block_1.clone(), height_1));
4142+
nodes[0].chain_monitor.chain_monitor.block_connected(&block_1, height_1);
4143+
4144+
// Create channel, and it gets added to chain_monitor in funding_created.
4145+
let funding_tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 1_000_000, 0);
4146+
4147+
// channel_manager can't really skip block_1, it should get it eventually.
4148+
nodes[0].node.block_connected(&block_1, height_1);
4149+
4150+
// Now, newly added channel_monitor in chain_monitor hasn't processed block_1, it's best_block is
4151+
// the block before block_1, since that was populated by channel_manager, and channel_manager was
4152+
// running behind at the time of funding_created.
4153+
// Later on, subsequent blocks are connected to both channel_manager and chain_monitor.
4154+
// Hence, this channel's channel_monitor skipped block_1, directly tries to process subsequent blocks.
4155+
confirm_transaction_at(&nodes[0], &funding_tx, nodes[0].best_block_info().1 + 1);
4156+
connect_blocks(&nodes[0], CHAN_CONFIRM_DEPTH);
4157+
4158+
// Ensure nodes[0] generates a channel_ready after the transactions_confirmed
4159+
let as_channel_ready = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, nodes[1].node.get_our_node_id());
4160+
nodes[1].node.handle_channel_ready(&nodes[0].node.get_our_node_id(), &as_channel_ready);
4161+
}
4162+
40964163
#[test]
40974164
fn test_drop_messages_peer_disconnect_dual_htlc() {
40984165
// Test that we can handle reconnecting when both sides of a channel have pending

0 commit comments

Comments
 (0)