Skip to content

Commit ccd11fc

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 1ab2c7c commit ccd11fc

File tree

7 files changed

+91
-36
lines changed

7 files changed

+91
-36
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 5 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,11 @@ 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+
let secret_key = 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();
171+
let pubkey_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &secret_key).serialize());
172+
ShutdownScript::new_p2wpkh(&pubkey_hash)
170173
}
171174

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

fuzz/src/full_stack.rs

Lines changed: 5 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,11 @@ 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+
let secret_key = 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();
278+
let pubkey_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &secret_key).serialize());
279+
ShutdownScript::new_p2wpkh(&pubkey_hash)
277280
}
278281

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

lightning/src/chain/channelmonitor.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ pub(crate) struct ChannelMonitorImpl<Signer: Sign> {
493493
destination_script: Script,
494494
broadcasted_holder_revokable_script: Option<(Script, PublicKey, PublicKey)>,
495495
counterparty_payment_script: Script,
496-
shutdown_script: Script,
496+
shutdown_script: Option<Script>,
497497

498498
channel_keys_id: [u8; 32],
499499
holder_revocation_basepoint: PublicKey,
@@ -669,7 +669,10 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
669669
}
670670

671671
self.counterparty_payment_script.write(writer)?;
672-
self.shutdown_script.write(writer)?;
672+
match &self.shutdown_script {
673+
Some(script) => script.write(writer)?,
674+
None => Script::new().write(writer)?,
675+
}
673676

674677
self.channel_keys_id.write(writer)?;
675678
self.holder_revocation_basepoint.write(writer)?;
@@ -799,7 +802,7 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
799802
}
800803

801804
impl<Signer: Sign> ChannelMonitor<Signer> {
802-
pub(crate) fn new(secp_ctx: Secp256k1<secp256k1::All>, keys: Signer, shutdown_pubkey: &PublicKey,
805+
pub(crate) fn new(secp_ctx: Secp256k1<secp256k1::All>, keys: Signer, shutdown_script: Option<Script>,
803806
on_counterparty_tx_csv: u16, destination_script: &Script, funding_info: (OutPoint, Script),
804807
channel_parameters: &ChannelTransactionParameters,
805808
funding_redeemscript: Script, channel_value_satoshis: u64,
@@ -808,8 +811,6 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
808811
best_block: BestBlock) -> ChannelMonitor<Signer> {
809812

810813
assert!(commitment_transaction_number_obscure_factor <= (1 << 48));
811-
let our_channel_close_key_hash = WPubkeyHash::hash(&shutdown_pubkey.serialize());
812-
let shutdown_script = Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_close_key_hash[..]).into_script();
813814
let payment_key_hash = WPubkeyHash::hash(&keys.pubkeys().payment_point.serialize());
814815
let counterparty_payment_script = Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&payment_key_hash[..]).into_script();
815816

@@ -2485,7 +2486,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
24852486
}));
24862487
break;
24872488
}
2488-
if outp.script_pubkey == self.shutdown_script {
2489+
if self.shutdown_script.as_ref() == Some(&outp.script_pubkey) {
24892490
spendable_output = Some(SpendableOutputDescriptor::StaticOutput {
24902491
outpoint: OutPoint { txid: tx.txid(), index: i as u16 },
24912492
output: outp.clone(),
@@ -2622,7 +2623,10 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
26222623
_ => return Err(DecodeError::InvalidValue),
26232624
};
26242625
let counterparty_payment_script = Readable::read(reader)?;
2625-
let shutdown_script = Readable::read(reader)?;
2626+
let shutdown_script = {
2627+
let script = <Script as Readable>::read(reader)?;
2628+
if script.is_empty() { None } else { Some(script) }
2629+
};
26262630

26272631
let channel_keys_id = Readable::read(reader)?;
26282632
let holder_revocation_basepoint = Readable::read(reader)?;
@@ -2854,6 +2858,7 @@ mod tests {
28542858
use ln::{PaymentPreimage, PaymentHash};
28552859
use ln::chan_utils;
28562860
use ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, ChannelTransactionParameters, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters};
2861+
use ln::script::ShutdownScript;
28572862
use util::test_utils::{TestLogger, TestBroadcaster, TestFeeEstimator};
28582863
use bitcoin::secp256k1::key::{SecretKey,PublicKey};
28592864
use bitcoin::secp256k1::Secp256k1;
@@ -2947,9 +2952,10 @@ mod tests {
29472952
};
29482953
// Prune with one old state and a holder commitment tx holding a few overlaps with the
29492954
// old state.
2955+
let shutdown_pubkey = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
29502956
let best_block = BestBlock::from_genesis(Network::Testnet);
29512957
let monitor = ChannelMonitor::new(Secp256k1::new(), keys,
2952-
&PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()), 0, &Script::new(),
2958+
Some(ShutdownScript::new_p2wpkh_from_pubkey(shutdown_pubkey).into_inner()), 0, &Script::new(),
29532959
(OutPoint { txid: Txid::from_slice(&[43; 32]).unwrap(), index: 0 }, Script::new()),
29542960
&channel_parameters,
29552961
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::new_p2wpkh_from_pubkey(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: 30 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;
@@ -356,7 +356,7 @@ pub(super) struct Channel<Signer: Sign> {
356356
latest_monitor_update_id: u64,
357357

358358
holder_signer: Signer,
359-
shutdown_pubkey: PublicKey,
359+
shutdown_scriptpubkey: Option<ShutdownScript>,
360360
destination_script: Script,
361361

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

616616
holder_signer,
617-
shutdown_pubkey: keys_provider.get_shutdown_pubkey(),
617+
shutdown_scriptpubkey: Some(keys_provider.get_shutdown_scriptpubkey()),
618618
destination_script: keys_provider.get_destination_script(),
619619

620620
cur_holder_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER,
@@ -858,7 +858,7 @@ impl<Signer: Sign> Channel<Signer> {
858858
latest_monitor_update_id: 0,
859859

860860
holder_signer,
861-
shutdown_pubkey: keys_provider.get_shutdown_pubkey(),
861+
shutdown_scriptpubkey: Some(keys_provider.get_shutdown_scriptpubkey()),
862862
destination_script: keys_provider.get_destination_script(),
863863

864864
cur_holder_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER,
@@ -1137,8 +1137,10 @@ impl<Signer: Sign> Channel<Signer> {
11371137

11381138
#[inline]
11391139
fn get_closing_scriptpubkey(&self) -> Script {
1140-
let channel_close_key_hash = WPubkeyHash::hash(&self.shutdown_pubkey.serialize());
1141-
Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&channel_close_key_hash[..]).into_script()
1140+
// The shutdown scriptpubkey is set on channel opening when option_upfront_shutdown_script
1141+
// is signaled. Otherwise, it is set when sending a shutdown message. Calling this method
1142+
// outside of those situations will fail.
1143+
self.shutdown_scriptpubkey.clone().unwrap().into_inner()
11421144
}
11431145

11441146
#[inline]
@@ -1687,8 +1689,9 @@ impl<Signer: Sign> Channel<Signer> {
16871689
let funding_redeemscript = self.get_funding_redeemscript();
16881690
let funding_txo_script = funding_redeemscript.to_v0_p2wsh();
16891691
let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.is_outbound());
1692+
let shutdown_script = self.shutdown_scriptpubkey.clone().map(|script| script.into_inner());
16901693
let channel_monitor = ChannelMonitor::new(self.secp_ctx.clone(), self.holder_signer.clone(),
1691-
&self.shutdown_pubkey, self.get_holder_selected_contest_delay(),
1694+
shutdown_script, self.get_holder_selected_contest_delay(),
16921695
&self.destination_script, (funding_txo, funding_txo_script.clone()),
16931696
&self.channel_transaction_parameters,
16941697
funding_redeemscript.clone(), self.channel_value_satoshis,
@@ -1760,8 +1763,9 @@ impl<Signer: Sign> Channel<Signer> {
17601763
let funding_txo = self.get_funding_txo().unwrap();
17611764
let funding_txo_script = funding_redeemscript.to_v0_p2wsh();
17621765
let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.is_outbound());
1766+
let shutdown_script = self.shutdown_scriptpubkey.clone().map(|script| script.into_inner());
17631767
let channel_monitor = ChannelMonitor::new(self.secp_ctx.clone(), self.holder_signer.clone(),
1764-
&self.shutdown_pubkey, self.get_holder_selected_contest_delay(),
1768+
shutdown_script, self.get_holder_selected_contest_delay(),
17651769
&self.destination_script, (funding_txo, funding_txo_script),
17661770
&self.channel_transaction_parameters,
17671771
funding_redeemscript.clone(), self.channel_value_satoshis,
@@ -4560,7 +4564,12 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
45604564
(key_data.0.len() as u32).write(writer)?;
45614565
writer.write_all(&key_data.0[..])?;
45624566

4563-
self.shutdown_pubkey.write(writer)?;
4567+
// Write out the old serialization for shutdown_pubkey for backwards compatibility, if
4568+
// deserialized from that format.
4569+
match self.shutdown_scriptpubkey.as_ref().and_then(|script| script.as_legacy_pubkey()) {
4570+
Some(shutdown_pubkey) => shutdown_pubkey.write(writer)?,
4571+
None => [0u8; PUBLIC_KEY_SIZE].write(writer)?,
4572+
}
45644573
self.destination_script.write(writer)?;
45654574

45664575
self.cur_holder_commitment_transaction_number.write(writer)?;
@@ -4756,6 +4765,7 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
47564765
(1, self.minimum_depth, option),
47574766
(3, self.counterparty_selected_channel_reserve_satoshis, option),
47584767
(5, self.config, required),
4768+
(7, self.shutdown_scriptpubkey, option),
47594769
});
47604770

47614771
Ok(())
@@ -4799,7 +4809,11 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
47994809
}
48004810
let holder_signer = keys_source.read_chan_signer(&keys_data)?;
48014811

4802-
let shutdown_pubkey = Readable::read(reader)?;
4812+
// Read the old serialization for shutdown_pubkey, preferring the TLV field later if set.
4813+
let mut shutdown_scriptpubkey = match <PublicKey as Readable>::read(reader) {
4814+
Ok(pubkey) => Some(ShutdownScript::new_p2wpkh_from_pubkey(pubkey)),
4815+
Err(_) => None,
4816+
};
48034817
let destination_script = Readable::read(reader)?;
48044818

48054819
let cur_holder_commitment_transaction_number = Readable::read(reader)?;
@@ -4970,6 +4984,7 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
49704984
(1, minimum_depth, option),
49714985
(3, counterparty_selected_channel_reserve_satoshis, option),
49724986
(5, config, option), // Note that if none is provided we will *not* overwrite the existing one.
4987+
(7, shutdown_scriptpubkey, option),
49734988
});
49744989

49754990
let mut secp_ctx = Secp256k1::new();
@@ -4987,7 +5002,7 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
49875002
latest_monitor_update_id,
49885003

49895004
holder_signer,
4990-
shutdown_pubkey,
5005+
shutdown_scriptpubkey,
49915006
destination_script,
49925007

49935008
cur_holder_commitment_transaction_number,
@@ -5080,6 +5095,7 @@ mod tests {
50805095
use ln::channel::MAX_FUNDING_SATOSHIS;
50815096
use ln::features::InitFeatures;
50825097
use ln::msgs::{ChannelUpdate, DataLossProtect, DecodeError, OptionalField, UnsignedChannelUpdate};
5098+
use ln::script::ShutdownScript;
50835099
use ln::chan_utils;
50845100
use ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT};
50855101
use chain::BestBlock;
@@ -5129,10 +5145,10 @@ mod tests {
51295145
Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&channel_monitor_claim_key_hash[..]).into_script()
51305146
}
51315147

5132-
fn get_shutdown_pubkey(&self) -> PublicKey {
5148+
fn get_shutdown_scriptpubkey(&self) -> ShutdownScript {
51335149
let secp_ctx = Secp256k1::signing_only();
51345150
let channel_close_key = SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap();
5135-
PublicKey::from_secret_key(&secp_ctx, &channel_close_key)
5151+
ShutdownScript::new_p2wpkh_from_pubkey(PublicKey::from_secret_key(&secp_ctx, &channel_close_key))
51365152
}
51375153

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

lightning/src/ln/script.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@ use bitcoin::hash_types::{PubkeyHash, ScriptHash, WPubkeyHash, WScriptHash};
77
use bitcoin::secp256k1::key::PublicKey;
88

99
use ln::features::InitFeatures;
10+
use ln::msgs::DecodeError;
11+
use util::ser::{Readable, Writeable, Writer};
1012

1113
use core::convert::TryFrom;
1214
use core::num::NonZeroU8;
15+
use io;
1316

1417
/// A script pubkey for shutting down a channel as defined by [BOLT #2].
1518
///
1619
/// [BOLT #2]: https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md
20+
#[derive(Clone)]
1721
pub struct ShutdownScript(ShutdownScriptImpl);
1822

1923
/// An error occurring when converting from [`Script`] to [`ShutdownScript`].
@@ -25,6 +29,7 @@ pub struct InvalidShutdownScript {
2529
pub script: Script
2630
}
2731

32+
#[derive(Clone)]
2833
enum ShutdownScriptImpl {
2934
/// [`PublicKey`] used to form a P2WPKH script pubkey. Used to support backward-compatible
3035
/// serialization.
@@ -34,9 +39,30 @@ enum ShutdownScriptImpl {
3439
Bolt2(Script),
3540
}
3641

42+
impl Writeable for ShutdownScript {
43+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
44+
self.0.write(w)
45+
}
46+
47+
fn serialized_length(&self) -> usize {
48+
self.0.serialized_length()
49+
}
50+
}
51+
52+
impl Readable for ShutdownScript {
53+
fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
54+
Ok(ShutdownScript(ShutdownScriptImpl::read(r)?))
55+
}
56+
}
57+
58+
impl_writeable_tlv_based_enum!(ShutdownScriptImpl, ;
59+
(0, Legacy),
60+
(1, Bolt2),
61+
);
62+
3763
impl ShutdownScript {
3864
/// Generates a P2WPKH script pubkey from the given [`PublicKey`].
39-
pub fn new_p2wpkh_from_pubkey(pubkey: PublicKey) -> Self {
65+
pub(crate) fn new_p2wpkh_from_pubkey(pubkey: PublicKey) -> Self {
4066
Self(ShutdownScriptImpl::Legacy(pubkey))
4167
}
4268

0 commit comments

Comments
 (0)