Skip to content

Commit b416c1e

Browse files
committed
Support all shutdown scripts defined in BOLT 2
KeysInterface::get_shutdown_pubkey is used to form P2WPKH shutdown scripts. However, BOLT 2 allows for a wider variety of scripts. Refactor KeysInterface to allow any supported script while still maintaining serialization backwards compatibility with P2WPKH script pubkeys stored simply as the PublicKey. Add an optional TLV field to Channel and ChannelMonitor to support the new format, but continue to serialize the legacy PublicKey format.
1 parent b3c6926 commit b416c1e

File tree

7 files changed

+100
-37
lines changed

7 files changed

+100
-37
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
3939
use lightning::ln::channelmanager::{ChainParameters, ChannelManager, PaymentSendFailure, ChannelManagerReadArgs};
4040
use lightning::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
4141
use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, DecodeError, UpdateAddHTLC, Init};
42+
use lightning::ln::script::ShutdownScript;
4243
use lightning::util::enforcing_trait_impls::{EnforcingSigner, INITIAL_REVOKED_COMMITMENT_NUMBER};
4344
use lightning::util::errors::APIError;
4445
use lightning::util::events;
@@ -164,9 +165,9 @@ impl KeysInterface for KeyProvider {
164165
Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script()
165166
}
166167

167-
fn get_shutdown_pubkey(&self) -> PublicKey {
168+
fn get_shutdown_scriptpubkey(&self) -> ShutdownScript {
168169
let secp_ctx = Secp256k1::signing_only();
169-
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, self.node_id]).unwrap())
170+
ShutdownScript::from(PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, self.node_id]).unwrap()))
170171
}
171172

172173
fn get_channel_signer(&self, _inbound: bool, channel_value_satoshis: u64) -> EnforcingSigner {

fuzz/src/full_stack.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
3636
use lightning::ln::channelmanager::{ChainParameters, ChannelManager};
3737
use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor};
3838
use lightning::ln::msgs::DecodeError;
39+
use lightning::ln::script::ShutdownScript;
3940
use lightning::routing::router::get_route;
4041
use lightning::routing::network_graph::NetGraphMsgHandler;
4142
use lightning::util::config::UserConfig;
@@ -271,9 +272,9 @@ impl KeysInterface for KeyProvider {
271272
Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script()
272273
}
273274

274-
fn get_shutdown_pubkey(&self) -> PublicKey {
275+
fn get_shutdown_scriptpubkey(&self) -> ShutdownScript {
275276
let secp_ctx = Secp256k1::signing_only();
276-
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]).unwrap())
277+
ShutdownScript::from(PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]).unwrap()))
277278
}
278279

279280
fn get_channel_signer(&self, inbound: bool, channel_value_satoshis: u64) -> EnforcingSigner {

lightning/src/chain/channelmonitor.rs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ pub(crate) struct ChannelMonitorImpl<Signer: Sign> {
489489
destination_script: Script,
490490
broadcasted_holder_revokable_script: Option<(Script, PublicKey, PublicKey)>,
491491
counterparty_payment_script: Script,
492-
shutdown_script: Script,
492+
shutdown_script: Option<Script>,
493493

494494
channel_keys_id: [u8; 32],
495495
holder_revocation_basepoint: PublicKey,
@@ -665,7 +665,10 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
665665
}
666666

667667
self.counterparty_payment_script.write(writer)?;
668-
self.shutdown_script.write(writer)?;
668+
match &self.shutdown_script {
669+
Some(script) => script.write(writer)?,
670+
None => Script::new().write(writer)?,
671+
}
669672

670673
self.channel_keys_id.write(writer)?;
671674
self.holder_revocation_basepoint.write(writer)?;
@@ -788,14 +791,16 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
788791
self.lockdown_from_offchain.write(writer)?;
789792
self.holder_tx_signed.write(writer)?;
790793

791-
write_tlv_fields!(writer, {});
794+
write_tlv_fields!(writer, {
795+
(1, self.shutdown_script, option),
796+
});
792797

793798
Ok(())
794799
}
795800
}
796801

797802
impl<Signer: Sign> ChannelMonitor<Signer> {
798-
pub(crate) fn new(secp_ctx: Secp256k1<secp256k1::All>, keys: Signer, shutdown_pubkey: &PublicKey,
803+
pub(crate) fn new(secp_ctx: Secp256k1<secp256k1::All>, keys: Signer, shutdown_script: Option<Script>,
799804
on_counterparty_tx_csv: u16, destination_script: &Script, funding_info: (OutPoint, Script),
800805
channel_parameters: &ChannelTransactionParameters,
801806
funding_redeemscript: Script, channel_value_satoshis: u64,
@@ -804,8 +809,6 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
804809
best_block: BestBlock) -> ChannelMonitor<Signer> {
805810

806811
assert!(commitment_transaction_number_obscure_factor <= (1 << 48));
807-
let our_channel_close_key_hash = WPubkeyHash::hash(&shutdown_pubkey.serialize());
808-
let shutdown_script = Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_close_key_hash[..]).into_script();
809812
let payment_key_hash = WPubkeyHash::hash(&keys.pubkeys().payment_point.serialize());
810813
let counterparty_payment_script = Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&payment_key_hash[..]).into_script();
811814

@@ -2472,7 +2475,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
24722475
channel_value_satoshis: self.channel_value_satoshis,
24732476
}));
24742477
break;
2475-
} else if outp.script_pubkey == self.shutdown_script {
2478+
} else if self.shutdown_script.as_ref() == Some(&outp.script_pubkey) {
24762479
spendable_output = Some(SpendableOutputDescriptor::StaticOutput {
24772480
outpoint: OutPoint { txid: tx.txid(), index: i as u16 },
24782481
output: outp.clone(),
@@ -2608,7 +2611,10 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
26082611
_ => return Err(DecodeError::InvalidValue),
26092612
};
26102613
let counterparty_payment_script = Readable::read(reader)?;
2611-
let shutdown_script = Readable::read(reader)?;
2614+
let mut shutdown_script = {
2615+
let script = <Script as Readable>::read(reader)?;
2616+
if script.is_empty() { None } else { Some(script) }
2617+
};
26122618

26132619
let channel_keys_id = Readable::read(reader)?;
26142620
let holder_revocation_basepoint = Readable::read(reader)?;
@@ -2762,7 +2768,9 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
27622768
let lockdown_from_offchain = Readable::read(reader)?;
27632769
let holder_tx_signed = Readable::read(reader)?;
27642770

2765-
read_tlv_fields!(reader, {});
2771+
read_tlv_fields!(reader, {
2772+
(1, shutdown_script, option),
2773+
});
27662774

27672775
let mut secp_ctx = Secp256k1::new();
27682776
secp_ctx.seeded_randomize(&keys_manager.get_secure_random_bytes());
@@ -2840,6 +2848,7 @@ mod tests {
28402848
use ln::{PaymentPreimage, PaymentHash};
28412849
use ln::chan_utils;
28422850
use ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, ChannelTransactionParameters, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters};
2851+
use ln::script::ShutdownScript;
28432852
use util::test_utils::{TestLogger, TestBroadcaster, TestFeeEstimator};
28442853
use bitcoin::secp256k1::key::{SecretKey,PublicKey};
28452854
use bitcoin::secp256k1::Secp256k1;
@@ -2933,9 +2942,10 @@ mod tests {
29332942
};
29342943
// Prune with one old state and a holder commitment tx holding a few overlaps with the
29352944
// old state.
2945+
let shutdown_pubkey = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
29362946
let best_block = BestBlock::from_genesis(Network::Testnet);
29372947
let monitor = ChannelMonitor::new(Secp256k1::new(), keys,
2938-
&PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()), 0, &Script::new(),
2948+
Some(ShutdownScript::from(shutdown_pubkey).into_inner()), 0, &Script::new(),
29392949
(OutPoint { txid: Txid::from_slice(&[43; 32]).unwrap(), index: 0 }, Script::new()),
29402950
&channel_parameters,
29412951
Script::new(), 46, 0,

lightning/src/chain/keysinterface.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use chain::transaction::OutPoint;
3636
use ln::chan_utils;
3737
use ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, HolderCommitmentTransaction, ChannelTransactionParameters, CommitmentTransaction};
3838
use ln::msgs::UnsignedChannelAnnouncement;
39+
use ln::script::ShutdownScript;
3940

4041
use prelude::*;
4142
use core::sync::atomic::{AtomicUsize, Ordering};
@@ -118,8 +119,8 @@ impl_writeable_tlv_based!(StaticPaymentOutputDescriptor, {
118119
#[derive(Clone, Debug, PartialEq)]
119120
pub enum SpendableOutputDescriptor {
120121
/// An output to a script which was provided via KeysInterface directly, either from
121-
/// `get_destination_script()` or `get_shutdown_pubkey()`, thus you should already know how to
122-
/// spend it. No secret keys are provided as rust-lightning was never given any key.
122+
/// `get_destination_script()` or `get_shutdown_scriptpubkey()`, thus you should already know
123+
/// how to spend it. No secret keys are provided as rust-lightning was never given any key.
123124
/// These may include outputs from a transaction punishing our counterparty or claiming an HTLC
124125
/// on-chain using the payment preimage or after it has timed out.
125126
StaticOutput {
@@ -351,12 +352,11 @@ pub trait KeysInterface {
351352
/// This method should return a different value each time it is called, to avoid linking
352353
/// on-chain funds across channels as controlled to the same user.
353354
fn get_destination_script(&self) -> Script;
354-
/// Get a public key which we will send funds to (in the form of a P2WPKH output) when closing
355-
/// a channel.
355+
/// Get a script pubkey which we will send funds to when closing a channel.
356356
///
357357
/// This method should return a different value each time it is called, to avoid linking
358358
/// on-chain funds across channels as controlled to the same user.
359-
fn get_shutdown_pubkey(&self) -> PublicKey;
359+
fn get_shutdown_scriptpubkey(&self) -> ShutdownScript;
360360
/// Get a new set of Sign for per-channel secrets. These MUST be unique even if you
361361
/// restarted with some stale data!
362362
///
@@ -1013,8 +1013,8 @@ impl KeysInterface for KeysManager {
10131013
self.destination_script.clone()
10141014
}
10151015

1016-
fn get_shutdown_pubkey(&self) -> PublicKey {
1017-
self.shutdown_pubkey.clone()
1016+
fn get_shutdown_scriptpubkey(&self) -> ShutdownScript {
1017+
ShutdownScript::from(self.shutdown_pubkey.clone())
10181018
}
10191019

10201020
fn get_channel_signer(&self, _inbound: bool, channel_value_satoshis: u64) -> Self::Signer {

lightning/src/ln/channel.rs

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@
99

1010
use bitcoin::blockdata::script::{Script,Builder};
1111
use bitcoin::blockdata::transaction::{TxIn, TxOut, Transaction, SigHashType};
12-
use bitcoin::blockdata::opcodes;
1312
use bitcoin::util::bip143;
1413
use bitcoin::consensus::encode;
1514

1615
use bitcoin::hashes::Hash;
1716
use bitcoin::hashes::sha256::Hash as Sha256;
1817
use bitcoin::hashes::sha256d::Hash as Sha256d;
19-
use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash};
18+
use bitcoin::hash_types::{Txid, BlockHash};
2019

20+
use bitcoin::secp256k1::constants::PUBLIC_KEY_SIZE;
2121
use bitcoin::secp256k1::key::{PublicKey,SecretKey};
2222
use bitcoin::secp256k1::{Secp256k1,Signature};
2323
use bitcoin::secp256k1;
@@ -349,7 +349,7 @@ pub(super) struct Channel<Signer: Sign> {
349349
latest_monitor_update_id: u64,
350350

351351
holder_signer: Signer,
352-
shutdown_pubkey: PublicKey,
352+
shutdown_scriptpubkey: Option<ShutdownScript>,
353353
destination_script: Script,
354354

355355
// Our commitment numbers start at 2^48-1 and count down, whereas the ones used in transaction
@@ -607,7 +607,7 @@ impl<Signer: Sign> Channel<Signer> {
607607
latest_monitor_update_id: 0,
608608

609609
holder_signer,
610-
shutdown_pubkey: keys_provider.get_shutdown_pubkey(),
610+
shutdown_scriptpubkey: Some(keys_provider.get_shutdown_scriptpubkey()),
611611
destination_script: keys_provider.get_destination_script(),
612612

613613
cur_holder_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER,
@@ -851,7 +851,7 @@ impl<Signer: Sign> Channel<Signer> {
851851
latest_monitor_update_id: 0,
852852

853853
holder_signer,
854-
shutdown_pubkey: keys_provider.get_shutdown_pubkey(),
854+
shutdown_scriptpubkey: Some(keys_provider.get_shutdown_scriptpubkey()),
855855
destination_script: keys_provider.get_destination_script(),
856856

857857
cur_holder_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER,
@@ -1130,8 +1130,7 @@ impl<Signer: Sign> Channel<Signer> {
11301130

11311131
#[inline]
11321132
fn get_closing_scriptpubkey(&self) -> Script {
1133-
let channel_close_key_hash = WPubkeyHash::hash(&self.shutdown_pubkey.serialize());
1134-
Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&channel_close_key_hash[..]).into_script()
1133+
self.shutdown_scriptpubkey.clone().unwrap().into_inner()
11351134
}
11361135

11371136
#[inline]
@@ -1676,8 +1675,9 @@ impl<Signer: Sign> Channel<Signer> {
16761675
let funding_redeemscript = self.get_funding_redeemscript();
16771676
let funding_txo_script = funding_redeemscript.to_v0_p2wsh();
16781677
let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.is_outbound());
1678+
let shutdown_script = self.shutdown_scriptpubkey.clone().map(|script| script.into_inner());
16791679
let channel_monitor = ChannelMonitor::new(self.secp_ctx.clone(), self.holder_signer.clone(),
1680-
&self.shutdown_pubkey, self.get_holder_selected_contest_delay(),
1680+
shutdown_script, self.get_holder_selected_contest_delay(),
16811681
&self.destination_script, (funding_txo, funding_txo_script.clone()),
16821682
&self.channel_transaction_parameters,
16831683
funding_redeemscript.clone(), self.channel_value_satoshis,
@@ -1749,8 +1749,9 @@ impl<Signer: Sign> Channel<Signer> {
17491749
let funding_txo = self.get_funding_txo().unwrap();
17501750
let funding_txo_script = funding_redeemscript.to_v0_p2wsh();
17511751
let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.is_outbound());
1752+
let shutdown_script = self.shutdown_scriptpubkey.clone().map(|script| script.into_inner());
17521753
let channel_monitor = ChannelMonitor::new(self.secp_ctx.clone(), self.holder_signer.clone(),
1753-
&self.shutdown_pubkey, self.get_holder_selected_contest_delay(),
1754+
shutdown_script, self.get_holder_selected_contest_delay(),
17541755
&self.destination_script, (funding_txo, funding_txo_script),
17551756
&self.channel_transaction_parameters,
17561757
funding_redeemscript.clone(), self.channel_value_satoshis,
@@ -4549,7 +4550,12 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
45494550
(key_data.0.len() as u32).write(writer)?;
45504551
writer.write_all(&key_data.0[..])?;
45514552

4552-
self.shutdown_pubkey.write(writer)?;
4553+
// Write out the old serialization for shutdown_pubkey for backwards compatibility, if
4554+
// deserialized from that format.
4555+
match self.shutdown_scriptpubkey.as_ref().and_then(|script| script.as_legacy_pubkey()) {
4556+
Some(shutdown_pubkey) => shutdown_pubkey.write(writer)?,
4557+
None => [0u8; PUBLIC_KEY_SIZE].write(writer)?,
4558+
}
45534559
self.destination_script.write(writer)?;
45544560

45554561
self.cur_holder_commitment_transaction_number.write(writer)?;
@@ -4745,6 +4751,7 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
47454751
(1, self.minimum_depth, option),
47464752
(3, self.counterparty_selected_channel_reserve_satoshis, option),
47474753
(5, self.config, required),
4754+
(7, self.shutdown_scriptpubkey, option),
47484755
});
47494756

47504757
Ok(())
@@ -4788,7 +4795,12 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
47884795
}
47894796
let holder_signer = keys_source.read_chan_signer(&keys_data)?;
47904797

4791-
let shutdown_pubkey = Readable::read(reader)?;
4798+
// Read the old serialization for shutdown_pubkey, preferring it for shutdown_scriptpubkey
4799+
// over the TLV if valid.
4800+
let mut shutdown_scriptpubkey = match <PublicKey as Readable>::read(reader) {
4801+
Ok(pubkey) => Some(ShutdownScript::from(pubkey)),
4802+
Err(_) => None,
4803+
};
47924804
let destination_script = Readable::read(reader)?;
47934805

47944806
let cur_holder_commitment_transaction_number = Readable::read(reader)?;
@@ -4959,6 +4971,7 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
49594971
(1, minimum_depth, option),
49604972
(3, counterparty_selected_channel_reserve_satoshis, option),
49614973
(5, config, option), // Note that if none is provided we will *not* overwrite the existing one.
4974+
(7, shutdown_scriptpubkey, option),
49624975
});
49634976

49644977
let mut secp_ctx = Secp256k1::new();
@@ -4976,7 +4989,7 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
49764989
latest_monitor_update_id,
49774990

49784991
holder_signer,
4979-
shutdown_pubkey,
4992+
shutdown_scriptpubkey,
49804993
destination_script,
49814994

49824995
cur_holder_commitment_transaction_number,
@@ -5069,6 +5082,7 @@ mod tests {
50695082
use ln::channel::MAX_FUNDING_SATOSHIS;
50705083
use ln::features::InitFeatures;
50715084
use ln::msgs::{ChannelUpdate, DataLossProtect, DecodeError, OptionalField, UnsignedChannelUpdate};
5085+
use ln::script::ShutdownScript;
50725086
use ln::chan_utils;
50735087
use ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT};
50745088
use chain::BestBlock;
@@ -5118,10 +5132,10 @@ mod tests {
51185132
Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&channel_monitor_claim_key_hash[..]).into_script()
51195133
}
51205134

5121-
fn get_shutdown_pubkey(&self) -> PublicKey {
5135+
fn get_shutdown_scriptpubkey(&self) -> ShutdownScript {
51225136
let secp_ctx = Secp256k1::signing_only();
51235137
let channel_close_key = SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap();
5124-
PublicKey::from_secret_key(&secp_ctx, &channel_close_key)
5138+
ShutdownScript::from(PublicKey::from_secret_key(&secp_ctx, &channel_close_key))
51255139
}
51265140

51275141
fn get_channel_signer(&self, _inbound: bool, _channel_value_satoshis: u64) -> InMemorySigner {

0 commit comments

Comments
 (0)