X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fscript.rs;h=a9f44bae1aec79199230d467f426b50934c225dd;hb=6b8ad4ec33eb4f90395aac21c56c804b0b6c9429;hp=b6fcdbd19045c0586eb65f5686092319592c6888;hpb=ecc70757f9863a76ab9d4cc8b6bfe1a9cc9f4977;p=rust-lightning diff --git a/lightning/src/ln/script.rs b/lightning/src/ln/script.rs index b6fcdbd1..a9f44bae 100644 --- a/lightning/src/ln/script.rs +++ b/lightning/src/ln/script.rs @@ -3,21 +3,25 @@ use bitcoin::blockdata::opcodes::all::OP_PUSHBYTES_0 as SEGWIT_V0; use bitcoin::blockdata::script::{Builder, Script}; use bitcoin::hashes::Hash; -use bitcoin::hash_types::{PubkeyHash, ScriptHash, WPubkeyHash, WScriptHash}; +use bitcoin::hash_types::{WPubkeyHash, WScriptHash}; use bitcoin::secp256k1::key::PublicKey; use ln::features::InitFeatures; +use ln::msgs::DecodeError; +use util::ser::{Readable, Writeable, Writer}; use core::convert::TryFrom; use core::num::NonZeroU8; +use io; /// 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, PartialEq)] pub struct ShutdownScript(ShutdownScriptImpl); /// An error occurring when converting from [`Script`] to [`ShutdownScript`]. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct InvalidShutdownScript { /// The script that did not meet the requirements from [BOLT #2]. /// @@ -25,6 +29,7 @@ pub struct InvalidShutdownScript { pub script: Script } +#[derive(Clone, PartialEq)] enum ShutdownScriptImpl { /// [`PublicKey`] used to form a P2WPKH script pubkey. Used to support backward-compatible /// serialization. @@ -34,20 +39,31 @@ enum ShutdownScriptImpl { Bolt2(Script), } -impl ShutdownScript { - /// Generates a P2WPKH script pubkey from the given [`PublicKey`]. - pub fn new_p2wpkh_from_pubkey(pubkey: PublicKey) -> Self { - Self(ShutdownScriptImpl::Legacy(pubkey)) +impl Writeable for ShutdownScript { + fn write(&self, w: &mut W) -> Result<(), io::Error> { + self.0.write(w) } - /// 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))) + fn serialized_length(&self) -> usize { + self.0.serialized_length() } +} - /// Generates a P2SH script pubkey from the given [`ScriptHash`]. - pub fn new_p2sh(script_hash: &ScriptHash) -> Self { - Self(ShutdownScriptImpl::Bolt2(Script::new_p2sh(script_hash))) +impl Readable for ShutdownScript { + fn read(r: &mut R) -> Result { + 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 P2WPKH script pubkey from the given [`WPubkeyHash`]. @@ -60,7 +76,10 @@ impl ShutdownScript { Self(ShutdownScriptImpl::Bolt2(Script::new_v0_wsh(script_hash))) } - /// Generates a P2WSH script pubkey from the given segwit version and program. + /// Generates a witness script pubkey from the given segwit version and program. + /// + /// Note for version-zero witness scripts you must use [`ShutdownScript::new_p2wpkh`] or + /// [`ShutdownScript::new_p2wsh`] instead. /// /// # Errors /// @@ -97,7 +116,9 @@ impl ShutdownScript { } } -fn is_bolt2_compliant(script: &Script, features: &InitFeatures) -> bool { +/// Check if a given script is compliant with BOLT 2's shutdown script requirements for the given +/// counterparty features. +pub(crate) fn is_bolt2_compliant(script: &Script, features: &InitFeatures) -> bool { if script.is_p2pkh() || script.is_p2sh() || script.is_v0_p2wpkh() || script.is_v0_p2wsh() { true } else if features.supports_shutdown_anysegwit() { @@ -107,6 +128,8 @@ fn is_bolt2_compliant(script: &Script, features: &InitFeatures) -> bool { } } +// Note that this is only for our own shutdown scripts. Counterparties are still allowed to send us +// non-witness shutdown scripts which this rejects. impl TryFrom