2022-06-29 04:05:31 +00:00
// SPDX-License-Identifier: CC0-1.0
2021-07-16 08:14:07 +00:00
2021-11-05 21:58:18 +00:00
//! Generalized, efficient, signature hash implementation.
2021-07-16 08:14:07 +00:00
//!
2021-11-05 21:58:18 +00:00
//! Implementation of the algorithm to compute the message to be signed according to
//! [Bip341](https://github.com/bitcoin/bips/blob/150ab6f5c3aca9da05fccc5b435e9667853407f4/bip-0341.mediawiki),
2021-07-16 08:14:07 +00:00
//! [Bip143](https://github.com/bitcoin/bips/blob/99701f68a88ce33b2d0838eb84e115cef505b4c2/bip-0143.mediawiki)
2021-11-05 21:58:18 +00:00
//! and legacy (before Bip143).
2021-07-16 08:14:07 +00:00
//!
2022-05-30 03:52:20 +00:00
use crate ::blockdata ::transaction ::EncodeSigningDataResult ;
2022-05-02 22:13:57 +00:00
use crate ::prelude ::* ;
2022-02-22 18:50:06 +00:00
2022-05-02 22:13:57 +00:00
pub use crate ::blockdata ::transaction ::{ EcdsaSighashType , SighashTypeParseError } ;
use crate ::blockdata ::witness ::Witness ;
use crate ::consensus ::{ encode , Encodable } ;
2022-02-22 18:50:06 +00:00
use core ::{ str , fmt } ;
2021-07-16 08:14:07 +00:00
use core ::ops ::{ Deref , DerefMut } ;
2022-02-17 07:35:54 +00:00
use core ::borrow ::Borrow ;
2022-05-02 22:13:57 +00:00
use crate ::hashes ::{ sha256 , sha256d , Hash } ;
use crate ::io ;
use crate ::util ::taproot ::{ TapLeafHash , TAPROOT_ANNEX_PREFIX , TapSighashHash } ;
use crate ::Sighash ;
use crate ::{ Script , Transaction , TxOut } ;
2022-06-07 03:25:27 +00:00
use crate ::internal_macros ::serde_string_impl ;
2021-07-16 08:14:07 +00:00
2021-10-06 23:07:55 +00:00
use super ::taproot ::LeafVersion ;
2022-05-30 03:52:20 +00:00
/// Used for signature hash for invalid use of SIGHASH_SINGLE.
pub ( crate ) const UINT256_ONE : [ u8 ; 32 ] = [
1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
] ;
2021-07-16 08:14:07 +00:00
/// Efficiently calculates signature hash message for legacy, segwit and taproot inputs.
2021-07-16 14:39:51 +00:00
#[ derive(Debug) ]
2022-03-28 21:59:14 +00:00
pub struct SighashCache < T : Deref < Target = Transaction > > {
2022-03-16 03:02:21 +00:00
/// Access to transaction required for transaction introspection. Moreover, type
/// `T: Deref<Target=Transaction>` allows us to use borrowed and mutable borrowed types,
/// the latter in particular is necessary for [`SighashCache::witness_mut`].
2021-07-16 08:14:07 +00:00
tx : T ,
2022-03-16 03:02:21 +00:00
/// Common cache for taproot and segwit inputs, `None` for legacy inputs.
2021-07-16 08:14:07 +00:00
common_cache : Option < CommonCache > ,
2022-04-19 05:26:26 +00:00
/// Cache for segwit v0 inputs (the result of another round of sha256 on `common_cache`).
2021-07-16 08:14:07 +00:00
segwit_cache : Option < SegwitCache > ,
2022-03-16 03:02:21 +00:00
/// Cache for taproot v1 inputs.
2021-07-16 08:14:07 +00:00
taproot_cache : Option < TaprootCache > ,
}
2022-03-16 03:02:21 +00:00
/// Common values cached between segwit and taproot inputs.
2021-07-16 14:39:51 +00:00
#[ derive(Debug) ]
struct CommonCache {
2021-07-16 08:14:07 +00:00
prevouts : sha256 ::Hash ,
sequences : sha256 ::Hash ,
2022-03-16 03:02:21 +00:00
/// In theory `outputs` could be an `Option` since `SIGHASH_NONE` and `SIGHASH_SINGLE` do not
/// need it, but since `SIGHASH_ALL` is by far the most used variant we don't bother.
2021-07-16 08:14:07 +00:00
outputs : sha256 ::Hash ,
}
2022-03-16 03:02:21 +00:00
/// Values cached for segwit inputs, equivalent to [`CommonCache`] plus another round of `sha256`.
2021-07-16 14:39:51 +00:00
#[ derive(Debug) ]
struct SegwitCache {
2021-07-16 08:14:07 +00:00
prevouts : sha256d ::Hash ,
sequences : sha256d ::Hash ,
outputs : sha256d ::Hash ,
}
2022-03-16 03:02:21 +00:00
/// Values cached for taproot inputs.
2021-07-16 14:39:51 +00:00
#[ derive(Debug) ]
struct TaprootCache {
2021-07-16 08:14:07 +00:00
amounts : sha256 ::Hash ,
script_pubkeys : sha256 ::Hash ,
}
2022-03-16 03:02:21 +00:00
/// Contains outputs of previous transactions. In the case [`SchnorrSighashType`] variant is
/// `SIGHASH_ANYONECANPAY`, [`Prevouts::One`] may be used.
2021-07-16 14:39:51 +00:00
#[ derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug) ]
2022-02-17 07:35:54 +00:00
pub enum Prevouts < ' u , T > where T : ' u + Borrow < TxOut > {
2022-03-16 03:02:21 +00:00
/// `One` variant allows provision of the single prevout needed. It's useful, for example, when
/// modifier `SIGHASH_ANYONECANPAY` is provided, only prevout of the current input is needed.
2021-08-31 10:00:49 +00:00
/// The first `usize` argument is the input index this [`TxOut`] is referring to.
2022-02-17 07:35:54 +00:00
One ( usize , T ) ,
2022-03-16 03:02:21 +00:00
/// When `SIGHASH_ANYONECANPAY` is not provided, or when the caller is giving all prevouts so
/// the same variable can be used for multiple inputs.
2022-02-17 07:35:54 +00:00
All ( & ' u [ T ] ) ,
2021-07-16 08:14:07 +00:00
}
2021-07-16 14:46:57 +00:00
const KEY_VERSION_0 : u8 = 0 u8 ;
2021-07-16 08:14:07 +00:00
2022-03-16 03:02:21 +00:00
/// Information related to the script path spending.
2021-11-25 10:47:40 +00:00
///
/// This can be hashed into a [`TapLeafHash`].
2021-07-16 14:39:51 +00:00
#[ derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug) ]
2021-07-16 08:14:07 +00:00
pub struct ScriptPath < ' s > {
script : & ' s Script ,
2021-10-06 23:07:55 +00:00
leaf_version : LeafVersion ,
2021-07-16 08:14:07 +00:00
}
2022-04-19 05:26:26 +00:00
/// 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.
2021-07-16 14:39:51 +00:00
#[ derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug) ]
2022-03-28 21:52:33 +00:00
pub enum SchnorrSighashType {
2022-03-16 03:02:21 +00:00
/// 0x0: Used when not explicitly specified, defaults to [`SchnorrSighashType::All`]
2021-07-16 08:14:07 +00:00
Default = 0x00 ,
2022-03-16 03:02:21 +00:00
/// 0x1: Sign all outputs.
2021-07-16 08:14:07 +00:00
All = 0x01 ,
2022-03-16 03:02:21 +00:00
/// 0x2: Sign no outputs --- anyone can choose the destination.
2021-07-16 08:14:07 +00:00
None = 0x02 ,
/// 0x3: Sign the output whose index matches this input's index. If none exists,
/// sign the hash `0000000000000000000000000000000000000000000000000000000000000001`.
/// (This rule is probably an unintentional C++ism, but it's consensus so we have
/// to follow it.)
Single = 0x03 ,
2022-03-16 03:02:21 +00:00
/// 0x81: Sign all outputs but only this input.
2021-07-16 08:14:07 +00:00
AllPlusAnyoneCanPay = 0x81 ,
2022-03-16 03:02:21 +00:00
/// 0x82: Sign no outputs and only this input.
2021-07-16 08:14:07 +00:00
NonePlusAnyoneCanPay = 0x82 ,
2022-03-16 03:02:21 +00:00
/// 0x83: Sign one output and only this input (see `Single` for what "one output" means).
2021-07-16 08:14:07 +00:00
SinglePlusAnyoneCanPay = 0x83 ,
}
2022-03-28 21:52:33 +00:00
serde_string_impl! ( SchnorrSighashType , " a SchnorrSighashType data " ) ;
2022-02-22 18:50:06 +00:00
2022-03-28 21:52:33 +00:00
impl fmt ::Display for SchnorrSighashType {
2022-02-22 18:50:06 +00:00
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
let s = match self {
2022-03-28 21:52:33 +00:00
SchnorrSighashType ::Default = > " SIGHASH_DEFAULT " ,
SchnorrSighashType ::All = > " SIGHASH_ALL " ,
SchnorrSighashType ::None = > " SIGHASH_NONE " ,
SchnorrSighashType ::Single = > " SIGHASH_SINGLE " ,
SchnorrSighashType ::AllPlusAnyoneCanPay = > " SIGHASH_ALL|SIGHASH_ANYONECANPAY " ,
SchnorrSighashType ::NonePlusAnyoneCanPay = > " SIGHASH_NONE|SIGHASH_ANYONECANPAY " ,
SchnorrSighashType ::SinglePlusAnyoneCanPay = > " SIGHASH_SINGLE|SIGHASH_ANYONECANPAY " ,
2022-02-22 18:50:06 +00:00
} ;
f . write_str ( s )
}
}
2022-03-28 21:52:33 +00:00
impl str ::FromStr for SchnorrSighashType {
2022-03-28 21:54:02 +00:00
type Err = SighashTypeParseError ;
2022-02-22 18:50:06 +00:00
fn from_str ( s : & str ) -> Result < Self , Self ::Err > {
match s {
2022-03-28 21:52:33 +00:00
" SIGHASH_DEFAULT " = > Ok ( SchnorrSighashType ::Default ) ,
" SIGHASH_ALL " = > Ok ( SchnorrSighashType ::All ) ,
" SIGHASH_NONE " = > Ok ( SchnorrSighashType ::None ) ,
" SIGHASH_SINGLE " = > Ok ( SchnorrSighashType ::Single ) ,
" SIGHASH_ALL|SIGHASH_ANYONECANPAY " = > Ok ( SchnorrSighashType ::AllPlusAnyoneCanPay ) ,
" SIGHASH_NONE|SIGHASH_ANYONECANPAY " = > Ok ( SchnorrSighashType ::NonePlusAnyoneCanPay ) ,
" SIGHASH_SINGLE|SIGHASH_ANYONECANPAY " = > Ok ( SchnorrSighashType ::SinglePlusAnyoneCanPay ) ,
2022-03-28 21:54:02 +00:00
_ = > Err ( SighashTypeParseError { unrecognized : s . to_owned ( ) } ) ,
2022-02-22 18:50:06 +00:00
}
}
}
2021-07-16 08:14:07 +00:00
2022-03-16 03:02:21 +00:00
/// Possible errors in computing the signature message.
2021-07-16 14:39:51 +00:00
#[ derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug) ]
2022-05-31 04:29:50 +00:00
#[ non_exhaustive ]
2021-07-16 08:14:07 +00:00
pub enum Error {
2021-07-19 11:46:46 +00:00
/// Could happen only by using `*_encode_signing_*` methods with custom writers, engines writers
2022-03-16 03:02:21 +00:00
/// like the ones used in methods `*_signature_hash` do not error.
2021-07-19 11:46:46 +00:00
Io ( io ::ErrorKind ) ,
2021-07-16 08:14:07 +00:00
2022-03-16 03:02:21 +00:00
/// Requested index is greater or equal than the number of inputs in the transaction.
2021-07-16 14:12:29 +00:00
IndexOutOfInputsBounds {
2022-03-16 03:02:21 +00:00
/// Requested index.
2021-07-16 14:12:29 +00:00
index : usize ,
2022-03-16 03:02:21 +00:00
/// Number of transaction inputs.
2021-07-16 14:12:29 +00:00
inputs_size : usize ,
} ,
2022-03-16 03:02:21 +00:00
/// Using `SIGHASH_SINGLE` without a "corresponding output" (an output with the same index as
/// the input being verified) is a validation failure.
2021-07-16 14:12:29 +00:00
SingleWithoutCorrespondingOutput {
2022-03-16 03:02:21 +00:00
/// Requested index.
2021-07-16 14:12:29 +00:00
index : usize ,
2022-03-16 03:02:21 +00:00
/// Number of transaction outputs.
2021-07-16 14:12:29 +00:00
outputs_size : usize ,
} ,
2021-07-16 08:14:07 +00:00
2022-03-16 03:02:21 +00:00
/// There are mismatches in the number of prevouts provided compared to the number of inputs in
/// the transaction.
2021-07-16 08:14:07 +00:00
PrevoutsSize ,
/// Requested a prevout index which is greater than the number of prevouts provided or a
2022-03-16 03:02:21 +00:00
/// [`Prevouts::One`] with different index.
2021-07-16 08:14:07 +00:00
PrevoutIndex ,
2022-03-16 03:02:21 +00:00
/// A single prevout has been provided but all prevouts are needed unless using
/// `SIGHASH_ANYONECANPAY`.
2021-07-16 08:14:07 +00:00
PrevoutKind ,
2022-03-16 03:02:21 +00:00
/// Annex must be at least one byte long and the first bytes must be `0x50`.
2021-07-16 08:14:07 +00:00
WrongAnnex ,
2021-10-27 13:04:23 +00:00
2022-03-16 03:02:21 +00:00
/// Invalid Sighash type.
2022-03-28 22:05:50 +00:00
InvalidSighashType ( u32 ) ,
2021-07-16 08:14:07 +00:00
}
impl fmt ::Display for Error {
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
match self {
2022-05-26 00:05:05 +00:00
Error ::Io ( error_kind ) = > write! ( f , " writer errored: {:?} " , error_kind ) ,
2021-07-16 14:12:29 +00:00
Error ::IndexOutOfInputsBounds { index , inputs_size } = > write! ( f , " Requested index ({}) is greater or equal than the number of transaction inputs ({}) " , index , inputs_size ) ,
Error ::SingleWithoutCorrespondingOutput { index , outputs_size } = > write! ( f , " SIGHASH_SINGLE for input ({}) haven't a corresponding output (#outputs:{}) " , index , outputs_size ) ,
2021-07-16 08:14:07 +00:00
Error ::PrevoutsSize = > write! ( f , " Number of supplied prevouts differs from the number of inputs in transaction " ) ,
Error ::PrevoutIndex = > write! ( f , " The index requested is greater than available prevouts or different from the provided [Provided::Anyone] index " ) ,
Error ::PrevoutKind = > write! ( f , " A single prevout has been provided but all prevouts are needed without `ANYONECANPAY` " ) ,
Error ::WrongAnnex = > write! ( f , " Annex must be at least one byte long and the first bytes must be `0x50` " ) ,
2022-03-28 22:05:50 +00:00
Error ::InvalidSighashType ( hash_ty ) = > write! ( f , " Invalid schnorr Signature hash type : {} " , hash_ty ) ,
2021-07-16 08:14:07 +00:00
}
}
}
#[ cfg(feature = " std " ) ]
2022-05-04 05:56:24 +00:00
#[ cfg_attr(docsrs, doc(cfg(feature = " std " ))) ]
impl std ::error ::Error for Error {
fn source ( & self ) -> Option < & ( dyn std ::error ::Error + 'static ) > {
use self ::Error ::* ;
match self {
Io ( _ )
| IndexOutOfInputsBounds { .. }
| SingleWithoutCorrespondingOutput { .. }
| PrevoutsSize
| PrevoutIndex
| PrevoutKind
| WrongAnnex
| InvalidSighashType ( _ ) = > None ,
}
}
}
2021-07-16 08:14:07 +00:00
2022-02-17 07:35:54 +00:00
impl < ' u , T > Prevouts < ' u , T > where T : Borrow < TxOut > {
2021-07-16 08:14:07 +00:00
fn check_all ( & self , tx : & Transaction ) -> Result < ( ) , Error > {
if let Prevouts ::All ( prevouts ) = self {
if prevouts . len ( ) ! = tx . input . len ( ) {
return Err ( Error ::PrevoutsSize ) ;
}
}
Ok ( ( ) )
}
2022-02-17 07:35:54 +00:00
fn get_all ( & self ) -> Result < & [ T ] , Error > {
2021-07-16 08:14:07 +00:00
match self {
2022-02-17 07:35:54 +00:00
Prevouts ::All ( prevouts ) = > Ok ( * prevouts ) ,
2021-07-16 08:14:07 +00:00
_ = > Err ( Error ::PrevoutKind ) ,
}
}
fn get ( & self , input_index : usize ) -> Result < & TxOut , Error > {
match self {
Prevouts ::One ( index , prevout ) = > {
if input_index = = * index {
2022-02-17 07:35:54 +00:00
Ok ( prevout . borrow ( ) )
2021-07-16 08:14:07 +00:00
} else {
Err ( Error ::PrevoutIndex )
}
}
2022-02-17 07:35:54 +00:00
Prevouts ::All ( prevouts ) = > prevouts
. get ( input_index )
. map ( | x | x . borrow ( ) )
. ok_or ( Error ::PrevoutIndex ) ,
2021-07-16 08:14:07 +00:00
}
}
}
impl < ' s > ScriptPath < ' s > {
2022-03-16 03:02:21 +00:00
/// Creates a new `ScriptPath` structure.
2021-11-25 10:47:40 +00:00
pub fn new ( script : & ' s Script , leaf_version : LeafVersion ) -> Self {
2021-07-16 08:14:07 +00:00
ScriptPath {
script ,
leaf_version ,
}
}
2022-03-16 03:02:21 +00:00
/// Creates a new `ScriptPath` structure using default leaf version value.
2021-07-16 08:14:07 +00:00
pub fn with_defaults ( script : & ' s Script ) -> Self {
2021-11-24 23:01:21 +00:00
Self ::new ( script , LeafVersion ::TapScript )
2021-11-25 10:47:40 +00:00
}
2022-03-16 03:02:21 +00:00
/// Computes the leaf hash for this `ScriptPath`.
2021-11-25 10:47:40 +00:00
pub fn leaf_hash ( & self ) -> TapLeafHash {
let mut enc = TapLeafHash ::engine ( ) ;
2022-01-19 02:46:51 +00:00
self . leaf_version . to_consensus ( ) . consensus_encode ( & mut enc ) . expect ( " Writing to hash enging should never fail " ) ;
2021-11-25 10:47:40 +00:00
self . script . consensus_encode ( & mut enc ) . expect ( " Writing to hash enging should never fail " ) ;
TapLeafHash ::from_engine ( enc )
}
}
impl < ' s > From < ScriptPath < ' s > > for TapLeafHash {
fn from ( script_path : ScriptPath < ' s > ) -> TapLeafHash {
script_path . leaf_hash ( )
2021-07-16 08:14:07 +00:00
}
}
2022-03-28 21:52:33 +00:00
impl From < EcdsaSighashType > for SchnorrSighashType {
2022-03-28 21:48:53 +00:00
fn from ( s : EcdsaSighashType ) -> Self {
2021-07-16 08:14:07 +00:00
match s {
2022-03-28 21:52:33 +00:00
EcdsaSighashType ::All = > SchnorrSighashType ::All ,
EcdsaSighashType ::None = > SchnorrSighashType ::None ,
EcdsaSighashType ::Single = > SchnorrSighashType ::Single ,
EcdsaSighashType ::AllPlusAnyoneCanPay = > SchnorrSighashType ::AllPlusAnyoneCanPay ,
EcdsaSighashType ::NonePlusAnyoneCanPay = > SchnorrSighashType ::NonePlusAnyoneCanPay ,
EcdsaSighashType ::SinglePlusAnyoneCanPay = > SchnorrSighashType ::SinglePlusAnyoneCanPay ,
2021-07-16 08:14:07 +00:00
}
}
}
2022-03-28 21:52:33 +00:00
impl SchnorrSighashType {
2022-03-16 03:02:21 +00:00
/// Breaks the sighash flag into the "real" sighash flag and the `SIGHASH_ANYONECANPAY` boolean.
2022-03-28 21:52:33 +00:00
pub ( crate ) fn split_anyonecanpay_flag ( self ) -> ( SchnorrSighashType , bool ) {
2021-07-16 08:14:07 +00:00
match self {
2022-03-28 21:52:33 +00:00
SchnorrSighashType ::Default = > ( SchnorrSighashType ::Default , false ) ,
SchnorrSighashType ::All = > ( SchnorrSighashType ::All , false ) ,
SchnorrSighashType ::None = > ( SchnorrSighashType ::None , false ) ,
SchnorrSighashType ::Single = > ( SchnorrSighashType ::Single , false ) ,
SchnorrSighashType ::AllPlusAnyoneCanPay = > ( SchnorrSighashType ::All , true ) ,
SchnorrSighashType ::NonePlusAnyoneCanPay = > ( SchnorrSighashType ::None , true ) ,
SchnorrSighashType ::SinglePlusAnyoneCanPay = > ( SchnorrSighashType ::Single , true ) ,
2021-07-16 08:14:07 +00:00
}
}
2021-10-27 13:04:23 +00:00
2022-03-16 03:02:21 +00:00
/// Creates a [`SchnorrSighashType`] from raw `u8`.
2022-06-24 02:01:53 +00:00
#[ deprecated(since = " 0.29.0 " , note = " use from_consensus_u8 instead " ) ]
2021-10-27 13:04:23 +00:00
pub fn from_u8 ( hash_ty : u8 ) -> Result < Self , Error > {
2022-06-24 02:01:53 +00:00
Self ::from_consensus_u8 ( hash_ty )
}
/// Constructs a [`SchnorrSighashType`] from a raw `u8`.
pub fn from_consensus_u8 ( hash_ty : u8 ) -> Result < Self , Error > {
use SchnorrSighashType ::* ;
Ok ( match hash_ty {
0x00 = > Default ,
0x01 = > All ,
0x02 = > None ,
0x03 = > Single ,
0x81 = > AllPlusAnyoneCanPay ,
0x82 = > NonePlusAnyoneCanPay ,
0x83 = > SinglePlusAnyoneCanPay ,
x = > return Err ( Error ::InvalidSighashType ( x as u32 ) ) ,
} )
2021-10-27 13:04:23 +00:00
}
2021-07-16 08:14:07 +00:00
}
2022-03-16 03:02:21 +00:00
impl < R : Deref < Target = Transaction > > SighashCache < R > {
/// Constructs a new `SighashCache` from an unsigned transaction.
///
/// The sighash components are computed in a lazy manner when required. For the generated
/// sighashes to be valid, no fields in the transaction may change except for script_sig and
/// witness.
2021-07-16 08:14:07 +00:00
pub fn new ( tx : R ) -> Self {
2022-03-28 21:59:14 +00:00
SighashCache {
2021-07-16 08:14:07 +00:00
tx ,
common_cache : None ,
taproot_cache : None ,
segwit_cache : None ,
}
}
2022-03-16 03:02:21 +00:00
/// Encodes the BIP341 signing data for any flag type into a given object implementing a
2022-04-19 05:26:26 +00:00
/// [`io::Write`] trait.
2022-02-17 07:35:54 +00:00
pub fn taproot_encode_signing_data_to < Write : io ::Write , T : Borrow < TxOut > > (
2021-07-16 08:14:07 +00:00
& mut self ,
mut writer : Write ,
input_index : usize ,
2022-02-17 07:35:54 +00:00
prevouts : & Prevouts < T > ,
2021-07-16 08:14:07 +00:00
annex : Option < Annex > ,
2021-11-25 10:47:40 +00:00
leaf_hash_code_separator : Option < ( TapLeafHash , u32 ) > ,
2022-03-28 21:52:33 +00:00
sighash_type : SchnorrSighashType ,
2021-07-16 08:14:07 +00:00
) -> Result < ( ) , Error > {
prevouts . check_all ( & self . tx ) ? ;
let ( sighash , anyone_can_pay ) = sighash_type . split_anyonecanpay_flag ( ) ;
// epoch
0 u8 . consensus_encode ( & mut writer ) ? ;
// * Control:
// hash_type (1).
( sighash_type as u8 ) . consensus_encode ( & mut writer ) ? ;
// * Transaction Data:
// nVersion (4): the nVersion of the transaction.
self . tx . version . consensus_encode ( & mut writer ) ? ;
// nLockTime (4): the nLockTime of the transaction.
self . tx . lock_time . consensus_encode ( & mut writer ) ? ;
// If the hash_type & 0x80 does not equal SIGHASH_ANYONECANPAY:
// sha_prevouts (32): the SHA256 of the serialization of all input outpoints.
// sha_amounts (32): the SHA256 of the serialization of all spent output amounts.
// sha_scriptpubkeys (32): the SHA256 of the serialization of all spent output scriptPubKeys.
// sha_sequences (32): the SHA256 of the serialization of all input nSequence.
if ! anyone_can_pay {
self . common_cache ( ) . prevouts . consensus_encode ( & mut writer ) ? ;
self . taproot_cache ( prevouts . get_all ( ) ? )
. amounts
. consensus_encode ( & mut writer ) ? ;
self . taproot_cache ( prevouts . get_all ( ) ? )
. script_pubkeys
. consensus_encode ( & mut writer ) ? ;
self . common_cache ( )
. sequences
. consensus_encode ( & mut writer ) ? ;
}
// 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.
2022-03-28 21:52:33 +00:00
if sighash ! = SchnorrSighashType ::None & & sighash ! = SchnorrSighashType ::Single {
2021-07-16 08:14:07 +00:00
self . common_cache ( ) . outputs . consensus_encode ( & mut writer ) ? ;
}
// * Data about this input:
// spend_type (1): equal to (ext_flag * 2) + annex_present, where annex_present is 0
// if no annex is present, or 1 otherwise
let mut spend_type = 0 u8 ;
if annex . is_some ( ) {
spend_type | = 1 u8 ;
}
2021-11-25 10:47:40 +00:00
if leaf_hash_code_separator . is_some ( ) {
2021-07-16 08:14:07 +00:00
spend_type | = 2 u8 ;
}
spend_type . consensus_encode ( & mut writer ) ? ;
// If hash_type & 0x80 equals SIGHASH_ANYONECANPAY:
// outpoint (36): the COutPoint of this input (32-byte hash + 4-byte little-endian).
// amount (8): value of the previous output spent by this input.
// scriptPubKey (35): scriptPubKey of the previous output spent by this input, serialized as script inside CTxOut. Its size is always 35 bytes.
// nSequence (4): nSequence of this input.
if anyone_can_pay {
2021-07-16 14:12:29 +00:00
let txin =
& self
. tx
. input
. get ( input_index )
2022-05-25 03:28:31 +00:00
. ok_or ( Error ::IndexOutOfInputsBounds {
2021-07-16 14:12:29 +00:00
index : input_index ,
inputs_size : self . tx . input . len ( ) ,
} ) ? ;
2021-07-16 08:14:07 +00:00
let previous_output = prevouts . get ( input_index ) ? ;
txin . previous_output . consensus_encode ( & mut writer ) ? ;
previous_output . value . consensus_encode ( & mut writer ) ? ;
previous_output
. script_pubkey
. consensus_encode ( & mut writer ) ? ;
txin . sequence . consensus_encode ( & mut writer ) ? ;
} else {
( input_index as u32 ) . consensus_encode ( & mut writer ) ? ;
}
// If an annex is present (the lowest bit of spend_type is set):
// sha_annex (32): the SHA256 of (compact_size(size of annex) || annex), where annex
// includes the mandatory 0x50 prefix.
if let Some ( annex ) = annex {
let mut enc = sha256 ::Hash ::engine ( ) ;
2021-07-16 13:05:15 +00:00
annex . consensus_encode ( & mut enc ) ? ;
2021-07-16 08:14:07 +00:00
let hash = sha256 ::Hash ::from_engine ( enc ) ;
hash . consensus_encode ( & mut writer ) ? ;
}
// * Data about this output:
// If hash_type & 3 equals SIGHASH_SINGLE:
// sha_single_output (32): the SHA256 of the corresponding output in CTxOut format.
2022-03-28 21:52:33 +00:00
if sighash = = SchnorrSighashType ::Single {
2021-07-16 08:14:07 +00:00
let mut enc = sha256 ::Hash ::engine ( ) ;
2021-07-16 14:12:29 +00:00
self . tx
. output
. get ( input_index )
2022-05-25 03:28:31 +00:00
. ok_or ( Error ::SingleWithoutCorrespondingOutput {
2021-07-16 14:12:29 +00:00
index : input_index ,
outputs_size : self . tx . output . len ( ) ,
} ) ?
. consensus_encode ( & mut enc ) ? ;
2021-07-16 08:14:07 +00:00
let hash = sha256 ::Hash ::from_engine ( enc ) ;
hash . consensus_encode ( & mut writer ) ? ;
}
// if (scriptpath):
// ss += TaggedHash("TapLeaf", bytes([leaf_ver]) + ser_string(script))
// ss += bytes([0])
// ss += struct.pack("<i", codeseparator_pos)
2021-11-25 10:47:40 +00:00
if let Some ( ( hash , code_separator_pos ) ) = leaf_hash_code_separator {
2021-07-16 08:14:07 +00:00
hash . into_inner ( ) . consensus_encode ( & mut writer ) ? ;
2021-07-16 14:46:57 +00:00
KEY_VERSION_0 . consensus_encode ( & mut writer ) ? ;
2021-07-16 08:14:07 +00:00
code_separator_pos . consensus_encode ( & mut writer ) ? ;
}
Ok ( ( ) )
}
2022-03-16 03:02:21 +00:00
/// Computes the BIP341 sighash for any flag type.
2022-02-17 07:35:54 +00:00
pub fn taproot_signature_hash < T : Borrow < TxOut > > (
2021-07-16 08:14:07 +00:00
& mut self ,
input_index : usize ,
2022-02-17 07:35:54 +00:00
prevouts : & Prevouts < T > ,
2021-07-16 08:14:07 +00:00
annex : Option < Annex > ,
2021-11-25 10:47:40 +00:00
leaf_hash_code_separator : Option < ( TapLeafHash , u32 ) > ,
2022-03-28 21:52:33 +00:00
sighash_type : SchnorrSighashType ,
2021-07-16 08:14:07 +00:00
) -> Result < TapSighashHash , Error > {
let mut enc = TapSighashHash ::engine ( ) ;
self . taproot_encode_signing_data_to (
& mut enc ,
input_index ,
prevouts ,
annex ,
2021-11-25 10:47:40 +00:00
leaf_hash_code_separator ,
sighash_type ,
) ? ;
Ok ( TapSighashHash ::from_engine ( enc ) )
}
2022-03-16 03:02:21 +00:00
/// Computes the BIP341 sighash for a key spend.
2022-02-17 07:35:54 +00:00
pub fn taproot_key_spend_signature_hash < T : Borrow < TxOut > > (
2021-11-25 10:47:40 +00:00
& mut self ,
input_index : usize ,
2022-02-17 07:35:54 +00:00
prevouts : & Prevouts < T > ,
2022-03-28 21:52:33 +00:00
sighash_type : SchnorrSighashType ,
2021-11-25 10:47:40 +00:00
) -> Result < TapSighashHash , Error > {
let mut enc = TapSighashHash ::engine ( ) ;
self . taproot_encode_signing_data_to (
& mut enc ,
input_index ,
prevouts ,
None ,
None ,
sighash_type ,
) ? ;
Ok ( TapSighashHash ::from_engine ( enc ) )
}
2022-03-16 03:02:21 +00:00
/// Computes the BIP341 sighash for a script spend.
2021-11-25 10:47:40 +00:00
///
/// Assumes the default `OP_CODESEPARATOR` position of `0xFFFFFFFF`. Custom values can be
2022-03-28 21:59:14 +00:00
/// provided through the more fine-grained API of [`SighashCache::taproot_encode_signing_data_to`].
2022-02-17 07:35:54 +00:00
pub fn taproot_script_spend_signature_hash < S : Into < TapLeafHash > , T : Borrow < TxOut > > (
2021-11-25 10:47:40 +00:00
& mut self ,
input_index : usize ,
2022-02-17 07:35:54 +00:00
prevouts : & Prevouts < T > ,
2021-11-25 10:47:40 +00:00
leaf_hash : S ,
2022-03-28 21:52:33 +00:00
sighash_type : SchnorrSighashType ,
2021-11-25 10:47:40 +00:00
) -> Result < TapSighashHash , Error > {
let mut enc = TapSighashHash ::engine ( ) ;
self . taproot_encode_signing_data_to (
& mut enc ,
input_index ,
prevouts ,
None ,
Some ( ( leaf_hash . into ( ) , 0xFFFFFFFF ) ) ,
2021-07-16 08:14:07 +00:00
sighash_type ,
) ? ;
Ok ( TapSighashHash ::from_engine ( enc ) )
}
2022-03-16 03:02:21 +00:00
/// Encodes the BIP143 signing data for any flag type into a given object implementing a
2021-08-31 10:00:49 +00:00
/// [`std::io::Write`] trait.
2021-07-16 08:14:07 +00:00
pub fn segwit_encode_signing_data_to < Write : io ::Write > (
& mut self ,
mut writer : Write ,
input_index : usize ,
script_code : & Script ,
value : u64 ,
2022-03-28 21:48:53 +00:00
sighash_type : EcdsaSighashType ,
2021-07-16 08:14:07 +00:00
) -> Result < ( ) , Error > {
2022-06-07 02:39:25 +00:00
let zero_hash = sha256d ::Hash ::all_zeros ( ) ;
2021-07-16 08:14:07 +00:00
let ( sighash , anyone_can_pay ) = sighash_type . split_anyonecanpay_flag ( ) ;
self . tx . version . consensus_encode ( & mut writer ) ? ;
if ! anyone_can_pay {
self . segwit_cache ( ) . prevouts . consensus_encode ( & mut writer ) ? ;
} else {
zero_hash . consensus_encode ( & mut writer ) ? ;
}
if ! anyone_can_pay
2022-03-28 21:48:53 +00:00
& & sighash ! = EcdsaSighashType ::Single
& & sighash ! = EcdsaSighashType ::None
2021-07-16 08:14:07 +00:00
{
self . segwit_cache ( )
. sequences
. consensus_encode ( & mut writer ) ? ;
} else {
zero_hash . consensus_encode ( & mut writer ) ? ;
}
{
2021-07-16 14:12:29 +00:00
let txin =
& self
. tx
. input
. get ( input_index )
2022-05-25 03:28:31 +00:00
. ok_or ( Error ::IndexOutOfInputsBounds {
2021-07-16 14:12:29 +00:00
index : input_index ,
inputs_size : self . tx . input . len ( ) ,
} ) ? ;
2021-07-16 08:14:07 +00:00
txin . previous_output . consensus_encode ( & mut writer ) ? ;
script_code . consensus_encode ( & mut writer ) ? ;
value . consensus_encode ( & mut writer ) ? ;
txin . sequence . consensus_encode ( & mut writer ) ? ;
}
2022-03-28 21:48:53 +00:00
if sighash ! = EcdsaSighashType ::Single & & sighash ! = EcdsaSighashType ::None {
2021-07-16 08:14:07 +00:00
self . segwit_cache ( ) . outputs . consensus_encode ( & mut writer ) ? ;
2022-03-28 21:48:53 +00:00
} else if sighash = = EcdsaSighashType ::Single & & input_index < self . tx . output . len ( ) {
2022-03-28 22:21:43 +00:00
let mut single_enc = Sighash ::engine ( ) ;
2021-07-16 08:14:07 +00:00
self . tx . output [ input_index ] . consensus_encode ( & mut single_enc ) ? ;
2022-03-28 22:21:43 +00:00
Sighash ::from_engine ( single_enc ) . consensus_encode ( & mut writer ) ? ;
2021-07-16 08:14:07 +00:00
} else {
zero_hash . consensus_encode ( & mut writer ) ? ;
}
self . tx . lock_time . consensus_encode ( & mut writer ) ? ;
2022-02-22 18:02:37 +00:00
sighash_type . to_u32 ( ) . consensus_encode ( & mut writer ) ? ;
2021-07-16 08:14:07 +00:00
Ok ( ( ) )
}
2022-03-16 03:02:21 +00:00
/// Computes the BIP143 sighash for any flag type.
2021-07-16 08:14:07 +00:00
pub fn segwit_signature_hash (
& mut self ,
input_index : usize ,
script_code : & Script ,
value : u64 ,
2022-03-28 21:48:53 +00:00
sighash_type : EcdsaSighashType ,
2022-03-28 22:21:43 +00:00
) -> Result < Sighash , Error > {
let mut enc = Sighash ::engine ( ) ;
2021-07-16 08:14:07 +00:00
self . segwit_encode_signing_data_to (
& mut enc ,
input_index ,
script_code ,
value ,
sighash_type ,
) ? ;
2022-03-28 22:21:43 +00:00
Ok ( Sighash ::from_engine ( enc ) )
2021-07-16 08:14:07 +00:00
}
2022-03-16 03:02:21 +00:00
/// Encodes the legacy signing data for any flag type into a given object implementing a
/// [`std::io::Write`] trait. Internally calls [`Transaction::encode_signing_data_to`].
2021-07-16 08:14:07 +00:00
pub fn legacy_encode_signing_data_to < Write : io ::Write , U : Into < u32 > > (
& self ,
mut writer : Write ,
input_index : usize ,
script_pubkey : & Script ,
sighash_type : U ,
2022-05-30 03:52:20 +00:00
) -> EncodeSigningDataResult < Error > {
2021-07-16 14:12:29 +00:00
if input_index > = self . tx . input . len ( ) {
2022-05-30 03:52:20 +00:00
return EncodeSigningDataResult ::WriteResult ( Err ( Error ::IndexOutOfInputsBounds {
2021-07-16 14:12:29 +00:00
index : input_index ,
inputs_size : self . tx . input . len ( ) ,
2022-05-30 03:52:20 +00:00
} ) ) ;
2021-07-16 14:12:29 +00:00
}
2022-05-30 03:52:20 +00:00
2021-07-16 08:14:07 +00:00
self . tx
. encode_signing_data_to ( & mut writer , input_index , script_pubkey , sighash_type . into ( ) )
2022-05-30 03:52:20 +00:00
. map_err ( | e | e . into ( ) )
2021-07-16 08:14:07 +00:00
}
2022-03-16 03:02:21 +00:00
/// Computes the legacy sighash for any `sighash_type`.
2021-07-16 08:14:07 +00:00
pub fn legacy_signature_hash (
& self ,
input_index : usize ,
script_pubkey : & Script ,
sighash_type : u32 ,
2022-03-28 22:21:43 +00:00
) -> Result < Sighash , Error > {
let mut enc = Sighash ::engine ( ) ;
2022-05-30 03:52:20 +00:00
if self . legacy_encode_signing_data_to ( & mut enc , input_index , script_pubkey , sighash_type )
. is_sighash_single_bug ( ) ? {
Ok ( Sighash ::from_inner ( UINT256_ONE ) )
} else {
Ok ( Sighash ::from_engine ( enc ) )
}
2021-07-16 08:14:07 +00:00
}
2021-08-10 08:36:51 +00:00
#[ inline ]
2021-07-16 08:14:07 +00:00
fn common_cache ( & mut self ) -> & CommonCache {
2021-08-10 08:36:51 +00:00
Self ::common_cache_minimal_borrow ( & mut self . common_cache , & self . tx )
}
2021-08-31 06:14:47 +00:00
fn common_cache_minimal_borrow < ' a > (
common_cache : & ' a mut Option < CommonCache > ,
tx : & R ,
) -> & ' a CommonCache {
2021-08-10 08:36:51 +00:00
common_cache . get_or_insert_with ( | | {
2021-07-16 08:14:07 +00:00
let mut enc_prevouts = sha256 ::Hash ::engine ( ) ;
let mut enc_sequences = sha256 ::Hash ::engine ( ) ;
2021-08-10 08:10:01 +00:00
for txin in tx . input . iter ( ) {
2021-07-16 08:14:07 +00:00
txin . previous_output
. consensus_encode ( & mut enc_prevouts )
. unwrap ( ) ;
txin . sequence . consensus_encode ( & mut enc_sequences ) . unwrap ( ) ;
}
2021-08-10 08:10:01 +00:00
CommonCache {
2021-07-16 08:14:07 +00:00
prevouts : sha256 ::Hash ::from_engine ( enc_prevouts ) ,
sequences : sha256 ::Hash ::from_engine ( enc_sequences ) ,
outputs : {
let mut enc = sha256 ::Hash ::engine ( ) ;
2021-08-10 08:10:01 +00:00
for txout in tx . output . iter ( ) {
2021-07-16 08:14:07 +00:00
txout . consensus_encode ( & mut enc ) . unwrap ( ) ;
}
sha256 ::Hash ::from_engine ( enc )
} ,
2021-08-10 08:10:01 +00:00
}
} )
2021-07-16 08:14:07 +00:00
}
fn segwit_cache ( & mut self ) -> & SegwitCache {
2021-08-10 08:36:51 +00:00
let common_cache = & mut self . common_cache ;
let tx = & self . tx ;
self . segwit_cache . get_or_insert_with ( | | {
let common_cache = Self ::common_cache_minimal_borrow ( common_cache , tx ) ;
SegwitCache {
2021-07-16 08:14:07 +00:00
prevouts : sha256d ::Hash ::from_inner (
2021-08-10 08:36:51 +00:00
sha256 ::Hash ::hash ( & common_cache . prevouts ) . into_inner ( ) ,
2021-07-16 08:14:07 +00:00
) ,
sequences : sha256d ::Hash ::from_inner (
2021-08-10 08:36:51 +00:00
sha256 ::Hash ::hash ( & common_cache . sequences ) . into_inner ( ) ,
2021-07-16 08:14:07 +00:00
) ,
outputs : sha256d ::Hash ::from_inner (
2021-08-10 08:36:51 +00:00
sha256 ::Hash ::hash ( & common_cache . outputs ) . into_inner ( ) ,
2021-07-16 08:14:07 +00:00
) ,
2021-08-10 08:36:51 +00:00
}
} )
2021-07-16 08:14:07 +00:00
}
2022-02-17 07:35:54 +00:00
fn taproot_cache < T : Borrow < TxOut > > ( & mut self , prevouts : & [ T ] ) -> & TaprootCache
{
2021-08-10 08:02:33 +00:00
self . taproot_cache . get_or_insert_with ( | | {
2021-07-16 08:14:07 +00:00
let mut enc_amounts = sha256 ::Hash ::engine ( ) ;
let mut enc_script_pubkeys = sha256 ::Hash ::engine ( ) ;
for prevout in prevouts {
2022-02-17 07:35:54 +00:00
prevout . borrow ( ) . value . consensus_encode ( & mut enc_amounts ) . unwrap ( ) ;
2021-07-16 08:14:07 +00:00
prevout
2022-02-17 07:35:54 +00:00
. borrow ( )
2021-07-16 08:14:07 +00:00
. script_pubkey
. consensus_encode ( & mut enc_script_pubkeys )
. unwrap ( ) ;
}
2021-08-10 08:02:33 +00:00
TaprootCache {
2021-07-16 08:14:07 +00:00
amounts : sha256 ::Hash ::from_engine ( enc_amounts ) ,
script_pubkeys : sha256 ::Hash ::from_engine ( enc_script_pubkeys ) ,
2021-08-10 08:02:33 +00:00
}
} )
2021-07-16 08:14:07 +00:00
}
}
2022-03-28 21:59:14 +00:00
impl < R : DerefMut < Target = Transaction > > SighashCache < R > {
2022-03-16 03:02:21 +00:00
/// 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.
2021-07-16 08:14:07 +00:00
///
/// This allows in-line signing such as
/// ```
2022-03-28 21:48:53 +00:00
/// use bitcoin::blockdata::transaction::{Transaction, EcdsaSighashType};
2022-03-28 21:59:14 +00:00
/// use bitcoin::util::sighash::SighashCache;
2022-05-16 20:27:31 +00:00
/// use bitcoin::{PackedLockTime, Script};
2021-07-16 08:14:07 +00:00
///
2022-05-16 20:27:31 +00:00
/// let mut tx_to_sign = Transaction { version: 2, lock_time: PackedLockTime::ZERO, input: Vec::new(), output: Vec::new() };
2021-07-16 08:14:07 +00:00
/// let input_count = tx_to_sign.input.len();
///
2022-03-28 21:59:14 +00:00
/// let mut sig_hasher = SighashCache::new(&mut tx_to_sign);
2021-07-16 08:14:07 +00:00
/// for inp in 0..input_count {
/// let prevout_script = Script::new();
2022-03-28 21:48:53 +00:00
/// let _sighash = sig_hasher.segwit_signature_hash(inp, &prevout_script, 42, EcdsaSighashType::All);
2021-07-16 08:14:07 +00:00
/// // ... sign the sighash
2021-10-05 13:07:55 +00:00
/// sig_hasher.witness_mut(inp).unwrap().push(&Vec::new());
2021-07-16 08:14:07 +00:00
/// }
/// ```
2021-10-05 13:07:55 +00:00
pub fn witness_mut ( & mut self , input_index : usize ) -> Option < & mut Witness > {
2021-08-31 06:26:20 +00:00
self . tx . input . get_mut ( input_index ) . map ( | i | & mut i . witness )
2021-07-16 08:14:07 +00:00
}
}
impl From < io ::Error > for Error {
2021-07-19 11:46:46 +00:00
fn from ( e : io ::Error ) -> Self {
Error ::Io ( e . kind ( ) )
2021-07-16 08:14:07 +00:00
}
}
2022-03-16 03:02:21 +00:00
/// The `Annex` struct is a slice wrapper enforcing first byte is `0x50`.
2021-07-16 08:14:07 +00:00
#[ derive(Clone, PartialEq, Eq, Hash, Debug) ]
pub struct Annex < ' a > ( & ' a [ u8 ] ) ;
impl < ' a > Annex < ' a > {
2022-03-16 03:02:21 +00:00
/// Creates a new `Annex` struct checking the first byte is `0x50`.
2021-07-16 08:14:07 +00:00
pub fn new ( annex_bytes : & ' a [ u8 ] ) -> Result < Self , Error > {
2022-01-06 09:49:19 +00:00
if annex_bytes . first ( ) = = Some ( & TAPROOT_ANNEX_PREFIX ) {
2021-07-16 08:14:07 +00:00
Ok ( Annex ( annex_bytes ) )
} else {
Err ( Error ::WrongAnnex )
}
}
2022-03-16 03:02:21 +00:00
/// Returns the Annex bytes data (including first byte `0x50`).
2021-07-16 08:14:07 +00:00
pub fn as_bytes ( & self ) -> & [ u8 ] {
& * self . 0
}
}
2021-07-16 13:05:15 +00:00
impl < ' a > Encodable for Annex < ' a > {
2022-06-29 01:22:12 +00:00
fn consensus_encode < W : io ::Write + ? Sized > ( & self , w : & mut W ) -> Result < usize , io ::Error > {
Take Writer/Reader by `&mut` in consensus en/decoding
Fix #1020 (see more relevant discussion there)
This definitely makes the amount of generics compiler
has to generate by avoding generating the same functions
for `R`, &mut R`, `&mut &mut R` and so on.
old:
```
> ls -al target/release/deps/bitcoin-07a9dabf1f3e0266
-rwxrwxr-x 1 dpc dpc 9947832 Jun 2 22:42 target/release/deps/bitcoin-07a9dabf1f3e0266
> strip target/release/deps/bitcoin-07a9dabf1f3e0266
> ls -al target/release/deps/bitcoin-07a9dabf1f3e0266
-rwxrwxr-x 1 dpc dpc 4463024 Jun 2 22:46 target/release/deps/bitcoin-07a9dabf1f3e0266
```
new:
```
> ls -al target/release/deps/bitcoin-07a9dabf1f3e0266
-rwxrwxr-x 1 dpc dpc 9866800 Jun 2 22:44 target/release/deps/bitcoin-07a9dabf1f3e0266
> strip target/release/deps/bitcoin-07a9dabf1f3e0266
> ls -al target/release/deps/bitcoin-07a9dabf1f3e0266
-rwxrwxr-x 1 dpc dpc 4393392 Jun 2 22:45 target/release/deps/bitcoin-07a9dabf1f3e0266
```
In the unit-test binary itself, it saves ~100KB of data.
I did not expect much performance gains, but turn out I was wrong(*):
old:
```
test blockdata::block::benches::bench_block_deserialize ... bench: 1,072,710 ns/iter (+/- 21,871)
test blockdata::block::benches::bench_block_serialize ... bench: 191,223 ns/iter (+/- 5,833)
test blockdata::block::benches::bench_block_serialize_logic ... bench: 37,543 ns/iter (+/- 732)
test blockdata::block::benches::bench_stream_reader ... bench: 1,872,455 ns/iter (+/- 149,519)
test blockdata::transaction::benches::bench_transaction_deserialize ... bench: 136 ns/iter (+/- 3)
test blockdata::transaction::benches::bench_transaction_serialize ... bench: 51 ns/iter (+/- 8)
test blockdata::transaction::benches::bench_transaction_serialize_logic ... bench: 5 ns/iter (+/- 0)
test blockdata::transaction::benches::bench_transaction_size ... bench: 3 ns/iter (+/- 0)
```
new:
```
test blockdata::block::benches::bench_block_deserialize ... bench: 1,028,574 ns/iter (+/- 10,910)
test blockdata::block::benches::bench_block_serialize ... bench: 162,143 ns/iter (+/- 3,363)
test blockdata::block::benches::bench_block_serialize_logic ... bench: 30,725 ns/iter (+/- 695)
test blockdata::block::benches::bench_stream_reader ... bench: 1,437,071 ns/iter (+/- 53,694)
test blockdata::transaction::benches::bench_transaction_deserialize ... bench: 92 ns/iter (+/- 2)
test blockdata::transaction::benches::bench_transaction_serialize ... bench: 17 ns/iter (+/- 0)
test blockdata::transaction::benches::bench_transaction_serialize_logic ... bench: 5 ns/iter (+/- 0)
test blockdata::transaction::benches::bench_transaction_size ... bench: 4 ns/iter (+/- 0)
```
(*) - I'm benchmarking on a noisy laptop. Take this with a grain of salt. But I think
at least it doesn't make anything slower.
While doing all this manual labor that will probably generate conflicts,
I took a liberty of changing generic type names and variable names to
`r` and `R` (reader) and `w` and `W` for writer.
2022-06-03 04:50:42 +00:00
encode ::consensus_encode_with_size ( self . 0 , w )
2021-07-16 13:05:15 +00:00
}
}
2021-07-16 08:14:07 +00:00
#[ cfg(test) ]
mod tests {
2021-11-15 20:38:24 +00:00
use super ::* ;
2022-05-16 20:27:31 +00:00
use crate ::blockdata ::locktime ::PackedLockTime ;
2022-05-02 22:13:57 +00:00
use crate ::consensus ::deserialize ;
use crate ::hashes ::hex ::FromHex ;
use crate ::hashes ::{ Hash , HashEngine } ;
use crate ::util ::sighash ::{ Annex , Error , Prevouts , ScriptPath , SighashCache } ;
2021-11-16 22:03:37 +00:00
use std ::str ::FromStr ;
2022-05-02 22:13:57 +00:00
use crate ::hashes ::hex ::ToHex ;
use crate ::util ::taproot ::{ TapTweakHash , TapSighashHash , TapBranchHash , TapLeafHash } ;
2022-01-03 02:52:44 +00:00
use secp256k1 ::{ self , SecretKey , XOnlyPublicKey } ;
2022-06-07 03:25:27 +00:00
use crate ::internal_macros ::{ hex_hash , hex_script , hex_decode } ;
2021-11-16 22:03:37 +00:00
extern crate serde_json ;
2022-05-02 22:13:57 +00:00
use crate ::{ Script , Transaction , TxIn , TxOut } ;
2021-07-16 08:14:07 +00:00
#[ test ]
fn test_tap_sighash_hash ( ) {
let bytes = Vec ::from_hex ( " 00011b96877db45ffa23b307e9f0ac87b80ef9a80b4c5f0db3fbe734422453e83cc5576f3d542c5d4898fb2b696c15d43332534a7c1d1255fda38993545882df92c3e353ff6d36fbfadc4d168452afd8467f02fe53d71714fcea5dfe2ea759bd00185c4cb02bc76d42620393ca358a1a713f4997f9fc222911890afb3fe56c6a19b202df7bffdcfad08003821294279043746631b00e2dc5e52a111e213bbfe6ef09a19428d418dab0d50000000000 " ) . unwrap ( ) ;
let expected =
Vec ::from_hex ( " 04e808aad07a40b3767a1442fead79af6ef7e7c9316d82dec409bb31e77699b0 " )
. unwrap ( ) ;
let mut enc = TapSighashHash ::engine ( ) ;
enc . input ( & bytes ) ;
let hash = TapSighashHash ::from_engine ( enc ) ;
assert_eq! ( expected , hash . into_inner ( ) ) ;
}
#[ test ]
fn test_sighashes_keyspending ( ) {
// following test case has been taken from bitcoin core test framework
test_taproot_sighash (
" 020000000164eb050a5e3da0c2a65e4786f26d753b7bc69691fabccafb11f7acef36641f1846010000003101b2b404392a22000000000017a9147f2bde86fe78bf68a0544a4f290e12f0b7e0a08c87580200000000000017a91425d11723074ecfb96a0a83c3956bfaf362ae0c908758020000000000001600147e20f938993641de67bb0cdd71682aa34c4d29ad5802000000000000160014c64984dc8761acfa99418bd6bedc79b9287d652d72000000 " ,
" 01365724000000000023542156b39dab4f8f3508e0432cfb41fab110170acaa2d4c42539cb90a4dc7c093bc500 " ,
0 ,
" 33ca0ebfb4a945eeee9569fc0f5040221275f88690b7f8592ada88ce3bdf6703 " ,
2022-03-28 21:52:33 +00:00
SchnorrSighashType ::Default , None , None , None
2021-07-16 08:14:07 +00:00
) ;
test_taproot_sighash (
" 0200000002fff49be59befe7566050737910f6ccdc5e749c7f8860ddc140386463d88c5ad0f3000000002cf68eb4a3d67f9d4c079249f7e4f27b8854815cb1ed13842d4fbf395f9e217fd605ee24090100000065235d9203f458520000000000160014b6d48333bb13b4c644e57c43a9a26df3a44b785e58020000000000001976a914eea9461a9e1e3f765d3af3e726162e0229fe3eb688ac58020000000000001976a9143a8869c9f2b5ea1d4ff3aeeb6a8fb2fffb1ad5fe88ac0ad7125c " ,
" 02591f220000000000225120f25ad35583ea31998d968871d7de1abd2a52f6fe4178b54ea158274806ff4ece48fb310000000000225120f25ad35583ea31998d968871d7de1abd2a52f6fe4178b54ea158274806ff4ece " ,
1 ,
" 626ab955d58c9a8a600a0c580549d06dc7da4e802eb2a531f62a588e430967a8 " ,
2022-03-28 21:52:33 +00:00
SchnorrSighashType ::All , None , None , None
2021-07-16 08:14:07 +00:00
) ;
test_taproot_sighash (
" 0200000001350005f65aa830ced2079df348e2d8c2bdb4f10e2dde6a161d8a07b40d1ad87dae000000001611d0d603d9dc0e000000000017a914459b6d7d6bbb4d8837b4bf7e9a4556f952da2f5c8758020000000000001976a9141dd70e1299ffc2d5b51f6f87de9dfe9398c33cbb88ac58020000000000001976a9141dd70e1299ffc2d5b51f6f87de9dfe9398c33cbb88aca71c1f4f " ,
" 01c4811000000000002251201bf9297d0a2968ae6693aadd0fa514717afefd218087a239afb7418e2d22e65c " ,
0 ,
" dfa9437f9c9a1d1f9af271f79f2f5482f287cdb0d2e03fa92c8a9b216cc6061c " ,
2022-03-28 21:52:33 +00:00
SchnorrSighashType ::AllPlusAnyoneCanPay , None , None , None
2021-07-16 08:14:07 +00:00
) ;
test_taproot_sighash (
" 020000000185bed1a6da2bffbd60ec681a1bfb71c5111d6395b99b3f8b2bf90167111bcb18f5010000007c83ace802ded24a00000000001600142c4698f9f7a773866879755aa78c516fb332af8e5802000000000000160014d38639dfbac4259323b98a472405db0c461b31fa61073747 " ,
" 0144c84d0000000000225120e3f2107989c88e67296ab2faca930efa2e3a5bd3ff0904835a11c9e807458621 " ,
0 ,
" 3129de36a5d05fff97ffca31eb75fcccbbbc27b3147a7a36a9e4b45d8b625067 " ,
2022-03-28 21:52:33 +00:00
SchnorrSighashType ::None , None , None , None
2021-07-16 08:14:07 +00:00
) ;
test_taproot_sighash (
" eb93dbb901028c8515589dac980b6e7f8e4088b77ed866ca0d6d210a7218b6fd0f6b22dd6d7300000000eb4740a9047efc0e0000000000160014913da2128d8fcf292b3691db0e187414aa1783825802000000000000160014913da2128d8fcf292b3691db0e187414aa178382580200000000000017a9143dd27f01c6f7ef9bb9159937b17f17065ed01a0c875802000000000000160014d7630e19df70ada9905ede1722b800c0005f246641000000 " ,
" 013fed110000000000225120eb536ae8c33580290630fc495046e998086a64f8f33b93b07967d9029b265c55 " ,
0 ,
" 2441e8b0e063a2083ee790f14f2045022f07258ddde5ee01de543c9e789d80ae " ,
2022-03-28 21:52:33 +00:00
SchnorrSighashType ::NonePlusAnyoneCanPay , None , None , None
2021-07-16 08:14:07 +00:00
) ;
test_taproot_sighash (
" 02000000017836b409a5fed32211407e44b971591f2032053f14701fb5b3a30c0ff382f2cc9c0100000061ac55f60288fb5600000000001976a9144ea02f6f182b082fb6ce47e36bbde390b6a41b5088ac58020000000000001976a9144ea02f6f182b082fb6ce47e36bbde390b6a41b5088ace4000000 " ,
" 01efa558000000000022512007071ea3dc7e331b0687d0193d1e6d6ed10e645ef36f10ef8831d5e522ac9e80 " ,
0 ,
" 30239345177cadd0e3ea413d49803580abb6cb27971b481b7788a78d35117a88 " ,
2022-03-28 21:52:33 +00:00
SchnorrSighashType ::Single , None , None , None
2021-07-16 08:14:07 +00:00
) ;
test_taproot_sighash (
" 0100000001aa6deae89d5e0aaca58714fc76ef6f3c8284224888089232d4e663843ed3ab3eae010000008b6657a60450cb4c0000000000160014a3d42b5413ef0c0701c4702f3cd7d4df222c147058020000000000001976a91430b4ed8723a4ee8992aa2c8814cfe5c3ad0ab9d988ac5802000000000000160014365b1166a6ed0a5e8e9dff17a6d00bbb43454bc758020000000000001976a914bc98c51a84fe7fad5dc380eb8b39586eff47241688ac4f313247 " ,
" 0107af4e00000000002251202c36d243dfc06cb56a248e62df27ecba7417307511a81ae61aa41c597a929c69 " ,
0 ,
" bf9c83f26c6dd16449e4921f813f551c4218e86f2ec906ca8611175b41b566df " ,
2022-03-28 21:52:33 +00:00
SchnorrSighashType ::SinglePlusAnyoneCanPay , None , None , None
2021-07-16 08:14:07 +00:00
) ;
}
#[ test ]
fn test_sighashes_with_annex ( ) {
test_taproot_sighash (
" 0200000001df8123752e8f37d132c4e9f1ff7e4f9b986ade9211267e9ebd5fd22a5e718dec6d01000000ce4023b903cb7b23000000000017a914a18b36ea7a094db2f4940fc09edf154e86de7bd787580200000000000017a914afd0d512a2c5c2b40e25669e9cc460303c325b8b87580200000000000017a914a18b36ea7a094db2f4940fc09edf154e86de7bd787f6020000 " ,
" 01ea49260000000000225120ab5e9800806bf18cb246edcf5fe63441208fe955a4b5a35bbff65f5db622a010 " ,
0 ,
" 3b003000add359a364a156e73e02846782a59d0d95ca8c4638aaad99f2ef915c " ,
2022-03-28 21:52:33 +00:00
SchnorrSighashType ::SinglePlusAnyoneCanPay ,
2021-07-16 08:14:07 +00:00
Some ( " 507b979802e62d397acb29f56743a791894b99372872fc5af06a4f6e8d242d0615cda53062bb20e6ec79756fe39183f0c128adfe85559a8fa042b042c018aa8010143799e44f0893c40e1e " ) ,
None ,
2021-11-25 10:47:40 +00:00
None ,
2021-07-16 08:14:07 +00:00
) ;
}
#[ test ]
fn test_sighashes_with_script_path ( ) {
test_taproot_sighash (
" 020000000189fc651483f9296b906455dd939813bf086b1bbe7c77635e157c8e14ae29062195010000004445b5c7044561320000000000160014331414dbdada7fb578f700f38fb69995fc9b5ab958020000000000001976a914268db0a8104cc6d8afd91233cc8b3d1ace8ac3ef88ac580200000000000017a914ec00dcb368d6a693e11986d265f659d2f59e8be2875802000000000000160014c715799a49a0bae3956df9c17cb4440a673ac0df6f010000 " ,
" 011bec34000000000022512028055142ea437db73382e991861446040b61dd2185c4891d7daf6893d79f7182 " ,
0 ,
" d66de5274a60400c7b08c86ba6b7f198f40660079edf53aca89d2a9501317f2e " ,
2022-03-28 21:52:33 +00:00
SchnorrSighashType ::All ,
2021-07-16 08:14:07 +00:00
None ,
Some ( " 20cc4e1107aea1d170c5ff5b6817e1303010049724fb3caa7941792ea9d29b3e2bacab " ) ,
2021-11-25 10:47:40 +00:00
None ,
) ;
}
#[ test ]
fn test_sighashes_with_script_path_raw_hash ( ) {
test_taproot_sighash (
" 020000000189fc651483f9296b906455dd939813bf086b1bbe7c77635e157c8e14ae29062195010000004445b5c7044561320000000000160014331414dbdada7fb578f700f38fb69995fc9b5ab958020000000000001976a914268db0a8104cc6d8afd91233cc8b3d1ace8ac3ef88ac580200000000000017a914ec00dcb368d6a693e11986d265f659d2f59e8be2875802000000000000160014c715799a49a0bae3956df9c17cb4440a673ac0df6f010000 " ,
" 011bec34000000000022512028055142ea437db73382e991861446040b61dd2185c4891d7daf6893d79f7182 " ,
0 ,
" d66de5274a60400c7b08c86ba6b7f198f40660079edf53aca89d2a9501317f2e " ,
2022-03-28 21:52:33 +00:00
SchnorrSighashType ::All ,
2021-11-25 10:47:40 +00:00
None ,
None ,
Some ( " 15a2530514e399f8b5cf0b3d3112cf5b289eaa3e308ba2071b58392fdc6da68a " ) ,
2021-07-16 08:14:07 +00:00
) ;
}
#[ test ]
fn test_sighashes_with_annex_and_script ( ) {
test_taproot_sighash (
" 020000000132fb72cb8fba496755f027a9743e2d698c831fdb8304e4d1a346ac92cbf51acba50100000026bdc7df044aad34000000000017a9144fa2554ed6174586854fa3bc01de58dcf33567d0875802000000000000160014950367e1e62cdf240b35b883fc2f5e39f0eb9ab95802000000000000160014950367e1e62cdf240b35b883fc2f5e39f0eb9ab958020000000000001600141b31217d48ccc8760dcc0710fade5866d628e733a02d5122 " ,
" 011458360000000000225120a7baec3fb9f84614e3899fcc010c638f80f13539344120e1f4d8b68a9a011a13 " ,
0 ,
" a0042aa434f9a75904b64043f2a283f8b4c143c7f4f7f49a6cbe5b9f745f4c15 " ,
2022-03-28 21:52:33 +00:00
SchnorrSighashType ::All ,
2021-07-16 08:14:07 +00:00
Some ( " 50a6272b470e1460e3332ade7bb14b81671c564fb6245761bd5bd531394b28860e0b3808ab229fb51791fb6ae6fa82d915b2efb8f6df83ae1f5ab3db13e30928875e2a22b749d89358de481f19286cd4caa792ce27f9559082d227a731c5486882cc707f83da361c51b7aadd9a0cf68fe7480c410fa137b454482d9a1ebf0f96d760b4d61426fc109c6e8e99a508372c45caa7b000a41f8251305da3f206c1849985ba03f3d9592832b4053afbd23ab25d0465df0bc25a36c223aacf8e04ec736a418c72dc319e4da3e972e349713ca600965e7c665f2090d5a70e241ac164115a1f5639f28b1773327715ca307ace64a2de7f0e3df70a2ffee3857689f909c0dad46d8a20fa373a4cc6eed6d4c9806bf146f0d76baae1 " ) ,
Some ( " 7520ab9160dd8299dc1367659be3e8f66781fe440d52940c7f8d314a89b9f2698d406ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac " ) ,
2021-11-25 10:47:40 +00:00
None ,
2021-07-16 08:14:07 +00:00
) ;
}
#[ test ]
fn test_sighash_errors ( ) {
let dumb_tx = Transaction {
version : 0 ,
2022-05-16 20:27:31 +00:00
lock_time : PackedLockTime ::ZERO ,
2021-07-16 08:14:07 +00:00
input : vec ! [ TxIn ::default ( ) ] ,
output : vec ! [ ] ,
} ;
2022-03-28 21:59:14 +00:00
let mut c = SighashCache ::new ( & dumb_tx ) ;
2021-07-16 08:14:07 +00:00
2022-02-17 07:35:54 +00:00
// 1.29 fixes
let empty_vec = vec! [ ] ;
let empty_prevouts : Prevouts < TxOut > = Prevouts ::All ( & empty_vec ) ;
2021-07-16 08:14:07 +00:00
assert_eq! (
2022-03-28 21:52:33 +00:00
c . taproot_signature_hash ( 0 , & empty_prevouts , None , None , SchnorrSighashType ::All ) ,
2021-07-16 08:14:07 +00:00
Err ( Error ::PrevoutsSize )
) ;
let two = vec! [ TxOut ::default ( ) , TxOut ::default ( ) ] ;
let too_many_prevouts = Prevouts ::All ( & two ) ;
assert_eq! (
2022-03-28 21:52:33 +00:00
c . taproot_signature_hash ( 0 , & too_many_prevouts , None , None , SchnorrSighashType ::All ) ,
2021-07-16 08:14:07 +00:00
Err ( Error ::PrevoutsSize )
) ;
let tx_out = TxOut ::default ( ) ;
let prevout = Prevouts ::One ( 1 , & tx_out ) ;
assert_eq! (
2022-03-28 21:52:33 +00:00
c . taproot_signature_hash ( 0 , & prevout , None , None , SchnorrSighashType ::All ) ,
2021-07-16 08:14:07 +00:00
Err ( Error ::PrevoutKind )
) ;
assert_eq! (
2022-03-28 21:52:33 +00:00
c . taproot_signature_hash ( 0 , & prevout , None , None , SchnorrSighashType ::AllPlusAnyoneCanPay ) ,
2021-07-16 08:14:07 +00:00
Err ( Error ::PrevoutIndex )
) ;
assert_eq! (
2022-03-28 21:52:33 +00:00
c . taproot_signature_hash ( 10 , & prevout , None , None , SchnorrSighashType ::AllPlusAnyoneCanPay ) ,
2021-07-16 14:12:29 +00:00
Err ( Error ::IndexOutOfInputsBounds {
index : 10 ,
inputs_size : 1
} )
) ;
let prevout = Prevouts ::One ( 0 , & tx_out ) ;
assert_eq! (
2022-03-28 21:52:33 +00:00
c . taproot_signature_hash ( 0 , & prevout , None , None , SchnorrSighashType ::SinglePlusAnyoneCanPay ) ,
2021-07-16 14:12:29 +00:00
Err ( Error ::SingleWithoutCorrespondingOutput {
index : 0 ,
outputs_size : 0
} )
) ;
assert_eq! (
c . legacy_signature_hash ( 10 , & Script ::default ( ) , 0 u32 ) ,
Err ( Error ::IndexOutOfInputsBounds {
index : 10 ,
inputs_size : 1
} )
2021-07-16 08:14:07 +00:00
) ;
}
#[ test ]
fn test_annex_errors ( ) {
2022-06-07 05:20:07 +00:00
assert_eq! ( Annex ::new ( & [ ] ) , Err ( Error ::WrongAnnex ) ) ;
assert_eq! ( Annex ::new ( & [ 0x51 ] ) , Err ( Error ::WrongAnnex ) ) ;
assert_eq! ( Annex ::new ( & [ 0x51 , 0x50 ] ) , Err ( Error ::WrongAnnex ) ) ;
2021-07-16 08:14:07 +00:00
}
2022-06-07 05:24:31 +00:00
#[ allow(clippy::too_many_arguments) ]
2021-07-16 08:14:07 +00:00
fn test_taproot_sighash (
tx_hex : & str ,
prevout_hex : & str ,
input_index : usize ,
expected_hash : & str ,
2022-03-28 21:52:33 +00:00
sighash_type : SchnorrSighashType ,
2021-07-16 08:14:07 +00:00
annex_hex : Option < & str > ,
script_hex : Option < & str > ,
2021-11-25 10:47:40 +00:00
script_leaf_hash : Option < & str > ,
2021-07-16 08:14:07 +00:00
) {
let tx_bytes = Vec ::from_hex ( tx_hex ) . unwrap ( ) ;
let tx : Transaction = deserialize ( & tx_bytes ) . unwrap ( ) ;
let prevout_bytes = Vec ::from_hex ( prevout_hex ) . unwrap ( ) ;
let prevouts : Vec < TxOut > = deserialize ( & prevout_bytes ) . unwrap ( ) ;
let annex_inner ;
let annex = match annex_hex {
Some ( annex_hex ) = > {
annex_inner = Vec ::from_hex ( annex_hex ) . unwrap ( ) ;
Some ( Annex ::new ( & annex_inner ) . unwrap ( ) )
}
None = > None ,
} ;
2021-11-25 10:47:40 +00:00
let leaf_hash = match ( script_hex , script_leaf_hash ) {
( Some ( script_hex ) , _ ) = > {
let script_inner = Script ::from_hex ( script_hex ) . unwrap ( ) ;
Some ( ScriptPath ::with_defaults ( & script_inner ) . leaf_hash ( ) )
2021-07-16 08:14:07 +00:00
}
2021-11-25 10:47:40 +00:00
( _ , Some ( script_leaf_hash ) ) = > {
Some ( TapLeafHash ::from_hex ( script_leaf_hash ) . unwrap ( ) )
}
_ = > None ,
2021-07-16 08:14:07 +00:00
} ;
2021-11-25 10:47:40 +00:00
// All our tests use the default `0xFFFFFFFF` codeseparator value
let leaf_hash = leaf_hash . map ( | lh | ( lh , 0xFFFFFFFF ) ) ;
2021-07-16 08:14:07 +00:00
let prevouts = if sighash_type . split_anyonecanpay_flag ( ) . 1 & & tx_bytes [ 0 ] % 2 = = 0 {
// for anyonecanpay the `Prevouts::All` variant is good anyway, but sometimes we want to
// test other codepaths
2022-02-17 07:35:54 +00:00
Prevouts ::One ( input_index , prevouts [ input_index ] . clone ( ) )
2021-07-16 08:14:07 +00:00
} else {
Prevouts ::All ( & prevouts )
} ;
2022-03-28 22:50:43 +00:00
let mut sighash_cache = SighashCache ::new ( & tx ) ;
2021-07-16 08:14:07 +00:00
2022-03-28 22:50:43 +00:00
let hash = sighash_cache
2021-11-25 10:47:40 +00:00
. taproot_signature_hash ( input_index , & prevouts , annex , leaf_hash , sighash_type )
2021-07-16 08:14:07 +00:00
. unwrap ( ) ;
let expected = Vec ::from_hex ( expected_hash ) . unwrap ( ) ;
assert_eq! ( expected , hash . into_inner ( ) ) ;
}
2021-11-16 22:03:37 +00:00
#[ test ]
fn bip_341_sighash_tests ( ) {
let data = bip_341_read_json ( ) ;
assert! ( data [ " version " ] . as_u64 ( ) . unwrap ( ) = = 1 u64 ) ;
let secp = & secp256k1 ::Secp256k1 ::new ( ) ;
let key_path = & data [ " keyPathSpending " ] . as_array ( ) . unwrap ( ) [ 0 ] ;
let raw_unsigned_tx = hex_decode! ( Transaction , key_path [ " given " ] [ " rawUnsignedTx " ] . as_str ( ) . unwrap ( ) ) ;
let mut utxos = vec! [ ] ;
for utxo in key_path [ " given " ] [ " utxosSpent " ] . as_array ( ) . unwrap ( ) {
let spk = hex_script! ( utxo [ " scriptPubKey " ] . as_str ( ) . unwrap ( ) ) ;
let amt = utxo [ " amountSats " ] . as_u64 ( ) . unwrap ( ) ;
utxos . push ( TxOut { value : amt , script_pubkey : spk } ) ;
}
// Test intermediary
2022-03-28 21:59:14 +00:00
let mut cache = SighashCache ::new ( & raw_unsigned_tx ) ;
2021-11-16 22:03:37 +00:00
let expected_amt_hash = key_path [ " intermediary " ] [ " hashAmounts " ] . 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_spks_hash = key_path [ " intermediary " ] [ " hashScriptPubkeys " ] . as_str ( ) . unwrap ( ) ;
let expected_sequences_hash = key_path [ " intermediary " ] [ " hashSequences " ] . as_str ( ) . unwrap ( ) ;
// Compute all caches
assert_eq! ( expected_amt_hash , cache . taproot_cache ( & utxos ) . amounts . to_hex ( ) ) ;
assert_eq! ( expected_outputs_hash , cache . common_cache ( ) . outputs . to_hex ( ) ) ;
assert_eq! ( expected_prevouts_hash , cache . common_cache ( ) . prevouts . to_hex ( ) ) ;
assert_eq! ( expected_spks_hash , cache . taproot_cache ( & utxos ) . script_pubkeys . to_hex ( ) ) ;
assert_eq! ( expected_sequences_hash , cache . common_cache ( ) . sequences . to_hex ( ) ) ;
for inp in key_path [ " inputSpending " ] . as_array ( ) . unwrap ( ) {
let tx_ind = inp [ " given " ] [ " txinIndex " ] . as_u64 ( ) . unwrap ( ) as usize ;
let internal_priv_key = hex_hash! ( SecretKey , inp [ " given " ] [ " internalPrivkey " ] . as_str ( ) . unwrap ( ) ) ;
let merkle_root = if inp [ " given " ] [ " merkleRoot " ] . is_null ( ) {
None
} else {
Some ( hex_hash! ( TapBranchHash , inp [ " given " ] [ " merkleRoot " ] . as_str ( ) . unwrap ( ) ) )
} ;
2022-06-24 02:01:53 +00:00
let hash_ty = SchnorrSighashType ::from_consensus_u8 ( inp [ " given " ] [ " hashType " ] . as_u64 ( ) . unwrap ( ) as u8 ) . unwrap ( ) ;
2021-11-16 22:03:37 +00:00
2022-01-03 02:52:44 +00:00
let expected_internal_pk = hex_hash! ( XOnlyPublicKey , inp [ " intermediary " ] [ " internalPubkey " ] . as_str ( ) . unwrap ( ) ) ;
2021-11-16 22:03:37 +00:00
let expected_tweak = hex_hash! ( TapTweakHash , inp [ " intermediary " ] [ " tweak " ] . as_str ( ) . unwrap ( ) ) ;
2022-01-06 22:59:58 +00:00
let expected_tweaked_priv_key = hex_hash! ( SecretKey , inp [ " intermediary " ] [ " tweakedPrivkey " ] . as_str ( ) . unwrap ( ) ) ;
2021-11-16 22:03:37 +00:00
let expected_sig_msg = Vec ::< u8 > ::from_hex ( inp [ " intermediary " ] [ " sigMsg " ] . as_str ( ) . unwrap ( ) ) . unwrap ( ) ;
2022-03-28 22:50:43 +00:00
let expected_sighash = hex_hash! ( TapSighashHash , inp [ " intermediary " ] [ " sigHash " ] . as_str ( ) . unwrap ( ) ) ;
2021-11-16 22:03:37 +00:00
let sig_str = inp [ " expected " ] [ " witness " ] [ 0 ] . as_str ( ) . unwrap ( ) ;
let ( expected_key_spend_sig , expected_hash_ty ) = if sig_str . len ( ) = = 128 {
2022-03-28 21:52:33 +00:00
( secp256k1 ::schnorr ::Signature ::from_str ( sig_str ) . unwrap ( ) , SchnorrSighashType ::Default )
2021-11-16 22:03:37 +00:00
} else {
2022-06-24 02:01:53 +00:00
let hash_ty = SchnorrSighashType ::from_consensus_u8 ( Vec ::< u8 > ::from_hex ( & sig_str [ 128 .. ] ) . unwrap ( ) [ 0 ] ) . unwrap ( ) ;
2022-01-03 02:52:44 +00:00
( secp256k1 ::schnorr ::Signature ::from_str ( & sig_str [ .. 128 ] ) . unwrap ( ) , hash_ty )
2021-11-16 22:03:37 +00:00
} ;
// tests
2022-06-28 02:47:29 +00:00
let keypair = secp256k1 ::KeyPair ::from_secret_key ( secp , & internal_priv_key ) ;
let ( internal_key , _parity ) = XOnlyPublicKey ::from_keypair ( & keypair ) ;
2021-11-16 22:03:37 +00:00
let tweak = TapTweakHash ::from_key_and_tweak ( internal_key , merkle_root ) ;
2022-06-28 02:47:29 +00:00
let tweaked_keypair = keypair . add_xonly_tweak ( secp , & tweak . to_scalar ( ) ) . unwrap ( ) ;
2021-11-16 22:03:37 +00:00
let mut sig_msg = Vec ::new ( ) ;
cache . taproot_encode_signing_data_to (
& mut sig_msg ,
tx_ind ,
& Prevouts ::All ( & utxos ) ,
None ,
None ,
hash_ty
) . unwrap ( ) ;
2022-03-28 22:50:43 +00:00
let sighash = cache . taproot_signature_hash (
2021-11-16 22:03:37 +00:00
tx_ind ,
& Prevouts ::All ( & utxos ) ,
None ,
None ,
hash_ty
) . unwrap ( ) ;
2022-07-21 00:23:28 +00:00
let msg = secp256k1 ::Message ::from ( sighash ) ;
2022-01-03 02:52:44 +00:00
let key_spend_sig = secp . sign_schnorr_with_aux_rand ( & msg , & tweaked_keypair , & [ 0 u8 ; 32 ] ) ;
2021-11-16 22:03:37 +00:00
assert_eq! ( expected_internal_pk , internal_key ) ;
assert_eq! ( expected_tweak , tweak ) ;
assert_eq! ( expected_sig_msg , sig_msg ) ;
2022-03-28 22:50:43 +00:00
assert_eq! ( expected_sighash , sighash ) ;
2021-11-16 22:03:37 +00:00
assert_eq! ( expected_hash_ty , hash_ty ) ;
assert_eq! ( expected_key_spend_sig , key_spend_sig ) ;
2022-01-06 22:59:58 +00:00
let tweaked_priv_key = SecretKey ::from_keypair ( & tweaked_keypair ) ;
assert_eq! ( expected_tweaked_priv_key , tweaked_priv_key ) ;
2021-11-16 22:03:37 +00:00
}
}
fn bip_341_read_json ( ) -> serde_json ::Value {
let json_str = include_str! ( " ../../test_data/bip341_tests.json " ) ;
serde_json ::from_str ( json_str ) . expect ( " JSON was not well-formatted " )
}
2022-02-22 18:50:06 +00:00
#[ test ]
fn sighashtype_fromstr_display ( ) {
let sighashtypes = vec! [
2022-03-28 21:52:33 +00:00
( " SIGHASH_DEFAULT " , SchnorrSighashType ::Default ) ,
( " SIGHASH_ALL " , SchnorrSighashType ::All ) ,
( " SIGHASH_NONE " , SchnorrSighashType ::None ) ,
( " SIGHASH_SINGLE " , SchnorrSighashType ::Single ) ,
( " SIGHASH_ALL|SIGHASH_ANYONECANPAY " , SchnorrSighashType ::AllPlusAnyoneCanPay ) ,
( " SIGHASH_NONE|SIGHASH_ANYONECANPAY " , SchnorrSighashType ::NonePlusAnyoneCanPay ) ,
( " SIGHASH_SINGLE|SIGHASH_ANYONECANPAY " , SchnorrSighashType ::SinglePlusAnyoneCanPay ) ,
2022-02-22 18:50:06 +00:00
] ;
for ( s , sht ) in sighashtypes {
assert_eq! ( sht . to_string ( ) , s ) ;
2022-03-28 21:52:33 +00:00
assert_eq! ( SchnorrSighashType ::from_str ( s ) . unwrap ( ) , sht ) ;
2022-02-22 18:50:06 +00:00
}
let sht_mistakes = vec! [
" SIGHASH_ALL | SIGHASH_ANYONECANPAY " ,
" SIGHASH_NONE |SIGHASH_ANYONECANPAY " ,
" SIGHASH_SINGLE| SIGHASH_ANYONECANPAY " ,
" SIGHASH_ALL SIGHASH_ANYONECANPAY " ,
" SIGHASH_NONE | " ,
" SIGHASH_SIGNLE " ,
" DEFAULT " ,
" ALL " ,
" sighash_none " ,
" Sighash_none " ,
" SigHash_None " ,
" SigHash_NONE " ,
] ;
for s in sht_mistakes {
2022-03-28 21:52:33 +00:00
assert_eq! ( SchnorrSighashType ::from_str ( s ) . unwrap_err ( ) . to_string ( ) , format! ( " Unrecognized SIGHASH string ' {} ' " , s ) ) ;
2022-02-22 18:50:06 +00:00
}
}
2021-07-16 08:14:07 +00:00
}