Skip to content

Commit ecb0b84

Browse files
committed
Generate shutdown script at channel close
When a shutdown script is omitted from open_channel or accept_channel, it must be provided when sending shutdown. Generate the shutdown script at channel closing time in this case rather at channel opening. This requires producing a ChannelMonitorUpdate with the shutdown script since it is no longer known at ChannelMonitor creation.
1 parent 1c449a3 commit ecb0b84

File tree

6 files changed

+388
-84
lines changed

6 files changed

+388
-84
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,9 @@ pub(crate) enum ChannelMonitorUpdateStep {
438438
/// think we've fallen behind!
439439
should_broadcast: bool,
440440
},
441+
ShutdownScript {
442+
scriptpubkey: Script,
443+
},
441444
}
442445

443446
impl_writeable_tlv_based_enum!(ChannelMonitorUpdateStep,
@@ -461,6 +464,9 @@ impl_writeable_tlv_based_enum!(ChannelMonitorUpdateStep,
461464
(4, ChannelForceClosed) => {
462465
(0, should_broadcast, required),
463466
},
467+
(5, ShutdownScript) => {
468+
(0, scriptpubkey, required),
469+
},
464470
;);
465471

466472
/// A ChannelMonitor handles chain events (blocks connected and disconnected) and generates
@@ -1437,7 +1443,13 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
14371443
// shouldn't print the scary warning above.
14381444
log_info!(logger, "Channel off-chain state closed after we broadcasted our latest commitment transaction.");
14391445
}
1440-
}
1446+
},
1447+
ChannelMonitorUpdateStep::ShutdownScript { scriptpubkey } => {
1448+
log_trace!(logger, "Updating ChannelMonitor with shutdown script");
1449+
if let Some(shutdown_script) = self.shutdown_script.replace(scriptpubkey.clone()) {
1450+
panic!("Attempted to replace shutdown script {} with {}", shutdown_script, scriptpubkey);
1451+
}
1452+
},
14411453
}
14421454
}
14431455
self.latest_update_id = updates.update_id;

lightning/src/ln/chanmon_update_fail_tests.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2369,3 +2369,66 @@ fn test_reconnect_dup_htlc_claims() {
23692369
do_test_reconnect_dup_htlc_claims(HTLCStatusAtDupClaim::HoldingCell, true);
23702370
do_test_reconnect_dup_htlc_claims(HTLCStatusAtDupClaim::Cleared, true);
23712371
}
2372+
2373+
#[test]
2374+
fn test_temporary_error_during_shutdown() {
2375+
// Test that temporary failures when updating the monitor's shutdown script do not prevent
2376+
// cooperative close.
2377+
let mut config = test_default_channel_config();
2378+
config.channel_options.commit_upfront_shutdown_pubkey = false;
2379+
2380+
let chanmon_cfgs = create_chanmon_cfgs(2);
2381+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
2382+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config), Some(config)]);
2383+
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
2384+
2385+
let (_, _, channel_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
2386+
2387+
*nodes[0].chain_monitor.update_ret.lock().unwrap() = Some(Err(ChannelMonitorUpdateErr::TemporaryFailure));
2388+
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Some(Err(ChannelMonitorUpdateErr::TemporaryFailure));
2389+
close_channel(&nodes[0], &nodes[1], &channel_id, funding_tx, false);
2390+
check_added_monitors!(nodes[0], 1);
2391+
check_added_monitors!(nodes[1], 1);
2392+
}
2393+
2394+
#[test]
2395+
fn test_permanent_error_during_sending_shutdown() {
2396+
// Test that permanent failures when updating the monitor's shutdown script result in a force
2397+
// close when initiating a cooperative close.
2398+
let mut config = test_default_channel_config();
2399+
config.channel_options.commit_upfront_shutdown_pubkey = false;
2400+
2401+
let chanmon_cfgs = create_chanmon_cfgs(2);
2402+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
2403+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config), None]);
2404+
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
2405+
2406+
let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
2407+
*nodes[0].chain_monitor.update_ret.lock().unwrap() = Some(Err(ChannelMonitorUpdateErr::PermanentFailure));
2408+
2409+
assert!(nodes[0].node.close_channel(&channel_id).is_ok());
2410+
check_closed_broadcast!(nodes[0], true);
2411+
check_added_monitors!(nodes[0], 2);
2412+
}
2413+
2414+
#[test]
2415+
fn test_permanent_error_during_handling_shutdown() {
2416+
// Test that permanent failures when updating the monitor's shutdown script result in a force
2417+
// close when handling a cooperative close.
2418+
let mut config = test_default_channel_config();
2419+
config.channel_options.commit_upfront_shutdown_pubkey = false;
2420+
2421+
let chanmon_cfgs = create_chanmon_cfgs(2);
2422+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
2423+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(config)]);
2424+
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
2425+
2426+
let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
2427+
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Some(Err(ChannelMonitorUpdateErr::PermanentFailure));
2428+
2429+
assert!(nodes[0].node.close_channel(&channel_id).is_ok());
2430+
let shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
2431+
nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &shutdown);
2432+
check_closed_broadcast!(nodes[1], true);
2433+
check_added_monitors!(nodes[1], 2);
2434+
}

0 commit comments

Comments
 (0)