From fa112a793ac538c82230a4015f45f28ae736c43b Mon Sep 17 00:00:00 2001 From: sanket1729 Date: Mon, 15 Nov 2021 12:12:25 -0800 Subject: [PATCH 1/5] Add EcdsaSig --- src/util/ecdsa.rs | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/src/util/ecdsa.rs b/src/util/ecdsa.rs index 33e3685d..1724128a 100644 --- a/src/util/ecdsa.rs +++ b/src/util/ecdsa.rs @@ -29,6 +29,8 @@ use hashes::{Hash, hash160}; use hash_types::{PubkeyHash, WPubkeyHash}; use util::base58; use util::key::Error; +use blockdata::transaction::SigHashType; + /// A Bitcoin ECDSA public key #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -413,6 +415,72 @@ impl<'de> ::serde::Deserialize<'de> for PublicKey { } } +/// An ECDSA signature with the corresponding hash type. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct EcdsaSig { + /// The underlying ECDSA Signature + pub sig: secp256k1::Signature, + /// The corresponding hash type + pub hash_ty: SigHashType, +} + +impl EcdsaSig { + + /// Deserialize from slice + pub fn from_slice(sl: &[u8]) -> Result { + let (hash_ty, sig) = sl.split_last() + .ok_or(EcdsaSigError::EmptySignature)?; + let hash_ty = SigHashType::from_u32_standard(*hash_ty as u32) + .map_err(|_| EcdsaSigError::NonStandardSigHashType(*hash_ty))?; + let sig = secp256k1::Signature::from_der(sig) + .map_err(EcdsaSigError::Secp256k1)?; + Ok(EcdsaSig { sig, hash_ty }) + } + + /// Serialize EcdsaSig + pub fn to_vec(&self) -> Vec { + // TODO: add support to serialize to a writer to SerializedSig + let mut ser_sig = self.sig.serialize_der().to_vec(); + ser_sig.push(self.hash_ty.as_u32() as u8); + ser_sig + } +} + +/// A key-related error. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub enum EcdsaSigError { + /// Base58 encoding error + NonStandardSigHashType(u8), + /// Empty Signature + EmptySignature, + /// secp256k1-related error + Secp256k1(secp256k1::Error), +} + + +impl fmt::Display for EcdsaSigError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + EcdsaSigError::NonStandardSigHashType(hash_ty) => + write!(f, "Non standard signature hash type {}", hash_ty), + EcdsaSigError::Secp256k1(ref e) => + write!(f, "Invalid Ecdsa signature: {}", e), + EcdsaSigError::EmptySignature => + write!(f, "Empty ECDSA signature"), + } + } +} + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl ::std::error::Error for EcdsaSigError {} + +impl From for EcdsaSigError { + fn from(e: secp256k1::Error) -> EcdsaSigError { + EcdsaSigError::Secp256k1(e) + } +} + #[cfg(test)] mod tests { use io; From 410e8bf46c6b8ffdc96d0fa39d7f3232e3d3117a Mon Sep 17 00:00:00 2001 From: sanket1729 Date: Mon, 15 Nov 2021 12:38:24 -0800 Subject: [PATCH 2/5] Rename sighash::SigHashType::SigHashType to SchnorrSigHashType --- src/lib.rs | 1 + src/util/sighash.rs | 81 +++++++++++++++++++++++---------------------- 2 files changed, 42 insertions(+), 40 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 11bde770..f2f97f75 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -133,6 +133,7 @@ pub use util::amount::Amount; pub use util::amount::Denomination; pub use util::amount::SignedAmount; pub use util::merkleblock::MerkleBlock; +pub use util::sighash::SchnorrSigHashType; pub use util::ecdsa; pub use util::schnorr; diff --git a/src/util/sighash.rs b/src/util/sighash.rs index 77f6d4ee..ae874660 100644 --- a/src/util/sighash.rs +++ b/src/util/sighash.rs @@ -104,7 +104,7 @@ pub struct ScriptPath<'s> { /// Hashtype of an input's signature, encoded in the last byte of the signature /// Fixed values so they can be casted as integer types for encoding #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -pub enum SigHashType { +pub enum SchnorrSigHashType { /// 0x0: Used when not explicitly specified, defaulting to [`SigHashType::All`] Default = 0x00, /// 0x1: Sign all outputs @@ -229,31 +229,31 @@ impl<'s> ScriptPath<'s> { } } -impl From for SigHashType { +impl From for SchnorrSigHashType { fn from(s: LegacySigHashType) -> Self { match s { - LegacySigHashType::All => SigHashType::All, - LegacySigHashType::None => SigHashType::None, - LegacySigHashType::Single => SigHashType::Single, - LegacySigHashType::AllPlusAnyoneCanPay => SigHashType::AllPlusAnyoneCanPay, - LegacySigHashType::NonePlusAnyoneCanPay => SigHashType::NonePlusAnyoneCanPay, - LegacySigHashType::SinglePlusAnyoneCanPay => SigHashType::SinglePlusAnyoneCanPay, + LegacySigHashType::All => SchnorrSigHashType::All, + LegacySigHashType::None => SchnorrSigHashType::None, + LegacySigHashType::Single => SchnorrSigHashType::Single, + LegacySigHashType::AllPlusAnyoneCanPay => SchnorrSigHashType::AllPlusAnyoneCanPay, + LegacySigHashType::NonePlusAnyoneCanPay => SchnorrSigHashType::NonePlusAnyoneCanPay, + LegacySigHashType::SinglePlusAnyoneCanPay => SchnorrSigHashType::SinglePlusAnyoneCanPay, } } } -impl SigHashType { +impl SchnorrSigHashType { /// Break the sighash flag into the "real" sighash flag and the ANYONECANPAY boolean - pub(crate) fn split_anyonecanpay_flag(self) -> (SigHashType, bool) { + pub(crate) fn split_anyonecanpay_flag(self) -> (SchnorrSigHashType, bool) { match self { - SigHashType::Default => (SigHashType::Default, false), - SigHashType::All => (SigHashType::All, false), - SigHashType::None => (SigHashType::None, false), - SigHashType::Single => (SigHashType::Single, false), - SigHashType::AllPlusAnyoneCanPay => (SigHashType::All, true), - SigHashType::NonePlusAnyoneCanPay => (SigHashType::None, true), - SigHashType::SinglePlusAnyoneCanPay => (SigHashType::Single, true), - SigHashType::Reserved => (SigHashType::Reserved, false), + SchnorrSigHashType::Default => (SchnorrSigHashType::Default, false), + SchnorrSigHashType::All => (SchnorrSigHashType::All, false), + SchnorrSigHashType::None => (SchnorrSigHashType::None, false), + SchnorrSigHashType::Single => (SchnorrSigHashType::Single, false), + SchnorrSigHashType::AllPlusAnyoneCanPay => (SchnorrSigHashType::All, true), + SchnorrSigHashType::NonePlusAnyoneCanPay => (SchnorrSigHashType::None, true), + SchnorrSigHashType::SinglePlusAnyoneCanPay => (SchnorrSigHashType::Single, true), + SchnorrSigHashType::Reserved => (SchnorrSigHashType::Reserved, false), } } } @@ -281,7 +281,7 @@ impl> SigHashCache { prevouts: &Prevouts, annex: Option, script_path: Option, - sighash_type: SigHashType, + sighash_type: SchnorrSigHashType, ) -> Result<(), Error> { prevouts.check_all(&self.tx)?; @@ -321,7 +321,7 @@ impl> SigHashCache { // If hash_type & 3 does not equal SIGHASH_NONE or SIGHASH_SINGLE: // sha_outputs (32): the SHA256 of the serialization of all outputs in CTxOut format. - if sighash != SigHashType::None && sighash != SigHashType::Single { + if sighash != SchnorrSigHashType::None && sighash != SchnorrSigHashType::Single { self.common_cache().outputs.consensus_encode(&mut writer)?; } @@ -376,7 +376,7 @@ impl> SigHashCache { // * Data about this output: // If hash_type & 3 equals SIGHASH_SINGLE: // sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. - if sighash == SigHashType::Single { + if sighash == SchnorrSigHashType::Single { let mut enc = sha256::Hash::engine(); self.tx .output @@ -420,7 +420,7 @@ impl> SigHashCache { prevouts: &Prevouts, annex: Option, script_path: Option, - sighash_type: SigHashType, + sighash_type: SchnorrSigHashType, ) -> Result { let mut enc = TapSighashHash::engine(); self.taproot_encode_signing_data_to( @@ -681,10 +681,11 @@ impl<'a> Encodable for Annex<'a> { #[cfg(test)] mod tests { + use super::*; use consensus::deserialize; use hashes::hex::FromHex; use hashes::{Hash, HashEngine}; - use util::sighash::{Annex, Error, Prevouts, ScriptPath, SigHashCache, SigHashType}; + use util::sighash::{Annex, Error, Prevouts, ScriptPath, SigHashCache}; use util::taproot::TapSighashHash; use {Script, Transaction, TxIn, TxOut}; @@ -709,7 +710,7 @@ mod tests { "01365724000000000023542156b39dab4f8f3508e0432cfb41fab110170acaa2d4c42539cb90a4dc7c093bc500", 0, "33ca0ebfb4a945eeee9569fc0f5040221275f88690b7f8592ada88ce3bdf6703", - SigHashType::Default, None,None, + SchnorrSigHashType::Default, None,None, ); test_taproot_sighash( @@ -717,7 +718,7 @@ mod tests { "02591f220000000000225120f25ad35583ea31998d968871d7de1abd2a52f6fe4178b54ea158274806ff4ece48fb310000000000225120f25ad35583ea31998d968871d7de1abd2a52f6fe4178b54ea158274806ff4ece", 1, "626ab955d58c9a8a600a0c580549d06dc7da4e802eb2a531f62a588e430967a8", - SigHashType::All, None,None, + SchnorrSigHashType::All, None,None, ); test_taproot_sighash( @@ -725,7 +726,7 @@ mod tests { "01c4811000000000002251201bf9297d0a2968ae6693aadd0fa514717afefd218087a239afb7418e2d22e65c", 0, "dfa9437f9c9a1d1f9af271f79f2f5482f287cdb0d2e03fa92c8a9b216cc6061c", - SigHashType::AllPlusAnyoneCanPay, None,None, + SchnorrSigHashType::AllPlusAnyoneCanPay, None,None, ); test_taproot_sighash( @@ -733,7 +734,7 @@ mod tests { "0144c84d0000000000225120e3f2107989c88e67296ab2faca930efa2e3a5bd3ff0904835a11c9e807458621", 0, "3129de36a5d05fff97ffca31eb75fcccbbbc27b3147a7a36a9e4b45d8b625067", - SigHashType::None, None,None, + SchnorrSigHashType::None, None,None, ); test_taproot_sighash( @@ -741,7 +742,7 @@ mod tests { "013fed110000000000225120eb536ae8c33580290630fc495046e998086a64f8f33b93b07967d9029b265c55", 0, "2441e8b0e063a2083ee790f14f2045022f07258ddde5ee01de543c9e789d80ae", - SigHashType::NonePlusAnyoneCanPay, None,None, + SchnorrSigHashType::NonePlusAnyoneCanPay, None,None, ); test_taproot_sighash( @@ -749,7 +750,7 @@ mod tests { "01efa558000000000022512007071ea3dc7e331b0687d0193d1e6d6ed10e645ef36f10ef8831d5e522ac9e80", 0, "30239345177cadd0e3ea413d49803580abb6cb27971b481b7788a78d35117a88", - SigHashType::Single, None,None, + SchnorrSigHashType::Single, None,None, ); test_taproot_sighash( @@ -757,7 +758,7 @@ mod tests { "0107af4e00000000002251202c36d243dfc06cb56a248e62df27ecba7417307511a81ae61aa41c597a929c69", 0, "bf9c83f26c6dd16449e4921f813f551c4218e86f2ec906ca8611175b41b566df", - SigHashType::SinglePlusAnyoneCanPay, None,None, + SchnorrSigHashType::SinglePlusAnyoneCanPay, None,None, ); } @@ -768,7 +769,7 @@ mod tests { "01ea49260000000000225120ab5e9800806bf18cb246edcf5fe63441208fe955a4b5a35bbff65f5db622a010", 0, "3b003000add359a364a156e73e02846782a59d0d95ca8c4638aaad99f2ef915c", - SigHashType::SinglePlusAnyoneCanPay, + SchnorrSigHashType::SinglePlusAnyoneCanPay, Some("507b979802e62d397acb29f56743a791894b99372872fc5af06a4f6e8d242d0615cda53062bb20e6ec79756fe39183f0c128adfe85559a8fa042b042c018aa8010143799e44f0893c40e1e"), None, ); @@ -781,7 +782,7 @@ mod tests { "011bec34000000000022512028055142ea437db73382e991861446040b61dd2185c4891d7daf6893d79f7182", 0, "d66de5274a60400c7b08c86ba6b7f198f40660079edf53aca89d2a9501317f2e", - SigHashType::All, + SchnorrSigHashType::All, None, Some("20cc4e1107aea1d170c5ff5b6817e1303010049724fb3caa7941792ea9d29b3e2bacab"), ); @@ -794,7 +795,7 @@ mod tests { "011458360000000000225120a7baec3fb9f84614e3899fcc010c638f80f13539344120e1f4d8b68a9a011a13", 0, "a0042aa434f9a75904b64043f2a283f8b4c143c7f4f7f49a6cbe5b9f745f4c15", - SigHashType::All, + SchnorrSigHashType::All, Some("50a6272b470e1460e3332ade7bb14b81671c564fb6245761bd5bd531394b28860e0b3808ab229fb51791fb6ae6fa82d915b2efb8f6df83ae1f5ab3db13e30928875e2a22b749d89358de481f19286cd4caa792ce27f9559082d227a731c5486882cc707f83da361c51b7aadd9a0cf68fe7480c410fa137b454482d9a1ebf0f96d760b4d61426fc109c6e8e99a508372c45caa7b000a41f8251305da3f206c1849985ba03f3d9592832b4053afbd23ab25d0465df0bc25a36c223aacf8e04ec736a418c72dc319e4da3e972e349713ca600965e7c665f2090d5a70e241ac164115a1f5639f28b1773327715ca307ace64a2de7f0e3df70a2ffee3857689f909c0dad46d8a20fa373a4cc6eed6d4c9806bf146f0d76baae1"), Some("7520ab9160dd8299dc1367659be3e8f66781fe440d52940c7f8d314a89b9f2698d406ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac"), ); @@ -811,27 +812,27 @@ mod tests { let mut c = SigHashCache::new(&dumb_tx); assert_eq!( - c.taproot_signature_hash(0, &Prevouts::All(&vec![]), None, None, SigHashType::All), + c.taproot_signature_hash(0, &Prevouts::All(&vec![]), None, None, SchnorrSigHashType::All), Err(Error::PrevoutsSize) ); let two = vec![TxOut::default(), TxOut::default()]; let too_many_prevouts = Prevouts::All(&two); assert_eq!( - c.taproot_signature_hash(0, &too_many_prevouts, None, None, SigHashType::All), + c.taproot_signature_hash(0, &too_many_prevouts, None, None, SchnorrSigHashType::All), Err(Error::PrevoutsSize) ); let tx_out = TxOut::default(); let prevout = Prevouts::One(1, &tx_out); assert_eq!( - c.taproot_signature_hash(0, &prevout, None, None, SigHashType::All), + c.taproot_signature_hash(0, &prevout, None, None, SchnorrSigHashType::All), Err(Error::PrevoutKind) ); assert_eq!( - c.taproot_signature_hash(0, &prevout, None, None, SigHashType::AllPlusAnyoneCanPay), + c.taproot_signature_hash(0, &prevout, None, None, SchnorrSigHashType::AllPlusAnyoneCanPay), Err(Error::PrevoutIndex) ); assert_eq!( - c.taproot_signature_hash(10, &prevout, None, None, SigHashType::AllPlusAnyoneCanPay), + c.taproot_signature_hash(10, &prevout, None, None, SchnorrSigHashType::AllPlusAnyoneCanPay), Err(Error::IndexOutOfInputsBounds { index: 10, inputs_size: 1 @@ -839,7 +840,7 @@ mod tests { ); let prevout = Prevouts::One(0, &tx_out); assert_eq!( - c.taproot_signature_hash(0, &prevout, None, None, SigHashType::SinglePlusAnyoneCanPay), + c.taproot_signature_hash(0, &prevout, None, None, SchnorrSigHashType::SinglePlusAnyoneCanPay), Err(Error::SingleWithoutCorrespondingOutput { index: 0, outputs_size: 0 @@ -866,7 +867,7 @@ mod tests { prevout_hex: &str, input_index: usize, expected_hash: &str, - sighash_type: SigHashType, + sighash_type: SchnorrSigHashType, annex_hex: Option<&str>, script_hex: Option<&str>, ) { From 648b3975a534bd55567efab7db0ac0419af4eecc Mon Sep 17 00:00:00 2001 From: sanket1729 Date: Wed, 27 Oct 2021 06:04:23 -0700 Subject: [PATCH 3/5] Add SchnorrSigHashType::from_u8 --- src/util/sighash.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/util/sighash.rs b/src/util/sighash.rs index ae874660..4d4047c8 100644 --- a/src/util/sighash.rs +++ b/src/util/sighash.rs @@ -164,6 +164,9 @@ pub enum Error { /// Annex must be at least one byte long and the first bytes must be `0x50` WrongAnnex, + + /// Invalid Sighash type + InvalidSigHashType(u8), } impl fmt::Display for Error { @@ -176,6 +179,7 @@ impl fmt::Display for Error { Error::PrevoutIndex => write!(f, "The index requested is greater than available prevouts or different from the provided [Provided::Anyone] index"), Error::PrevoutKind => write!(f, "A single prevout has been provided but all prevouts are needed without `ANYONECANPAY`"), Error::WrongAnnex => write!(f, "Annex must be at least one byte long and the first bytes must be `0x50`"), + Error::InvalidSigHashType(hash_ty) => write!(f, "Invalid schnorr Signature hash type : {} ", hash_ty), } } } @@ -256,6 +260,20 @@ impl SchnorrSigHashType { SchnorrSigHashType::Reserved => (SchnorrSigHashType::Reserved, false), } } + + /// Create a [`SchnorrSigHashType`] from raw u8 + pub fn from_u8(hash_ty: u8) -> Result { + match hash_ty { + 0x00 => Ok(SchnorrSigHashType::Default), + 0x01 => Ok(SchnorrSigHashType::All), + 0x02 => Ok(SchnorrSigHashType::None), + 0x03 => Ok(SchnorrSigHashType::Single), + 0x81 => Ok(SchnorrSigHashType::AllPlusAnyoneCanPay), + 0x82 => Ok(SchnorrSigHashType::NonePlusAnyoneCanPay), + 0x83 => Ok(SchnorrSigHashType::SinglePlusAnyoneCanPay), + x => Err(Error::InvalidSigHashType(x)), + } + } } impl> SigHashCache { From 94cfe791700ab373f337ebc8bf6176f5b8dc20e6 Mon Sep 17 00:00:00 2001 From: sanket1729 Date: Mon, 15 Nov 2021 12:55:24 -0800 Subject: [PATCH 4/5] Rename existing SigHashType to EcdsaSigHashType --- src/blockdata/transaction.rs | 127 ++++++++++++++++++----------------- src/lib.rs | 2 +- src/util/bip143.rs | 12 ++-- src/util/ecdsa.rs | 6 +- src/util/psbt/map/input.rs | 6 +- src/util/psbt/mod.rs | 4 +- src/util/psbt/serialize.rs | 8 +-- src/util/sighash.rs | 38 +++++------ 8 files changed, 104 insertions(+), 99 deletions(-) diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index f1952022..045e0aba 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -333,10 +333,10 @@ impl Transaction { let sighash_type : u32 = sighash_type.into(); assert!(input_index < self.input.len()); // Panic on OOB - let (sighash, anyone_can_pay) = SigHashType::from_u32_consensus(sighash_type).split_anyonecanpay_flag(); + let (sighash, anyone_can_pay) = EcdsaSigHashType::from_u32_consensus(sighash_type).split_anyonecanpay_flag(); // Special-case sighash_single bug because this is easy enough. - if sighash == SigHashType::Single && input_index >= self.output.len() { + if sighash == EcdsaSigHashType::Single && input_index >= self.output.len() { writer.write_all(&[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -365,22 +365,22 @@ impl Transaction { tx.input.push(TxIn { previous_output: input.previous_output, script_sig: if n == input_index { script_pubkey.clone() } else { Script::new() }, - sequence: if n != input_index && (sighash == SigHashType::Single || sighash == SigHashType::None) { 0 } else { input.sequence }, + sequence: if n != input_index && (sighash == EcdsaSigHashType::Single || sighash == EcdsaSigHashType::None) { 0 } else { input.sequence }, witness: vec![], }); } } // ..then all outputs tx.output = match sighash { - SigHashType::All => self.output.clone(), - SigHashType::Single => { + EcdsaSigHashType::All => self.output.clone(), + EcdsaSigHashType::Single => { let output_iter = self.output.iter() .take(input_index + 1) // sign all outputs up to and including this one, but erase .enumerate() // all of them except for this one .map(|(n, out)| if n == input_index { out.clone() } else { TxOut::default() }); output_iter.collect() } - SigHashType::None => vec![], + EcdsaSigHashType::None => vec![], _ => unreachable!() }; // hash the result @@ -673,10 +673,15 @@ impl fmt::Display for NonStandardSigHashType { #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl error::Error for NonStandardSigHashType {} +/// Legacy Hashtype of an input's signature +#[deprecated(since="0.28.0", note="Please use [`EcdsaSigHashType`] instead")] +pub type SigHashType = EcdsaSigHashType; + /// Hashtype of an input's signature, encoded in the last byte of the signature /// Fixed values so they can be casted as integer types for encoding +/// See also [`crate::SchnorrSigHashType`] #[derive(PartialEq, Eq, Debug, Copy, Clone)] -pub enum SigHashType { +pub enum EcdsaSigHashType { /// 0x1: Sign all outputs All = 0x01, /// 0x2: Sign no outputs --- anyone can choose the destination @@ -693,54 +698,54 @@ pub enum SigHashType { /// 0x83: Sign one output and only this input (see `Single` for what "one output" means) SinglePlusAnyoneCanPay = 0x83 } -serde_string_impl!(SigHashType, "a SigHashType data"); +serde_string_impl!(EcdsaSigHashType, "a EcdsaSigHashType data"); -impl fmt::Display for SigHashType { +impl fmt::Display for EcdsaSigHashType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let s = match self { - SigHashType::All => "SIGHASH_ALL", - SigHashType::None => "SIGHASH_NONE", - SigHashType::Single => "SIGHASH_SINGLE", - SigHashType::AllPlusAnyoneCanPay => "SIGHASH_ALL|SIGHASH_ANYONECANPAY", - SigHashType::NonePlusAnyoneCanPay => "SIGHASH_NONE|SIGHASH_ANYONECANPAY", - SigHashType::SinglePlusAnyoneCanPay => "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", + EcdsaSigHashType::All => "SIGHASH_ALL", + EcdsaSigHashType::None => "SIGHASH_NONE", + EcdsaSigHashType::Single => "SIGHASH_SINGLE", + EcdsaSigHashType::AllPlusAnyoneCanPay => "SIGHASH_ALL|SIGHASH_ANYONECANPAY", + EcdsaSigHashType::NonePlusAnyoneCanPay => "SIGHASH_NONE|SIGHASH_ANYONECANPAY", + EcdsaSigHashType::SinglePlusAnyoneCanPay => "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", }; f.write_str(s) } } -impl str::FromStr for SigHashType { +impl str::FromStr for EcdsaSigHashType { type Err = String; fn from_str(s: &str) -> Result { match s.as_ref() { - "SIGHASH_ALL" => Ok(SigHashType::All), - "SIGHASH_NONE" => Ok(SigHashType::None), - "SIGHASH_SINGLE" => Ok(SigHashType::Single), - "SIGHASH_ALL|SIGHASH_ANYONECANPAY" => Ok(SigHashType::AllPlusAnyoneCanPay), - "SIGHASH_NONE|SIGHASH_ANYONECANPAY" => Ok(SigHashType::NonePlusAnyoneCanPay), - "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY" => Ok(SigHashType::SinglePlusAnyoneCanPay), + "SIGHASH_ALL" => Ok(EcdsaSigHashType::All), + "SIGHASH_NONE" => Ok(EcdsaSigHashType::None), + "SIGHASH_SINGLE" => Ok(EcdsaSigHashType::Single), + "SIGHASH_ALL|SIGHASH_ANYONECANPAY" => Ok(EcdsaSigHashType::AllPlusAnyoneCanPay), + "SIGHASH_NONE|SIGHASH_ANYONECANPAY" => Ok(EcdsaSigHashType::NonePlusAnyoneCanPay), + "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY" => Ok(EcdsaSigHashType::SinglePlusAnyoneCanPay), _ => Err("can't recognize SIGHASH string".to_string()) } } } -impl SigHashType { +impl EcdsaSigHashType { /// Break the sighash flag into the "real" sighash flag and the ANYONECANPAY boolean - pub(crate) fn split_anyonecanpay_flag(self) -> (SigHashType, bool) { + pub(crate) fn split_anyonecanpay_flag(self) -> (EcdsaSigHashType, bool) { match self { - SigHashType::All => (SigHashType::All, false), - SigHashType::None => (SigHashType::None, false), - SigHashType::Single => (SigHashType::Single, false), - SigHashType::AllPlusAnyoneCanPay => (SigHashType::All, true), - SigHashType::NonePlusAnyoneCanPay => (SigHashType::None, true), - SigHashType::SinglePlusAnyoneCanPay => (SigHashType::Single, true) + EcdsaSigHashType::All => (EcdsaSigHashType::All, false), + EcdsaSigHashType::None => (EcdsaSigHashType::None, false), + EcdsaSigHashType::Single => (EcdsaSigHashType::Single, false), + EcdsaSigHashType::AllPlusAnyoneCanPay => (EcdsaSigHashType::All, true), + EcdsaSigHashType::NonePlusAnyoneCanPay => (EcdsaSigHashType::None, true), + EcdsaSigHashType::SinglePlusAnyoneCanPay => (EcdsaSigHashType::Single, true) } } /// Reads a 4-byte uint32 as a sighash type. #[deprecated(since="0.26.1", note="please use `from_u32_consensus` or `from_u32_standard` instead")] - pub fn from_u32(n: u32) -> SigHashType { + pub fn from_u32(n: u32) -> EcdsaSigHashType { Self::from_u32_consensus(n) } @@ -748,7 +753,7 @@ impl SigHashType { /// /// **Note**: this replicates consensus behaviour, for current standardness rules correctness /// you probably want [Self::from_u32_standard]. - pub fn from_u32_consensus(n: u32) -> SigHashType { + pub fn from_u32_consensus(n: u32) -> EcdsaSigHashType { // In Bitcoin Core, the SignatureHash function will mask the (int32) value with // 0x1f to (apparently) deactivate ACP when checking for SINGLE and NONE bits. // We however want to be matching also against on ACP-masked ALL, SINGLE, and NONE. @@ -756,29 +761,29 @@ impl SigHashType { let mask = 0x1f | 0x80; match n & mask { // "real" sighashes - 0x01 => SigHashType::All, - 0x02 => SigHashType::None, - 0x03 => SigHashType::Single, - 0x81 => SigHashType::AllPlusAnyoneCanPay, - 0x82 => SigHashType::NonePlusAnyoneCanPay, - 0x83 => SigHashType::SinglePlusAnyoneCanPay, + 0x01 => EcdsaSigHashType::All, + 0x02 => EcdsaSigHashType::None, + 0x03 => EcdsaSigHashType::Single, + 0x81 => EcdsaSigHashType::AllPlusAnyoneCanPay, + 0x82 => EcdsaSigHashType::NonePlusAnyoneCanPay, + 0x83 => EcdsaSigHashType::SinglePlusAnyoneCanPay, // catchalls - x if x & 0x80 == 0x80 => SigHashType::AllPlusAnyoneCanPay, - _ => SigHashType::All + x if x & 0x80 == 0x80 => EcdsaSigHashType::AllPlusAnyoneCanPay, + _ => EcdsaSigHashType::All } } /// Read a 4-byte uint32 as a standard sighash type, returning an error if the type /// is non standard. - pub fn from_u32_standard(n: u32) -> Result { + pub fn from_u32_standard(n: u32) -> Result { match n { // Standard sighashes, see https://github.com/bitcoin/bitcoin/blob/b805dbb0b9c90dadef0424e5b3bf86ac308e103e/src/script/interpreter.cpp#L189-L198 - 0x01 => Ok(SigHashType::All), - 0x02 => Ok(SigHashType::None), - 0x03 => Ok(SigHashType::Single), - 0x81 => Ok(SigHashType::AllPlusAnyoneCanPay), - 0x82 => Ok(SigHashType::NonePlusAnyoneCanPay), - 0x83 => Ok(SigHashType::SinglePlusAnyoneCanPay), + 0x01 => Ok(EcdsaSigHashType::All), + 0x02 => Ok(EcdsaSigHashType::None), + 0x03 => Ok(EcdsaSigHashType::Single), + 0x81 => Ok(EcdsaSigHashType::AllPlusAnyoneCanPay), + 0x82 => Ok(EcdsaSigHashType::NonePlusAnyoneCanPay), + 0x83 => Ok(EcdsaSigHashType::SinglePlusAnyoneCanPay), _ => Err(NonStandardSigHashType) } } @@ -787,8 +792,8 @@ impl SigHashType { pub fn as_u32(self) -> u32 { self as u32 } } -impl From for u32 { - fn from(t: SigHashType) -> u32 { +impl From for u32 { + fn from(t: EcdsaSigHashType) -> u32 { t.as_u32() } } @@ -807,7 +812,7 @@ mod tests { use hashes::hex::FromHex; use hash_types::*; - use SigHashType; + use super::EcdsaSigHashType; use util::sighash::SigHashCache; #[test] @@ -1088,15 +1093,15 @@ mod tests { #[test] fn test_sighashtype_fromstr_display() { - let sighashtypes = vec![("SIGHASH_ALL", SigHashType::All), - ("SIGHASH_NONE", SigHashType::None), - ("SIGHASH_SINGLE", SigHashType::Single), - ("SIGHASH_ALL|SIGHASH_ANYONECANPAY", SigHashType::AllPlusAnyoneCanPay), - ("SIGHASH_NONE|SIGHASH_ANYONECANPAY", SigHashType::NonePlusAnyoneCanPay), - ("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", SigHashType::SinglePlusAnyoneCanPay)]; + let sighashtypes = vec![("SIGHASH_ALL", EcdsaSigHashType::All), + ("SIGHASH_NONE", EcdsaSigHashType::None), + ("SIGHASH_SINGLE", EcdsaSigHashType::Single), + ("SIGHASH_ALL|SIGHASH_ANYONECANPAY", EcdsaSigHashType::AllPlusAnyoneCanPay), + ("SIGHASH_NONE|SIGHASH_ANYONECANPAY", EcdsaSigHashType::NonePlusAnyoneCanPay), + ("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", EcdsaSigHashType::SinglePlusAnyoneCanPay)]; for (s, sht) in sighashtypes { assert_eq!(sht.to_string(), s); - assert_eq!(SigHashType::from_str(s).unwrap(), sht); + assert_eq!(EcdsaSigHashType::from_str(s).unwrap(), sht); } let sht_mistakes = vec![ "SIGHASH_ALL | SIGHASH_ANYONECANPAY", @@ -1111,7 +1116,7 @@ mod tests { "SigHash_NONE", ]; for s in sht_mistakes { - assert_eq!(SigHashType::from_str(s).unwrap_err(), "can't recognize SIGHASH string"); + assert_eq!(EcdsaSigHashType::from_str(s).unwrap_err(), "can't recognize SIGHASH string"); } } @@ -1120,10 +1125,10 @@ mod tests { fn test_sighashtype_standard() { let nonstandard_hashtype = 0x04; // This type is not well defined, by consensus it becomes ALL - assert_eq!(SigHashType::from_u32(nonstandard_hashtype), SigHashType::All); - assert_eq!(SigHashType::from_u32_consensus(nonstandard_hashtype), SigHashType::All); + assert_eq!(EcdsaSigHashType::from_u32(nonstandard_hashtype), EcdsaSigHashType::All); + assert_eq!(EcdsaSigHashType::from_u32_consensus(nonstandard_hashtype), EcdsaSigHashType::All); // But it's policy-invalid to use it! - assert_eq!(SigHashType::from_u32_standard(nonstandard_hashtype), Err(NonStandardSigHashType)); + assert_eq!(EcdsaSigHashType::from_u32_standard(nonstandard_hashtype), Err(NonStandardSigHashType)); } // These test vectors were stolen from libbtc, which is Copyright 2014 Jonas Schnelli MIT diff --git a/src/lib.rs b/src/lib.rs index f2f97f75..aad5e612 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -123,7 +123,7 @@ pub use blockdata::transaction::Transaction; pub use blockdata::transaction::TxIn; pub use blockdata::transaction::TxOut; pub use blockdata::transaction::OutPoint; -pub use blockdata::transaction::SigHashType; +pub use blockdata::transaction::EcdsaSigHashType; pub use consensus::encode::VarInt; pub use network::constants::Network; pub use util::Error; diff --git a/src/util/bip143.rs b/src/util/bip143.rs index 979174fb..a00da490 100644 --- a/src/util/bip143.rs +++ b/src/util/bip143.rs @@ -22,7 +22,7 @@ use hashes::Hash; use hash_types::SigHash; use blockdata::script::Script; -use blockdata::transaction::{Transaction, TxIn, SigHashType}; +use blockdata::transaction::{Transaction, TxIn, EcdsaSigHashType}; use consensus::{encode, Encodable}; use prelude::*; @@ -131,7 +131,7 @@ impl> SigHashCache { input_index: usize, script_code: &Script, value: u64, - sighash_type: SigHashType, + sighash_type: EcdsaSigHashType, ) -> Result<(), encode::Error> { self.cache .segwit_encode_signing_data_to(writer, input_index, script_code, value, sighash_type.into()) @@ -146,7 +146,7 @@ impl> SigHashCache { input_index: usize, script_code: &Script, value: u64, - sighash_type: SigHashType + sighash_type: EcdsaSigHashType ) -> SigHash { let mut enc = SigHash::engine(); self.encode_signing_data_to(&mut enc, input_index, script_code, value, sighash_type) @@ -165,7 +165,7 @@ impl> SigHashCache { /// panics if `input_index` is out of bounds with respect of the number of inputs /// /// ``` - /// use bitcoin::blockdata::transaction::{Transaction, SigHashType}; + /// use bitcoin::blockdata::transaction::{Transaction, EcdsaSigHashType}; /// use bitcoin::util::bip143::SigHashCache; /// use bitcoin::Script; /// @@ -175,7 +175,7 @@ impl> SigHashCache { /// let mut sig_hasher = SigHashCache::new(&mut tx_to_sign); /// for inp in 0..input_count { /// let prevout_script = Script::new(); - /// let _sighash = sig_hasher.signature_hash(inp, &prevout_script, 42, SigHashType::All); + /// let _sighash = sig_hasher.signature_hash(inp, &prevout_script, 42, EcdsaSigHashType::All); /// // ... sign the sighash /// sig_hasher.access_witness(inp).push(Vec::new()); /// } @@ -212,7 +212,7 @@ mod tests { let raw_expected = SigHash::from_hex(expected_result).unwrap(); let expected_result = SigHash::from_slice(&raw_expected[..]).unwrap(); let mut cache = SigHashCache::new(&tx); - let sighash_type = SigHashType::from_u32_consensus(hash_type); + let sighash_type = EcdsaSigHashType::from_u32_consensus(hash_type); let actual_result = cache.signature_hash(input_index, &script, value, sighash_type); assert_eq!(actual_result, expected_result); } diff --git a/src/util/ecdsa.rs b/src/util/ecdsa.rs index 1724128a..f1333225 100644 --- a/src/util/ecdsa.rs +++ b/src/util/ecdsa.rs @@ -29,7 +29,7 @@ use hashes::{Hash, hash160}; use hash_types::{PubkeyHash, WPubkeyHash}; use util::base58; use util::key::Error; -use blockdata::transaction::SigHashType; +use blockdata::transaction::EcdsaSigHashType; /// A Bitcoin ECDSA public key @@ -421,7 +421,7 @@ pub struct EcdsaSig { /// The underlying ECDSA Signature pub sig: secp256k1::Signature, /// The corresponding hash type - pub hash_ty: SigHashType, + pub hash_ty: EcdsaSigHashType, } impl EcdsaSig { @@ -430,7 +430,7 @@ impl EcdsaSig { pub fn from_slice(sl: &[u8]) -> Result { let (hash_ty, sig) = sl.split_last() .ok_or(EcdsaSigError::EmptySignature)?; - let hash_ty = SigHashType::from_u32_standard(*hash_ty as u32) + let hash_ty = EcdsaSigHashType::from_u32_standard(*hash_ty as u32) .map_err(|_| EcdsaSigError::NonStandardSigHashType(*hash_ty))?; let sig = secp256k1::Signature::from_der(sig) .map_err(EcdsaSigError::Secp256k1)?; diff --git a/src/util/psbt/map/input.rs b/src/util/psbt/map/input.rs index 04b0c6e4..2eca6d0c 100644 --- a/src/util/psbt/map/input.rs +++ b/src/util/psbt/map/input.rs @@ -17,7 +17,7 @@ use prelude::*; use io; use blockdata::script::Script; -use blockdata::transaction::{SigHashType, Transaction, TxOut}; +use blockdata::transaction::{EcdsaSigHashType, Transaction, TxOut}; use consensus::encode; use util::bip32::KeySource; use hashes::{self, hash160, ripemd160, sha256, sha256d}; @@ -76,7 +76,7 @@ pub struct Input { pub partial_sigs: BTreeMap>, /// The sighash type to be used for this input. Signatures for this input /// must use the sighash type. - pub sighash_type: Option, + pub sighash_type: Option, /// The redeem script for this input. pub redeem_script: Option