use bitcoin::secp256k1::key::PublicKey;
use ln::features::InitFeatures;
+use ln::msgs::DecodeError;
+use util::ser::{Readable, Writeable, Writer};
-use std::convert::From;
use std::convert::TryFrom;
+use std::io::Read;
+use core::num::NonZeroU8;
/// A script pubkey for shutting down a channel as defined by [BOLT #2].
///
/// [BOLT #2]: https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md
+#[derive(Clone)]
pub struct ShutdownScript(ShutdownScriptImpl);
/// An error occurring when converting from [`Script`] to [`ShutdownScript`].
#[derive(Debug)]
pub struct InvalidShutdownScript(Script);
+#[derive(Clone)]
enum ShutdownScriptImpl {
/// [`PublicKey`] used to form a P2WPKH script pubkey. Used to support backward-compatible
/// serialization.
Bolt2(Script),
}
+impl Writeable for ShutdownScript {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ self.0.write(w)
+ }
+
+ fn serialized_length(&self) -> usize {
+ self.0.serialized_length()
+ }
+}
+
+impl Readable for ShutdownScript {
+ fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
+ Ok(ShutdownScript(ShutdownScriptImpl::read(r)?))
+ }
+}
+
+impl_writeable_tlv_based_enum!(ShutdownScriptImpl, ;
+ (0, Legacy),
+ (1, Bolt2),
+);
+
impl ShutdownScript {
+ /// Generates a P2WPKH script pubkey from the given [`PublicKey`].
+ pub(crate) fn new_p2wpkh_from_pubkey(pubkey: PublicKey) -> Self {
+ Self(ShutdownScriptImpl::Legacy(pubkey))
+ }
+
/// Generates a P2PKH script pubkey from the given [`PubkeyHash`].
pub fn new_p2pkh(pubkey_hash: &PubkeyHash) -> Self {
Self(ShutdownScriptImpl::Bolt2(Script::new_p2pkh(pubkey_hash)))
/// # Panics
///
/// This function may panic if given a segwit program with an invalid length.
- pub fn new_witness_program(version: u5, program: &[u8]) -> Self {
+ pub fn new_witness_program(version: NonZeroU8, program: &[u8]) -> Self {
+ let version = u5::try_from_u8(version.get()).expect("Invalid segwit version");
let script = Script::new_witness_program(version, program);
Self::try_from(script).expect("Invalid segwit program")
}
pub fn into_inner(self) -> Script {
self.into()
}
-}
-impl From<PublicKey> for ShutdownScript {
- fn from(pubkey: PublicKey) -> Self {
- Self(ShutdownScriptImpl::Legacy(pubkey))
+ /// Returns the [`PublicKey`] used for a P2WPKH shutdown script if constructed directly from it.
+ pub fn as_legacy_pubkey(&self) -> Option<&PublicKey> {
+ match &self.0 {
+ ShutdownScriptImpl::Legacy(pubkey) => Some(pubkey),
+ ShutdownScriptImpl::Bolt2(_) => None,
+ }
}
}
let pubkey_hash = pubkey.wpubkey_hash().unwrap();
let p2wpkh_script = Script::new_v0_wpkh(&pubkey_hash);
- let shutdown_script = ShutdownScript::from(pubkey.key);
+ let shutdown_script = ShutdownScript::new_p2wpkh_from_pubkey(pubkey.key);
assert_eq!(shutdown_script.into_inner(), p2wpkh_script);
}