Skip to content

Commit e75d748

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 52d53bb commit e75d748

File tree

4 files changed

+101
-25
lines changed

4 files changed

+101
-25
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,9 @@ pub(crate) enum ChannelMonitorUpdateStep {
434434
/// think we've fallen behind!
435435
should_broadcast: bool,
436436
},
437+
ShutdownScript {
438+
scriptpubkey: Script,
439+
},
437440
}
438441

439442
impl_writeable_tlv_based_enum!(ChannelMonitorUpdateStep,
@@ -457,6 +460,9 @@ impl_writeable_tlv_based_enum!(ChannelMonitorUpdateStep,
457460
(4, ChannelForceClosed) => {
458461
(0, should_broadcast, required),
459462
},
463+
(5, ShutdownScript) => {
464+
(0, scriptpubkey, required),
465+
},
460466
;);
461467

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

lightning/src/ln/channel.rs

Lines changed: 65 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,12 @@ impl<Signer: Sign> Channel<Signer> {
559559
let mut secp_ctx = Secp256k1::new();
560560
secp_ctx.seeded_randomize(&keys_provider.get_secure_random_bytes());
561561

562+
let shutdown_scriptpubkey = if config.channel_options.commit_upfront_shutdown_pubkey {
563+
Some(keys_provider.get_shutdown_scriptpubkey())
564+
} else {
565+
None
566+
};
567+
562568
Ok(Channel {
563569
user_id,
564570
config: config.channel_options.clone(),
@@ -571,7 +577,7 @@ impl<Signer: Sign> Channel<Signer> {
571577
latest_monitor_update_id: 0,
572578

573579
holder_signer,
574-
shutdown_scriptpubkey: Some(keys_provider.get_shutdown_scriptpubkey()),
580+
shutdown_scriptpubkey,
575581
destination_script: keys_provider.get_destination_script(),
576582

577583
cur_holder_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER,
@@ -801,6 +807,12 @@ impl<Signer: Sign> Channel<Signer> {
801807
let mut secp_ctx = Secp256k1::new();
802808
secp_ctx.seeded_randomize(&keys_provider.get_secure_random_bytes());
803809

810+
let shutdown_scriptpubkey = if config.channel_options.commit_upfront_shutdown_pubkey {
811+
Some(keys_provider.get_shutdown_scriptpubkey())
812+
} else {
813+
None
814+
};
815+
804816
let chan = Channel {
805817
user_id,
806818
config: local_config,
@@ -812,7 +824,7 @@ impl<Signer: Sign> Channel<Signer> {
812824
latest_monitor_update_id: 0,
813825

814826
holder_signer,
815-
shutdown_scriptpubkey: Some(keys_provider.get_shutdown_scriptpubkey()),
827+
shutdown_scriptpubkey,
816828
destination_script: keys_provider.get_destination_script(),
817829

818830
cur_holder_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER,
@@ -1154,6 +1166,7 @@ impl<Signer: Sign> Channel<Signer> {
11541166
}, ()));
11551167
}
11561168

1169+
assert!(self.shutdown_scriptpubkey.is_some());
11571170
if value_to_self as u64 > self.holder_dust_limit_satoshis {
11581171
txouts.push((TxOut {
11591172
script_pubkey: self.get_closing_scriptpubkey(),
@@ -3023,6 +3036,7 @@ impl<Signer: Sign> Channel<Signer> {
30233036
self.channel_state &= !(ChannelState::PeerDisconnected as u32);
30243037

30253038
let shutdown_msg = if self.channel_state & (ChannelState::LocalShutdownSent as u32) != 0 {
3039+
assert!(self.shutdown_scriptpubkey.is_some());
30263040
Some(msgs::Shutdown {
30273041
channel_id: self.channel_id,
30283042
scriptpubkey: self.get_closing_scriptpubkey(),
@@ -3134,6 +3148,7 @@ impl<Signer: Sign> Channel<Signer> {
31343148
if self.feerate_per_kw > proposed_feerate {
31353149
proposed_feerate = self.feerate_per_kw;
31363150
}
3151+
assert!(self.shutdown_scriptpubkey.is_some());
31373152
let tx_weight = self.get_closing_transaction_weight(Some(&self.get_closing_scriptpubkey()), Some(self.counterparty_shutdown_scriptpubkey.as_ref().unwrap()));
31383153
let proposed_total_fee_satoshis = proposed_feerate as u64 * tx_weight / 1000;
31393154

@@ -3152,8 +3167,12 @@ impl<Signer: Sign> Channel<Signer> {
31523167
})
31533168
}
31543169

3155-
pub fn shutdown<F: Deref>(&mut self, fee_estimator: &F, _their_features: &InitFeatures, msg: &msgs::Shutdown) -> Result<(Option<msgs::Shutdown>, Option<msgs::ClosingSigned>, Vec<(HTLCSource, PaymentHash)>), ChannelError>
3156-
where F::Target: FeeEstimator
3170+
pub fn shutdown<F: Deref, K: Deref>(
3171+
&mut self, fee_estimator: &F, keys_provider: &K, _their_features: &InitFeatures, msg: &msgs::Shutdown
3172+
) -> Result<(Option<msgs::Shutdown>, Option<msgs::ClosingSigned>, Option<ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>), ChannelError>
3173+
where
3174+
F::Target: FeeEstimator,
3175+
K::Target: KeysInterface<Signer = Signer>
31573176
{
31583177
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
31593178
return Err(ChannelError::Close("Peer sent shutdown when we needed a channel_reestablish".to_owned()));
@@ -3203,23 +3222,36 @@ impl<Signer: Sign> Channel<Signer> {
32033222
_ => true
32043223
}
32053224
});
3225+
32063226
// If we have any LocalAnnounced updates we'll probably just get back a update_fail_htlc
32073227
// immediately after the commitment dance, but we can send a Shutdown cause we won't send
32083228
// any further commitment updates after we set LocalShutdownSent.
3209-
3210-
let shutdown = if (self.channel_state & ChannelState::LocalShutdownSent as u32) == ChannelState::LocalShutdownSent as u32 {
3211-
None
3212-
} else {
3229+
let send_shutdown = (self.channel_state & ChannelState::LocalShutdownSent as u32) != ChannelState::LocalShutdownSent as u32;
3230+
let monitor_update = match self.shutdown_scriptpubkey {
3231+
Some(_) => None,
3232+
None => {
3233+
assert!(send_shutdown);
3234+
self.shutdown_scriptpubkey = Some(keys_provider.get_shutdown_scriptpubkey());
3235+
self.latest_monitor_update_id += 1;
3236+
Some(ChannelMonitorUpdate {
3237+
update_id: self.latest_monitor_update_id,
3238+
updates: vec![ChannelMonitorUpdateStep::ShutdownScript {
3239+
scriptpubkey: self.get_closing_scriptpubkey(),
3240+
}],
3241+
})
3242+
},
3243+
};
3244+
let shutdown = if send_shutdown {
32133245
Some(msgs::Shutdown {
32143246
channel_id: self.channel_id,
32153247
scriptpubkey: self.get_closing_scriptpubkey(),
32163248
})
3217-
};
3249+
} else { None };
32183250

32193251
self.channel_state |= ChannelState::LocalShutdownSent as u32;
32203252
self.update_time_counter += 1;
32213253

3222-
Ok((shutdown, self.maybe_propose_first_closing_signed(fee_estimator), dropped_outbound_htlcs))
3254+
Ok((shutdown, self.maybe_propose_first_closing_signed(fee_estimator), monitor_update, dropped_outbound_htlcs))
32233255
}
32243256

32253257
fn build_signed_closing_transaction(&self, tx: &mut Transaction, counterparty_sig: &Signature, sig: &Signature) {
@@ -3294,6 +3326,7 @@ impl<Signer: Sign> Channel<Signer> {
32943326

32953327
macro_rules! propose_new_feerate {
32963328
($new_feerate: expr) => {
3329+
assert!(self.shutdown_scriptpubkey.is_some());
32973330
let tx_weight = self.get_closing_transaction_weight(Some(&self.get_closing_scriptpubkey()), Some(self.counterparty_shutdown_scriptpubkey.as_ref().unwrap()));
32983331
let (closing_tx, used_total_fee) = self.build_closing_transaction($new_feerate as u64 * tx_weight / 1000, false);
32993332
let sig = self.holder_signer
@@ -3792,7 +3825,10 @@ impl<Signer: Sign> Channel<Signer> {
37923825
htlc_basepoint: keys.htlc_basepoint,
37933826
first_per_commitment_point,
37943827
channel_flags: if self.config.announced_channel {1} else {0},
3795-
shutdown_scriptpubkey: OptionalField::Present(if self.config.commit_upfront_shutdown_pubkey { self.get_closing_scriptpubkey() } else { Builder::new().into_script() })
3828+
shutdown_scriptpubkey: OptionalField::Present(match &self.shutdown_scriptpubkey {
3829+
Some(script) => script.clone().into_inner(),
3830+
None => Builder::new().into_script(),
3831+
}),
37963832
}
37973833
}
37983834

@@ -3825,7 +3861,10 @@ impl<Signer: Sign> Channel<Signer> {
38253861
delayed_payment_basepoint: keys.delayed_payment_basepoint,
38263862
htlc_basepoint: keys.htlc_basepoint,
38273863
first_per_commitment_point,
3828-
shutdown_scriptpubkey: OptionalField::Present(if self.config.commit_upfront_shutdown_pubkey { self.get_closing_scriptpubkey() } else { Builder::new().into_script() })
3864+
shutdown_scriptpubkey: OptionalField::Present(match &self.shutdown_scriptpubkey {
3865+
Some(script) => script.clone().into_inner(),
3866+
None => Builder::new().into_script(),
3867+
}),
38293868
}
38303869
}
38313870

@@ -4333,7 +4372,8 @@ impl<Signer: Sign> Channel<Signer> {
43334372

43344373
/// Begins the shutdown process, getting a message for the remote peer and returning all
43354374
/// holding cell HTLCs for payment failure.
4336-
pub fn get_shutdown(&mut self) -> Result<(msgs::Shutdown, Vec<(HTLCSource, PaymentHash)>), APIError> {
4375+
pub fn get_shutdown<K: Deref>(&mut self, keys_provider: &K) -> Result<(msgs::Shutdown, Option<ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>), APIError>
4376+
where K::Target: KeysInterface<Signer = Signer> {
43374377
for htlc in self.pending_outbound_htlcs.iter() {
43384378
if let OutboundHTLCState::LocalAnnounced(_) = htlc.state {
43394379
return Err(APIError::APIMisuseError{err: "Cannot begin shutdown with pending HTLCs. Process pending events first".to_owned()});
@@ -4352,7 +4392,16 @@ impl<Signer: Sign> Channel<Signer> {
43524392
return Err(APIError::ChannelUnavailable{err: "Cannot begin shutdown while peer is disconnected or we're waiting on a monitor update, maybe force-close instead?".to_owned()});
43534393
}
43544394

4355-
let closing_script = self.get_closing_scriptpubkey();
4395+
let monitor_update = if self.shutdown_scriptpubkey.is_none() {
4396+
self.shutdown_scriptpubkey = Some(keys_provider.get_shutdown_scriptpubkey());
4397+
self.latest_monitor_update_id += 1;
4398+
Some(ChannelMonitorUpdate {
4399+
update_id: self.latest_monitor_update_id,
4400+
updates: vec![ChannelMonitorUpdateStep::ShutdownScript {
4401+
scriptpubkey: self.get_closing_scriptpubkey(),
4402+
}],
4403+
})
4404+
} else { None };
43564405

43574406
// From here on out, we may not fail!
43584407
if self.channel_state < ChannelState::FundingSent as u32 {
@@ -4378,8 +4427,8 @@ impl<Signer: Sign> Channel<Signer> {
43784427

43794428
Ok((msgs::Shutdown {
43804429
channel_id: self.channel_id,
4381-
scriptpubkey: closing_script,
4382-
}, dropped_outbound_htlcs))
4430+
scriptpubkey: self.get_closing_scriptpubkey(),
4431+
}, monitor_update, dropped_outbound_htlcs))
43834432
}
43844433

43854434
/// Gets the latest commitment transaction and any dependent transactions for relay (forcing

lightning/src/ln/channelmanager.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,11 +1246,17 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
12461246
let channel_state = &mut *channel_state_lock;
12471247
match channel_state.by_id.entry(channel_id.clone()) {
12481248
hash_map::Entry::Occupied(mut chan_entry) => {
1249-
let (shutdown_msg, failed_htlcs) = chan_entry.get_mut().get_shutdown()?;
1249+
let (shutdown_msg, monitor_update, failed_htlcs) = chan_entry.get_mut().get_shutdown(&self.keys_manager)?;
12501250
channel_state.pending_msg_events.push(events::MessageSendEvent::SendShutdown {
12511251
node_id: chan_entry.get().get_counterparty_node_id(),
12521252
msg: shutdown_msg
12531253
});
1254+
if let Some(monitor_update) = monitor_update {
1255+
if let Err(_) = self.chain_monitor.update_channel(chan_entry.get().get_funding_txo().unwrap(), monitor_update) {
1256+
// TODO: How should this be handled?
1257+
unimplemented!();
1258+
}
1259+
}
12541260
if chan_entry.get().is_shutdown() {
12551261
if let Some(short_id) = chan_entry.get().get_short_channel_id() {
12561262
channel_state.short_to_id.remove(&short_id);
@@ -3053,7 +3059,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
30533059
if chan_entry.get().get_counterparty_node_id() != *counterparty_node_id {
30543060
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!".to_owned(), msg.channel_id));
30553061
}
3056-
let (shutdown, closing_signed, dropped_htlcs) = try_chan_entry!(self, chan_entry.get_mut().shutdown(&self.fee_estimator, &their_features, &msg), channel_state, chan_entry);
3062+
let (shutdown, closing_signed, monitor_update, dropped_htlcs) = try_chan_entry!(self, chan_entry.get_mut().shutdown(&self.fee_estimator, &self.keys_manager, &their_features, &msg), channel_state, chan_entry);
30573063
if let Some(msg) = shutdown {
30583064
channel_state.pending_msg_events.push(events::MessageSendEvent::SendShutdown {
30593065
node_id: counterparty_node_id.clone(),
@@ -3066,6 +3072,12 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
30663072
msg,
30673073
});
30683074
}
3075+
if let Some(monitor_update) = monitor_update {
3076+
if let Err(_) = self.chain_monitor.update_channel(chan_entry.get().get_funding_txo().unwrap(), monitor_update) {
3077+
// TODO: How should this be handled?
3078+
unimplemented!();
3079+
}
3080+
}
30693081
if chan_entry.get().is_shutdown() {
30703082
if let Some(short_id) = chan_entry.get().get_short_channel_id() {
30713083
channel_state.short_to_id.remove(&short_id);

lightning/src/ln/functional_tests.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7430,9 +7430,9 @@ fn test_upfront_shutdown_script() {
74307430
let flags_no = InitFeatures::known().clear_upfront_shutdown_script();
74317431
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, flags_no, flags.clone());
74327432
nodes[0].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id()).unwrap();
7433-
let mut node_1_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
7434-
node_1_shutdown.scriptpubkey = Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script().to_p2sh();
7433+
let node_1_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
74357434
nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_1_shutdown);
7435+
check_added_monitors!(nodes[1], 1);
74367436
let events = nodes[1].node.get_and_clear_pending_msg_events();
74377437
assert_eq!(events.len(), 1);
74387438
match events[0] {
@@ -7444,8 +7444,8 @@ fn test_upfront_shutdown_script() {
74447444
// channel smoothly, opt-out is from channel initiator here
74457445
let chan = create_announced_chan_between_nodes_with_value(&nodes, 1, 0, 1000000, 1000000, flags.clone(), flags.clone());
74467446
nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id()).unwrap();
7447-
let mut node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
7448-
node_0_shutdown.scriptpubkey = Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script().to_p2sh();
7447+
check_added_monitors!(nodes[1], 1);
7448+
let node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
74497449
nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
74507450
let events = nodes[0].node.get_and_clear_pending_msg_events();
74517451
assert_eq!(events.len(), 1);
@@ -7458,8 +7458,8 @@ fn test_upfront_shutdown_script() {
74587458
//// channel smoothly
74597459
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, flags.clone(), flags.clone());
74607460
nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id()).unwrap();
7461-
let mut node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
7462-
node_0_shutdown.scriptpubkey = Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script().to_p2sh();
7461+
check_added_monitors!(nodes[1], 1);
7462+
let node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
74637463
nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
74647464
let events = nodes[0].node.get_and_clear_pending_msg_events();
74657465
assert_eq!(events.len(), 2);
@@ -7514,6 +7514,7 @@ fn test_segwit_v0_shutdown_script() {
75147514

75157515
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, InitFeatures::known(), InitFeatures::known());
75167516
nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id()).unwrap();
7517+
check_added_monitors!(nodes[1], 1);
75177518

75187519
// Use a segwit v0 script supported even without opt_shutdown_anysegwit
75197520
let mut node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
@@ -7555,6 +7556,7 @@ fn test_anysegwit_shutdown_script() {
75557556
.push_slice(&[0, 0])
75567557
.into_script();
75577558
nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
7559+
check_added_monitors!(nodes[1], 1);
75587560

75597561
let events = nodes[0].node.get_and_clear_pending_msg_events();
75607562
assert_eq!(events.len(), 2);
@@ -7582,6 +7584,7 @@ fn test_invalid_shutdown_script() {
75827584

75837585
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, InitFeatures::known(), InitFeatures::known());
75847586
nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id()).unwrap();
7587+
check_added_monitors!(nodes[1], 1);
75857588

75867589
// Use a segwit v0 script with an unsupported witness program
75877590
let mut node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());

0 commit comments

Comments
 (0)