Merge rust-bitcoin/rust-bitcoin#917: Rename SigHash to Sighash

46c34b3fb7 Fix code comments referring to sighash (Tobin Harding)
8f36c3979c Use sighash not sig_hash in identifiers (Tobin Harding)
c3a167b96b Rename SigHash -> Sighash (Tobin Harding)
52b711c084 Rename InvalidSigHashType -> InvalidSighashType (Tobin Harding)
b84f25584e Rename SigHashCache -> SighashCache (Tobin Harding)
e37652578b Rename PsbtSigHashType -> PsbtSighashType (Tobin Harding)
c19ec339ef Rename NonStandardSigHashType -> NonStandardSighashType (Tobin Harding)
130e27349e Rename SigHashTypeParseError -> SighashTypeParseError (Tobin Harding)
6caba2ed24 Rename SchnorrSigHashType -> SchnorrSighashType (Tobin Harding)
5522454583 Rename EcdsaSigHashType -> EcdsaSighashType (Tobin Harding)

Pull request description:

  Our usage of `SigHash` implies that 'sighash' is _two_ words; 'sighash' is a well known word in the Bitcoin ecosystem it should appear in identifiers as `Sighash`.

  Change various types, variants, and code comments to use sighash as a single word.

  - Patches 1-8 are code changes `s/SigHash/Sighash/g`
  - Patch 9 is code changes `s/sig_hash/sighash/g`
  - Patch 11 is docs fixes

  Fixes: #911

  ## Note to reviewers

  I've been particularly pedantic with the patch separation because we are so close to release.

  Done as separate patches to make review easier if review is to be done by reading the diffs. Perhaps at least one person could verify this PR programmatically by doing
  - Reset the last 2 patches (those are easy to do manually)
  - Check out master
  - Do `s/SigHash/Sighash/g` on all source files (bash function below)
  - Use `git diff branchA..branchB` to verify

  The difference between the two branches should only include comment lines (last three patches) and these seven instances of `SigHash:

  ```
  CHANGELOG.md:82:- [Add FromStr/Display implementation for SigHashType](a4a7035a94)
  CHANGELOG.md:93:- [Introduce `SigHashCache` structure](https://github.com/rust-bitcoin/rust-bitcoin/pull/390) to replace `SighashComponents` and support all sighash modes
  CHANGELOG.md:121:    - `SigHash`
  src/blockdata/transaction.rs:1190:            "SigHash_None",
  src/blockdata/transaction.rs:1191:            "SigHash_NONE",
  src/util/sighash.rs:1175:            "SigHash_None",
  src/util/sighash.rs:1176:            "SigHash_NONE",
  ```

  In case its useful, the shell function I used to do these changes is:
  ```bash
  function search-and-replace() {
      if (($# != 2))
      then
          echo "Usage: $0 <this> <that>"
          return
      fi

      local this="$1"
      local that="$2"

      # For all files containing $this, replace $this with $that.
      for file in $(git grep -l "$this")
      do
          perl -pi -e "s/$this/$that/g" "$file"
      done
  }
  ```

ACKs for top commit:
  dr-orlovsky:
    ACK 46c34b3fb7
  apoelstra:
    ACK 46c34b3fb7

Tree-SHA512: fe7e25e9cfb5155e4921de5ac185dbf9f4ca0770846d7892f6968b44fc5431f3f1a183380107449e90f7ea662094c60b118dc0468230384e8f9a8ef98d5ee0a0
This commit is contained in:
Andrew Poelstra 2022-04-01 17:30:04 +00:00
commit 9316c52946
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
12 changed files with 373 additions and 373 deletions

View File

@ -39,11 +39,11 @@ use blockdata::script::Script;
use blockdata::witness::Witness; use blockdata::witness::Witness;
use consensus::{encode, Decodable, Encodable}; use consensus::{encode, Decodable, Encodable};
use consensus::encode::MAX_VEC_SIZE; use consensus::encode::MAX_VEC_SIZE;
use hash_types::{SigHash, Txid, Wtxid}; use hash_types::{Sighash, Txid, Wtxid};
use VarInt; use VarInt;
#[cfg(doc)] #[cfg(doc)]
use util::sighash::SchnorrSigHashType; use util::sighash::SchnorrSighashType;
/// Used for signature hash for invalid use of SIGHASH_SINGLE. /// Used for signature hash for invalid use of SIGHASH_SINGLE.
const UINT256_ONE: [u8; 32] = [ const UINT256_ONE: [u8; 32] = [
@ -319,10 +319,10 @@ impl Transaction {
/// sighash flag can be computed. /// sighash flag can be computed.
/// ///
/// To actually produce a scriptSig, this hash needs to be run through an ECDSA signer, the /// To actually produce a scriptSig, this hash needs to be run through an ECDSA signer, the
/// [`EcdsaSigHashType`] appended to the resulting sig, and a script written around this, but /// [`EcdsaSighashType`] appended to the resulting sig, and a script written around this, but
/// this is the general (and hard) part. /// this is the general (and hard) part.
/// ///
/// The `sighash_type` supports an arbitrary `u32` value, instead of just [`EcdsaSigHashType`], /// The `sighash_type` supports an arbitrary `u32` value, instead of just [`EcdsaSighashType`],
/// because internally 4 bytes are being hashed, even though only the lowest byte is appended to /// because internally 4 bytes are being hashed, even though only the lowest byte is appended to
/// signature in a transaction. /// signature in a transaction.
/// ///
@ -356,7 +356,7 @@ impl Transaction {
return Ok(()) return Ok(())
} }
let (sighash, anyone_can_pay) = EcdsaSigHashType::from_consensus(sighash_type).split_anyonecanpay_flag(); let (sighash, anyone_can_pay) = EcdsaSighashType::from_consensus(sighash_type).split_anyonecanpay_flag();
// Build tx to sign // Build tx to sign
let mut tx = Transaction { let mut tx = Transaction {
@ -379,22 +379,22 @@ impl Transaction {
tx.input.push(TxIn { tx.input.push(TxIn {
previous_output: input.previous_output, previous_output: input.previous_output,
script_sig: if n == input_index { script_pubkey.clone() } else { Script::new() }, script_sig: if n == input_index { script_pubkey.clone() } else { Script::new() },
sequence: if n != input_index && (sighash == EcdsaSigHashType::Single || sighash == EcdsaSigHashType::None) { 0 } else { input.sequence }, sequence: if n != input_index && (sighash == EcdsaSighashType::Single || sighash == EcdsaSighashType::None) { 0 } else { input.sequence },
witness: Witness::default(), witness: Witness::default(),
}); });
} }
} }
// ..then all outputs // ..then all outputs
tx.output = match sighash { tx.output = match sighash {
EcdsaSigHashType::All => self.output.clone(), EcdsaSighashType::All => self.output.clone(),
EcdsaSigHashType::Single => { EcdsaSighashType::Single => {
let output_iter = self.output.iter() let output_iter = self.output.iter()
.take(input_index + 1) // sign all outputs up to and including this one, but erase .take(input_index + 1) // sign all outputs up to and including this one, but erase
.enumerate() // all of them except for this one .enumerate() // all of them except for this one
.map(|(n, out)| if n == input_index { out.clone() } else { TxOut::default() }); .map(|(n, out)| if n == input_index { out.clone() } else { TxOut::default() });
output_iter.collect() output_iter.collect()
} }
EcdsaSigHashType::None => vec![], EcdsaSighashType::None => vec![],
_ => unreachable!() _ => unreachable!()
}; };
// hash the result // hash the result
@ -407,10 +407,10 @@ impl Transaction {
/// Computes a signature hash for a given input index with a given sighash flag. /// Computes a signature hash for a given input index with a given sighash flag.
/// ///
/// To actually produce a scriptSig, this hash needs to be run through an ECDSA signer, the /// To actually produce a scriptSig, this hash needs to be run through an ECDSA signer, the
/// [`EcdsaSigHashType`] appended to the resulting sig, and a script written around this, but /// [`EcdsaSighashType`] appended to the resulting sig, and a script written around this, but
/// this is the general (and hard) part. /// this is the general (and hard) part.
/// ///
/// The `sighash_type` supports an arbitrary `u32` value, instead of just [`EcdsaSigHashType`], /// The `sighash_type` supports an arbitrary `u32` value, instead of just [`EcdsaSighashType`],
/// because internally 4 bytes are being hashed, even though only the lowest byte is appended to /// because internally 4 bytes are being hashed, even though only the lowest byte is appended to
/// signature in a transaction. /// signature in a transaction.
/// ///
@ -432,20 +432,20 @@ impl Transaction {
input_index: usize, input_index: usize,
script_pubkey: &Script, script_pubkey: &Script,
sighash_u32: u32 sighash_u32: u32
) -> SigHash { ) -> Sighash {
if self.is_invalid_use_of_sighash_single(sighash_u32, input_index) { if self.is_invalid_use_of_sighash_single(sighash_u32, input_index) {
return SigHash::from_slice(&UINT256_ONE).expect("const-size array"); return Sighash::from_slice(&UINT256_ONE).expect("const-size array");
} }
let mut engine = SigHash::engine(); let mut engine = Sighash::engine();
self.encode_signing_data_to(&mut engine, input_index, script_pubkey, sighash_u32) self.encode_signing_data_to(&mut engine, input_index, script_pubkey, sighash_u32)
.expect("engines don't error"); .expect("engines don't error");
SigHash::from_engine(engine) Sighash::from_engine(engine)
} }
fn is_invalid_use_of_sighash_single(&self, sighash: u32, input_index: usize) -> bool { fn is_invalid_use_of_sighash_single(&self, sighash: u32, input_index: usize) -> bool {
let ty = EcdsaSigHashType::from_consensus(sighash); let ty = EcdsaSighashType::from_consensus(sighash);
ty == EcdsaSigHashType::Single && input_index >= self.output.len() ty == EcdsaSighashType::Single && input_index >= self.output.len()
} }
/// Returns the "weight" of this transaction, as defined by BIP141. /// Returns the "weight" of this transaction, as defined by BIP141.
@ -723,9 +723,9 @@ impl Decodable for Transaction {
/// This type is consensus valid but an input including it would prevent the transaction from /// This type is consensus valid but an input including it would prevent the transaction from
/// being relayed on today's Bitcoin network. /// being relayed on today's Bitcoin network.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct NonStandardSigHashType(pub u32); pub struct NonStandardSighashType(pub u32);
impl fmt::Display for NonStandardSigHashType { impl fmt::Display for NonStandardSighashType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Non standard sighash type {}", self.0) write!(f, "Non standard sighash type {}", self.0)
} }
@ -733,18 +733,18 @@ impl fmt::Display for NonStandardSigHashType {
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl error::Error for NonStandardSigHashType {} impl error::Error for NonStandardSighashType {}
/// Legacy Hashtype of an input's signature /// Legacy Hashtype of an input's signature
#[deprecated(since = "0.28.0", note = "Please use [`EcdsaSigHashType`] instead")] #[deprecated(since = "0.28.0", note = "Please use [`EcdsaSighashType`] instead")]
pub type SigHashType = EcdsaSigHashType; pub type SigHashType = EcdsaSighashType;
/// Hashtype of an input's signature, encoded in the last byte of the signature. /// Hashtype of an input's signature, encoded in the last byte of the signature.
/// ///
/// Fixed values so they can be cast as integer types for encoding (see also /// Fixed values so they can be cast as integer types for encoding (see also
/// [`SchnorrSigHashType`]). /// [`SchnorrSighashType`]).
#[derive(PartialEq, Eq, Debug, Copy, Clone)] #[derive(PartialEq, Eq, Debug, Copy, Clone)]
pub enum EcdsaSigHashType { pub enum EcdsaSighashType {
/// 0x1: Sign all outputs. /// 0x1: Sign all outputs.
All = 0x01, All = 0x01,
/// 0x2: Sign no outputs --- anyone can choose the destination. /// 0x2: Sign no outputs --- anyone can choose the destination.
@ -761,67 +761,67 @@ pub enum EcdsaSigHashType {
/// 0x83: Sign one output and only this input (see `Single` for what "one output" means). /// 0x83: Sign one output and only this input (see `Single` for what "one output" means).
SinglePlusAnyoneCanPay = 0x83 SinglePlusAnyoneCanPay = 0x83
} }
serde_string_impl!(EcdsaSigHashType, "a EcdsaSigHashType data"); serde_string_impl!(EcdsaSighashType, "a EcdsaSighashType data");
impl fmt::Display for EcdsaSigHashType { impl fmt::Display for EcdsaSighashType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self { let s = match self {
EcdsaSigHashType::All => "SIGHASH_ALL", EcdsaSighashType::All => "SIGHASH_ALL",
EcdsaSigHashType::None => "SIGHASH_NONE", EcdsaSighashType::None => "SIGHASH_NONE",
EcdsaSigHashType::Single => "SIGHASH_SINGLE", EcdsaSighashType::Single => "SIGHASH_SINGLE",
EcdsaSigHashType::AllPlusAnyoneCanPay => "SIGHASH_ALL|SIGHASH_ANYONECANPAY", EcdsaSighashType::AllPlusAnyoneCanPay => "SIGHASH_ALL|SIGHASH_ANYONECANPAY",
EcdsaSigHashType::NonePlusAnyoneCanPay => "SIGHASH_NONE|SIGHASH_ANYONECANPAY", EcdsaSighashType::NonePlusAnyoneCanPay => "SIGHASH_NONE|SIGHASH_ANYONECANPAY",
EcdsaSigHashType::SinglePlusAnyoneCanPay => "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", EcdsaSighashType::SinglePlusAnyoneCanPay => "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY",
}; };
f.write_str(s) f.write_str(s)
} }
} }
impl str::FromStr for EcdsaSigHashType { impl str::FromStr for EcdsaSighashType {
type Err = SigHashTypeParseError; type Err = SighashTypeParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
match s { match s {
"SIGHASH_ALL" => Ok(EcdsaSigHashType::All), "SIGHASH_ALL" => Ok(EcdsaSighashType::All),
"SIGHASH_NONE" => Ok(EcdsaSigHashType::None), "SIGHASH_NONE" => Ok(EcdsaSighashType::None),
"SIGHASH_SINGLE" => Ok(EcdsaSigHashType::Single), "SIGHASH_SINGLE" => Ok(EcdsaSighashType::Single),
"SIGHASH_ALL|SIGHASH_ANYONECANPAY" => Ok(EcdsaSigHashType::AllPlusAnyoneCanPay), "SIGHASH_ALL|SIGHASH_ANYONECANPAY" => Ok(EcdsaSighashType::AllPlusAnyoneCanPay),
"SIGHASH_NONE|SIGHASH_ANYONECANPAY" => Ok(EcdsaSigHashType::NonePlusAnyoneCanPay), "SIGHASH_NONE|SIGHASH_ANYONECANPAY" => Ok(EcdsaSighashType::NonePlusAnyoneCanPay),
"SIGHASH_SINGLE|SIGHASH_ANYONECANPAY" => Ok(EcdsaSigHashType::SinglePlusAnyoneCanPay), "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY" => Ok(EcdsaSighashType::SinglePlusAnyoneCanPay),
_ => Err(SigHashTypeParseError { unrecognized: s.to_owned() }), _ => Err(SighashTypeParseError { unrecognized: s.to_owned() }),
} }
} }
} }
impl EcdsaSigHashType { impl EcdsaSighashType {
/// Splits the sighash flag into the "real" sighash flag and the ANYONECANPAY boolean. /// Splits the sighash flag into the "real" sighash flag and the ANYONECANPAY boolean.
pub(crate) fn split_anyonecanpay_flag(self) -> (EcdsaSigHashType, bool) { pub(crate) fn split_anyonecanpay_flag(self) -> (EcdsaSighashType, bool) {
match self { match self {
EcdsaSigHashType::All => (EcdsaSigHashType::All, false), EcdsaSighashType::All => (EcdsaSighashType::All, false),
EcdsaSigHashType::None => (EcdsaSigHashType::None, false), EcdsaSighashType::None => (EcdsaSighashType::None, false),
EcdsaSigHashType::Single => (EcdsaSigHashType::Single, false), EcdsaSighashType::Single => (EcdsaSighashType::Single, false),
EcdsaSigHashType::AllPlusAnyoneCanPay => (EcdsaSigHashType::All, true), EcdsaSighashType::AllPlusAnyoneCanPay => (EcdsaSighashType::All, true),
EcdsaSigHashType::NonePlusAnyoneCanPay => (EcdsaSigHashType::None, true), EcdsaSighashType::NonePlusAnyoneCanPay => (EcdsaSighashType::None, true),
EcdsaSigHashType::SinglePlusAnyoneCanPay => (EcdsaSigHashType::Single, true) EcdsaSighashType::SinglePlusAnyoneCanPay => (EcdsaSighashType::Single, true)
} }
} }
/// Creates a [`EcdsaSigHashType`] from a raw `u32`. /// Creates a [`EcdsaSighashType`] from a raw `u32`.
#[deprecated(since="0.28.0", note="please use `from_consensus`")] #[deprecated(since="0.28.0", note="please use `from_consensus`")]
pub fn from_u32_consensus(n: u32) -> EcdsaSigHashType { pub fn from_u32_consensus(n: u32) -> EcdsaSighashType {
EcdsaSigHashType::from_consensus(n) EcdsaSighashType::from_consensus(n)
} }
/// Creates a [`EcdsaSigHashType`] from a raw `u32`. /// Creates a [`EcdsaSighashType`] from a raw `u32`.
/// ///
/// **Note**: this replicates consensus behaviour, for current standardness rules correctness /// **Note**: this replicates consensus behaviour, for current standardness rules correctness
/// you probably want [`Self::from_standard`]. /// you probably want [`Self::from_standard`].
/// ///
/// This might cause unexpected behavior because it does not roundtrip. That is, /// This might cause unexpected behavior because it does not roundtrip. That is,
/// `EcdsaSigHashType::from_consensus(n) as u32 != n` for non-standard values of `n`. While /// `EcdsaSighashType::from_consensus(n) as u32 != n` for non-standard values of `n`. While
/// verifying signatures, the user should retain the `n` and use it compute the signature hash /// verifying signatures, the user should retain the `n` and use it compute the signature hash
/// message. /// message.
pub fn from_consensus(n: u32) -> EcdsaSigHashType { pub fn from_consensus(n: u32) -> EcdsaSighashType {
// In Bitcoin Core, the SignatureHash function will mask the (int32) value with // In Bitcoin Core, the SignatureHash function will mask the (int32) value with
// 0x1f to (apparently) deactivate ACP when checking for SINGLE and NONE bits. // 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. // We however want to be matching also against on ACP-masked ALL, SINGLE, and NONE.
@ -829,58 +829,58 @@ impl EcdsaSigHashType {
let mask = 0x1f | 0x80; let mask = 0x1f | 0x80;
match n & mask { match n & mask {
// "real" sighashes // "real" sighashes
0x01 => EcdsaSigHashType::All, 0x01 => EcdsaSighashType::All,
0x02 => EcdsaSigHashType::None, 0x02 => EcdsaSighashType::None,
0x03 => EcdsaSigHashType::Single, 0x03 => EcdsaSighashType::Single,
0x81 => EcdsaSigHashType::AllPlusAnyoneCanPay, 0x81 => EcdsaSighashType::AllPlusAnyoneCanPay,
0x82 => EcdsaSigHashType::NonePlusAnyoneCanPay, 0x82 => EcdsaSighashType::NonePlusAnyoneCanPay,
0x83 => EcdsaSigHashType::SinglePlusAnyoneCanPay, 0x83 => EcdsaSighashType::SinglePlusAnyoneCanPay,
// catchalls // catchalls
x if x & 0x80 == 0x80 => EcdsaSigHashType::AllPlusAnyoneCanPay, x if x & 0x80 == 0x80 => EcdsaSighashType::AllPlusAnyoneCanPay,
_ => EcdsaSigHashType::All _ => EcdsaSighashType::All
} }
} }
/// Creates a [`EcdsaSigHashType`] from a raw `u32`. /// Creates a [`EcdsaSighashType`] from a raw `u32`.
#[deprecated(since="0.28.0", note="please use `from_standard`")] #[deprecated(since="0.28.0", note="please use `from_standard`")]
pub fn from_u32_standard(n: u32) -> Result<EcdsaSigHashType, NonStandardSigHashType> { pub fn from_u32_standard(n: u32) -> Result<EcdsaSighashType, NonStandardSighashType> {
EcdsaSigHashType::from_standard(n) EcdsaSighashType::from_standard(n)
} }
/// Creates a [`EcdsaSigHashType`] from a raw `u32`. /// Creates a [`EcdsaSighashType`] from a raw `u32`.
/// ///
/// # Errors /// # Errors
/// ///
/// If `n` is a non-standard sighash value. /// If `n` is a non-standard sighash value.
pub fn from_standard(n: u32) -> Result<EcdsaSigHashType, NonStandardSigHashType> { pub fn from_standard(n: u32) -> Result<EcdsaSighashType, NonStandardSighashType> {
match n { match n {
// Standard sighashes, see https://github.com/bitcoin/bitcoin/blob/b805dbb0b9c90dadef0424e5b3bf86ac308e103e/src/script/interpreter.cpp#L189-L198 // Standard sighashes, see https://github.com/bitcoin/bitcoin/blob/b805dbb0b9c90dadef0424e5b3bf86ac308e103e/src/script/interpreter.cpp#L189-L198
0x01 => Ok(EcdsaSigHashType::All), 0x01 => Ok(EcdsaSighashType::All),
0x02 => Ok(EcdsaSigHashType::None), 0x02 => Ok(EcdsaSighashType::None),
0x03 => Ok(EcdsaSigHashType::Single), 0x03 => Ok(EcdsaSighashType::Single),
0x81 => Ok(EcdsaSigHashType::AllPlusAnyoneCanPay), 0x81 => Ok(EcdsaSighashType::AllPlusAnyoneCanPay),
0x82 => Ok(EcdsaSigHashType::NonePlusAnyoneCanPay), 0x82 => Ok(EcdsaSighashType::NonePlusAnyoneCanPay),
0x83 => Ok(EcdsaSigHashType::SinglePlusAnyoneCanPay), 0x83 => Ok(EcdsaSighashType::SinglePlusAnyoneCanPay),
non_standard => Err(NonStandardSigHashType(non_standard)) non_standard => Err(NonStandardSighashType(non_standard))
} }
} }
/// Converts [`EcdsaSigHashType`] to a `u32` sighash flag. /// Converts [`EcdsaSighashType`] to a `u32` sighash flag.
/// ///
/// The returned value is guaranteed to be a valid according to standardness rules. /// The returned value is guaranteed to be a valid according to standardness rules.
pub fn to_u32(self) -> u32 { self as u32 } pub fn to_u32(self) -> u32 { self as u32 }
} }
/// Error returned when parsing `SigHashType` fails. /// Error returned for failure during parsing one of the sighash types.
/// ///
/// This is currently returned for unrecognized sighash strings. /// This is currently returned for unrecognized sighash strings.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct SigHashTypeParseError { pub struct SighashTypeParseError {
/// The unrecognized string we attempted to parse. /// The unrecognized string we attempted to parse.
pub unrecognized: String, pub unrecognized: String,
} }
impl fmt::Display for SigHashTypeParseError { impl fmt::Display for SighashTypeParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Unrecognized SIGHASH string '{}'", self.unrecognized) write!(f, "Unrecognized SIGHASH string '{}'", self.unrecognized)
} }
@ -888,7 +888,7 @@ impl fmt::Display for SigHashTypeParseError {
#[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl ::std::error::Error for SigHashTypeParseError {} impl ::std::error::Error for SighashTypeParseError {}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
@ -904,8 +904,8 @@ mod tests {
use hashes::hex::FromHex; use hashes::hex::FromHex;
use hash_types::*; use hash_types::*;
use super::EcdsaSigHashType; use super::EcdsaSighashType;
use util::sighash::SigHashCache; use util::sighash::SighashCache;
#[test] #[test]
fn test_outpoint() { fn test_outpoint() {
@ -1167,16 +1167,16 @@ mod tests {
#[test] #[test]
fn test_sighashtype_fromstr_display() { fn test_sighashtype_fromstr_display() {
let sighashtypes = vec![ let sighashtypes = vec![
("SIGHASH_ALL", EcdsaSigHashType::All), ("SIGHASH_ALL", EcdsaSighashType::All),
("SIGHASH_NONE", EcdsaSigHashType::None), ("SIGHASH_NONE", EcdsaSighashType::None),
("SIGHASH_SINGLE", EcdsaSigHashType::Single), ("SIGHASH_SINGLE", EcdsaSighashType::Single),
("SIGHASH_ALL|SIGHASH_ANYONECANPAY", EcdsaSigHashType::AllPlusAnyoneCanPay), ("SIGHASH_ALL|SIGHASH_ANYONECANPAY", EcdsaSighashType::AllPlusAnyoneCanPay),
("SIGHASH_NONE|SIGHASH_ANYONECANPAY", EcdsaSigHashType::NonePlusAnyoneCanPay), ("SIGHASH_NONE|SIGHASH_ANYONECANPAY", EcdsaSighashType::NonePlusAnyoneCanPay),
("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", EcdsaSigHashType::SinglePlusAnyoneCanPay) ("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", EcdsaSighashType::SinglePlusAnyoneCanPay)
]; ];
for (s, sht) in sighashtypes { for (s, sht) in sighashtypes {
assert_eq!(sht.to_string(), s); assert_eq!(sht.to_string(), s);
assert_eq!(EcdsaSigHashType::from_str(s).unwrap(), sht); assert_eq!(EcdsaSighashType::from_str(s).unwrap(), sht);
} }
let sht_mistakes = vec![ let sht_mistakes = vec![
"SIGHASH_ALL | SIGHASH_ANYONECANPAY", "SIGHASH_ALL | SIGHASH_ANYONECANPAY",
@ -1191,7 +1191,7 @@ mod tests {
"SigHash_NONE", "SigHash_NONE",
]; ];
for s in sht_mistakes { for s in sht_mistakes {
assert_eq!(EcdsaSigHashType::from_str(s).unwrap_err().to_string(), format!("Unrecognized SIGHASH string '{}'", s)); assert_eq!(EcdsaSighashType::from_str(s).unwrap_err().to_string(), format!("Unrecognized SIGHASH string '{}'", s));
} }
} }
@ -1200,9 +1200,9 @@ mod tests {
fn test_sighashtype_standard() { fn test_sighashtype_standard() {
let nonstandard_hashtype = 0x04; let nonstandard_hashtype = 0x04;
// This type is not well defined, by consensus it becomes ALL // This type is not well defined, by consensus it becomes ALL
assert_eq!(EcdsaSigHashType::from_u32_consensus(nonstandard_hashtype), EcdsaSigHashType::All); assert_eq!(EcdsaSighashType::from_u32_consensus(nonstandard_hashtype), EcdsaSighashType::All);
// But it's policy-invalid to use it! // But it's policy-invalid to use it!
assert_eq!(EcdsaSigHashType::from_u32_standard(nonstandard_hashtype), Err(NonStandardSigHashType(0x04))); assert_eq!(EcdsaSighashType::from_u32_standard(nonstandard_hashtype), Err(NonStandardSighashType(0x04)));
} }
#[test] #[test]
@ -1223,7 +1223,7 @@ mod tests {
}; };
let script = Script::new(); let script = Script::new();
let got = tx.signature_hash(1, &script, SIGHASH_SINGLE); let got = tx.signature_hash(1, &script, SIGHASH_SINGLE);
let want = SigHash::from_slice(&UINT256_ONE).unwrap(); let want = Sighash::from_slice(&UINT256_ONE).unwrap();
assert_eq!(got, want) assert_eq!(got, want)
} }
@ -1233,14 +1233,14 @@ mod tests {
let script = Script::from(Vec::from_hex(script).unwrap()); let script = Script::from(Vec::from_hex(script).unwrap());
let mut raw_expected = Vec::from_hex(expected_result).unwrap(); let mut raw_expected = Vec::from_hex(expected_result).unwrap();
raw_expected.reverse(); raw_expected.reverse();
let expected_result = SigHash::from_slice(&raw_expected[..]).unwrap(); let expected_result = Sighash::from_slice(&raw_expected[..]).unwrap();
let actual_result = if raw_expected[0] % 2 == 0 { let actual_result = if raw_expected[0] % 2 == 0 {
// tx.signature_hash and cache.legacy_signature_hash are the same, this if helps to test // tx.signature_hash and cache.legacy_signature_hash are the same, this if helps to test
// both the codepaths without repeating the test code // both the codepaths without repeating the test code
tx.signature_hash(input_index, &script, hash_type as u32) tx.signature_hash(input_index, &script, hash_type as u32)
} else { } else {
let cache = SigHashCache::new(&tx); let cache = SighashCache::new(&tx);
cache.legacy_signature_hash(input_index, &script, hash_type as u32).unwrap() cache.legacy_signature_hash(input_index, &script, hash_type as u32).unwrap()
}; };

View File

@ -42,7 +42,7 @@ macro_rules! impl_hashencode {
hash_newtype!(Txid, sha256d::Hash, 32, doc="A bitcoin transaction hash/transaction ID."); hash_newtype!(Txid, sha256d::Hash, 32, doc="A bitcoin transaction hash/transaction ID.");
hash_newtype!(Wtxid, sha256d::Hash, 32, doc="A bitcoin witness transaction ID."); hash_newtype!(Wtxid, sha256d::Hash, 32, doc="A bitcoin witness transaction ID.");
hash_newtype!(BlockHash, sha256d::Hash, 32, doc="A bitcoin block hash."); hash_newtype!(BlockHash, sha256d::Hash, 32, doc="A bitcoin block hash.");
hash_newtype!(SigHash, sha256d::Hash, 32, doc="Hash of the transaction according to the signature algorithm"); hash_newtype!(Sighash, sha256d::Hash, 32, doc="Hash of the transaction according to the signature algorithm");
hash_newtype!(PubkeyHash, hash160::Hash, 20, doc="A hash of a public key."); hash_newtype!(PubkeyHash, hash160::Hash, 20, doc="A hash of a public key.");
hash_newtype!(ScriptHash, hash160::Hash, 20, doc="A hash of Bitcoin Script bytecode."); hash_newtype!(ScriptHash, hash160::Hash, 20, doc="A hash of Bitcoin Script bytecode.");
@ -61,7 +61,7 @@ hash_newtype!(FilterHeader, sha256d::Hash, 32, doc="Filter header, as defined in
impl_hashencode!(Txid); impl_hashencode!(Txid);
impl_hashencode!(Wtxid); impl_hashencode!(Wtxid);
impl_hashencode!(BlockHash); impl_hashencode!(BlockHash);
impl_hashencode!(SigHash); impl_hashencode!(Sighash);
impl_hashencode!(TxMerkleNode); impl_hashencode!(TxMerkleNode);
impl_hashencode!(WitnessMerkleNode); impl_hashencode!(WitnessMerkleNode);

View File

@ -123,7 +123,7 @@ pub use blockdata::transaction::Transaction;
pub use blockdata::transaction::TxIn; pub use blockdata::transaction::TxIn;
pub use blockdata::transaction::TxOut; pub use blockdata::transaction::TxOut;
pub use blockdata::transaction::OutPoint; pub use blockdata::transaction::OutPoint;
pub use blockdata::transaction::EcdsaSigHashType; pub use blockdata::transaction::EcdsaSighashType;
pub use blockdata::witness::Witness; pub use blockdata::witness::Witness;
pub use consensus::encode::VarInt; pub use consensus::encode::VarInt;
pub use network::constants::Network; pub use network::constants::Network;
@ -134,7 +134,7 @@ pub use util::amount::Amount;
pub use util::amount::Denomination; pub use util::amount::Denomination;
pub use util::amount::SignedAmount; pub use util::amount::SignedAmount;
pub use util::merkleblock::MerkleBlock; pub use util::merkleblock::MerkleBlock;
pub use util::sighash::SchnorrSigHashType; pub use util::sighash::SchnorrSighashType;
pub use util::ecdsa::{self, EcdsaSig, EcdsaSigError}; pub use util::ecdsa::{self, EcdsaSig, EcdsaSigError};
pub use util::schnorr::{self, SchnorrSig, SchnorrSigError}; pub use util::schnorr::{self, SchnorrSig, SchnorrSigError};

View File

@ -20,10 +20,10 @@
//! //!
use hashes::Hash; use hashes::Hash;
use hash_types::SigHash; use hash_types::Sighash;
use blockdata::script::Script; use blockdata::script::Script;
use blockdata::witness::Witness; use blockdata::witness::Witness;
use blockdata::transaction::{Transaction, TxIn, EcdsaSigHashType}; use blockdata::transaction::{Transaction, TxIn, EcdsaSighashType};
use consensus::{encode, Encodable}; use consensus::{encode, Encodable};
use io; use io;
@ -33,16 +33,16 @@ use util::sighash;
/// Parts of a sighash which are common across inputs or signatures, and which are /// Parts of a sighash which are common across inputs or signatures, and which are
/// sufficient (in conjunction with a private key) to sign the transaction /// sufficient (in conjunction with a private key) to sign the transaction
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
#[deprecated(since = "0.24.0", note = "please use [sighash::SigHashCache] instead")] #[deprecated(since = "0.24.0", note = "please use [sighash::SighashCache] instead")]
pub struct SighashComponents { pub struct SighashComponents {
tx_version: i32, tx_version: i32,
tx_locktime: u32, tx_locktime: u32,
/// Hash of all the previous outputs /// Hash of all the previous outputs
pub hash_prevouts: SigHash, pub hash_prevouts: Sighash,
/// Hash of all the input sequence nos /// Hash of all the input sequence nos
pub hash_sequence: SigHash, pub hash_sequence: Sighash,
/// Hash of all the outputs in this transaction /// Hash of all the outputs in this transaction
pub hash_outputs: SigHash, pub hash_outputs: Sighash,
} }
#[allow(deprecated)] #[allow(deprecated)]
@ -53,27 +53,27 @@ impl SighashComponents {
/// script_sig and witnesses. /// script_sig and witnesses.
pub fn new(tx: &Transaction) -> SighashComponents { pub fn new(tx: &Transaction) -> SighashComponents {
let hash_prevouts = { let hash_prevouts = {
let mut enc = SigHash::engine(); let mut enc = Sighash::engine();
for txin in &tx.input { for txin in &tx.input {
txin.previous_output.consensus_encode(&mut enc).expect("engines don't error"); txin.previous_output.consensus_encode(&mut enc).expect("engines don't error");
} }
SigHash::from_engine(enc) Sighash::from_engine(enc)
}; };
let hash_sequence = { let hash_sequence = {
let mut enc = SigHash::engine(); let mut enc = Sighash::engine();
for txin in &tx.input { for txin in &tx.input {
txin.sequence.consensus_encode(&mut enc).expect("engines don't error"); txin.sequence.consensus_encode(&mut enc).expect("engines don't error");
} }
SigHash::from_engine(enc) Sighash::from_engine(enc)
}; };
let hash_outputs = { let hash_outputs = {
let mut enc = SigHash::engine(); let mut enc = Sighash::engine();
for txout in &tx.output { for txout in &tx.output {
txout.consensus_encode(&mut enc).expect("engines don't error"); txout.consensus_encode(&mut enc).expect("engines don't error");
} }
SigHash::from_engine(enc) Sighash::from_engine(enc)
}; };
SighashComponents { SighashComponents {
@ -87,8 +87,8 @@ impl SighashComponents {
/// Compute the BIP143 sighash for a `SIGHASH_ALL` signature for the given /// Compute the BIP143 sighash for a `SIGHASH_ALL` signature for the given
/// input. /// input.
pub fn sighash_all(&self, txin: &TxIn, script_code: &Script, value: u64) -> SigHash { pub fn sighash_all(&self, txin: &TxIn, script_code: &Script, value: u64) -> Sighash {
let mut enc = SigHash::engine(); let mut enc = Sighash::engine();
self.tx_version.consensus_encode(&mut enc).expect("engines don't error"); self.tx_version.consensus_encode(&mut enc).expect("engines don't error");
self.hash_prevouts.consensus_encode(&mut enc).expect("engines don't error"); self.hash_prevouts.consensus_encode(&mut enc).expect("engines don't error");
self.hash_sequence.consensus_encode(&mut enc).expect("engines don't error"); self.hash_sequence.consensus_encode(&mut enc).expect("engines don't error");
@ -102,14 +102,14 @@ impl SighashComponents {
self.hash_outputs.consensus_encode(&mut enc).expect("engines don't error"); self.hash_outputs.consensus_encode(&mut enc).expect("engines don't error");
self.tx_locktime.consensus_encode(&mut enc).expect("engines don't error"); self.tx_locktime.consensus_encode(&mut enc).expect("engines don't error");
1u32.consensus_encode(&mut enc).expect("engines don't error"); // hashtype 1u32.consensus_encode(&mut enc).expect("engines don't error"); // hashtype
SigHash::from_engine(enc) Sighash::from_engine(enc)
} }
} }
/// A replacement for SigHashComponents which supports all sighash modes /// A replacement for SigHashComponents which supports all sighash modes
#[deprecated(since = "0.28.0", note = "please use [sighash::SigHashCache] instead")] #[deprecated(since = "0.28.0", note = "please use [sighash::SighashCache] instead")]
pub struct SigHashCache<R: Deref<Target = Transaction>> { pub struct SigHashCache<R: Deref<Target = Transaction>> {
cache: sighash::SigHashCache<R>, cache: sighash::SighashCache<R>,
} }
#[allow(deprecated)] #[allow(deprecated)]
@ -119,7 +119,7 @@ impl<R: Deref<Target = Transaction>> SigHashCache<R> {
/// For the generated sighashes to be valid, no fields in the transaction may change except for /// For the generated sighashes to be valid, no fields in the transaction may change except for
/// script_sig and witnesses. /// script_sig and witnesses.
pub fn new(tx: R) -> Self { pub fn new(tx: R) -> Self {
Self { cache: sighash::SigHashCache::new(tx) } Self { cache: sighash::SighashCache::new(tx) }
} }
/// Encode the BIP143 signing data for any flag type into a given object implementing a /// Encode the BIP143 signing data for any flag type into a given object implementing a
@ -130,7 +130,7 @@ impl<R: Deref<Target = Transaction>> SigHashCache<R> {
input_index: usize, input_index: usize,
script_code: &Script, script_code: &Script,
value: u64, value: u64,
sighash_type: EcdsaSigHashType, sighash_type: EcdsaSighashType,
) -> Result<(), encode::Error> { ) -> Result<(), encode::Error> {
self.cache self.cache
.segwit_encode_signing_data_to(writer, input_index, script_code, value, sighash_type) .segwit_encode_signing_data_to(writer, input_index, script_code, value, sighash_type)
@ -145,12 +145,12 @@ impl<R: Deref<Target = Transaction>> SigHashCache<R> {
input_index: usize, input_index: usize,
script_code: &Script, script_code: &Script,
value: u64, value: u64,
sighash_type: EcdsaSigHashType sighash_type: EcdsaSighashType
) -> SigHash { ) -> Sighash {
let mut enc = SigHash::engine(); let mut enc = Sighash::engine();
self.encode_signing_data_to(&mut enc, input_index, script_code, value, sighash_type) self.encode_signing_data_to(&mut enc, input_index, script_code, value, sighash_type)
.expect("engines don't error"); .expect("engines don't error");
SigHash::from_engine(enc) Sighash::from_engine(enc)
} }
} }
@ -164,7 +164,7 @@ impl<R: DerefMut<Target = Transaction>> SigHashCache<R> {
/// panics if `input_index` is out of bounds with respect of the number of inputs /// panics if `input_index` is out of bounds with respect of the number of inputs
/// ///
/// ``` /// ```
/// use bitcoin::blockdata::transaction::{Transaction, EcdsaSigHashType}; /// use bitcoin::blockdata::transaction::{Transaction, EcdsaSighashType};
/// use bitcoin::util::bip143::SigHashCache; /// use bitcoin::util::bip143::SigHashCache;
/// use bitcoin::Script; /// use bitcoin::Script;
/// ///
@ -174,7 +174,7 @@ impl<R: DerefMut<Target = Transaction>> SigHashCache<R> {
/// let mut sig_hasher = SigHashCache::new(&mut tx_to_sign); /// let mut sig_hasher = SigHashCache::new(&mut tx_to_sign);
/// for inp in 0..input_count { /// for inp in 0..input_count {
/// let prevout_script = Script::new(); /// let prevout_script = Script::new();
/// let _sighash = sig_hasher.signature_hash(inp, &prevout_script, 42, EcdsaSigHashType::All); /// let _sighash = sig_hasher.signature_hash(inp, &prevout_script, 42, EcdsaSighashType::All);
/// // ... sign the sighash /// // ... sign the sighash
/// sig_hasher.access_witness(inp).push(&[]); /// sig_hasher.access_witness(inp).push(&[]);
/// } /// }
@ -188,7 +188,7 @@ impl<R: DerefMut<Target = Transaction>> SigHashCache<R> {
#[allow(deprecated)] #[allow(deprecated)]
mod tests { mod tests {
use std::str::FromStr; use std::str::FromStr;
use hash_types::SigHash; use hash_types::Sighash;
use blockdata::script::Script; use blockdata::script::Script;
use blockdata::transaction::Transaction; use blockdata::transaction::Transaction;
use consensus::encode::deserialize; use consensus::encode::deserialize;
@ -208,10 +208,10 @@ mod tests {
fn run_test_sighash_bip143(tx: &str, script: &str, input_index: usize, value: u64, hash_type: u32, expected_result: &str) { fn run_test_sighash_bip143(tx: &str, script: &str, input_index: usize, value: u64, hash_type: u32, expected_result: &str) {
let tx: Transaction = deserialize(&Vec::<u8>::from_hex(tx).unwrap()[..]).unwrap(); let tx: Transaction = deserialize(&Vec::<u8>::from_hex(tx).unwrap()[..]).unwrap();
let script = Script::from(Vec::<u8>::from_hex(script).unwrap()); let script = Script::from(Vec::<u8>::from_hex(script).unwrap());
let raw_expected = SigHash::from_hex(expected_result).unwrap(); let raw_expected = Sighash::from_hex(expected_result).unwrap();
let expected_result = SigHash::from_slice(&raw_expected[..]).unwrap(); let expected_result = Sighash::from_slice(&raw_expected[..]).unwrap();
let mut cache = SigHashCache::new(&tx); let mut cache = SigHashCache::new(&tx);
let sighash_type = EcdsaSigHashType::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); let actual_result = cache.signature_hash(input_index, &script, value, sighash_type);
assert_eq!(actual_result, expected_result); assert_eq!(actual_result, expected_result);
} }
@ -237,20 +237,20 @@ mod tests {
tx_version: 1, tx_version: 1,
tx_locktime: 17, tx_locktime: 17,
hash_prevouts: hex_hash!( hash_prevouts: hex_hash!(
SigHash, "96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37" Sighash, "96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37"
), ),
hash_sequence: hex_hash!( hash_sequence: hex_hash!(
SigHash, "52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b" Sighash, "52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b"
), ),
hash_outputs: hex_hash!( hash_outputs: hex_hash!(
SigHash, "863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5" Sighash, "863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5"
), ),
} }
); );
assert_eq!( assert_eq!(
comp.sighash_all(&tx.input[1], &witness_script, value), comp.sighash_all(&tx.input[1], &witness_script, value),
hex_hash!(SigHash, "c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670") hex_hash!(Sighash, "c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670")
); );
} }
@ -273,20 +273,20 @@ mod tests {
tx_version: 1, tx_version: 1,
tx_locktime: 1170, tx_locktime: 1170,
hash_prevouts: hex_hash!( hash_prevouts: hex_hash!(
SigHash, "b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a" Sighash, "b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a"
), ),
hash_sequence: hex_hash!( hash_sequence: hex_hash!(
SigHash, "18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198" Sighash, "18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198"
), ),
hash_outputs: hex_hash!( hash_outputs: hex_hash!(
SigHash, "de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83" Sighash, "de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83"
), ),
} }
); );
assert_eq!( assert_eq!(
comp.sighash_all(&tx.input[0], &witness_script, value), comp.sighash_all(&tx.input[0], &witness_script, value),
hex_hash!(SigHash, "64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6") hex_hash!(Sighash, "64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6")
); );
} }
@ -316,20 +316,20 @@ mod tests {
tx_version: 1, tx_version: 1,
tx_locktime: 0, tx_locktime: 0,
hash_prevouts: hex_hash!( hash_prevouts: hex_hash!(
SigHash, "74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0" Sighash, "74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0"
), ),
hash_sequence: hex_hash!( hash_sequence: hex_hash!(
SigHash, "3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044" Sighash, "3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044"
), ),
hash_outputs: hex_hash!( hash_outputs: hex_hash!(
SigHash, "bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc" Sighash, "bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc"
), ),
} }
); );
assert_eq!( assert_eq!(
comp.sighash_all(&tx.input[0], &witness_script, value), comp.sighash_all(&tx.input[0], &witness_script, value),
hex_hash!(SigHash, "185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c") hex_hash!(Sighash, "185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c")
); );
} }
#[test] #[test]

View File

@ -20,9 +20,9 @@ use prelude::*;
use core::str::FromStr; use core::str::FromStr;
use core::{fmt, iter}; use core::{fmt, iter};
use hashes::hex::{self, FromHex}; use hashes::hex::{self, FromHex};
use blockdata::transaction::NonStandardSigHashType; use blockdata::transaction::NonStandardSighashType;
use secp256k1; use secp256k1;
use EcdsaSigHashType; use EcdsaSighashType;
/// An ECDSA signature with the corresponding hash type. /// An ECDSA signature with the corresponding hash type.
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
@ -31,24 +31,24 @@ pub struct EcdsaSig {
/// The underlying ECDSA Signature /// The underlying ECDSA Signature
pub sig: secp256k1::ecdsa::Signature, pub sig: secp256k1::ecdsa::Signature,
/// The corresponding hash type /// The corresponding hash type
pub hash_ty: EcdsaSigHashType, pub hash_ty: EcdsaSighashType,
} }
impl EcdsaSig { impl EcdsaSig {
/// Constructs ECDSA bitcoin signature for [`EcdsaSigHashType::All`] /// Constructs ECDSA bitcoin signature for [`EcdsaSighashType::All`]
pub fn sighash_all(sig: secp256k1::ecdsa::Signature) -> EcdsaSig { pub fn sighash_all(sig: secp256k1::ecdsa::Signature) -> EcdsaSig {
EcdsaSig { EcdsaSig {
sig, sig,
hash_ty: EcdsaSigHashType::All hash_ty: EcdsaSighashType::All
} }
} }
/// Deserialize from slice following the standardness rules for [`EcdsaSigHashType`] /// Deserialize from slice following the standardness rules for [`EcdsaSighashType`]
pub fn from_slice(sl: &[u8]) -> Result<Self, EcdsaSigError> { pub fn from_slice(sl: &[u8]) -> Result<Self, EcdsaSigError> {
let (hash_ty, sig) = sl.split_last() let (hash_ty, sig) = sl.split_last()
.ok_or(EcdsaSigError::EmptySignature)?; .ok_or(EcdsaSigError::EmptySignature)?;
let hash_ty = EcdsaSigHashType::from_standard(*hash_ty as u32) let hash_ty = EcdsaSighashType::from_standard(*hash_ty as u32)
.map_err(|_| EcdsaSigError::NonStandardSigHashType(*hash_ty as u32))?; .map_err(|_| EcdsaSigError::NonStandardSighashType(*hash_ty as u32))?;
let sig = secp256k1::ecdsa::Signature::from_der(sig) let sig = secp256k1::ecdsa::Signature::from_der(sig)
.map_err(EcdsaSigError::Secp256k1)?; .map_err(EcdsaSigError::Secp256k1)?;
Ok(EcdsaSig { sig, hash_ty }) Ok(EcdsaSig { sig, hash_ty })
@ -80,7 +80,7 @@ impl FromStr for EcdsaSig {
.ok_or(EcdsaSigError::EmptySignature)?; .ok_or(EcdsaSigError::EmptySignature)?;
Ok(EcdsaSig { Ok(EcdsaSig {
sig: secp256k1::ecdsa::Signature::from_der(signature)?, sig: secp256k1::ecdsa::Signature::from_der(signature)?,
hash_ty: EcdsaSigHashType::from_standard(*sighash_byte as u32)? hash_ty: EcdsaSighashType::from_standard(*sighash_byte as u32)?
}) })
} }
} }
@ -91,7 +91,7 @@ pub enum EcdsaSigError {
/// Hex encoding error /// Hex encoding error
HexEncoding(hex::Error), HexEncoding(hex::Error),
/// Base58 encoding error /// Base58 encoding error
NonStandardSigHashType(u32), NonStandardSighashType(u32),
/// Empty Signature /// Empty Signature
EmptySignature, EmptySignature,
/// secp256k1-related error /// secp256k1-related error
@ -102,7 +102,7 @@ pub enum EcdsaSigError {
impl fmt::Display for EcdsaSigError { impl fmt::Display for EcdsaSigError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
EcdsaSigError::NonStandardSigHashType(hash_ty) => EcdsaSigError::NonStandardSighashType(hash_ty) =>
write!(f, "Non standard signature hash type {}", hash_ty), write!(f, "Non standard signature hash type {}", hash_ty),
EcdsaSigError::Secp256k1(ref e) => EcdsaSigError::Secp256k1(ref e) =>
write!(f, "Invalid Ecdsa signature: {}", e), write!(f, "Invalid Ecdsa signature: {}", e),
@ -123,9 +123,9 @@ impl From<secp256k1::Error> for EcdsaSigError {
} }
} }
impl From<NonStandardSigHashType> for EcdsaSigError { impl From<NonStandardSighashType> for EcdsaSigError {
fn from(err: NonStandardSigHashType) -> Self { fn from(err: NonStandardSighashType) -> Self {
EcdsaSigError::NonStandardSigHashType(err.0) EcdsaSigError::NonStandardSighashType(err.0)
} }
} }

View File

@ -61,8 +61,8 @@ pub enum Error {
/// Actual /// Actual
actual: Box<Transaction>, actual: Box<Transaction>,
}, },
/// Unable to parse as a standard SigHash type. /// Unable to parse as a standard sighash type.
NonStandardSigHashType(u32), NonStandardSighashType(u32),
/// Parsing errors from bitcoin_hashes /// Parsing errors from bitcoin_hashes
HashParseError(hashes::Error), HashParseError(hashes::Error),
/// The pre-image must hash to the correponding psbt hash /// The pre-image must hash to the correponding psbt hash
@ -88,7 +88,7 @@ impl fmt::Display for Error {
Error::InvalidProprietaryKey => write!(f, "non-proprietary key type found when proprietary key was expected"), Error::InvalidProprietaryKey => write!(f, "non-proprietary key type found when proprietary key was expected"),
Error::DuplicateKey(ref rkey) => write!(f, "duplicate key: {}", rkey), Error::DuplicateKey(ref rkey) => write!(f, "duplicate key: {}", rkey),
Error::UnexpectedUnsignedTx { expected: ref e, actual: ref a } => write!(f, "different unsigned transaction: expected {}, actual {}", e.txid(), a.txid()), Error::UnexpectedUnsignedTx { expected: ref e, actual: ref a } => write!(f, "different unsigned transaction: expected {}, actual {}", e.txid(), a.txid()),
Error::NonStandardSigHashType(ref sht) => write!(f, "non-standard sighash type: {}", sht), Error::NonStandardSighashType(ref sht) => write!(f, "non-standard sighash type: {}", sht),
Error::InvalidMagic => f.write_str("invalid magic"), Error::InvalidMagic => f.write_str("invalid magic"),
Error::InvalidSeparator => f.write_str("invalid separator"), Error::InvalidSeparator => f.write_str("invalid separator"),
Error::UnsignedTxHasScriptSigs => f.write_str("the unsigned transaction has script sigs"), Error::UnsignedTxHasScriptSigs => f.write_str("the unsigned transaction has script sigs"),

View File

@ -20,7 +20,7 @@ use core::str::FromStr;
use secp256k1; use secp256k1;
use blockdata::script::Script; use blockdata::script::Script;
use blockdata::witness::Witness; use blockdata::witness::Witness;
use blockdata::transaction::{Transaction, TxOut, NonStandardSigHashType, SigHashTypeParseError}; use blockdata::transaction::{Transaction, TxOut, NonStandardSighashType, SighashTypeParseError};
use consensus::encode; use consensus::encode;
use hashes::{self, hash160, ripemd160, sha256, sha256d}; use hashes::{self, hash160, ripemd160, sha256, sha256d};
use secp256k1::XOnlyPublicKey; use secp256k1::XOnlyPublicKey;
@ -34,7 +34,7 @@ use util::key::PublicKey;
use util::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapBranchHash}; use util::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapBranchHash};
use util::sighash; use util::sighash;
use {EcdsaSigHashType, SchnorrSigHashType, EcdsaSig, SchnorrSig}; use {EcdsaSighashType, SchnorrSighashType, EcdsaSig, SchnorrSig};
/// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00 /// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00
const PSBT_IN_NON_WITNESS_UTXO: u8 = 0x00; const PSBT_IN_NON_WITNESS_UTXO: u8 = 0x00;
@ -95,7 +95,7 @@ pub struct Input {
pub partial_sigs: BTreeMap<PublicKey, EcdsaSig>, pub partial_sigs: BTreeMap<PublicKey, EcdsaSig>,
/// The sighash type to be used for this input. Signatures for this input /// The sighash type to be used for this input. Signatures for this input
/// must use the sighash type. /// must use the sighash type.
pub sighash_type: Option<PsbtSigHashType>, pub sighash_type: Option<PsbtSighashType>,
/// The redeem script for this input. /// The redeem script for this input.
pub redeem_script: Option<Script>, pub redeem_script: Option<Script>,
/// The witness script for this input. /// The witness script for this input.
@ -148,26 +148,26 @@ pub struct Input {
/// A Signature hash type for the corresponding input. As of taproot upgrade, the signature hash /// A Signature hash type for the corresponding input. As of taproot upgrade, the signature hash
/// type can be either [`EcdsaSigHashType`] or [`SchnorrSigHashType`] but it is not possible to know /// type can be either [`EcdsaSighashType`] or [`SchnorrSighashType`] but it is not possible to know
/// directly which signature hash type the user is dealing with. Therefore, the user is responsible /// directly which signature hash type the user is dealing with. Therefore, the user is responsible
/// for converting to/from [`PsbtSigHashType`] from/to the desired signature hash type they need. /// for converting to/from [`PsbtSighashType`] from/to the desired signature hash type they need.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct PsbtSigHashType { pub struct PsbtSighashType {
pub (in ::util::psbt) inner: u32, pub (in ::util::psbt) inner: u32,
} }
impl fmt::Display for PsbtSigHashType { impl fmt::Display for PsbtSighashType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.schnorr_hash_ty() { match self.schnorr_hash_ty() {
Ok(SchnorrSigHashType::Reserved) | Err(_) => write!(f, "{:#x}", self.inner), Ok(SchnorrSighashType::Reserved) | Err(_) => write!(f, "{:#x}", self.inner),
Ok(schnorr_hash_ty) => fmt::Display::fmt(&schnorr_hash_ty, f), Ok(schnorr_hash_ty) => fmt::Display::fmt(&schnorr_hash_ty, f),
} }
} }
} }
impl FromStr for PsbtSigHashType { impl FromStr for PsbtSighashType {
type Err = SigHashTypeParseError; type Err = SighashTypeParseError;
#[inline] #[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
@ -176,8 +176,8 @@ impl FromStr for PsbtSigHashType {
// NB: some of Schnorr sighash types are non-standard for pre-taproot // NB: some of Schnorr sighash types are non-standard for pre-taproot
// inputs. We also do not support SIGHASH_RESERVED in verbatim form // inputs. We also do not support SIGHASH_RESERVED in verbatim form
// ("0xFF" string should be used instead). // ("0xFF" string should be used instead).
match SchnorrSigHashType::from_str(s) { match SchnorrSighashType::from_str(s) {
Ok(SchnorrSigHashType::Reserved) => return Err(SigHashTypeParseError{ unrecognized: s.to_owned() }), Ok(SchnorrSighashType::Reserved) => return Err(SighashTypeParseError{ unrecognized: s.to_owned() }),
Ok(ty) => return Ok(ty.into()), Ok(ty) => return Ok(ty.into()),
Err(_) => {} Err(_) => {}
} }
@ -185,51 +185,51 @@ impl FromStr for PsbtSigHashType {
// We accept non-standard sighash values. // We accept non-standard sighash values.
// TODO: Swap `trim_left_matches` for `trim_start_matches` once MSRV >= 1.30. // TODO: Swap `trim_left_matches` for `trim_start_matches` once MSRV >= 1.30.
if let Ok(inner) = u32::from_str_radix(s.trim_left_matches("0x"), 16) { if let Ok(inner) = u32::from_str_radix(s.trim_left_matches("0x"), 16) {
return Ok(PsbtSigHashType { inner }); return Ok(PsbtSighashType { inner });
} }
Err(SigHashTypeParseError{ unrecognized: s.to_owned() }) Err(SighashTypeParseError{ unrecognized: s.to_owned() })
} }
} }
impl From<EcdsaSigHashType> for PsbtSigHashType { impl From<EcdsaSighashType> for PsbtSighashType {
fn from(ecdsa_hash_ty: EcdsaSigHashType) -> Self { fn from(ecdsa_hash_ty: EcdsaSighashType) -> Self {
PsbtSigHashType { inner: ecdsa_hash_ty as u32 } PsbtSighashType { inner: ecdsa_hash_ty as u32 }
} }
} }
impl From<SchnorrSigHashType> for PsbtSigHashType { impl From<SchnorrSighashType> for PsbtSighashType {
fn from(schnorr_hash_ty: SchnorrSigHashType) -> Self { fn from(schnorr_hash_ty: SchnorrSighashType) -> Self {
PsbtSigHashType { inner: schnorr_hash_ty as u32 } PsbtSighashType { inner: schnorr_hash_ty as u32 }
} }
} }
impl PsbtSigHashType { impl PsbtSighashType {
/// Returns the [`EcdsaSigHashType`] if the [`PsbtSigHashType`] can be /// Returns the [`EcdsaSighashType`] if the [`PsbtSighashType`] can be
/// converted to one. /// converted to one.
pub fn ecdsa_hash_ty(self) -> Result<EcdsaSigHashType, NonStandardSigHashType> { pub fn ecdsa_hash_ty(self) -> Result<EcdsaSighashType, NonStandardSighashType> {
EcdsaSigHashType::from_standard(self.inner) EcdsaSighashType::from_standard(self.inner)
} }
/// Returns the [`SchnorrSigHashType`] if the [`PsbtSigHashType`] can be /// Returns the [`SchnorrSighashType`] if the [`PsbtSighashType`] can be
/// converted to one. /// converted to one.
pub fn schnorr_hash_ty(self) -> Result<SchnorrSigHashType, sighash::Error> { pub fn schnorr_hash_ty(self) -> Result<SchnorrSighashType, sighash::Error> {
if self.inner > 0xffu32 { if self.inner > 0xffu32 {
Err(sighash::Error::InvalidSigHashType(self.inner)) Err(sighash::Error::InvalidSighashType(self.inner))
} else { } else {
SchnorrSigHashType::from_u8(self.inner as u8) SchnorrSighashType::from_u8(self.inner as u8)
} }
} }
/// Creates a [`PsbtSigHashType`] from a raw `u32`. /// Creates a [`PsbtSighashType`] from a raw `u32`.
/// ///
/// Allows construction of a non-standard or non-valid sighash flag /// Allows construction of a non-standard or non-valid sighash flag
/// ([`EcdsaSigHashType`], [`SchnorrSigHashType`] respectively). /// ([`EcdsaSighashType`], [`SchnorrSighashType`] respectively).
pub fn from_u32(n: u32) -> PsbtSigHashType { pub fn from_u32(n: u32) -> PsbtSighashType {
PsbtSigHashType { inner: n } PsbtSighashType { inner: n }
} }
/// Converts [`PsbtSigHashType`] to a raw `u32` sighash flag. /// Converts [`PsbtSighashType`] to a raw `u32` sighash flag.
/// ///
/// No guarantees are made as to the standardness or validity of the returned value. /// No guarantees are made as to the standardness or validity of the returned value.
pub fn to_u32(self) -> u32 { pub fn to_u32(self) -> u32 {
@ -238,28 +238,28 @@ impl PsbtSigHashType {
} }
impl Input { impl Input {
/// Obtains the [`EcdsaSigHashType`] for this input if one is specified. If no sighash type is /// Obtains the [`EcdsaSighashType`] for this input if one is specified. If no sighash type is
/// specified, returns [`EcdsaSigHashType::All`]. /// specified, returns [`EcdsaSighashType::All`].
/// ///
/// # Errors /// # Errors
/// ///
/// If the `sighash_type` field is set to a non-standard ECDSA sighash value. /// If the `sighash_type` field is set to a non-standard ECDSA sighash value.
pub fn ecdsa_hash_ty(&self) -> Result<EcdsaSigHashType, NonStandardSigHashType> { pub fn ecdsa_hash_ty(&self) -> Result<EcdsaSighashType, NonStandardSighashType> {
self.sighash_type self.sighash_type
.map(|sighash_type| sighash_type.ecdsa_hash_ty()) .map(|sighash_type| sighash_type.ecdsa_hash_ty())
.unwrap_or(Ok(EcdsaSigHashType::All)) .unwrap_or(Ok(EcdsaSighashType::All))
} }
/// Obtains the [`SchnorrSigHashType`] for this input if one is specified. If no sighash type is /// Obtains the [`SchnorrSighashType`] for this input if one is specified. If no sighash type is
/// specified, returns [`SchnorrSigHashType::Default`]. /// specified, returns [`SchnorrSighashType::Default`].
/// ///
/// # Errors /// # Errors
/// ///
/// If the `sighash_type` field is set to a invalid Schnorr sighash value. /// If the `sighash_type` field is set to a invalid Schnorr sighash value.
pub fn schnorr_hash_ty(&self) -> Result<SchnorrSigHashType, sighash::Error> { pub fn schnorr_hash_ty(&self) -> Result<SchnorrSighashType, sighash::Error> {
self.sighash_type self.sighash_type
.map(|sighash_type| sighash_type.schnorr_hash_ty()) .map(|sighash_type| sighash_type.schnorr_hash_ty())
.unwrap_or(Ok(SchnorrSigHashType::Default)) .unwrap_or(Ok(SchnorrSighashType::Default))
} }
pub(super) fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> { pub(super) fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> {
@ -286,7 +286,7 @@ impl Input {
} }
PSBT_IN_SIGHASH_TYPE => { PSBT_IN_SIGHASH_TYPE => {
impl_psbt_insert_pair! { impl_psbt_insert_pair! {
self.sighash_type <= <raw_key: _>|<raw_value: PsbtSigHashType> self.sighash_type <= <raw_key: _>|<raw_value: PsbtSighashType>
} }
} }
PSBT_IN_REDEEM_SCRIPT => { PSBT_IN_REDEEM_SCRIPT => {
@ -544,16 +544,16 @@ mod test {
#[test] #[test]
fn psbt_sighash_type_ecdsa() { fn psbt_sighash_type_ecdsa() {
for ecdsa in &[ for ecdsa in &[
EcdsaSigHashType::All, EcdsaSighashType::All,
EcdsaSigHashType::None, EcdsaSighashType::None,
EcdsaSigHashType::Single, EcdsaSighashType::Single,
EcdsaSigHashType::AllPlusAnyoneCanPay, EcdsaSighashType::AllPlusAnyoneCanPay,
EcdsaSigHashType::NonePlusAnyoneCanPay, EcdsaSighashType::NonePlusAnyoneCanPay,
EcdsaSigHashType::SinglePlusAnyoneCanPay, EcdsaSighashType::SinglePlusAnyoneCanPay,
] { ] {
let sighash = PsbtSigHashType::from(*ecdsa); let sighash = PsbtSighashType::from(*ecdsa);
let s = format!("{}", sighash); let s = format!("{}", sighash);
let back = PsbtSigHashType::from_str(&s).unwrap(); let back = PsbtSighashType::from_str(&s).unwrap();
assert_eq!(back, sighash); assert_eq!(back, sighash);
assert_eq!(back.ecdsa_hash_ty().unwrap(), *ecdsa); assert_eq!(back.ecdsa_hash_ty().unwrap(), *ecdsa);
} }
@ -562,17 +562,17 @@ mod test {
#[test] #[test]
fn psbt_sighash_type_schnorr() { fn psbt_sighash_type_schnorr() {
for schnorr in &[ for schnorr in &[
SchnorrSigHashType::Default, SchnorrSighashType::Default,
SchnorrSigHashType::All, SchnorrSighashType::All,
SchnorrSigHashType::None, SchnorrSighashType::None,
SchnorrSigHashType::Single, SchnorrSighashType::Single,
SchnorrSigHashType::AllPlusAnyoneCanPay, SchnorrSighashType::AllPlusAnyoneCanPay,
SchnorrSigHashType::NonePlusAnyoneCanPay, SchnorrSighashType::NonePlusAnyoneCanPay,
SchnorrSigHashType::SinglePlusAnyoneCanPay, SchnorrSighashType::SinglePlusAnyoneCanPay,
] { ] {
let sighash = PsbtSigHashType::from(*schnorr); let sighash = PsbtSighashType::from(*schnorr);
let s = format!("{}", sighash); let s = format!("{}", sighash);
let back = PsbtSigHashType::from_str(&s).unwrap(); let back = PsbtSighashType::from_str(&s).unwrap();
assert_eq!(back, sighash); assert_eq!(back, sighash);
assert_eq!(back.schnorr_hash_ty().unwrap(), *schnorr); assert_eq!(back.schnorr_hash_ty().unwrap(), *schnorr);
} }
@ -581,12 +581,12 @@ mod test {
#[test] #[test]
fn psbt_sighash_type_schnorr_notstd() { fn psbt_sighash_type_schnorr_notstd() {
for (schnorr, schnorr_str) in &[ for (schnorr, schnorr_str) in &[
(SchnorrSigHashType::Reserved, "0xff"), (SchnorrSighashType::Reserved, "0xff"),
] { ] {
let sighash = PsbtSigHashType::from(*schnorr); let sighash = PsbtSighashType::from(*schnorr);
let s = format!("{}", sighash); let s = format!("{}", sighash);
assert_eq!(&s, schnorr_str); assert_eq!(&s, schnorr_str);
let back = PsbtSigHashType::from_str(&s).unwrap(); let back = PsbtSighashType::from_str(&s).unwrap();
assert_eq!(back, sighash); assert_eq!(back, sighash);
assert_eq!(back.schnorr_hash_ty().unwrap(), *schnorr); assert_eq!(back.schnorr_hash_ty().unwrap(), *schnorr);
} }
@ -595,12 +595,12 @@ mod test {
#[test] #[test]
fn psbt_sighash_type_notstd() { fn psbt_sighash_type_notstd() {
let nonstd = 0xdddddddd; let nonstd = 0xdddddddd;
let sighash = PsbtSigHashType { inner: nonstd }; let sighash = PsbtSighashType { inner: nonstd };
let s = format!("{}", sighash); let s = format!("{}", sighash);
let back = PsbtSigHashType::from_str(&s).unwrap(); let back = PsbtSighashType::from_str(&s).unwrap();
assert_eq!(back, sighash); assert_eq!(back, sighash);
assert_eq!(back.ecdsa_hash_ty(), Err(NonStandardSigHashType(nonstd))); assert_eq!(back.ecdsa_hash_ty(), Err(NonStandardSighashType(nonstd)));
assert_eq!(back.schnorr_hash_ty(), Err(sighash::Error::InvalidSigHashType(nonstd))); assert_eq!(back.schnorr_hash_ty(), Err(sighash::Error::InvalidSighashType(nonstd)));
} }
} }

View File

@ -23,7 +23,7 @@ mod global;
mod input; mod input;
mod output; mod output;
pub use self::input::{Input, PsbtSigHashType}; pub use self::input::{Input, PsbtSighashType};
pub use self::output::{Output, TapTree}; pub use self::output::{Output, TapTree};
/// A trait that describes a PSBT key-value map. /// A trait that describes a PSBT key-value map.

View File

@ -16,7 +16,7 @@
//! //!
//! Implementation of BIP174 Partially Signed Bitcoin Transaction Format as //! Implementation of BIP174 Partially Signed Bitcoin Transaction Format as
//! defined at <https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki> //! defined at <https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki>
//! except we define PSBTs containing non-standard SigHash types as invalid. //! except we define PSBTs containing non-standard sighash types as invalid.
//! //!
use core::cmp; use core::cmp;
@ -41,7 +41,7 @@ mod macros;
pub mod serialize; pub mod serialize;
mod map; mod map;
pub use self::map::{Input, Output, TapTree, PsbtSigHashType}; pub use self::map::{Input, Output, TapTree, PsbtSighashType};
use self::map::Map; use self::map::Map;
use util::bip32::{ExtendedPubKey, KeySource}; use util::bip32::{ExtendedPubKey, KeySource};
@ -468,7 +468,7 @@ mod tests {
//! Create a full PSBT value with various fields filled and make sure it can be JSONized. //! Create a full PSBT value with various fields filled and make sure it can be JSONized.
use hashes::sha256d; use hashes::sha256d;
use util::psbt::map::Input; use util::psbt::map::Input;
use EcdsaSigHashType; use EcdsaSighashType;
// create some values to use in the PSBT // create some values to use in the PSBT
let tx = Transaction { let tx = Transaction {
@ -532,7 +532,7 @@ mod tests {
value: 190303501938, value: 190303501938,
script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"), script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"),
}), }),
sighash_type: Some("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse::<EcdsaSigHashType>().unwrap().into()), sighash_type: Some("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse::<EcdsaSighashType>().unwrap().into()),
redeem_script: Some(vec![0x51].into()), redeem_script: Some(vec![0x51].into()),
witness_script: None, witness_script: None,
partial_sigs: vec![( partial_sigs: vec![(
@ -569,7 +569,7 @@ mod tests {
use hash_types::Txid; use hash_types::Txid;
use blockdata::script::Script; use blockdata::script::Script;
use blockdata::transaction::{EcdsaSigHashType, Transaction, TxIn, TxOut, OutPoint}; use blockdata::transaction::{EcdsaSighashType, Transaction, TxIn, TxOut, OutPoint};
use consensus::encode::serialize_hex; use consensus::encode::serialize_hex;
use util::psbt::map::{Map, Input, Output}; use util::psbt::map::{Map, Input, Output};
use util::psbt::raw; use util::psbt::raw;
@ -795,7 +795,7 @@ mod tests {
); );
assert_eq!( assert_eq!(
(&psbt.inputs[0].sighash_type).as_ref().unwrap().ecdsa_hash_ty().unwrap(), (&psbt.inputs[0].sighash_type).as_ref().unwrap().ecdsa_hash_ty().unwrap(),
EcdsaSigHashType::All EcdsaSighashType::All
); );
} }

View File

@ -35,7 +35,7 @@ use util::taproot::{TapBranchHash, TapLeafHash, ControlBlock, LeafVersion};
use schnorr; use schnorr;
use util::key::PublicKey; use util::key::PublicKey;
use super::map::{TapTree, PsbtSigHashType}; use super::map::{TapTree, PsbtSighashType};
use util::taproot::TaprootBuilder; use util::taproot::TaprootBuilder;
/// A trait for serializing a value as raw data for insertion into PSBT /// A trait for serializing a value as raw data for insertion into PSBT
@ -118,7 +118,7 @@ impl Deserialize for EcdsaSig {
// //
// 1) the current implementation of from_u32_consensus(`flag`) does not preserve // 1) the current implementation of from_u32_consensus(`flag`) does not preserve
// the sighash byte `flag` mapping all unknown values to EcdsaSighashType::All or // the sighash byte `flag` mapping all unknown values to EcdsaSighashType::All or
// EcdsaSigHashType::AllPlusAnyOneCanPay. Therefore, break the invariant // EcdsaSighashType::AllPlusAnyOneCanPay. Therefore, break the invariant
// EcdsaSig::from_slice(&sl[..]).to_vec = sl. // EcdsaSig::from_slice(&sl[..]).to_vec = sl.
// //
// 2) This would cause to have invalid signatures because the sighash message // 2) This would cause to have invalid signatures because the sighash message
@ -130,8 +130,8 @@ impl Deserialize for EcdsaSig {
EcdsaSigError::EmptySignature => { EcdsaSigError::EmptySignature => {
encode::Error::ParseFailed("Empty partial signature data") encode::Error::ParseFailed("Empty partial signature data")
} }
EcdsaSigError::NonStandardSigHashType(flag) => { EcdsaSigError::NonStandardSighashType(flag) => {
encode::Error::from(psbt::Error::NonStandardSigHashType(flag)) encode::Error::from(psbt::Error::NonStandardSighashType(flag))
} }
EcdsaSigError::Secp256k1(..) => { EcdsaSigError::Secp256k1(..) => {
encode::Error::ParseFailed("Invalid Ecdsa signature") encode::Error::ParseFailed("Invalid Ecdsa signature")
@ -191,16 +191,16 @@ impl Deserialize for Vec<u8> {
} }
} }
impl Serialize for PsbtSigHashType { impl Serialize for PsbtSighashType {
fn serialize(&self) -> Vec<u8> { fn serialize(&self) -> Vec<u8> {
serialize(&self.to_u32()) serialize(&self.to_u32())
} }
} }
impl Deserialize for PsbtSigHashType { impl Deserialize for PsbtSighashType {
fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error> { fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error> {
let raw: u32 = encode::deserialize(bytes)?; let raw: u32 = encode::deserialize(bytes)?;
Ok(PsbtSigHashType { inner: raw }) Ok(PsbtSighashType { inner: raw })
} }
} }
@ -229,7 +229,7 @@ impl Deserialize for schnorr::SchnorrSig {
schnorr::SchnorrSig::from_slice(&bytes) schnorr::SchnorrSig::from_slice(&bytes)
.map_err(|e| match e { .map_err(|e| match e {
schnorr::SchnorrSigError::InvalidSighashType(flag) => { schnorr::SchnorrSigError::InvalidSighashType(flag) => {
encode::Error::from(psbt::Error::NonStandardSigHashType(flag as u32)) encode::Error::from(psbt::Error::NonStandardSighashType(flag as u32))
} }
schnorr::SchnorrSigError::InvalidSchnorrSigSize(_) => { schnorr::SchnorrSigError::InvalidSchnorrSigSize(_) => {
encode::Error::ParseFailed("Invalid Schnorr signature length") encode::Error::ParseFailed("Invalid Schnorr signature length")
@ -373,9 +373,9 @@ mod tests {
use super::*; use super::*;
#[test] #[test]
fn can_deserialize_non_standard_psbt_sig_hash_type() { fn can_deserialize_non_standard_psbt_sighash_type() {
let non_standard_sighash = [222u8, 0u8, 0u8, 0u8]; // 32 byte value. let non_standard_sighash = [222u8, 0u8, 0u8, 0u8]; // 32 byte value.
let sighash = PsbtSigHashType::deserialize(&non_standard_sighash); let sighash = PsbtSighashType::deserialize(&non_standard_sighash);
assert!(sighash.is_ok()) assert!(sighash.is_ok())
} }
} }

View File

@ -25,7 +25,7 @@ use secp256k1::{XOnlyPublicKey as _XOnlyPublicKey, KeyPair as _KeyPair};
use secp256k1::{self, Secp256k1, Verification, constants}; use secp256k1::{self, Secp256k1, Verification, constants};
use hashes::Hash; use hashes::Hash;
use util::taproot::{TapBranchHash, TapTweakHash}; use util::taproot::{TapBranchHash, TapTweakHash};
use SchnorrSigHashType; use SchnorrSighashType;
/// Deprecated re-export of [`secp256k1::XOnlyPublicKey`] /// Deprecated re-export of [`secp256k1::XOnlyPublicKey`]
#[deprecated(since = "0.28.0", note = "Please use `util::key::XOnlyPublicKey` instead")] #[deprecated(since = "0.28.0", note = "Please use `util::key::XOnlyPublicKey` instead")]
@ -220,7 +220,7 @@ pub struct SchnorrSig {
/// The underlying schnorr signature /// The underlying schnorr signature
pub sig: secp256k1::schnorr::Signature, pub sig: secp256k1::schnorr::Signature,
/// The corresponding hash type /// The corresponding hash type
pub hash_ty: SchnorrSigHashType, pub hash_ty: SchnorrSighashType,
} }
impl SchnorrSig { impl SchnorrSig {
@ -231,11 +231,11 @@ impl SchnorrSig {
// default type // default type
let sig = secp256k1::schnorr::Signature::from_slice(sl) let sig = secp256k1::schnorr::Signature::from_slice(sl)
.map_err(SchnorrSigError::Secp256k1)?; .map_err(SchnorrSigError::Secp256k1)?;
return Ok( SchnorrSig { sig, hash_ty : SchnorrSigHashType::Default }); return Ok( SchnorrSig { sig, hash_ty : SchnorrSighashType::Default });
}, },
65 => { 65 => {
let (hash_ty, sig) = sl.split_last().expect("Slice len checked == 65"); let (hash_ty, sig) = sl.split_last().expect("Slice len checked == 65");
let hash_ty = SchnorrSigHashType::from_u8(*hash_ty) let hash_ty = SchnorrSighashType::from_u8(*hash_ty)
.map_err(|_| SchnorrSigError::InvalidSighashType(*hash_ty))?; .map_err(|_| SchnorrSigError::InvalidSighashType(*hash_ty))?;
let sig = secp256k1::schnorr::Signature::from_slice(sig) let sig = secp256k1::schnorr::Signature::from_slice(sig)
.map_err(SchnorrSigError::Secp256k1)?; .map_err(SchnorrSigError::Secp256k1)?;
@ -251,7 +251,7 @@ impl SchnorrSig {
pub fn to_vec(&self) -> Vec<u8> { pub fn to_vec(&self) -> Vec<u8> {
// TODO: add support to serialize to a writer to SerializedSig // TODO: add support to serialize to a writer to SerializedSig
let mut ser_sig = self.sig.as_ref().to_vec(); let mut ser_sig = self.sig.as_ref().to_vec();
if self.hash_ty == SchnorrSigHashType::Default { if self.hash_ty == SchnorrSighashType::Default {
// default sighash type, don't add extra sighash byte // default sighash type, don't add extra sighash byte
} else { } else {
ser_sig.push(self.hash_ty as u8); ser_sig.push(self.hash_ty as u8);

View File

@ -22,7 +22,7 @@
use prelude::*; use prelude::*;
pub use blockdata::transaction::{EcdsaSigHashType, SigHashTypeParseError}; pub use blockdata::transaction::{EcdsaSighashType, SighashTypeParseError};
use blockdata::witness::Witness; use blockdata::witness::Witness;
use consensus::{encode, Encodable}; use consensus::{encode, Encodable};
use core::{str, fmt}; use core::{str, fmt};
@ -31,17 +31,17 @@ use core::borrow::Borrow;
use hashes::{sha256, sha256d, Hash}; use hashes::{sha256, sha256d, Hash};
use io; use io;
use util::taproot::{TapLeafHash, TAPROOT_ANNEX_PREFIX, TapSighashHash}; use util::taproot::{TapLeafHash, TAPROOT_ANNEX_PREFIX, TapSighashHash};
use SigHash; use Sighash;
use {Script, Transaction, TxOut}; use {Script, Transaction, TxOut};
use super::taproot::LeafVersion; use super::taproot::LeafVersion;
/// Efficiently calculates signature hash message for legacy, segwit and taproot inputs. /// Efficiently calculates signature hash message for legacy, segwit and taproot inputs.
#[derive(Debug)] #[derive(Debug)]
pub struct SigHashCache<T: Deref<Target=Transaction>> { pub struct SighashCache<T: Deref<Target=Transaction>> {
/// Access to transaction required for various introspection, moreover type /// Access to transaction required for various introspection, moreover type
/// `T: Deref<Target=Transaction>` allows to accept borrow and mutable borrow, the /// `T: Deref<Target=Transaction>` allows to accept borrow and mutable borrow, the
/// latter in particular is necessary for [`SigHashCache::witness_mut`] /// latter in particular is necessary for [`SighashCache::witness_mut`]
tx: T, tx: T,
/// Common cache for taproot and segwit inputs. It's an option because it's not needed for legacy inputs /// Common cache for taproot and segwit inputs. It's an option because it's not needed for legacy inputs
@ -81,7 +81,7 @@ struct TaprootCache {
} }
/// Contains outputs of previous transactions. /// Contains outputs of previous transactions.
/// In the case [`SchnorrSigHashType`] variant is `ANYONECANPAY`, [`Prevouts::One`] may be provided /// In the case [`SchnorrSighashType`] variant is `ANYONECANPAY`, [`Prevouts::One`] may be provided
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Prevouts<'u, T> where T: 'u + Borrow<TxOut> { pub enum Prevouts<'u, T> where T: 'u + Borrow<TxOut> {
/// `One` variant allows to provide the single Prevout needed. It's useful for example /// `One` variant allows to provide the single Prevout needed. It's useful for example
@ -107,8 +107,8 @@ pub struct ScriptPath<'s> {
/// Hashtype of an input's signature, encoded in the last byte of the signature /// 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 /// Fixed values so they can be casted as integer types for encoding
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum SchnorrSigHashType { pub enum SchnorrSighashType {
/// 0x0: Used when not explicitly specified, defaulting to [`SchnorrSigHashType::All`] /// 0x0: Used when not explicitly specified, defaulting to [`SchnorrSighashType::All`]
Default = 0x00, Default = 0x00,
/// 0x1: Sign all outputs /// 0x1: Sign all outputs
All = 0x01, All = 0x01,
@ -129,38 +129,38 @@ pub enum SchnorrSigHashType {
/// Reserved for future use, `#[non_exhaustive]` is not available with current MSRV /// Reserved for future use, `#[non_exhaustive]` is not available with current MSRV
Reserved = 0xFF, Reserved = 0xFF,
} }
serde_string_impl!(SchnorrSigHashType, "a SchnorrSigHashType data"); serde_string_impl!(SchnorrSighashType, "a SchnorrSighashType data");
impl fmt::Display for SchnorrSigHashType { impl fmt::Display for SchnorrSighashType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self { let s = match self {
SchnorrSigHashType::Default => "SIGHASH_DEFAULT", SchnorrSighashType::Default => "SIGHASH_DEFAULT",
SchnorrSigHashType::All => "SIGHASH_ALL", SchnorrSighashType::All => "SIGHASH_ALL",
SchnorrSigHashType::None => "SIGHASH_NONE", SchnorrSighashType::None => "SIGHASH_NONE",
SchnorrSigHashType::Single => "SIGHASH_SINGLE", SchnorrSighashType::Single => "SIGHASH_SINGLE",
SchnorrSigHashType::AllPlusAnyoneCanPay => "SIGHASH_ALL|SIGHASH_ANYONECANPAY", SchnorrSighashType::AllPlusAnyoneCanPay => "SIGHASH_ALL|SIGHASH_ANYONECANPAY",
SchnorrSigHashType::NonePlusAnyoneCanPay => "SIGHASH_NONE|SIGHASH_ANYONECANPAY", SchnorrSighashType::NonePlusAnyoneCanPay => "SIGHASH_NONE|SIGHASH_ANYONECANPAY",
SchnorrSigHashType::SinglePlusAnyoneCanPay => "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", SchnorrSighashType::SinglePlusAnyoneCanPay => "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY",
SchnorrSigHashType::Reserved => "SIGHASH_RESERVED", SchnorrSighashType::Reserved => "SIGHASH_RESERVED",
}; };
f.write_str(s) f.write_str(s)
} }
} }
impl str::FromStr for SchnorrSigHashType { impl str::FromStr for SchnorrSighashType {
type Err = SigHashTypeParseError; type Err = SighashTypeParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
match s { match s {
"SIGHASH_DEFAULT" => Ok(SchnorrSigHashType::Default), "SIGHASH_DEFAULT" => Ok(SchnorrSighashType::Default),
"SIGHASH_ALL" => Ok(SchnorrSigHashType::All), "SIGHASH_ALL" => Ok(SchnorrSighashType::All),
"SIGHASH_NONE" => Ok(SchnorrSigHashType::None), "SIGHASH_NONE" => Ok(SchnorrSighashType::None),
"SIGHASH_SINGLE" => Ok(SchnorrSigHashType::Single), "SIGHASH_SINGLE" => Ok(SchnorrSighashType::Single),
"SIGHASH_ALL|SIGHASH_ANYONECANPAY" => Ok(SchnorrSigHashType::AllPlusAnyoneCanPay), "SIGHASH_ALL|SIGHASH_ANYONECANPAY" => Ok(SchnorrSighashType::AllPlusAnyoneCanPay),
"SIGHASH_NONE|SIGHASH_ANYONECANPAY" => Ok(SchnorrSigHashType::NonePlusAnyoneCanPay), "SIGHASH_NONE|SIGHASH_ANYONECANPAY" => Ok(SchnorrSighashType::NonePlusAnyoneCanPay),
"SIGHASH_SINGLE|SIGHASH_ANYONECANPAY" => Ok(SchnorrSigHashType::SinglePlusAnyoneCanPay), "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY" => Ok(SchnorrSighashType::SinglePlusAnyoneCanPay),
"SIGHASH_RESERVED" => Ok(SchnorrSigHashType::Reserved), "SIGHASH_RESERVED" => Ok(SchnorrSighashType::Reserved),
_ => Err(SigHashTypeParseError{ unrecognized: s.to_owned() }), _ => Err(SighashTypeParseError{ unrecognized: s.to_owned() }),
} }
} }
} }
@ -204,7 +204,7 @@ pub enum Error {
WrongAnnex, WrongAnnex,
/// Invalid Sighash type /// Invalid Sighash type
InvalidSigHashType(u32), InvalidSighashType(u32),
} }
impl fmt::Display for Error { impl fmt::Display for Error {
@ -217,7 +217,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::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::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::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), Error::InvalidSighashType(hash_ty) => write!(f, "Invalid schnorr Signature hash type : {} ", hash_ty),
} }
} }
} }
@ -288,57 +288,57 @@ impl<'s> From<ScriptPath<'s>> for TapLeafHash {
} }
} }
impl From<EcdsaSigHashType> for SchnorrSigHashType { impl From<EcdsaSighashType> for SchnorrSighashType {
fn from(s: EcdsaSigHashType) -> Self { fn from(s: EcdsaSighashType) -> Self {
match s { match s {
EcdsaSigHashType::All => SchnorrSigHashType::All, EcdsaSighashType::All => SchnorrSighashType::All,
EcdsaSigHashType::None => SchnorrSigHashType::None, EcdsaSighashType::None => SchnorrSighashType::None,
EcdsaSigHashType::Single => SchnorrSigHashType::Single, EcdsaSighashType::Single => SchnorrSighashType::Single,
EcdsaSigHashType::AllPlusAnyoneCanPay => SchnorrSigHashType::AllPlusAnyoneCanPay, EcdsaSighashType::AllPlusAnyoneCanPay => SchnorrSighashType::AllPlusAnyoneCanPay,
EcdsaSigHashType::NonePlusAnyoneCanPay => SchnorrSigHashType::NonePlusAnyoneCanPay, EcdsaSighashType::NonePlusAnyoneCanPay => SchnorrSighashType::NonePlusAnyoneCanPay,
EcdsaSigHashType::SinglePlusAnyoneCanPay => SchnorrSigHashType::SinglePlusAnyoneCanPay, EcdsaSighashType::SinglePlusAnyoneCanPay => SchnorrSighashType::SinglePlusAnyoneCanPay,
} }
} }
} }
impl SchnorrSigHashType { impl SchnorrSighashType {
/// Break the sighash flag into the "real" sighash flag and the ANYONECANPAY boolean /// Break the sighash flag into the "real" sighash flag and the ANYONECANPAY boolean
pub(crate) fn split_anyonecanpay_flag(self) -> (SchnorrSigHashType, bool) { pub(crate) fn split_anyonecanpay_flag(self) -> (SchnorrSighashType, bool) {
match self { match self {
SchnorrSigHashType::Default => (SchnorrSigHashType::Default, false), SchnorrSighashType::Default => (SchnorrSighashType::Default, false),
SchnorrSigHashType::All => (SchnorrSigHashType::All, false), SchnorrSighashType::All => (SchnorrSighashType::All, false),
SchnorrSigHashType::None => (SchnorrSigHashType::None, false), SchnorrSighashType::None => (SchnorrSighashType::None, false),
SchnorrSigHashType::Single => (SchnorrSigHashType::Single, false), SchnorrSighashType::Single => (SchnorrSighashType::Single, false),
SchnorrSigHashType::AllPlusAnyoneCanPay => (SchnorrSigHashType::All, true), SchnorrSighashType::AllPlusAnyoneCanPay => (SchnorrSighashType::All, true),
SchnorrSigHashType::NonePlusAnyoneCanPay => (SchnorrSigHashType::None, true), SchnorrSighashType::NonePlusAnyoneCanPay => (SchnorrSighashType::None, true),
SchnorrSigHashType::SinglePlusAnyoneCanPay => (SchnorrSigHashType::Single, true), SchnorrSighashType::SinglePlusAnyoneCanPay => (SchnorrSighashType::Single, true),
SchnorrSigHashType::Reserved => (SchnorrSigHashType::Reserved, false), SchnorrSighashType::Reserved => (SchnorrSighashType::Reserved, false),
} }
} }
/// Create a [`SchnorrSigHashType`] from raw `u8` /// Create a [`SchnorrSighashType`] from raw `u8`
pub fn from_u8(hash_ty: u8) -> Result<Self, Error> { pub fn from_u8(hash_ty: u8) -> Result<Self, Error> {
match hash_ty { match hash_ty {
0x00 => Ok(SchnorrSigHashType::Default), 0x00 => Ok(SchnorrSighashType::Default),
0x01 => Ok(SchnorrSigHashType::All), 0x01 => Ok(SchnorrSighashType::All),
0x02 => Ok(SchnorrSigHashType::None), 0x02 => Ok(SchnorrSighashType::None),
0x03 => Ok(SchnorrSigHashType::Single), 0x03 => Ok(SchnorrSighashType::Single),
0x81 => Ok(SchnorrSigHashType::AllPlusAnyoneCanPay), 0x81 => Ok(SchnorrSighashType::AllPlusAnyoneCanPay),
0x82 => Ok(SchnorrSigHashType::NonePlusAnyoneCanPay), 0x82 => Ok(SchnorrSighashType::NonePlusAnyoneCanPay),
0x83 => Ok(SchnorrSigHashType::SinglePlusAnyoneCanPay), 0x83 => Ok(SchnorrSighashType::SinglePlusAnyoneCanPay),
0xFF => Ok(SchnorrSigHashType::Reserved), 0xFF => Ok(SchnorrSighashType::Reserved),
x => Err(Error::InvalidSigHashType(x as u32)), x => Err(Error::InvalidSighashType(x as u32)),
} }
} }
} }
impl<R: Deref<Target=Transaction>> SigHashCache<R> { impl<R: Deref<Target=Transaction>> SighashCache<R> {
/// Compute the sighash components from an unsigned transaction and auxiliary /// Compute the sighash components from an unsigned transaction and auxiliary
/// in a lazy manner when required. /// in a lazy manner when required.
/// For the generated sighashes to be valid, no fields in the transaction may change except for /// For the generated sighashes to be valid, no fields in the transaction may change except for
/// script_sig and witnesses. /// script_sig and witnesses.
pub fn new(tx: R) -> Self { pub fn new(tx: R) -> Self {
SigHashCache { SighashCache {
tx, tx,
common_cache: None, common_cache: None,
taproot_cache: None, taproot_cache: None,
@ -355,7 +355,7 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
prevouts: &Prevouts<T>, prevouts: &Prevouts<T>,
annex: Option<Annex>, annex: Option<Annex>,
leaf_hash_code_separator: Option<(TapLeafHash, u32)>, leaf_hash_code_separator: Option<(TapLeafHash, u32)>,
sighash_type: SchnorrSigHashType, sighash_type: SchnorrSighashType,
) -> Result<(), Error> { ) -> Result<(), Error> {
prevouts.check_all(&self.tx)?; prevouts.check_all(&self.tx)?;
@ -395,7 +395,7 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
// If hash_type & 3 does not equal SIGHASH_NONE or SIGHASH_SINGLE: // 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. // sha_outputs (32): the SHA256 of the serialization of all outputs in CTxOut format.
if sighash != SchnorrSigHashType::None && sighash != SchnorrSigHashType::Single { if sighash != SchnorrSighashType::None && sighash != SchnorrSighashType::Single {
self.common_cache().outputs.consensus_encode(&mut writer)?; self.common_cache().outputs.consensus_encode(&mut writer)?;
} }
@ -450,7 +450,7 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
// * Data about this output: // * Data about this output:
// If hash_type & 3 equals SIGHASH_SINGLE: // If hash_type & 3 equals SIGHASH_SINGLE:
// sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. // sha_single_output (32): the SHA256 of the corresponding output in CTxOut format.
if sighash == SchnorrSigHashType::Single { if sighash == SchnorrSighashType::Single {
let mut enc = sha256::Hash::engine(); let mut enc = sha256::Hash::engine();
self.tx self.tx
.output .output
@ -484,7 +484,7 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
prevouts: &Prevouts<T>, prevouts: &Prevouts<T>,
annex: Option<Annex>, annex: Option<Annex>,
leaf_hash_code_separator: Option<(TapLeafHash, u32)>, leaf_hash_code_separator: Option<(TapLeafHash, u32)>,
sighash_type: SchnorrSigHashType, sighash_type: SchnorrSighashType,
) -> Result<TapSighashHash, Error> { ) -> Result<TapSighashHash, Error> {
let mut enc = TapSighashHash::engine(); let mut enc = TapSighashHash::engine();
self.taproot_encode_signing_data_to( self.taproot_encode_signing_data_to(
@ -503,7 +503,7 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
&mut self, &mut self,
input_index: usize, input_index: usize,
prevouts: &Prevouts<T>, prevouts: &Prevouts<T>,
sighash_type: SchnorrSigHashType, sighash_type: SchnorrSighashType,
) -> Result<TapSighashHash, Error> { ) -> Result<TapSighashHash, Error> {
let mut enc = TapSighashHash::engine(); let mut enc = TapSighashHash::engine();
self.taproot_encode_signing_data_to( self.taproot_encode_signing_data_to(
@ -520,13 +520,13 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
/// Compute the BIP341 sighash for a script spend /// Compute the BIP341 sighash for a script spend
/// ///
/// Assumes the default `OP_CODESEPARATOR` position of `0xFFFFFFFF`. Custom values can be /// Assumes the default `OP_CODESEPARATOR` position of `0xFFFFFFFF`. Custom values can be
/// provided through the more fine-grained API of [`SigHashCache::taproot_encode_signing_data_to`]. /// provided through the more fine-grained API of [`SighashCache::taproot_encode_signing_data_to`].
pub fn taproot_script_spend_signature_hash<S: Into<TapLeafHash>, T: Borrow<TxOut>>( pub fn taproot_script_spend_signature_hash<S: Into<TapLeafHash>, T: Borrow<TxOut>>(
&mut self, &mut self,
input_index: usize, input_index: usize,
prevouts: &Prevouts<T>, prevouts: &Prevouts<T>,
leaf_hash: S, leaf_hash: S,
sighash_type: SchnorrSigHashType, sighash_type: SchnorrSighashType,
) -> Result<TapSighashHash, Error> { ) -> Result<TapSighashHash, Error> {
let mut enc = TapSighashHash::engine(); let mut enc = TapSighashHash::engine();
self.taproot_encode_signing_data_to( self.taproot_encode_signing_data_to(
@ -548,7 +548,7 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
input_index: usize, input_index: usize,
script_code: &Script, script_code: &Script,
value: u64, value: u64,
sighash_type: EcdsaSigHashType, sighash_type: EcdsaSighashType,
) -> Result<(), Error> { ) -> Result<(), Error> {
let zero_hash = sha256d::Hash::default(); let zero_hash = sha256d::Hash::default();
@ -563,8 +563,8 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
} }
if !anyone_can_pay if !anyone_can_pay
&& sighash != EcdsaSigHashType::Single && sighash != EcdsaSighashType::Single
&& sighash != EcdsaSigHashType::None && sighash != EcdsaSighashType::None
{ {
self.segwit_cache() self.segwit_cache()
.sequences .sequences
@ -590,12 +590,12 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
txin.sequence.consensus_encode(&mut writer)?; txin.sequence.consensus_encode(&mut writer)?;
} }
if sighash != EcdsaSigHashType::Single && sighash != EcdsaSigHashType::None { if sighash != EcdsaSighashType::Single && sighash != EcdsaSighashType::None {
self.segwit_cache().outputs.consensus_encode(&mut writer)?; self.segwit_cache().outputs.consensus_encode(&mut writer)?;
} else if sighash == EcdsaSigHashType::Single && input_index < self.tx.output.len() { } else if sighash == EcdsaSighashType::Single && input_index < self.tx.output.len() {
let mut single_enc = SigHash::engine(); let mut single_enc = Sighash::engine();
self.tx.output[input_index].consensus_encode(&mut single_enc)?; self.tx.output[input_index].consensus_encode(&mut single_enc)?;
SigHash::from_engine(single_enc).consensus_encode(&mut writer)?; Sighash::from_engine(single_enc).consensus_encode(&mut writer)?;
} else { } else {
zero_hash.consensus_encode(&mut writer)?; zero_hash.consensus_encode(&mut writer)?;
} }
@ -611,9 +611,9 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
input_index: usize, input_index: usize,
script_code: &Script, script_code: &Script,
value: u64, value: u64,
sighash_type: EcdsaSigHashType, sighash_type: EcdsaSighashType,
) -> Result<SigHash, Error> { ) -> Result<Sighash, Error> {
let mut enc = SigHash::engine(); let mut enc = Sighash::engine();
self.segwit_encode_signing_data_to( self.segwit_encode_signing_data_to(
&mut enc, &mut enc,
input_index, input_index,
@ -621,7 +621,7 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
value, value,
sighash_type, sighash_type,
)?; )?;
Ok(SigHash::from_engine(enc)) Ok(Sighash::from_engine(enc))
} }
/// Encode the legacy signing data for any flag type into a given object implementing a /// Encode the legacy signing data for any flag type into a given object implementing a
@ -645,16 +645,16 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
Ok(()) Ok(())
} }
/// Computes the legacy sighash for any SigHashType /// Computes the legacy sighash for any sighash type.
pub fn legacy_signature_hash( pub fn legacy_signature_hash(
&self, &self,
input_index: usize, input_index: usize,
script_pubkey: &Script, script_pubkey: &Script,
sighash_type: u32, sighash_type: u32,
) -> Result<SigHash, Error> { ) -> Result<Sighash, Error> {
let mut enc = SigHash::engine(); let mut enc = Sighash::engine();
self.legacy_encode_signing_data_to(&mut enc, input_index, script_pubkey, sighash_type)?; self.legacy_encode_signing_data_to(&mut enc, input_index, script_pubkey, sighash_type)?;
Ok(SigHash::from_engine(enc)) Ok(Sighash::from_engine(enc))
} }
#[inline] #[inline]
@ -729,23 +729,23 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
} }
} }
impl<R: DerefMut<Target=Transaction>> SigHashCache<R> { impl<R: DerefMut<Target=Transaction>> SighashCache<R> {
/// When the SigHashCache is initialized with a mutable reference to a transaction instead of a /// When the SighashCache is initialized with a mutable reference to a transaction instead of a
/// regular reference, this method is available to allow modification to the witnesses. /// regular reference, this method is available to allow modification to the witnesses.
/// ///
/// This allows in-line signing such as /// This allows in-line signing such as
/// ``` /// ```
/// use bitcoin::blockdata::transaction::{Transaction, EcdsaSigHashType}; /// use bitcoin::blockdata::transaction::{Transaction, EcdsaSighashType};
/// use bitcoin::util::sighash::SigHashCache; /// use bitcoin::util::sighash::SighashCache;
/// use bitcoin::Script; /// use bitcoin::Script;
/// ///
/// let mut tx_to_sign = Transaction { version: 2, lock_time: 0, input: Vec::new(), output: Vec::new() }; /// let mut tx_to_sign = Transaction { version: 2, lock_time: 0, input: Vec::new(), output: Vec::new() };
/// let input_count = tx_to_sign.input.len(); /// let input_count = tx_to_sign.input.len();
/// ///
/// let mut sig_hasher = SigHashCache::new(&mut tx_to_sign); /// let mut sig_hasher = SighashCache::new(&mut tx_to_sign);
/// for inp in 0..input_count { /// for inp in 0..input_count {
/// let prevout_script = Script::new(); /// let prevout_script = Script::new();
/// let _sighash = sig_hasher.segwit_signature_hash(inp, &prevout_script, 42, EcdsaSigHashType::All); /// let _sighash = sig_hasher.segwit_signature_hash(inp, &prevout_script, 42, EcdsaSighashType::All);
/// // ... sign the sighash /// // ... sign the sighash
/// sig_hasher.witness_mut(inp).unwrap().push(&Vec::new()); /// sig_hasher.witness_mut(inp).unwrap().push(&Vec::new());
/// } /// }
@ -793,7 +793,7 @@ mod tests {
use consensus::deserialize; use consensus::deserialize;
use hashes::hex::FromHex; use hashes::hex::FromHex;
use hashes::{Hash, HashEngine}; use hashes::{Hash, HashEngine};
use util::sighash::{Annex, Error, Prevouts, ScriptPath, SigHashCache}; use util::sighash::{Annex, Error, Prevouts, ScriptPath, SighashCache};
use std::str::FromStr; use std::str::FromStr;
use hashes::hex::ToHex; use hashes::hex::ToHex;
use util::taproot::{TapTweakHash, TapSighashHash, TapBranchHash, TapLeafHash}; use util::taproot::{TapTweakHash, TapSighashHash, TapBranchHash, TapLeafHash};
@ -823,7 +823,7 @@ mod tests {
"01365724000000000023542156b39dab4f8f3508e0432cfb41fab110170acaa2d4c42539cb90a4dc7c093bc500", "01365724000000000023542156b39dab4f8f3508e0432cfb41fab110170acaa2d4c42539cb90a4dc7c093bc500",
0, 0,
"33ca0ebfb4a945eeee9569fc0f5040221275f88690b7f8592ada88ce3bdf6703", "33ca0ebfb4a945eeee9569fc0f5040221275f88690b7f8592ada88ce3bdf6703",
SchnorrSigHashType::Default, None, None, None SchnorrSighashType::Default, None, None, None
); );
test_taproot_sighash( test_taproot_sighash(
@ -831,7 +831,7 @@ mod tests {
"02591f220000000000225120f25ad35583ea31998d968871d7de1abd2a52f6fe4178b54ea158274806ff4ece48fb310000000000225120f25ad35583ea31998d968871d7de1abd2a52f6fe4178b54ea158274806ff4ece", "02591f220000000000225120f25ad35583ea31998d968871d7de1abd2a52f6fe4178b54ea158274806ff4ece48fb310000000000225120f25ad35583ea31998d968871d7de1abd2a52f6fe4178b54ea158274806ff4ece",
1, 1,
"626ab955d58c9a8a600a0c580549d06dc7da4e802eb2a531f62a588e430967a8", "626ab955d58c9a8a600a0c580549d06dc7da4e802eb2a531f62a588e430967a8",
SchnorrSigHashType::All, None, None, None SchnorrSighashType::All, None, None, None
); );
test_taproot_sighash( test_taproot_sighash(
@ -839,7 +839,7 @@ mod tests {
"01c4811000000000002251201bf9297d0a2968ae6693aadd0fa514717afefd218087a239afb7418e2d22e65c", "01c4811000000000002251201bf9297d0a2968ae6693aadd0fa514717afefd218087a239afb7418e2d22e65c",
0, 0,
"dfa9437f9c9a1d1f9af271f79f2f5482f287cdb0d2e03fa92c8a9b216cc6061c", "dfa9437f9c9a1d1f9af271f79f2f5482f287cdb0d2e03fa92c8a9b216cc6061c",
SchnorrSigHashType::AllPlusAnyoneCanPay, None, None, None SchnorrSighashType::AllPlusAnyoneCanPay, None, None, None
); );
test_taproot_sighash( test_taproot_sighash(
@ -847,7 +847,7 @@ mod tests {
"0144c84d0000000000225120e3f2107989c88e67296ab2faca930efa2e3a5bd3ff0904835a11c9e807458621", "0144c84d0000000000225120e3f2107989c88e67296ab2faca930efa2e3a5bd3ff0904835a11c9e807458621",
0, 0,
"3129de36a5d05fff97ffca31eb75fcccbbbc27b3147a7a36a9e4b45d8b625067", "3129de36a5d05fff97ffca31eb75fcccbbbc27b3147a7a36a9e4b45d8b625067",
SchnorrSigHashType::None, None, None, None SchnorrSighashType::None, None, None, None
); );
test_taproot_sighash( test_taproot_sighash(
@ -855,7 +855,7 @@ mod tests {
"013fed110000000000225120eb536ae8c33580290630fc495046e998086a64f8f33b93b07967d9029b265c55", "013fed110000000000225120eb536ae8c33580290630fc495046e998086a64f8f33b93b07967d9029b265c55",
0, 0,
"2441e8b0e063a2083ee790f14f2045022f07258ddde5ee01de543c9e789d80ae", "2441e8b0e063a2083ee790f14f2045022f07258ddde5ee01de543c9e789d80ae",
SchnorrSigHashType::NonePlusAnyoneCanPay, None, None, None SchnorrSighashType::NonePlusAnyoneCanPay, None, None, None
); );
test_taproot_sighash( test_taproot_sighash(
@ -863,7 +863,7 @@ mod tests {
"01efa558000000000022512007071ea3dc7e331b0687d0193d1e6d6ed10e645ef36f10ef8831d5e522ac9e80", "01efa558000000000022512007071ea3dc7e331b0687d0193d1e6d6ed10e645ef36f10ef8831d5e522ac9e80",
0, 0,
"30239345177cadd0e3ea413d49803580abb6cb27971b481b7788a78d35117a88", "30239345177cadd0e3ea413d49803580abb6cb27971b481b7788a78d35117a88",
SchnorrSigHashType::Single, None, None, None SchnorrSighashType::Single, None, None, None
); );
test_taproot_sighash( test_taproot_sighash(
@ -871,7 +871,7 @@ mod tests {
"0107af4e00000000002251202c36d243dfc06cb56a248e62df27ecba7417307511a81ae61aa41c597a929c69", "0107af4e00000000002251202c36d243dfc06cb56a248e62df27ecba7417307511a81ae61aa41c597a929c69",
0, 0,
"bf9c83f26c6dd16449e4921f813f551c4218e86f2ec906ca8611175b41b566df", "bf9c83f26c6dd16449e4921f813f551c4218e86f2ec906ca8611175b41b566df",
SchnorrSigHashType::SinglePlusAnyoneCanPay, None, None, None SchnorrSighashType::SinglePlusAnyoneCanPay, None, None, None
); );
} }
@ -882,7 +882,7 @@ mod tests {
"01ea49260000000000225120ab5e9800806bf18cb246edcf5fe63441208fe955a4b5a35bbff65f5db622a010", "01ea49260000000000225120ab5e9800806bf18cb246edcf5fe63441208fe955a4b5a35bbff65f5db622a010",
0, 0,
"3b003000add359a364a156e73e02846782a59d0d95ca8c4638aaad99f2ef915c", "3b003000add359a364a156e73e02846782a59d0d95ca8c4638aaad99f2ef915c",
SchnorrSigHashType::SinglePlusAnyoneCanPay, SchnorrSighashType::SinglePlusAnyoneCanPay,
Some("507b979802e62d397acb29f56743a791894b99372872fc5af06a4f6e8d242d0615cda53062bb20e6ec79756fe39183f0c128adfe85559a8fa042b042c018aa8010143799e44f0893c40e1e"), Some("507b979802e62d397acb29f56743a791894b99372872fc5af06a4f6e8d242d0615cda53062bb20e6ec79756fe39183f0c128adfe85559a8fa042b042c018aa8010143799e44f0893c40e1e"),
None, None,
None, None,
@ -896,7 +896,7 @@ mod tests {
"011bec34000000000022512028055142ea437db73382e991861446040b61dd2185c4891d7daf6893d79f7182", "011bec34000000000022512028055142ea437db73382e991861446040b61dd2185c4891d7daf6893d79f7182",
0, 0,
"d66de5274a60400c7b08c86ba6b7f198f40660079edf53aca89d2a9501317f2e", "d66de5274a60400c7b08c86ba6b7f198f40660079edf53aca89d2a9501317f2e",
SchnorrSigHashType::All, SchnorrSighashType::All,
None, None,
Some("20cc4e1107aea1d170c5ff5b6817e1303010049724fb3caa7941792ea9d29b3e2bacab"), Some("20cc4e1107aea1d170c5ff5b6817e1303010049724fb3caa7941792ea9d29b3e2bacab"),
None, None,
@ -910,7 +910,7 @@ mod tests {
"011bec34000000000022512028055142ea437db73382e991861446040b61dd2185c4891d7daf6893d79f7182", "011bec34000000000022512028055142ea437db73382e991861446040b61dd2185c4891d7daf6893d79f7182",
0, 0,
"d66de5274a60400c7b08c86ba6b7f198f40660079edf53aca89d2a9501317f2e", "d66de5274a60400c7b08c86ba6b7f198f40660079edf53aca89d2a9501317f2e",
SchnorrSigHashType::All, SchnorrSighashType::All,
None, None,
None, None,
Some("15a2530514e399f8b5cf0b3d3112cf5b289eaa3e308ba2071b58392fdc6da68a"), Some("15a2530514e399f8b5cf0b3d3112cf5b289eaa3e308ba2071b58392fdc6da68a"),
@ -924,7 +924,7 @@ mod tests {
"011458360000000000225120a7baec3fb9f84614e3899fcc010c638f80f13539344120e1f4d8b68a9a011a13", "011458360000000000225120a7baec3fb9f84614e3899fcc010c638f80f13539344120e1f4d8b68a9a011a13",
0, 0,
"a0042aa434f9a75904b64043f2a283f8b4c143c7f4f7f49a6cbe5b9f745f4c15", "a0042aa434f9a75904b64043f2a283f8b4c143c7f4f7f49a6cbe5b9f745f4c15",
SchnorrSigHashType::All, SchnorrSighashType::All,
Some("50a6272b470e1460e3332ade7bb14b81671c564fb6245761bd5bd531394b28860e0b3808ab229fb51791fb6ae6fa82d915b2efb8f6df83ae1f5ab3db13e30928875e2a22b749d89358de481f19286cd4caa792ce27f9559082d227a731c5486882cc707f83da361c51b7aadd9a0cf68fe7480c410fa137b454482d9a1ebf0f96d760b4d61426fc109c6e8e99a508372c45caa7b000a41f8251305da3f206c1849985ba03f3d9592832b4053afbd23ab25d0465df0bc25a36c223aacf8e04ec736a418c72dc319e4da3e972e349713ca600965e7c665f2090d5a70e241ac164115a1f5639f28b1773327715ca307ace64a2de7f0e3df70a2ffee3857689f909c0dad46d8a20fa373a4cc6eed6d4c9806bf146f0d76baae1"), Some("50a6272b470e1460e3332ade7bb14b81671c564fb6245761bd5bd531394b28860e0b3808ab229fb51791fb6ae6fa82d915b2efb8f6df83ae1f5ab3db13e30928875e2a22b749d89358de481f19286cd4caa792ce27f9559082d227a731c5486882cc707f83da361c51b7aadd9a0cf68fe7480c410fa137b454482d9a1ebf0f96d760b4d61426fc109c6e8e99a508372c45caa7b000a41f8251305da3f206c1849985ba03f3d9592832b4053afbd23ab25d0465df0bc25a36c223aacf8e04ec736a418c72dc319e4da3e972e349713ca600965e7c665f2090d5a70e241ac164115a1f5639f28b1773327715ca307ace64a2de7f0e3df70a2ffee3857689f909c0dad46d8a20fa373a4cc6eed6d4c9806bf146f0d76baae1"),
Some("7520ab9160dd8299dc1367659be3e8f66781fe440d52940c7f8d314a89b9f2698d406ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac"), Some("7520ab9160dd8299dc1367659be3e8f66781fe440d52940c7f8d314a89b9f2698d406ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac"),
None, None,
@ -939,33 +939,33 @@ mod tests {
input: vec![TxIn::default()], input: vec![TxIn::default()],
output: vec![], output: vec![],
}; };
let mut c = SigHashCache::new(&dumb_tx); let mut c = SighashCache::new(&dumb_tx);
// 1.29 fixes // 1.29 fixes
let empty_vec = vec![]; let empty_vec = vec![];
let empty_prevouts : Prevouts<TxOut> = Prevouts::All(&empty_vec); let empty_prevouts : Prevouts<TxOut> = Prevouts::All(&empty_vec);
assert_eq!( assert_eq!(
c.taproot_signature_hash(0, &empty_prevouts, None, None, SchnorrSigHashType::All), c.taproot_signature_hash(0, &empty_prevouts, None, None, SchnorrSighashType::All),
Err(Error::PrevoutsSize) Err(Error::PrevoutsSize)
); );
let two = vec![TxOut::default(), TxOut::default()]; let two = vec![TxOut::default(), TxOut::default()];
let too_many_prevouts = Prevouts::All(&two); let too_many_prevouts = Prevouts::All(&two);
assert_eq!( assert_eq!(
c.taproot_signature_hash(0, &too_many_prevouts, None, None, SchnorrSigHashType::All), c.taproot_signature_hash(0, &too_many_prevouts, None, None, SchnorrSighashType::All),
Err(Error::PrevoutsSize) Err(Error::PrevoutsSize)
); );
let tx_out = TxOut::default(); let tx_out = TxOut::default();
let prevout = Prevouts::One(1, &tx_out); let prevout = Prevouts::One(1, &tx_out);
assert_eq!( assert_eq!(
c.taproot_signature_hash(0, &prevout, None, None, SchnorrSigHashType::All), c.taproot_signature_hash(0, &prevout, None, None, SchnorrSighashType::All),
Err(Error::PrevoutKind) Err(Error::PrevoutKind)
); );
assert_eq!( assert_eq!(
c.taproot_signature_hash(0, &prevout, None, None, SchnorrSigHashType::AllPlusAnyoneCanPay), c.taproot_signature_hash(0, &prevout, None, None, SchnorrSighashType::AllPlusAnyoneCanPay),
Err(Error::PrevoutIndex) Err(Error::PrevoutIndex)
); );
assert_eq!( assert_eq!(
c.taproot_signature_hash(10, &prevout, None, None, SchnorrSigHashType::AllPlusAnyoneCanPay), c.taproot_signature_hash(10, &prevout, None, None, SchnorrSighashType::AllPlusAnyoneCanPay),
Err(Error::IndexOutOfInputsBounds { Err(Error::IndexOutOfInputsBounds {
index: 10, index: 10,
inputs_size: 1 inputs_size: 1
@ -973,7 +973,7 @@ mod tests {
); );
let prevout = Prevouts::One(0, &tx_out); let prevout = Prevouts::One(0, &tx_out);
assert_eq!( assert_eq!(
c.taproot_signature_hash(0, &prevout, None, None, SchnorrSigHashType::SinglePlusAnyoneCanPay), c.taproot_signature_hash(0, &prevout, None, None, SchnorrSighashType::SinglePlusAnyoneCanPay),
Err(Error::SingleWithoutCorrespondingOutput { Err(Error::SingleWithoutCorrespondingOutput {
index: 0, index: 0,
outputs_size: 0 outputs_size: 0
@ -1000,7 +1000,7 @@ mod tests {
prevout_hex: &str, prevout_hex: &str,
input_index: usize, input_index: usize,
expected_hash: &str, expected_hash: &str,
sighash_type: SchnorrSigHashType, sighash_type: SchnorrSighashType,
annex_hex: Option<&str>, annex_hex: Option<&str>,
script_hex: Option<&str>, script_hex: Option<&str>,
script_leaf_hash: Option<&str>, script_leaf_hash: Option<&str>,
@ -1039,9 +1039,9 @@ mod tests {
Prevouts::All(&prevouts) Prevouts::All(&prevouts)
}; };
let mut sig_hash_cache = SigHashCache::new(&tx); let mut sighash_cache = SighashCache::new(&tx);
let hash = sig_hash_cache let hash = sighash_cache
.taproot_signature_hash(input_index, &prevouts, annex, leaf_hash, sighash_type) .taproot_signature_hash(input_index, &prevouts, annex, leaf_hash, sighash_type)
.unwrap(); .unwrap();
let expected = Vec::from_hex(expected_hash).unwrap(); let expected = Vec::from_hex(expected_hash).unwrap();
@ -1065,7 +1065,7 @@ mod tests {
} }
// Test intermediary // Test intermediary
let mut cache = SigHashCache::new(&raw_unsigned_tx); let mut cache = SighashCache::new(&raw_unsigned_tx);
let expected_amt_hash = key_path["intermediary"]["hashAmounts"].as_str().unwrap(); let expected_amt_hash = key_path["intermediary"]["hashAmounts"].as_str().unwrap();
let expected_outputs_hash = key_path["intermediary"]["hashOutputs"].as_str().unwrap(); let expected_outputs_hash = key_path["intermediary"]["hashOutputs"].as_str().unwrap();
let expected_prevouts_hash = key_path["intermediary"]["hashPrevouts"].as_str().unwrap(); let expected_prevouts_hash = key_path["intermediary"]["hashPrevouts"].as_str().unwrap();
@ -1087,18 +1087,18 @@ mod tests {
} else { } else {
Some(hex_hash!(TapBranchHash, inp["given"]["merkleRoot"].as_str().unwrap())) Some(hex_hash!(TapBranchHash, inp["given"]["merkleRoot"].as_str().unwrap()))
}; };
let hash_ty = SchnorrSigHashType::from_u8(inp["given"]["hashType"].as_u64().unwrap() as u8).unwrap(); let hash_ty = SchnorrSighashType::from_u8(inp["given"]["hashType"].as_u64().unwrap() as u8).unwrap();
let expected_internal_pk = hex_hash!(XOnlyPublicKey, inp["intermediary"]["internalPubkey"].as_str().unwrap()); let expected_internal_pk = hex_hash!(XOnlyPublicKey, inp["intermediary"]["internalPubkey"].as_str().unwrap());
let expected_tweak = hex_hash!(TapTweakHash, inp["intermediary"]["tweak"].as_str().unwrap()); let expected_tweak = hex_hash!(TapTweakHash, inp["intermediary"]["tweak"].as_str().unwrap());
let expected_tweaked_priv_key = hex_hash!(SecretKey, inp["intermediary"]["tweakedPrivkey"].as_str().unwrap()); let expected_tweaked_priv_key = hex_hash!(SecretKey, inp["intermediary"]["tweakedPrivkey"].as_str().unwrap());
let expected_sig_msg = Vec::<u8>::from_hex(inp["intermediary"]["sigMsg"].as_str().unwrap()).unwrap(); let expected_sig_msg = Vec::<u8>::from_hex(inp["intermediary"]["sigMsg"].as_str().unwrap()).unwrap();
let expected_sig_hash = hex_hash!(TapSighashHash, inp["intermediary"]["sigHash"].as_str().unwrap()); let expected_sighash = hex_hash!(TapSighashHash, inp["intermediary"]["sigHash"].as_str().unwrap());
let sig_str = inp["expected"]["witness"][0].as_str().unwrap(); let sig_str = inp["expected"]["witness"][0].as_str().unwrap();
let (expected_key_spend_sig, expected_hash_ty) = if sig_str.len() == 128 { let (expected_key_spend_sig, expected_hash_ty) = if sig_str.len() == 128 {
(secp256k1::schnorr::Signature::from_str(sig_str).unwrap(), SchnorrSigHashType::Default) (secp256k1::schnorr::Signature::from_str(sig_str).unwrap(), SchnorrSighashType::Default)
} else { } else {
let hash_ty = SchnorrSigHashType::from_u8(Vec::<u8>::from_hex(&sig_str[128..]).unwrap()[0]).unwrap(); let hash_ty = SchnorrSighashType::from_u8(Vec::<u8>::from_hex(&sig_str[128..]).unwrap()[0]).unwrap();
(secp256k1::schnorr::Signature::from_str(&sig_str[..128]).unwrap(), hash_ty) (secp256k1::schnorr::Signature::from_str(&sig_str[..128]).unwrap(), hash_ty)
}; };
@ -1117,7 +1117,7 @@ mod tests {
None, None,
hash_ty hash_ty
).unwrap(); ).unwrap();
let sig_hash = cache.taproot_signature_hash( let sighash = cache.taproot_signature_hash(
tx_ind, tx_ind,
&Prevouts::All(&utxos), &Prevouts::All(&utxos),
None, None,
@ -1125,13 +1125,13 @@ mod tests {
hash_ty hash_ty
).unwrap(); ).unwrap();
let msg = secp256k1::Message::from_slice(&sig_hash).unwrap(); let msg = secp256k1::Message::from_slice(&sighash).unwrap();
let key_spend_sig = secp.sign_schnorr_with_aux_rand(&msg, &tweaked_keypair, &[0u8; 32]); let key_spend_sig = secp.sign_schnorr_with_aux_rand(&msg, &tweaked_keypair, &[0u8; 32]);
assert_eq!(expected_internal_pk, internal_key); assert_eq!(expected_internal_pk, internal_key);
assert_eq!(expected_tweak, tweak); assert_eq!(expected_tweak, tweak);
assert_eq!(expected_sig_msg, sig_msg); assert_eq!(expected_sig_msg, sig_msg);
assert_eq!(expected_sig_hash, sig_hash); assert_eq!(expected_sighash, sighash);
assert_eq!(expected_hash_ty, hash_ty); assert_eq!(expected_hash_ty, hash_ty);
assert_eq!(expected_key_spend_sig, key_spend_sig); assert_eq!(expected_key_spend_sig, key_spend_sig);
@ -1148,18 +1148,18 @@ mod tests {
#[test] #[test]
fn sighashtype_fromstr_display() { fn sighashtype_fromstr_display() {
let sighashtypes = vec![ let sighashtypes = vec![
("SIGHASH_DEFAULT", SchnorrSigHashType::Default), ("SIGHASH_DEFAULT", SchnorrSighashType::Default),
("SIGHASH_ALL", SchnorrSigHashType::All), ("SIGHASH_ALL", SchnorrSighashType::All),
("SIGHASH_NONE", SchnorrSigHashType::None), ("SIGHASH_NONE", SchnorrSighashType::None),
("SIGHASH_SINGLE", SchnorrSigHashType::Single), ("SIGHASH_SINGLE", SchnorrSighashType::Single),
("SIGHASH_ALL|SIGHASH_ANYONECANPAY", SchnorrSigHashType::AllPlusAnyoneCanPay), ("SIGHASH_ALL|SIGHASH_ANYONECANPAY", SchnorrSighashType::AllPlusAnyoneCanPay),
("SIGHASH_NONE|SIGHASH_ANYONECANPAY", SchnorrSigHashType::NonePlusAnyoneCanPay), ("SIGHASH_NONE|SIGHASH_ANYONECANPAY", SchnorrSighashType::NonePlusAnyoneCanPay),
("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", SchnorrSigHashType::SinglePlusAnyoneCanPay), ("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", SchnorrSighashType::SinglePlusAnyoneCanPay),
("SIGHASH_RESERVED", SchnorrSigHashType::Reserved), ("SIGHASH_RESERVED", SchnorrSighashType::Reserved),
]; ];
for (s, sht) in sighashtypes { for (s, sht) in sighashtypes {
assert_eq!(sht.to_string(), s); assert_eq!(sht.to_string(), s);
assert_eq!(SchnorrSigHashType::from_str(s).unwrap(), sht); assert_eq!(SchnorrSighashType::from_str(s).unwrap(), sht);
} }
let sht_mistakes = vec![ let sht_mistakes = vec![
"SIGHASH_ALL | SIGHASH_ANYONECANPAY", "SIGHASH_ALL | SIGHASH_ANYONECANPAY",
@ -1176,7 +1176,7 @@ mod tests {
"SigHash_NONE", "SigHash_NONE",
]; ];
for s in sht_mistakes { for s in sht_mistakes {
assert_eq!(SchnorrSigHashType::from_str(s).unwrap_err().to_string(), format!("Unrecognized SIGHASH string '{}'", s)); assert_eq!(SchnorrSighashType::from_str(s).unwrap_err().to_string(), format!("Unrecognized SIGHASH string '{}'", s));
} }
} }
} }