Skip to content

Commit c0bf4fd

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 b416c1e commit c0bf4fd

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
@@ -595,6 +595,12 @@ impl<Signer: Sign> Channel<Signer> {
595595
let mut secp_ctx = Secp256k1::new();
596596
secp_ctx.seeded_randomize(&keys_provider.get_secure_random_bytes());
597597

598+
let shutdown_scriptpubkey = if config.channel_options.commit_upfront_shutdown_pubkey {
599+
Some(keys_provider.get_shutdown_scriptpubkey())
600+
} else {
601+
None
602+
};
603+
598604
Ok(Channel {
599605
user_id,
600606
config: config.channel_options.clone(),
@@ -607,7 +613,7 @@ impl<Signer: Sign> Channel<Signer> {
607613
latest_monitor_update_id: 0,
608614

609615
holder_signer,
610-
shutdown_scriptpubkey: Some(keys_provider.get_shutdown_scriptpubkey()),
616+
shutdown_scriptpubkey,
611617
destination_script: keys_provider.get_destination_script(),
612618

613619
cur_holder_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER,
@@ -840,6 +846,12 @@ impl<Signer: Sign> Channel<Signer> {
840846
let mut secp_ctx = Secp256k1::new();
841847
secp_ctx.seeded_randomize(&keys_provider.get_secure_random_bytes());
842848

849+
let shutdown_scriptpubkey = if config.channel_options.commit_upfront_shutdown_pubkey {
850+
Some(keys_provider.get_shutdown_scriptpubkey())
851+
} else {
852+
None
853+
};
854+
843855
let chan = Channel {
844856
user_id,
845857
config: local_config,
@@ -851,7 +863,7 @@ impl<Signer: Sign> Channel<Signer> {
851863
latest_monitor_update_id: 0,
852864

853865
holder_signer,
854-
shutdown_scriptpubkey: Some(keys_provider.get_shutdown_scriptpubkey()),
866+
shutdown_scriptpubkey,
855867
destination_script: keys_provider.get_destination_script(),
856868

857869
cur_holder_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER,
@@ -1196,6 +1208,7 @@ impl<Signer: Sign> Channel<Signer> {
11961208
}, ()));
11971209
}
11981210

1211+
assert!(self.shutdown_scriptpubkey.is_some());
11991212
if value_to_self as u64 > self.holder_dust_limit_satoshis {
12001213
txouts.push((TxOut {
12011214
script_pubkey: self.get_closing_scriptpubkey(),
@@ -3082,6 +3095,7 @@ impl<Signer: Sign> Channel<Signer> {
30823095
self.channel_state &= !(ChannelState::PeerDisconnected as u32);
30833096

30843097
let shutdown_msg = if self.channel_state & (ChannelState::LocalShutdownSent as u32) != 0 {
3098+
assert!(self.shutdown_scriptpubkey.is_some());
30853099
Some(msgs::Shutdown {
30863100
channel_id: self.channel_id,
30873101
scriptpubkey: self.get_closing_scriptpubkey(),
@@ -3193,6 +3207,7 @@ impl<Signer: Sign> Channel<Signer> {
31933207
if self.feerate_per_kw > proposed_feerate {
31943208
proposed_feerate = self.feerate_per_kw;
31953209
}
3210+
assert!(self.shutdown_scriptpubkey.is_some());
31963211
let tx_weight = self.get_closing_transaction_weight(Some(&self.get_closing_scriptpubkey()), Some(self.counterparty_shutdown_scriptpubkey.as_ref().unwrap()));
31973212
let proposed_total_fee_satoshis = proposed_feerate as u64 * tx_weight / 1000;
31983213

@@ -3211,8 +3226,12 @@ impl<Signer: Sign> Channel<Signer> {
32113226
})
32123227
}
32133228

3214-
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>
3215-
where F::Target: FeeEstimator
3229+
pub fn shutdown<F: Deref, K: Deref>(
3230+
&mut self, fee_estimator: &F, keys_provider: &K, _their_features: &InitFeatures, msg: &msgs::Shutdown
3231+
) -> Result<(Option<msgs::Shutdown>, Option<msgs::ClosingSigned>, Option<ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>), ChannelError>
3232+
where
3233+
F::Target: FeeEstimator,
3234+
K::Target: KeysInterface<Signer = Signer>
32163235
{
32173236
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
32183237
return Err(ChannelError::Close("Peer sent shutdown when we needed a channel_reestablish".to_owned()));
@@ -3262,23 +3281,36 @@ impl<Signer: Sign> Channel<Signer> {
32623281
_ => true
32633282
}
32643283
});
3284+
32653285
// If we have any LocalAnnounced updates we'll probably just get back a update_fail_htlc
32663286
// immediately after the commitment dance, but we can send a Shutdown cause we won't send
32673287
// any further commitment updates after we set LocalShutdownSent.
3268-
3269-
let shutdown = if (self.channel_state & ChannelState::LocalShutdownSent as u32) == ChannelState::LocalShutdownSent as u32 {
3270-
None
3271-
} else {
3288+
let send_shutdown = (self.channel_state & ChannelState::LocalShutdownSent as u32) != ChannelState::LocalShutdownSent as u32;
3289+
let monitor_update = match self.shutdown_scriptpubkey {
3290+
Some(_) => None,
3291+
None => {
3292+
assert!(send_shutdown);
3293+
self.shutdown_scriptpubkey = Some(keys_provider.get_shutdown_scriptpubkey());
3294+
self.latest_monitor_update_id += 1;
3295+
Some(ChannelMonitorUpdate {
3296+
update_id: self.latest_monitor_update_id,
3297+
updates: vec![ChannelMonitorUpdateStep::ShutdownScript {
3298+
scriptpubkey: self.get_closing_scriptpubkey(),
3299+
}],
3300+
})
3301+
},
3302+
};
3303+
let shutdown = if send_shutdown {
32723304
Some(msgs::Shutdown {
32733305
channel_id: self.channel_id,
32743306
scriptpubkey: self.get_closing_scriptpubkey(),
32753307
})
3276-
};
3308+
} else { None };
32773309

32783310
self.channel_state |= ChannelState::LocalShutdownSent as u32;
32793311
self.update_time_counter += 1;
32803312

3281-
Ok((shutdown, self.maybe_propose_first_closing_signed(fee_estimator), dropped_outbound_htlcs))
3313+
Ok((shutdown, self.maybe_propose_first_closing_signed(fee_estimator), monitor_update, dropped_outbound_htlcs))
32823314
}
32833315

32843316
fn build_signed_closing_transaction(&self, tx: &mut Transaction, counterparty_sig: &Signature, sig: &Signature) {
@@ -3353,6 +3385,7 @@ impl<Signer: Sign> Channel<Signer> {
33533385

33543386
macro_rules! propose_new_feerate {
33553387
($new_feerate: expr) => {
3388+
assert!(self.shutdown_scriptpubkey.is_some());
33563389
let tx_weight = self.get_closing_transaction_weight(Some(&self.get_closing_scriptpubkey()), Some(self.counterparty_shutdown_scriptpubkey.as_ref().unwrap()));
33573390
let (closing_tx, used_total_fee) = self.build_closing_transaction($new_feerate as u64 * tx_weight / 1000, false);
33583391
let sig = self.holder_signer
@@ -3851,7 +3884,10 @@ impl<Signer: Sign> Channel<Signer> {
38513884
htlc_basepoint: keys.htlc_basepoint,
38523885
first_per_commitment_point,
38533886
channel_flags: if self.config.announced_channel {1} else {0},
3854-
shutdown_scriptpubkey: OptionalField::Present(if self.config.commit_upfront_shutdown_pubkey { self.get_closing_scriptpubkey() } else { Builder::new().into_script() })
3887+
shutdown_scriptpubkey: OptionalField::Present(match &self.shutdown_scriptpubkey {
3888+
Some(script) => script.clone().into_inner(),
3889+
None => Builder::new().into_script(),
3890+
}),
38553891
}
38563892
}
38573893

@@ -3884,7 +3920,10 @@ impl<Signer: Sign> Channel<Signer> {
38843920
delayed_payment_basepoint: keys.delayed_payment_basepoint,
38853921
htlc_basepoint: keys.htlc_basepoint,
38863922
first_per_commitment_point,
3887-
shutdown_scriptpubkey: OptionalField::Present(if self.config.commit_upfront_shutdown_pubkey { self.get_closing_scriptpubkey() } else { Builder::new().into_script() })
3923+
shutdown_scriptpubkey: OptionalField::Present(match &self.shutdown_scriptpubkey {
3924+
Some(script) => script.clone().into_inner(),
3925+
None => Builder::new().into_script(),
3926+
}),
38883927
}
38893928
}
38903929

@@ -4392,7 +4431,8 @@ impl<Signer: Sign> Channel<Signer> {
43924431

43934432
/// Begins the shutdown process, getting a message for the remote peer and returning all
43944433
/// holding cell HTLCs for payment failure.
4395-
pub fn get_shutdown(&mut self) -> Result<(msgs::Shutdown, Vec<(HTLCSource, PaymentHash)>), APIError> {
4434+
pub fn get_shutdown<K: Deref>(&mut self, keys_provider: &K) -> Result<(msgs::Shutdown, Option<ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>), APIError>
4435+
where K::Target: KeysInterface<Signer = Signer> {
43964436
for htlc in self.pending_outbound_htlcs.iter() {
43974437
if let OutboundHTLCState::LocalAnnounced(_) = htlc.state {
43984438
return Err(APIError::APIMisuseError{err: "Cannot begin shutdown with pending HTLCs. Process pending events first".to_owned()});
@@ -4411,7 +4451,16 @@ impl<Signer: Sign> Channel<Signer> {
44114451
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()});
44124452
}
44134453

4414-
let closing_script = self.get_closing_scriptpubkey();
4454+
let monitor_update = if self.shutdown_scriptpubkey.is_none() {
4455+
self.shutdown_scriptpubkey = Some(keys_provider.get_shutdown_scriptpubkey());
4456+
self.latest_monitor_update_id += 1;
4457+
Some(ChannelMonitorUpdate {
4458+
update_id: self.latest_monitor_update_id,
4459+
updates: vec![ChannelMonitorUpdateStep::ShutdownScript {
4460+
scriptpubkey: self.get_closing_scriptpubkey(),
4461+
}],
4462+
})
4463+
} else { None };
44154464

44164465
// From here on out, we may not fail!
44174466
if self.channel_state < ChannelState::FundingSent as u32 {
@@ -4437,8 +4486,8 @@ impl<Signer: Sign> Channel<Signer> {
44374486

44384487
Ok((msgs::Shutdown {
44394488
channel_id: self.channel_id,
4440-
scriptpubkey: closing_script,
4441-
}, dropped_outbound_htlcs))
4489+
scriptpubkey: self.get_closing_scriptpubkey(),
4490+
}, monitor_update, dropped_outbound_htlcs))
44424491
}
44434492

44444493
/// 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
@@ -1256,11 +1256,17 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
12561256
let channel_state = &mut *channel_state_lock;
12571257
match channel_state.by_id.entry(channel_id.clone()) {
12581258
hash_map::Entry::Occupied(mut chan_entry) => {
1259-
let (shutdown_msg, failed_htlcs) = chan_entry.get_mut().get_shutdown()?;
1259+
let (shutdown_msg, monitor_update, failed_htlcs) = chan_entry.get_mut().get_shutdown(&self.keys_manager)?;
12601260
channel_state.pending_msg_events.push(events::MessageSendEvent::SendShutdown {
12611261
node_id: chan_entry.get().get_counterparty_node_id(),
12621262
msg: shutdown_msg
12631263
});
1264+
if let Some(monitor_update) = monitor_update {
1265+
if let Err(_) = self.chain_monitor.update_channel(chan_entry.get().get_funding_txo().unwrap(), monitor_update) {
1266+
// TODO: How should this be handled?
1267+
unimplemented!();
1268+
}
1269+
}
12641270
if chan_entry.get().is_shutdown() {
12651271
if let Some(short_id) = chan_entry.get().get_short_channel_id() {
12661272
channel_state.short_to_id.remove(&short_id);
@@ -3159,7 +3165,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
31593165
if chan_entry.get().get_counterparty_node_id() != *counterparty_node_id {
31603166
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!".to_owned(), msg.channel_id));
31613167
}
3162-
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);
3168+
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);
31633169
if let Some(msg) = shutdown {
31643170
channel_state.pending_msg_events.push(events::MessageSendEvent::SendShutdown {
31653171
node_id: counterparty_node_id.clone(),
@@ -3172,6 +3178,12 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
31723178
msg,
31733179
});
31743180
}
3181+
if let Some(monitor_update) = monitor_update {
3182+
if let Err(_) = self.chain_monitor.update_channel(chan_entry.get().get_funding_txo().unwrap(), monitor_update) {
3183+
// TODO: How should this be handled?
3184+
unimplemented!();
3185+
}
3186+
}
31753187
if chan_entry.get().is_shutdown() {
31763188
if let Some(short_id) = chan_entry.get().get_short_channel_id() {
31773189
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
@@ -7474,9 +7474,9 @@ fn test_upfront_shutdown_script() {
74747474
let flags_no = InitFeatures::known().clear_upfront_shutdown_script();
74757475
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, flags_no, flags.clone());
74767476
nodes[0].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id()).unwrap();
7477-
let mut node_1_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
7478-
node_1_shutdown.scriptpubkey = Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script().to_p2sh();
7477+
let node_1_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
74797478
nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_1_shutdown);
7479+
check_added_monitors!(nodes[1], 1);
74807480
let events = nodes[1].node.get_and_clear_pending_msg_events();
74817481
assert_eq!(events.len(), 1);
74827482
match events[0] {
@@ -7488,8 +7488,8 @@ fn test_upfront_shutdown_script() {
74887488
// channel smoothly, opt-out is from channel initiator here
74897489
let chan = create_announced_chan_between_nodes_with_value(&nodes, 1, 0, 1000000, 1000000, flags.clone(), flags.clone());
74907490
nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id()).unwrap();
7491-
let mut node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
7492-
node_0_shutdown.scriptpubkey = Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script().to_p2sh();
7491+
check_added_monitors!(nodes[1], 1);
7492+
let node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
74937493
nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
74947494
let events = nodes[0].node.get_and_clear_pending_msg_events();
74957495
assert_eq!(events.len(), 1);
@@ -7502,8 +7502,8 @@ fn test_upfront_shutdown_script() {
75027502
//// channel smoothly
75037503
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, flags.clone(), flags.clone());
75047504
nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id()).unwrap();
7505-
let mut node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
7506-
node_0_shutdown.scriptpubkey = Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script().to_p2sh();
7505+
check_added_monitors!(nodes[1], 1);
7506+
let node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
75077507
nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
75087508
let events = nodes[0].node.get_and_clear_pending_msg_events();
75097509
assert_eq!(events.len(), 2);
@@ -7558,6 +7558,7 @@ fn test_segwit_v0_shutdown_script() {
75587558

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

75627563
// Use a segwit v0 script supported even without opt_shutdown_anysegwit
75637564
let mut node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
@@ -7599,6 +7600,7 @@ fn test_anysegwit_shutdown_script() {
75997600
.push_slice(&[0, 0])
76007601
.into_script();
76017602
nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
7603+
check_added_monitors!(nodes[1], 1);
76027604

76037605
let events = nodes[0].node.get_and_clear_pending_msg_events();
76047606
assert_eq!(events.len(), 2);
@@ -7626,6 +7628,7 @@ fn test_invalid_shutdown_script() {
76267628

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

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

0 commit comments

Comments
 (0)