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: ACK46c34b3fb7
apoelstra: ACK46c34b3fb7
Tree-SHA512: fe7e25e9cfb5155e4921de5ac185dbf9f4ca0770846d7892f6968b44fc5431f3f1a183380107449e90f7ea662094c60b118dc0468230384e8f9a8ef98d5ee0a0
This commit is contained in:
commit
9316c52946
|
@ -39,11 +39,11 @@ use blockdata::script::Script;
|
|||
use blockdata::witness::Witness;
|
||||
use consensus::{encode, Decodable, Encodable};
|
||||
use consensus::encode::MAX_VEC_SIZE;
|
||||
use hash_types::{SigHash, Txid, Wtxid};
|
||||
use hash_types::{Sighash, Txid, Wtxid};
|
||||
use VarInt;
|
||||
|
||||
#[cfg(doc)]
|
||||
use util::sighash::SchnorrSigHashType;
|
||||
use util::sighash::SchnorrSighashType;
|
||||
|
||||
/// Used for signature hash for invalid use of SIGHASH_SINGLE.
|
||||
const UINT256_ONE: [u8; 32] = [
|
||||
|
@ -319,10 +319,10 @@ impl Transaction {
|
|||
/// sighash flag can be computed.
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// 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
|
||||
/// signature in a transaction.
|
||||
///
|
||||
|
@ -356,7 +356,7 @@ impl Transaction {
|
|||
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
|
||||
let mut tx = Transaction {
|
||||
|
@ -379,22 +379,22 @@ impl Transaction {
|
|||
tx.input.push(TxIn {
|
||||
previous_output: input.previous_output,
|
||||
script_sig: if n == input_index { script_pubkey.clone() } else { Script::new() },
|
||||
sequence: if n != input_index && (sighash == 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(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// ..then all outputs
|
||||
tx.output = match sighash {
|
||||
EcdsaSigHashType::All => self.output.clone(),
|
||||
EcdsaSigHashType::Single => {
|
||||
EcdsaSighashType::All => self.output.clone(),
|
||||
EcdsaSighashType::Single => {
|
||||
let output_iter = self.output.iter()
|
||||
.take(input_index + 1) // sign all outputs up to and including this one, but erase
|
||||
.enumerate() // all of them except for this one
|
||||
.map(|(n, out)| if n == input_index { out.clone() } else { TxOut::default() });
|
||||
output_iter.collect()
|
||||
}
|
||||
EcdsaSigHashType::None => vec![],
|
||||
EcdsaSighashType::None => vec![],
|
||||
_ => unreachable!()
|
||||
};
|
||||
// hash the result
|
||||
|
@ -407,10 +407,10 @@ impl Transaction {
|
|||
/// 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
|
||||
/// [`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.
|
||||
///
|
||||
/// 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
|
||||
/// signature in a transaction.
|
||||
///
|
||||
|
@ -432,20 +432,20 @@ impl Transaction {
|
|||
input_index: usize,
|
||||
script_pubkey: &Script,
|
||||
sighash_u32: u32
|
||||
) -> SigHash {
|
||||
) -> Sighash {
|
||||
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)
|
||||
.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 {
|
||||
let ty = EcdsaSigHashType::from_consensus(sighash);
|
||||
ty == EcdsaSigHashType::Single && input_index >= self.output.len()
|
||||
let ty = EcdsaSighashType::from_consensus(sighash);
|
||||
ty == EcdsaSighashType::Single && input_index >= self.output.len()
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// being relayed on today's Bitcoin network.
|
||||
#[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 {
|
||||
write!(f, "Non standard sighash type {}", self.0)
|
||||
}
|
||||
|
@ -733,18 +733,18 @@ impl fmt::Display for NonStandardSigHashType {
|
|||
|
||||
#[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
|
||||
#[deprecated(since = "0.28.0", note = "Please use [`EcdsaSigHashType`] instead")]
|
||||
pub type SigHashType = EcdsaSigHashType;
|
||||
#[deprecated(since = "0.28.0", note = "Please use [`EcdsaSighashType`] instead")]
|
||||
pub type SigHashType = EcdsaSighashType;
|
||||
|
||||
/// Hashtype of an input's signature, encoded in the last byte of the signature.
|
||||
///
|
||||
/// Fixed values so they can be cast as integer types for encoding (see also
|
||||
/// [`SchnorrSigHashType`]).
|
||||
/// [`SchnorrSighashType`]).
|
||||
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
|
||||
pub enum EcdsaSigHashType {
|
||||
pub enum EcdsaSighashType {
|
||||
/// 0x1: Sign all outputs.
|
||||
All = 0x01,
|
||||
/// 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).
|
||||
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 {
|
||||
let s = match self {
|
||||
EcdsaSigHashType::All => "SIGHASH_ALL",
|
||||
EcdsaSigHashType::None => "SIGHASH_NONE",
|
||||
EcdsaSigHashType::Single => "SIGHASH_SINGLE",
|
||||
EcdsaSigHashType::AllPlusAnyoneCanPay => "SIGHASH_ALL|SIGHASH_ANYONECANPAY",
|
||||
EcdsaSigHashType::NonePlusAnyoneCanPay => "SIGHASH_NONE|SIGHASH_ANYONECANPAY",
|
||||
EcdsaSigHashType::SinglePlusAnyoneCanPay => "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY",
|
||||
EcdsaSighashType::All => "SIGHASH_ALL",
|
||||
EcdsaSighashType::None => "SIGHASH_NONE",
|
||||
EcdsaSighashType::Single => "SIGHASH_SINGLE",
|
||||
EcdsaSighashType::AllPlusAnyoneCanPay => "SIGHASH_ALL|SIGHASH_ANYONECANPAY",
|
||||
EcdsaSighashType::NonePlusAnyoneCanPay => "SIGHASH_NONE|SIGHASH_ANYONECANPAY",
|
||||
EcdsaSighashType::SinglePlusAnyoneCanPay => "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY",
|
||||
};
|
||||
f.write_str(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl str::FromStr for EcdsaSigHashType {
|
||||
type Err = SigHashTypeParseError;
|
||||
impl str::FromStr for EcdsaSighashType {
|
||||
type Err = SighashTypeParseError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"SIGHASH_ALL" => Ok(EcdsaSigHashType::All),
|
||||
"SIGHASH_NONE" => Ok(EcdsaSigHashType::None),
|
||||
"SIGHASH_SINGLE" => Ok(EcdsaSigHashType::Single),
|
||||
"SIGHASH_ALL|SIGHASH_ANYONECANPAY" => Ok(EcdsaSigHashType::AllPlusAnyoneCanPay),
|
||||
"SIGHASH_NONE|SIGHASH_ANYONECANPAY" => Ok(EcdsaSigHashType::NonePlusAnyoneCanPay),
|
||||
"SIGHASH_SINGLE|SIGHASH_ANYONECANPAY" => Ok(EcdsaSigHashType::SinglePlusAnyoneCanPay),
|
||||
_ => Err(SigHashTypeParseError { unrecognized: s.to_owned() }),
|
||||
"SIGHASH_ALL" => Ok(EcdsaSighashType::All),
|
||||
"SIGHASH_NONE" => Ok(EcdsaSighashType::None),
|
||||
"SIGHASH_SINGLE" => Ok(EcdsaSighashType::Single),
|
||||
"SIGHASH_ALL|SIGHASH_ANYONECANPAY" => Ok(EcdsaSighashType::AllPlusAnyoneCanPay),
|
||||
"SIGHASH_NONE|SIGHASH_ANYONECANPAY" => Ok(EcdsaSighashType::NonePlusAnyoneCanPay),
|
||||
"SIGHASH_SINGLE|SIGHASH_ANYONECANPAY" => Ok(EcdsaSighashType::SinglePlusAnyoneCanPay),
|
||||
_ => Err(SighashTypeParseError { unrecognized: s.to_owned() }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EcdsaSigHashType {
|
||||
impl EcdsaSighashType {
|
||||
/// 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 {
|
||||
EcdsaSigHashType::All => (EcdsaSigHashType::All, false),
|
||||
EcdsaSigHashType::None => (EcdsaSigHashType::None, false),
|
||||
EcdsaSigHashType::Single => (EcdsaSigHashType::Single, false),
|
||||
EcdsaSigHashType::AllPlusAnyoneCanPay => (EcdsaSigHashType::All, true),
|
||||
EcdsaSigHashType::NonePlusAnyoneCanPay => (EcdsaSigHashType::None, true),
|
||||
EcdsaSigHashType::SinglePlusAnyoneCanPay => (EcdsaSigHashType::Single, true)
|
||||
EcdsaSighashType::All => (EcdsaSighashType::All, false),
|
||||
EcdsaSighashType::None => (EcdsaSighashType::None, false),
|
||||
EcdsaSighashType::Single => (EcdsaSighashType::Single, false),
|
||||
EcdsaSighashType::AllPlusAnyoneCanPay => (EcdsaSighashType::All, true),
|
||||
EcdsaSighashType::NonePlusAnyoneCanPay => (EcdsaSighashType::None, true),
|
||||
EcdsaSighashType::SinglePlusAnyoneCanPay => (EcdsaSighashType::Single, true)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a [`EcdsaSigHashType`] from a raw `u32`.
|
||||
/// Creates a [`EcdsaSighashType`] from a raw `u32`.
|
||||
#[deprecated(since="0.28.0", note="please use `from_consensus`")]
|
||||
pub fn from_u32_consensus(n: u32) -> EcdsaSigHashType {
|
||||
EcdsaSigHashType::from_consensus(n)
|
||||
pub fn from_u32_consensus(n: u32) -> EcdsaSighashType {
|
||||
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
|
||||
/// you probably want [`Self::from_standard`].
|
||||
///
|
||||
/// 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
|
||||
/// 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
|
||||
// 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.
|
||||
|
@ -829,58 +829,58 @@ impl EcdsaSigHashType {
|
|||
let mask = 0x1f | 0x80;
|
||||
match n & mask {
|
||||
// "real" sighashes
|
||||
0x01 => EcdsaSigHashType::All,
|
||||
0x02 => EcdsaSigHashType::None,
|
||||
0x03 => EcdsaSigHashType::Single,
|
||||
0x81 => EcdsaSigHashType::AllPlusAnyoneCanPay,
|
||||
0x82 => EcdsaSigHashType::NonePlusAnyoneCanPay,
|
||||
0x83 => EcdsaSigHashType::SinglePlusAnyoneCanPay,
|
||||
0x01 => EcdsaSighashType::All,
|
||||
0x02 => EcdsaSighashType::None,
|
||||
0x03 => EcdsaSighashType::Single,
|
||||
0x81 => EcdsaSighashType::AllPlusAnyoneCanPay,
|
||||
0x82 => EcdsaSighashType::NonePlusAnyoneCanPay,
|
||||
0x83 => EcdsaSighashType::SinglePlusAnyoneCanPay,
|
||||
// catchalls
|
||||
x if x & 0x80 == 0x80 => EcdsaSigHashType::AllPlusAnyoneCanPay,
|
||||
_ => EcdsaSigHashType::All
|
||||
x if x & 0x80 == 0x80 => EcdsaSighashType::AllPlusAnyoneCanPay,
|
||||
_ => 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`")]
|
||||
pub fn from_u32_standard(n: u32) -> Result<EcdsaSigHashType, NonStandardSigHashType> {
|
||||
EcdsaSigHashType::from_standard(n)
|
||||
pub fn from_u32_standard(n: u32) -> Result<EcdsaSighashType, NonStandardSighashType> {
|
||||
EcdsaSighashType::from_standard(n)
|
||||
}
|
||||
|
||||
/// Creates a [`EcdsaSigHashType`] from a raw `u32`.
|
||||
/// Creates a [`EcdsaSighashType`] from a raw `u32`.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// 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 {
|
||||
// Standard sighashes, see https://github.com/bitcoin/bitcoin/blob/b805dbb0b9c90dadef0424e5b3bf86ac308e103e/src/script/interpreter.cpp#L189-L198
|
||||
0x01 => Ok(EcdsaSigHashType::All),
|
||||
0x02 => Ok(EcdsaSigHashType::None),
|
||||
0x03 => Ok(EcdsaSigHashType::Single),
|
||||
0x81 => Ok(EcdsaSigHashType::AllPlusAnyoneCanPay),
|
||||
0x82 => Ok(EcdsaSigHashType::NonePlusAnyoneCanPay),
|
||||
0x83 => Ok(EcdsaSigHashType::SinglePlusAnyoneCanPay),
|
||||
non_standard => Err(NonStandardSigHashType(non_standard))
|
||||
0x01 => Ok(EcdsaSighashType::All),
|
||||
0x02 => Ok(EcdsaSighashType::None),
|
||||
0x03 => Ok(EcdsaSighashType::Single),
|
||||
0x81 => Ok(EcdsaSighashType::AllPlusAnyoneCanPay),
|
||||
0x82 => Ok(EcdsaSighashType::NonePlusAnyoneCanPay),
|
||||
0x83 => Ok(EcdsaSighashType::SinglePlusAnyoneCanPay),
|
||||
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.
|
||||
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.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SigHashTypeParseError {
|
||||
pub struct SighashTypeParseError {
|
||||
/// The unrecognized string we attempted to parse.
|
||||
pub unrecognized: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for SigHashTypeParseError {
|
||||
impl fmt::Display for SighashTypeParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Unrecognized SIGHASH string '{}'", self.unrecognized)
|
||||
}
|
||||
|
@ -888,7 +888,7 @@ impl fmt::Display for SigHashTypeParseError {
|
|||
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
#[cfg(feature = "std")]
|
||||
impl ::std::error::Error for SigHashTypeParseError {}
|
||||
impl ::std::error::Error for SighashTypeParseError {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
@ -904,8 +904,8 @@ mod tests {
|
|||
use hashes::hex::FromHex;
|
||||
|
||||
use hash_types::*;
|
||||
use super::EcdsaSigHashType;
|
||||
use util::sighash::SigHashCache;
|
||||
use super::EcdsaSighashType;
|
||||
use util::sighash::SighashCache;
|
||||
|
||||
#[test]
|
||||
fn test_outpoint() {
|
||||
|
@ -1167,16 +1167,16 @@ mod tests {
|
|||
#[test]
|
||||
fn test_sighashtype_fromstr_display() {
|
||||
let sighashtypes = vec![
|
||||
("SIGHASH_ALL", EcdsaSigHashType::All),
|
||||
("SIGHASH_NONE", EcdsaSigHashType::None),
|
||||
("SIGHASH_SINGLE", EcdsaSigHashType::Single),
|
||||
("SIGHASH_ALL|SIGHASH_ANYONECANPAY", EcdsaSigHashType::AllPlusAnyoneCanPay),
|
||||
("SIGHASH_NONE|SIGHASH_ANYONECANPAY", EcdsaSigHashType::NonePlusAnyoneCanPay),
|
||||
("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", EcdsaSigHashType::SinglePlusAnyoneCanPay)
|
||||
("SIGHASH_ALL", EcdsaSighashType::All),
|
||||
("SIGHASH_NONE", EcdsaSighashType::None),
|
||||
("SIGHASH_SINGLE", EcdsaSighashType::Single),
|
||||
("SIGHASH_ALL|SIGHASH_ANYONECANPAY", EcdsaSighashType::AllPlusAnyoneCanPay),
|
||||
("SIGHASH_NONE|SIGHASH_ANYONECANPAY", EcdsaSighashType::NonePlusAnyoneCanPay),
|
||||
("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", EcdsaSighashType::SinglePlusAnyoneCanPay)
|
||||
];
|
||||
for (s, sht) in sighashtypes {
|
||||
assert_eq!(sht.to_string(), s);
|
||||
assert_eq!(EcdsaSigHashType::from_str(s).unwrap(), sht);
|
||||
assert_eq!(EcdsaSighashType::from_str(s).unwrap(), sht);
|
||||
}
|
||||
let sht_mistakes = vec![
|
||||
"SIGHASH_ALL | SIGHASH_ANYONECANPAY",
|
||||
|
@ -1191,7 +1191,7 @@ mod tests {
|
|||
"SigHash_NONE",
|
||||
];
|
||||
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() {
|
||||
let nonstandard_hashtype = 0x04;
|
||||
// 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!
|
||||
assert_eq!(EcdsaSigHashType::from_u32_standard(nonstandard_hashtype), Err(NonStandardSigHashType(0x04)));
|
||||
assert_eq!(EcdsaSighashType::from_u32_standard(nonstandard_hashtype), Err(NonStandardSighashType(0x04)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1223,7 +1223,7 @@ mod tests {
|
|||
};
|
||||
let script = Script::new();
|
||||
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)
|
||||
}
|
||||
|
@ -1233,14 +1233,14 @@ mod tests {
|
|||
let script = Script::from(Vec::from_hex(script).unwrap());
|
||||
let mut raw_expected = Vec::from_hex(expected_result).unwrap();
|
||||
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 {
|
||||
// tx.signature_hash and cache.legacy_signature_hash are the same, this if helps to test
|
||||
// both the codepaths without repeating the test code
|
||||
tx.signature_hash(input_index, &script, hash_type as u32)
|
||||
} else {
|
||||
let cache = SigHashCache::new(&tx);
|
||||
let cache = SighashCache::new(&tx);
|
||||
cache.legacy_signature_hash(input_index, &script, hash_type as u32).unwrap()
|
||||
};
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ macro_rules! impl_hashencode {
|
|||
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!(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!(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!(Wtxid);
|
||||
impl_hashencode!(BlockHash);
|
||||
impl_hashencode!(SigHash);
|
||||
impl_hashencode!(Sighash);
|
||||
|
||||
impl_hashencode!(TxMerkleNode);
|
||||
impl_hashencode!(WitnessMerkleNode);
|
||||
|
|
|
@ -123,7 +123,7 @@ pub use blockdata::transaction::Transaction;
|
|||
pub use blockdata::transaction::TxIn;
|
||||
pub use blockdata::transaction::TxOut;
|
||||
pub use blockdata::transaction::OutPoint;
|
||||
pub use blockdata::transaction::EcdsaSigHashType;
|
||||
pub use blockdata::transaction::EcdsaSighashType;
|
||||
pub use blockdata::witness::Witness;
|
||||
pub use consensus::encode::VarInt;
|
||||
pub use network::constants::Network;
|
||||
|
@ -134,7 +134,7 @@ pub use util::amount::Amount;
|
|||
pub use util::amount::Denomination;
|
||||
pub use util::amount::SignedAmount;
|
||||
pub use util::merkleblock::MerkleBlock;
|
||||
pub use util::sighash::SchnorrSigHashType;
|
||||
pub use util::sighash::SchnorrSighashType;
|
||||
|
||||
pub use util::ecdsa::{self, EcdsaSig, EcdsaSigError};
|
||||
pub use util::schnorr::{self, SchnorrSig, SchnorrSigError};
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
//!
|
||||
|
||||
use hashes::Hash;
|
||||
use hash_types::SigHash;
|
||||
use hash_types::Sighash;
|
||||
use blockdata::script::Script;
|
||||
use blockdata::witness::Witness;
|
||||
use blockdata::transaction::{Transaction, TxIn, EcdsaSigHashType};
|
||||
use blockdata::transaction::{Transaction, TxIn, EcdsaSighashType};
|
||||
use consensus::{encode, Encodable};
|
||||
|
||||
use io;
|
||||
|
@ -33,16 +33,16 @@ use util::sighash;
|
|||
/// 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
|
||||
#[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 {
|
||||
tx_version: i32,
|
||||
tx_locktime: u32,
|
||||
/// Hash of all the previous outputs
|
||||
pub hash_prevouts: SigHash,
|
||||
pub hash_prevouts: Sighash,
|
||||
/// Hash of all the input sequence nos
|
||||
pub hash_sequence: SigHash,
|
||||
pub hash_sequence: Sighash,
|
||||
/// Hash of all the outputs in this transaction
|
||||
pub hash_outputs: SigHash,
|
||||
pub hash_outputs: Sighash,
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
|
@ -53,27 +53,27 @@ impl SighashComponents {
|
|||
/// script_sig and witnesses.
|
||||
pub fn new(tx: &Transaction) -> SighashComponents {
|
||||
let hash_prevouts = {
|
||||
let mut enc = SigHash::engine();
|
||||
let mut enc = Sighash::engine();
|
||||
for txin in &tx.input {
|
||||
txin.previous_output.consensus_encode(&mut enc).expect("engines don't error");
|
||||
}
|
||||
SigHash::from_engine(enc)
|
||||
Sighash::from_engine(enc)
|
||||
};
|
||||
|
||||
let hash_sequence = {
|
||||
let mut enc = SigHash::engine();
|
||||
let mut enc = Sighash::engine();
|
||||
for txin in &tx.input {
|
||||
txin.sequence.consensus_encode(&mut enc).expect("engines don't error");
|
||||
}
|
||||
SigHash::from_engine(enc)
|
||||
Sighash::from_engine(enc)
|
||||
};
|
||||
|
||||
let hash_outputs = {
|
||||
let mut enc = SigHash::engine();
|
||||
let mut enc = Sighash::engine();
|
||||
for txout in &tx.output {
|
||||
txout.consensus_encode(&mut enc).expect("engines don't error");
|
||||
}
|
||||
SigHash::from_engine(enc)
|
||||
Sighash::from_engine(enc)
|
||||
};
|
||||
|
||||
SighashComponents {
|
||||
|
@ -87,8 +87,8 @@ impl SighashComponents {
|
|||
|
||||
/// Compute the BIP143 sighash for a `SIGHASH_ALL` signature for the given
|
||||
/// input.
|
||||
pub fn sighash_all(&self, txin: &TxIn, script_code: &Script, value: u64) -> SigHash {
|
||||
let mut enc = SigHash::engine();
|
||||
pub fn sighash_all(&self, txin: &TxIn, script_code: &Script, value: u64) -> Sighash {
|
||||
let mut enc = Sighash::engine();
|
||||
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_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.tx_locktime.consensus_encode(&mut enc).expect("engines don't error");
|
||||
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
|
||||
#[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>> {
|
||||
cache: sighash::SigHashCache<R>,
|
||||
cache: sighash::SighashCache<R>,
|
||||
}
|
||||
|
||||
#[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
|
||||
/// script_sig and witnesses.
|
||||
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
|
||||
|
@ -130,7 +130,7 @@ impl<R: Deref<Target = Transaction>> SigHashCache<R> {
|
|||
input_index: usize,
|
||||
script_code: &Script,
|
||||
value: u64,
|
||||
sighash_type: EcdsaSigHashType,
|
||||
sighash_type: EcdsaSighashType,
|
||||
) -> Result<(), encode::Error> {
|
||||
self.cache
|
||||
.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,
|
||||
script_code: &Script,
|
||||
value: u64,
|
||||
sighash_type: EcdsaSigHashType
|
||||
) -> SigHash {
|
||||
let mut enc = SigHash::engine();
|
||||
sighash_type: EcdsaSighashType
|
||||
) -> Sighash {
|
||||
let mut enc = Sighash::engine();
|
||||
self.encode_signing_data_to(&mut enc, input_index, script_code, value, sighash_type)
|
||||
.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
|
||||
///
|
||||
/// ```
|
||||
/// use bitcoin::blockdata::transaction::{Transaction, EcdsaSigHashType};
|
||||
/// use bitcoin::blockdata::transaction::{Transaction, EcdsaSighashType};
|
||||
/// use bitcoin::util::bip143::SigHashCache;
|
||||
/// use bitcoin::Script;
|
||||
///
|
||||
|
@ -174,7 +174,7 @@ impl<R: DerefMut<Target = Transaction>> SigHashCache<R> {
|
|||
/// let mut sig_hasher = SigHashCache::new(&mut tx_to_sign);
|
||||
/// for inp in 0..input_count {
|
||||
/// let prevout_script = Script::new();
|
||||
/// let _sighash = sig_hasher.signature_hash(inp, &prevout_script, 42, EcdsaSigHashType::All);
|
||||
/// let _sighash = sig_hasher.signature_hash(inp, &prevout_script, 42, EcdsaSighashType::All);
|
||||
/// // ... sign the sighash
|
||||
/// sig_hasher.access_witness(inp).push(&[]);
|
||||
/// }
|
||||
|
@ -188,7 +188,7 @@ impl<R: DerefMut<Target = Transaction>> SigHashCache<R> {
|
|||
#[allow(deprecated)]
|
||||
mod tests {
|
||||
use std::str::FromStr;
|
||||
use hash_types::SigHash;
|
||||
use hash_types::Sighash;
|
||||
use blockdata::script::Script;
|
||||
use blockdata::transaction::Transaction;
|
||||
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) {
|
||||
let tx: Transaction = deserialize(&Vec::<u8>::from_hex(tx).unwrap()[..]).unwrap();
|
||||
let script = Script::from(Vec::<u8>::from_hex(script).unwrap());
|
||||
let raw_expected = SigHash::from_hex(expected_result).unwrap();
|
||||
let expected_result = SigHash::from_slice(&raw_expected[..]).unwrap();
|
||||
let raw_expected = Sighash::from_hex(expected_result).unwrap();
|
||||
let expected_result = Sighash::from_slice(&raw_expected[..]).unwrap();
|
||||
let mut cache = SigHashCache::new(&tx);
|
||||
let sighash_type = 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);
|
||||
assert_eq!(actual_result, expected_result);
|
||||
}
|
||||
|
@ -237,20 +237,20 @@ mod tests {
|
|||
tx_version: 1,
|
||||
tx_locktime: 17,
|
||||
hash_prevouts: hex_hash!(
|
||||
SigHash, "96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37"
|
||||
Sighash, "96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37"
|
||||
),
|
||||
hash_sequence: hex_hash!(
|
||||
SigHash, "52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b"
|
||||
Sighash, "52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b"
|
||||
),
|
||||
hash_outputs: hex_hash!(
|
||||
SigHash, "863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5"
|
||||
Sighash, "863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5"
|
||||
),
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
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_locktime: 1170,
|
||||
hash_prevouts: hex_hash!(
|
||||
SigHash, "b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a"
|
||||
Sighash, "b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a"
|
||||
),
|
||||
hash_sequence: hex_hash!(
|
||||
SigHash, "18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198"
|
||||
Sighash, "18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198"
|
||||
),
|
||||
hash_outputs: hex_hash!(
|
||||
SigHash, "de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83"
|
||||
Sighash, "de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83"
|
||||
),
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
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_locktime: 0,
|
||||
hash_prevouts: hex_hash!(
|
||||
SigHash, "74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0"
|
||||
Sighash, "74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0"
|
||||
),
|
||||
hash_sequence: hex_hash!(
|
||||
SigHash, "3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044"
|
||||
Sighash, "3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044"
|
||||
),
|
||||
hash_outputs: hex_hash!(
|
||||
SigHash, "bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc"
|
||||
Sighash, "bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc"
|
||||
),
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
comp.sighash_all(&tx.input[0], &witness_script, value),
|
||||
hex_hash!(SigHash, "185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c")
|
||||
hex_hash!(Sighash, "185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c")
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
|
|
|
@ -20,9 +20,9 @@ use prelude::*;
|
|||
use core::str::FromStr;
|
||||
use core::{fmt, iter};
|
||||
use hashes::hex::{self, FromHex};
|
||||
use blockdata::transaction::NonStandardSigHashType;
|
||||
use blockdata::transaction::NonStandardSighashType;
|
||||
use secp256k1;
|
||||
use EcdsaSigHashType;
|
||||
use EcdsaSighashType;
|
||||
|
||||
/// An ECDSA signature with the corresponding hash type.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
|
@ -31,24 +31,24 @@ pub struct EcdsaSig {
|
|||
/// The underlying ECDSA Signature
|
||||
pub sig: secp256k1::ecdsa::Signature,
|
||||
/// The corresponding hash type
|
||||
pub hash_ty: EcdsaSigHashType,
|
||||
pub hash_ty: EcdsaSighashType,
|
||||
}
|
||||
|
||||
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 {
|
||||
EcdsaSig {
|
||||
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> {
|
||||
let (hash_ty, sig) = sl.split_last()
|
||||
.ok_or(EcdsaSigError::EmptySignature)?;
|
||||
let hash_ty = EcdsaSigHashType::from_standard(*hash_ty as u32)
|
||||
.map_err(|_| EcdsaSigError::NonStandardSigHashType(*hash_ty as u32))?;
|
||||
let hash_ty = EcdsaSighashType::from_standard(*hash_ty as u32)
|
||||
.map_err(|_| EcdsaSigError::NonStandardSighashType(*hash_ty as u32))?;
|
||||
let sig = secp256k1::ecdsa::Signature::from_der(sig)
|
||||
.map_err(EcdsaSigError::Secp256k1)?;
|
||||
Ok(EcdsaSig { sig, hash_ty })
|
||||
|
@ -80,7 +80,7 @@ impl FromStr for EcdsaSig {
|
|||
.ok_or(EcdsaSigError::EmptySignature)?;
|
||||
Ok(EcdsaSig {
|
||||
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
|
||||
HexEncoding(hex::Error),
|
||||
/// Base58 encoding error
|
||||
NonStandardSigHashType(u32),
|
||||
NonStandardSighashType(u32),
|
||||
/// Empty Signature
|
||||
EmptySignature,
|
||||
/// secp256k1-related error
|
||||
|
@ -102,7 +102,7 @@ pub enum EcdsaSigError {
|
|||
impl fmt::Display for EcdsaSigError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
EcdsaSigError::NonStandardSigHashType(hash_ty) =>
|
||||
EcdsaSigError::NonStandardSighashType(hash_ty) =>
|
||||
write!(f, "Non standard signature hash type {}", hash_ty),
|
||||
EcdsaSigError::Secp256k1(ref e) =>
|
||||
write!(f, "Invalid Ecdsa signature: {}", e),
|
||||
|
@ -123,9 +123,9 @@ impl From<secp256k1::Error> for EcdsaSigError {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<NonStandardSigHashType> for EcdsaSigError {
|
||||
fn from(err: NonStandardSigHashType) -> Self {
|
||||
EcdsaSigError::NonStandardSigHashType(err.0)
|
||||
impl From<NonStandardSighashType> for EcdsaSigError {
|
||||
fn from(err: NonStandardSighashType) -> Self {
|
||||
EcdsaSigError::NonStandardSighashType(err.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,8 +61,8 @@ pub enum Error {
|
|||
/// Actual
|
||||
actual: Box<Transaction>,
|
||||
},
|
||||
/// Unable to parse as a standard SigHash type.
|
||||
NonStandardSigHashType(u32),
|
||||
/// Unable to parse as a standard sighash type.
|
||||
NonStandardSighashType(u32),
|
||||
/// Parsing errors from bitcoin_hashes
|
||||
HashParseError(hashes::Error),
|
||||
/// 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::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::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::InvalidSeparator => f.write_str("invalid separator"),
|
||||
Error::UnsignedTxHasScriptSigs => f.write_str("the unsigned transaction has script sigs"),
|
||||
|
|
|
@ -20,7 +20,7 @@ use core::str::FromStr;
|
|||
use secp256k1;
|
||||
use blockdata::script::Script;
|
||||
use blockdata::witness::Witness;
|
||||
use blockdata::transaction::{Transaction, TxOut, NonStandardSigHashType, SigHashTypeParseError};
|
||||
use blockdata::transaction::{Transaction, TxOut, NonStandardSighashType, SighashTypeParseError};
|
||||
use consensus::encode;
|
||||
use hashes::{self, hash160, ripemd160, sha256, sha256d};
|
||||
use secp256k1::XOnlyPublicKey;
|
||||
|
@ -34,7 +34,7 @@ use util::key::PublicKey;
|
|||
|
||||
use util::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapBranchHash};
|
||||
use util::sighash;
|
||||
use {EcdsaSigHashType, SchnorrSigHashType, EcdsaSig, SchnorrSig};
|
||||
use {EcdsaSighashType, SchnorrSighashType, EcdsaSig, SchnorrSig};
|
||||
|
||||
/// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00
|
||||
const PSBT_IN_NON_WITNESS_UTXO: u8 = 0x00;
|
||||
|
@ -95,7 +95,7 @@ pub struct Input {
|
|||
pub partial_sigs: BTreeMap<PublicKey, EcdsaSig>,
|
||||
/// The sighash type to be used for this input. Signatures for this input
|
||||
/// must use the sighash type.
|
||||
pub sighash_type: Option<PsbtSigHashType>,
|
||||
pub sighash_type: Option<PsbtSighashType>,
|
||||
/// The redeem script for this input.
|
||||
pub redeem_script: Option<Script>,
|
||||
/// 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
|
||||
/// 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
|
||||
/// 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)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct PsbtSigHashType {
|
||||
pub struct PsbtSighashType {
|
||||
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 {
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for PsbtSigHashType {
|
||||
type Err = SigHashTypeParseError;
|
||||
impl FromStr for PsbtSighashType {
|
||||
type Err = SighashTypeParseError;
|
||||
|
||||
#[inline]
|
||||
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
|
||||
// inputs. We also do not support SIGHASH_RESERVED in verbatim form
|
||||
// ("0xFF" string should be used instead).
|
||||
match SchnorrSigHashType::from_str(s) {
|
||||
Ok(SchnorrSigHashType::Reserved) => return Err(SigHashTypeParseError{ unrecognized: s.to_owned() }),
|
||||
match SchnorrSighashType::from_str(s) {
|
||||
Ok(SchnorrSighashType::Reserved) => return Err(SighashTypeParseError{ unrecognized: s.to_owned() }),
|
||||
Ok(ty) => return Ok(ty.into()),
|
||||
Err(_) => {}
|
||||
}
|
||||
|
@ -185,51 +185,51 @@ impl FromStr for PsbtSigHashType {
|
|||
// We accept non-standard sighash values.
|
||||
// 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) {
|
||||
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 {
|
||||
fn from(ecdsa_hash_ty: EcdsaSigHashType) -> Self {
|
||||
PsbtSigHashType { inner: ecdsa_hash_ty as u32 }
|
||||
impl From<EcdsaSighashType> for PsbtSighashType {
|
||||
fn from(ecdsa_hash_ty: EcdsaSighashType) -> Self {
|
||||
PsbtSighashType { inner: ecdsa_hash_ty as u32 }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SchnorrSigHashType> for PsbtSigHashType {
|
||||
fn from(schnorr_hash_ty: SchnorrSigHashType) -> Self {
|
||||
PsbtSigHashType { inner: schnorr_hash_ty as u32 }
|
||||
impl From<SchnorrSighashType> for PsbtSighashType {
|
||||
fn from(schnorr_hash_ty: SchnorrSighashType) -> Self {
|
||||
PsbtSighashType { inner: schnorr_hash_ty as u32 }
|
||||
}
|
||||
}
|
||||
|
||||
impl PsbtSigHashType {
|
||||
/// Returns the [`EcdsaSigHashType`] if the [`PsbtSigHashType`] can be
|
||||
impl PsbtSighashType {
|
||||
/// Returns the [`EcdsaSighashType`] if the [`PsbtSighashType`] can be
|
||||
/// converted to one.
|
||||
pub fn ecdsa_hash_ty(self) -> Result<EcdsaSigHashType, NonStandardSigHashType> {
|
||||
EcdsaSigHashType::from_standard(self.inner)
|
||||
pub fn ecdsa_hash_ty(self) -> Result<EcdsaSighashType, NonStandardSighashType> {
|
||||
EcdsaSighashType::from_standard(self.inner)
|
||||
}
|
||||
|
||||
/// Returns the [`SchnorrSigHashType`] if the [`PsbtSigHashType`] can be
|
||||
/// Returns the [`SchnorrSighashType`] if the [`PsbtSighashType`] can be
|
||||
/// 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 {
|
||||
Err(sighash::Error::InvalidSigHashType(self.inner))
|
||||
Err(sighash::Error::InvalidSighashType(self.inner))
|
||||
} 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
|
||||
/// ([`EcdsaSigHashType`], [`SchnorrSigHashType`] respectively).
|
||||
pub fn from_u32(n: u32) -> PsbtSigHashType {
|
||||
PsbtSigHashType { inner: n }
|
||||
/// ([`EcdsaSighashType`], [`SchnorrSighashType`] respectively).
|
||||
pub fn from_u32(n: u32) -> PsbtSighashType {
|
||||
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.
|
||||
pub fn to_u32(self) -> u32 {
|
||||
|
@ -238,28 +238,28 @@ impl PsbtSigHashType {
|
|||
}
|
||||
|
||||
impl Input {
|
||||
/// Obtains the [`EcdsaSigHashType`] for this input if one is specified. If no sighash type is
|
||||
/// specified, returns [`EcdsaSigHashType::All`].
|
||||
/// Obtains the [`EcdsaSighashType`] for this input if one is specified. If no sighash type is
|
||||
/// specified, returns [`EcdsaSighashType::All`].
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// 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
|
||||
.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
|
||||
/// specified, returns [`SchnorrSigHashType::Default`].
|
||||
/// Obtains the [`SchnorrSighashType`] for this input if one is specified. If no sighash type is
|
||||
/// specified, returns [`SchnorrSighashType::Default`].
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// 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
|
||||
.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> {
|
||||
|
@ -286,7 +286,7 @@ impl Input {
|
|||
}
|
||||
PSBT_IN_SIGHASH_TYPE => {
|
||||
impl_psbt_insert_pair! {
|
||||
self.sighash_type <= <raw_key: _>|<raw_value: PsbtSigHashType>
|
||||
self.sighash_type <= <raw_key: _>|<raw_value: PsbtSighashType>
|
||||
}
|
||||
}
|
||||
PSBT_IN_REDEEM_SCRIPT => {
|
||||
|
@ -544,16 +544,16 @@ mod test {
|
|||
#[test]
|
||||
fn psbt_sighash_type_ecdsa() {
|
||||
for ecdsa in &[
|
||||
EcdsaSigHashType::All,
|
||||
EcdsaSigHashType::None,
|
||||
EcdsaSigHashType::Single,
|
||||
EcdsaSigHashType::AllPlusAnyoneCanPay,
|
||||
EcdsaSigHashType::NonePlusAnyoneCanPay,
|
||||
EcdsaSigHashType::SinglePlusAnyoneCanPay,
|
||||
EcdsaSighashType::All,
|
||||
EcdsaSighashType::None,
|
||||
EcdsaSighashType::Single,
|
||||
EcdsaSighashType::AllPlusAnyoneCanPay,
|
||||
EcdsaSighashType::NonePlusAnyoneCanPay,
|
||||
EcdsaSighashType::SinglePlusAnyoneCanPay,
|
||||
] {
|
||||
let sighash = PsbtSigHashType::from(*ecdsa);
|
||||
let sighash = PsbtSighashType::from(*ecdsa);
|
||||
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.ecdsa_hash_ty().unwrap(), *ecdsa);
|
||||
}
|
||||
|
@ -562,17 +562,17 @@ mod test {
|
|||
#[test]
|
||||
fn psbt_sighash_type_schnorr() {
|
||||
for schnorr in &[
|
||||
SchnorrSigHashType::Default,
|
||||
SchnorrSigHashType::All,
|
||||
SchnorrSigHashType::None,
|
||||
SchnorrSigHashType::Single,
|
||||
SchnorrSigHashType::AllPlusAnyoneCanPay,
|
||||
SchnorrSigHashType::NonePlusAnyoneCanPay,
|
||||
SchnorrSigHashType::SinglePlusAnyoneCanPay,
|
||||
SchnorrSighashType::Default,
|
||||
SchnorrSighashType::All,
|
||||
SchnorrSighashType::None,
|
||||
SchnorrSighashType::Single,
|
||||
SchnorrSighashType::AllPlusAnyoneCanPay,
|
||||
SchnorrSighashType::NonePlusAnyoneCanPay,
|
||||
SchnorrSighashType::SinglePlusAnyoneCanPay,
|
||||
] {
|
||||
let sighash = PsbtSigHashType::from(*schnorr);
|
||||
let sighash = PsbtSighashType::from(*schnorr);
|
||||
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.schnorr_hash_ty().unwrap(), *schnorr);
|
||||
}
|
||||
|
@ -581,12 +581,12 @@ mod test {
|
|||
#[test]
|
||||
fn psbt_sighash_type_schnorr_notstd() {
|
||||
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);
|
||||
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.schnorr_hash_ty().unwrap(), *schnorr);
|
||||
}
|
||||
|
@ -595,12 +595,12 @@ mod test {
|
|||
#[test]
|
||||
fn psbt_sighash_type_notstd() {
|
||||
let nonstd = 0xdddddddd;
|
||||
let sighash = PsbtSigHashType { inner: nonstd };
|
||||
let sighash = PsbtSighashType { inner: nonstd };
|
||||
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.ecdsa_hash_ty(), Err(NonStandardSigHashType(nonstd)));
|
||||
assert_eq!(back.schnorr_hash_ty(), Err(sighash::Error::InvalidSigHashType(nonstd)));
|
||||
assert_eq!(back.ecdsa_hash_ty(), Err(NonStandardSighashType(nonstd)));
|
||||
assert_eq!(back.schnorr_hash_ty(), Err(sighash::Error::InvalidSighashType(nonstd)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ mod global;
|
|||
mod input;
|
||||
mod output;
|
||||
|
||||
pub use self::input::{Input, PsbtSigHashType};
|
||||
pub use self::input::{Input, PsbtSighashType};
|
||||
pub use self::output::{Output, TapTree};
|
||||
|
||||
/// A trait that describes a PSBT key-value map.
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
//!
|
||||
//! Implementation of BIP174 Partially Signed Bitcoin Transaction Format as
|
||||
//! 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;
|
||||
|
@ -41,7 +41,7 @@ mod macros;
|
|||
pub mod serialize;
|
||||
|
||||
mod map;
|
||||
pub use self::map::{Input, Output, TapTree, PsbtSigHashType};
|
||||
pub use self::map::{Input, Output, TapTree, PsbtSighashType};
|
||||
use self::map::Map;
|
||||
|
||||
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.
|
||||
use hashes::sha256d;
|
||||
use util::psbt::map::Input;
|
||||
use EcdsaSigHashType;
|
||||
use EcdsaSighashType;
|
||||
|
||||
// create some values to use in the PSBT
|
||||
let tx = Transaction {
|
||||
|
@ -532,7 +532,7 @@ mod tests {
|
|||
value: 190303501938,
|
||||
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()),
|
||||
witness_script: None,
|
||||
partial_sigs: vec![(
|
||||
|
@ -569,7 +569,7 @@ mod tests {
|
|||
use hash_types::Txid;
|
||||
|
||||
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 util::psbt::map::{Map, Input, Output};
|
||||
use util::psbt::raw;
|
||||
|
@ -795,7 +795,7 @@ mod tests {
|
|||
);
|
||||
assert_eq!(
|
||||
(&psbt.inputs[0].sighash_type).as_ref().unwrap().ecdsa_hash_ty().unwrap(),
|
||||
EcdsaSigHashType::All
|
||||
EcdsaSighashType::All
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ use util::taproot::{TapBranchHash, TapLeafHash, ControlBlock, LeafVersion};
|
|||
use schnorr;
|
||||
use util::key::PublicKey;
|
||||
|
||||
use super::map::{TapTree, PsbtSigHashType};
|
||||
use super::map::{TapTree, PsbtSighashType};
|
||||
|
||||
use util::taproot::TaprootBuilder;
|
||||
/// 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
|
||||
// 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.
|
||||
//
|
||||
// 2) This would cause to have invalid signatures because the sighash message
|
||||
|
@ -130,8 +130,8 @@ impl Deserialize for EcdsaSig {
|
|||
EcdsaSigError::EmptySignature => {
|
||||
encode::Error::ParseFailed("Empty partial signature data")
|
||||
}
|
||||
EcdsaSigError::NonStandardSigHashType(flag) => {
|
||||
encode::Error::from(psbt::Error::NonStandardSigHashType(flag))
|
||||
EcdsaSigError::NonStandardSighashType(flag) => {
|
||||
encode::Error::from(psbt::Error::NonStandardSighashType(flag))
|
||||
}
|
||||
EcdsaSigError::Secp256k1(..) => {
|
||||
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> {
|
||||
serialize(&self.to_u32())
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for PsbtSigHashType {
|
||||
impl Deserialize for PsbtSighashType {
|
||||
fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error> {
|
||||
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)
|
||||
.map_err(|e| match e {
|
||||
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(_) => {
|
||||
encode::Error::ParseFailed("Invalid Schnorr signature length")
|
||||
|
@ -373,9 +373,9 @@ mod tests {
|
|||
use super::*;
|
||||
|
||||
#[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 sighash = PsbtSigHashType::deserialize(&non_standard_sighash);
|
||||
let sighash = PsbtSighashType::deserialize(&non_standard_sighash);
|
||||
assert!(sighash.is_ok())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ use secp256k1::{XOnlyPublicKey as _XOnlyPublicKey, KeyPair as _KeyPair};
|
|||
use secp256k1::{self, Secp256k1, Verification, constants};
|
||||
use hashes::Hash;
|
||||
use util::taproot::{TapBranchHash, TapTweakHash};
|
||||
use SchnorrSigHashType;
|
||||
use SchnorrSighashType;
|
||||
|
||||
/// Deprecated re-export of [`secp256k1::XOnlyPublicKey`]
|
||||
#[deprecated(since = "0.28.0", note = "Please use `util::key::XOnlyPublicKey` instead")]
|
||||
|
@ -220,7 +220,7 @@ pub struct SchnorrSig {
|
|||
/// The underlying schnorr signature
|
||||
pub sig: secp256k1::schnorr::Signature,
|
||||
/// The corresponding hash type
|
||||
pub hash_ty: SchnorrSigHashType,
|
||||
pub hash_ty: SchnorrSighashType,
|
||||
}
|
||||
|
||||
impl SchnorrSig {
|
||||
|
@ -231,11 +231,11 @@ impl SchnorrSig {
|
|||
// default type
|
||||
let sig = secp256k1::schnorr::Signature::from_slice(sl)
|
||||
.map_err(SchnorrSigError::Secp256k1)?;
|
||||
return Ok( SchnorrSig { sig, hash_ty : SchnorrSigHashType::Default });
|
||||
return Ok( SchnorrSig { sig, hash_ty : SchnorrSighashType::Default });
|
||||
},
|
||||
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))?;
|
||||
let sig = secp256k1::schnorr::Signature::from_slice(sig)
|
||||
.map_err(SchnorrSigError::Secp256k1)?;
|
||||
|
@ -251,7 +251,7 @@ impl SchnorrSig {
|
|||
pub fn to_vec(&self) -> Vec<u8> {
|
||||
// TODO: add support to serialize to a writer to SerializedSig
|
||||
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
|
||||
} else {
|
||||
ser_sig.push(self.hash_ty as u8);
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
use prelude::*;
|
||||
|
||||
pub use blockdata::transaction::{EcdsaSigHashType, SigHashTypeParseError};
|
||||
pub use blockdata::transaction::{EcdsaSighashType, SighashTypeParseError};
|
||||
use blockdata::witness::Witness;
|
||||
use consensus::{encode, Encodable};
|
||||
use core::{str, fmt};
|
||||
|
@ -31,17 +31,17 @@ use core::borrow::Borrow;
|
|||
use hashes::{sha256, sha256d, Hash};
|
||||
use io;
|
||||
use util::taproot::{TapLeafHash, TAPROOT_ANNEX_PREFIX, TapSighashHash};
|
||||
use SigHash;
|
||||
use Sighash;
|
||||
use {Script, Transaction, TxOut};
|
||||
|
||||
use super::taproot::LeafVersion;
|
||||
|
||||
/// Efficiently calculates signature hash message for legacy, segwit and taproot inputs.
|
||||
#[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
|
||||
/// `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,
|
||||
|
||||
/// 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.
|
||||
/// 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)]
|
||||
pub enum Prevouts<'u, T> where T: 'u + Borrow<TxOut> {
|
||||
/// `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
|
||||
/// Fixed values so they can be casted as integer types for encoding
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub enum SchnorrSigHashType {
|
||||
/// 0x0: Used when not explicitly specified, defaulting to [`SchnorrSigHashType::All`]
|
||||
pub enum SchnorrSighashType {
|
||||
/// 0x0: Used when not explicitly specified, defaulting to [`SchnorrSighashType::All`]
|
||||
Default = 0x00,
|
||||
/// 0x1: Sign all outputs
|
||||
All = 0x01,
|
||||
|
@ -129,38 +129,38 @@ pub enum SchnorrSigHashType {
|
|||
/// Reserved for future use, `#[non_exhaustive]` is not available with current MSRV
|
||||
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 {
|
||||
let s = match self {
|
||||
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",
|
||||
SchnorrSigHashType::Reserved => "SIGHASH_RESERVED",
|
||||
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",
|
||||
SchnorrSighashType::Reserved => "SIGHASH_RESERVED",
|
||||
};
|
||||
f.write_str(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl str::FromStr for SchnorrSigHashType {
|
||||
type Err = SigHashTypeParseError;
|
||||
impl str::FromStr for SchnorrSighashType {
|
||||
type Err = SighashTypeParseError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"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),
|
||||
"SIGHASH_RESERVED" => Ok(SchnorrSigHashType::Reserved),
|
||||
_ => Err(SigHashTypeParseError{ unrecognized: s.to_owned() }),
|
||||
"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),
|
||||
"SIGHASH_RESERVED" => Ok(SchnorrSighashType::Reserved),
|
||||
_ => Err(SighashTypeParseError{ unrecognized: s.to_owned() }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ pub enum Error {
|
|||
WrongAnnex,
|
||||
|
||||
/// Invalid Sighash type
|
||||
InvalidSigHashType(u32),
|
||||
InvalidSighashType(u32),
|
||||
}
|
||||
|
||||
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::PrevoutKind => write!(f, "A single prevout has been provided but all prevouts are needed without `ANYONECANPAY`"),
|
||||
Error::WrongAnnex => write!(f, "Annex must be at least one byte long and the first bytes must be `0x50`"),
|
||||
Error::InvalidSigHashType(hash_ty) => write!(f, "Invalid schnorr Signature hash type : {} ", hash_ty),
|
||||
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 {
|
||||
fn from(s: EcdsaSigHashType) -> Self {
|
||||
impl From<EcdsaSighashType> for SchnorrSighashType {
|
||||
fn from(s: EcdsaSighashType) -> Self {
|
||||
match s {
|
||||
EcdsaSigHashType::All => SchnorrSigHashType::All,
|
||||
EcdsaSigHashType::None => SchnorrSigHashType::None,
|
||||
EcdsaSigHashType::Single => SchnorrSigHashType::Single,
|
||||
EcdsaSigHashType::AllPlusAnyoneCanPay => SchnorrSigHashType::AllPlusAnyoneCanPay,
|
||||
EcdsaSigHashType::NonePlusAnyoneCanPay => SchnorrSigHashType::NonePlusAnyoneCanPay,
|
||||
EcdsaSigHashType::SinglePlusAnyoneCanPay => SchnorrSigHashType::SinglePlusAnyoneCanPay,
|
||||
EcdsaSighashType::All => SchnorrSighashType::All,
|
||||
EcdsaSighashType::None => SchnorrSighashType::None,
|
||||
EcdsaSighashType::Single => SchnorrSighashType::Single,
|
||||
EcdsaSighashType::AllPlusAnyoneCanPay => SchnorrSighashType::AllPlusAnyoneCanPay,
|
||||
EcdsaSighashType::NonePlusAnyoneCanPay => SchnorrSighashType::NonePlusAnyoneCanPay,
|
||||
EcdsaSighashType::SinglePlusAnyoneCanPay => SchnorrSighashType::SinglePlusAnyoneCanPay,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SchnorrSigHashType {
|
||||
impl SchnorrSighashType {
|
||||
/// 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 {
|
||||
SchnorrSigHashType::Default => (SchnorrSigHashType::Default, false),
|
||||
SchnorrSigHashType::All => (SchnorrSigHashType::All, false),
|
||||
SchnorrSigHashType::None => (SchnorrSigHashType::None, false),
|
||||
SchnorrSigHashType::Single => (SchnorrSigHashType::Single, false),
|
||||
SchnorrSigHashType::AllPlusAnyoneCanPay => (SchnorrSigHashType::All, true),
|
||||
SchnorrSigHashType::NonePlusAnyoneCanPay => (SchnorrSigHashType::None, true),
|
||||
SchnorrSigHashType::SinglePlusAnyoneCanPay => (SchnorrSigHashType::Single, true),
|
||||
SchnorrSigHashType::Reserved => (SchnorrSigHashType::Reserved, false),
|
||||
SchnorrSighashType::Default => (SchnorrSighashType::Default, false),
|
||||
SchnorrSighashType::All => (SchnorrSighashType::All, false),
|
||||
SchnorrSighashType::None => (SchnorrSighashType::None, false),
|
||||
SchnorrSighashType::Single => (SchnorrSighashType::Single, false),
|
||||
SchnorrSighashType::AllPlusAnyoneCanPay => (SchnorrSighashType::All, true),
|
||||
SchnorrSighashType::NonePlusAnyoneCanPay => (SchnorrSighashType::None, true),
|
||||
SchnorrSighashType::SinglePlusAnyoneCanPay => (SchnorrSighashType::Single, true),
|
||||
SchnorrSighashType::Reserved => (SchnorrSighashType::Reserved, false),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a [`SchnorrSigHashType`] from raw `u8`
|
||||
/// Create a [`SchnorrSighashType`] from raw `u8`
|
||||
pub fn from_u8(hash_ty: u8) -> Result<Self, Error> {
|
||||
match hash_ty {
|
||||
0x00 => Ok(SchnorrSigHashType::Default),
|
||||
0x01 => Ok(SchnorrSigHashType::All),
|
||||
0x02 => Ok(SchnorrSigHashType::None),
|
||||
0x03 => Ok(SchnorrSigHashType::Single),
|
||||
0x81 => Ok(SchnorrSigHashType::AllPlusAnyoneCanPay),
|
||||
0x82 => Ok(SchnorrSigHashType::NonePlusAnyoneCanPay),
|
||||
0x83 => Ok(SchnorrSigHashType::SinglePlusAnyoneCanPay),
|
||||
0xFF => Ok(SchnorrSigHashType::Reserved),
|
||||
x => Err(Error::InvalidSigHashType(x as u32)),
|
||||
0x00 => Ok(SchnorrSighashType::Default),
|
||||
0x01 => Ok(SchnorrSighashType::All),
|
||||
0x02 => Ok(SchnorrSighashType::None),
|
||||
0x03 => Ok(SchnorrSighashType::Single),
|
||||
0x81 => Ok(SchnorrSighashType::AllPlusAnyoneCanPay),
|
||||
0x82 => Ok(SchnorrSighashType::NonePlusAnyoneCanPay),
|
||||
0x83 => Ok(SchnorrSighashType::SinglePlusAnyoneCanPay),
|
||||
0xFF => Ok(SchnorrSighashType::Reserved),
|
||||
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
|
||||
/// 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 witnesses.
|
||||
pub fn new(tx: R) -> Self {
|
||||
SigHashCache {
|
||||
SighashCache {
|
||||
tx,
|
||||
common_cache: None,
|
||||
taproot_cache: None,
|
||||
|
@ -355,7 +355,7 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
|
|||
prevouts: &Prevouts<T>,
|
||||
annex: Option<Annex>,
|
||||
leaf_hash_code_separator: Option<(TapLeafHash, u32)>,
|
||||
sighash_type: SchnorrSigHashType,
|
||||
sighash_type: SchnorrSighashType,
|
||||
) -> Result<(), Error> {
|
||||
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:
|
||||
// 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)?;
|
||||
}
|
||||
|
||||
|
@ -450,7 +450,7 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
|
|||
// * Data about this output:
|
||||
// If hash_type & 3 equals SIGHASH_SINGLE:
|
||||
// sha_single_output (32): the SHA256 of the corresponding output in CTxOut format.
|
||||
if sighash == SchnorrSigHashType::Single {
|
||||
if sighash == SchnorrSighashType::Single {
|
||||
let mut enc = sha256::Hash::engine();
|
||||
self.tx
|
||||
.output
|
||||
|
@ -484,7 +484,7 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
|
|||
prevouts: &Prevouts<T>,
|
||||
annex: Option<Annex>,
|
||||
leaf_hash_code_separator: Option<(TapLeafHash, u32)>,
|
||||
sighash_type: SchnorrSigHashType,
|
||||
sighash_type: SchnorrSighashType,
|
||||
) -> Result<TapSighashHash, Error> {
|
||||
let mut enc = TapSighashHash::engine();
|
||||
self.taproot_encode_signing_data_to(
|
||||
|
@ -503,7 +503,7 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
|
|||
&mut self,
|
||||
input_index: usize,
|
||||
prevouts: &Prevouts<T>,
|
||||
sighash_type: SchnorrSigHashType,
|
||||
sighash_type: SchnorrSighashType,
|
||||
) -> Result<TapSighashHash, Error> {
|
||||
let mut enc = TapSighashHash::engine();
|
||||
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
|
||||
///
|
||||
/// 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>>(
|
||||
&mut self,
|
||||
input_index: usize,
|
||||
prevouts: &Prevouts<T>,
|
||||
leaf_hash: S,
|
||||
sighash_type: SchnorrSigHashType,
|
||||
sighash_type: SchnorrSighashType,
|
||||
) -> Result<TapSighashHash, Error> {
|
||||
let mut enc = TapSighashHash::engine();
|
||||
self.taproot_encode_signing_data_to(
|
||||
|
@ -548,7 +548,7 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
|
|||
input_index: usize,
|
||||
script_code: &Script,
|
||||
value: u64,
|
||||
sighash_type: EcdsaSigHashType,
|
||||
sighash_type: EcdsaSighashType,
|
||||
) -> Result<(), Error> {
|
||||
let zero_hash = sha256d::Hash::default();
|
||||
|
||||
|
@ -563,8 +563,8 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
|
|||
}
|
||||
|
||||
if !anyone_can_pay
|
||||
&& sighash != EcdsaSigHashType::Single
|
||||
&& sighash != EcdsaSigHashType::None
|
||||
&& sighash != EcdsaSighashType::Single
|
||||
&& sighash != EcdsaSighashType::None
|
||||
{
|
||||
self.segwit_cache()
|
||||
.sequences
|
||||
|
@ -590,12 +590,12 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
|
|||
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)?;
|
||||
} else if sighash == EcdsaSigHashType::Single && input_index < self.tx.output.len() {
|
||||
let mut single_enc = SigHash::engine();
|
||||
} else if sighash == EcdsaSighashType::Single && input_index < self.tx.output.len() {
|
||||
let mut single_enc = Sighash::engine();
|
||||
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 {
|
||||
zero_hash.consensus_encode(&mut writer)?;
|
||||
}
|
||||
|
@ -611,9 +611,9 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
|
|||
input_index: usize,
|
||||
script_code: &Script,
|
||||
value: u64,
|
||||
sighash_type: EcdsaSigHashType,
|
||||
) -> Result<SigHash, Error> {
|
||||
let mut enc = SigHash::engine();
|
||||
sighash_type: EcdsaSighashType,
|
||||
) -> Result<Sighash, Error> {
|
||||
let mut enc = Sighash::engine();
|
||||
self.segwit_encode_signing_data_to(
|
||||
&mut enc,
|
||||
input_index,
|
||||
|
@ -621,7 +621,7 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
|
|||
value,
|
||||
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
|
||||
|
@ -645,16 +645,16 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Computes the legacy sighash for any SigHashType
|
||||
/// Computes the legacy sighash for any sighash type.
|
||||
pub fn legacy_signature_hash(
|
||||
&self,
|
||||
input_index: usize,
|
||||
script_pubkey: &Script,
|
||||
sighash_type: u32,
|
||||
) -> Result<SigHash, Error> {
|
||||
let mut enc = SigHash::engine();
|
||||
) -> Result<Sighash, Error> {
|
||||
let mut enc = Sighash::engine();
|
||||
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]
|
||||
|
@ -729,23 +729,23 @@ impl<R: Deref<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
|
||||
impl<R: DerefMut<Target=Transaction>> SighashCache<R> {
|
||||
/// 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.
|
||||
///
|
||||
/// This allows in-line signing such as
|
||||
/// ```
|
||||
/// use bitcoin::blockdata::transaction::{Transaction, EcdsaSigHashType};
|
||||
/// use bitcoin::util::sighash::SigHashCache;
|
||||
/// use bitcoin::blockdata::transaction::{Transaction, EcdsaSighashType};
|
||||
/// use bitcoin::util::sighash::SighashCache;
|
||||
/// use bitcoin::Script;
|
||||
///
|
||||
/// 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 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 {
|
||||
/// 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
|
||||
/// sig_hasher.witness_mut(inp).unwrap().push(&Vec::new());
|
||||
/// }
|
||||
|
@ -793,7 +793,7 @@ mod tests {
|
|||
use consensus::deserialize;
|
||||
use hashes::hex::FromHex;
|
||||
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 hashes::hex::ToHex;
|
||||
use util::taproot::{TapTweakHash, TapSighashHash, TapBranchHash, TapLeafHash};
|
||||
|
@ -823,7 +823,7 @@ mod tests {
|
|||
"01365724000000000023542156b39dab4f8f3508e0432cfb41fab110170acaa2d4c42539cb90a4dc7c093bc500",
|
||||
0,
|
||||
"33ca0ebfb4a945eeee9569fc0f5040221275f88690b7f8592ada88ce3bdf6703",
|
||||
SchnorrSigHashType::Default, None, None, None
|
||||
SchnorrSighashType::Default, None, None, None
|
||||
);
|
||||
|
||||
test_taproot_sighash(
|
||||
|
@ -831,7 +831,7 @@ mod tests {
|
|||
"02591f220000000000225120f25ad35583ea31998d968871d7de1abd2a52f6fe4178b54ea158274806ff4ece48fb310000000000225120f25ad35583ea31998d968871d7de1abd2a52f6fe4178b54ea158274806ff4ece",
|
||||
1,
|
||||
"626ab955d58c9a8a600a0c580549d06dc7da4e802eb2a531f62a588e430967a8",
|
||||
SchnorrSigHashType::All, None, None, None
|
||||
SchnorrSighashType::All, None, None, None
|
||||
);
|
||||
|
||||
test_taproot_sighash(
|
||||
|
@ -839,7 +839,7 @@ mod tests {
|
|||
"01c4811000000000002251201bf9297d0a2968ae6693aadd0fa514717afefd218087a239afb7418e2d22e65c",
|
||||
0,
|
||||
"dfa9437f9c9a1d1f9af271f79f2f5482f287cdb0d2e03fa92c8a9b216cc6061c",
|
||||
SchnorrSigHashType::AllPlusAnyoneCanPay, None, None, None
|
||||
SchnorrSighashType::AllPlusAnyoneCanPay, None, None, None
|
||||
);
|
||||
|
||||
test_taproot_sighash(
|
||||
|
@ -847,7 +847,7 @@ mod tests {
|
|||
"0144c84d0000000000225120e3f2107989c88e67296ab2faca930efa2e3a5bd3ff0904835a11c9e807458621",
|
||||
0,
|
||||
"3129de36a5d05fff97ffca31eb75fcccbbbc27b3147a7a36a9e4b45d8b625067",
|
||||
SchnorrSigHashType::None, None, None, None
|
||||
SchnorrSighashType::None, None, None, None
|
||||
);
|
||||
|
||||
test_taproot_sighash(
|
||||
|
@ -855,7 +855,7 @@ mod tests {
|
|||
"013fed110000000000225120eb536ae8c33580290630fc495046e998086a64f8f33b93b07967d9029b265c55",
|
||||
0,
|
||||
"2441e8b0e063a2083ee790f14f2045022f07258ddde5ee01de543c9e789d80ae",
|
||||
SchnorrSigHashType::NonePlusAnyoneCanPay, None, None, None
|
||||
SchnorrSighashType::NonePlusAnyoneCanPay, None, None, None
|
||||
);
|
||||
|
||||
test_taproot_sighash(
|
||||
|
@ -863,7 +863,7 @@ mod tests {
|
|||
"01efa558000000000022512007071ea3dc7e331b0687d0193d1e6d6ed10e645ef36f10ef8831d5e522ac9e80",
|
||||
0,
|
||||
"30239345177cadd0e3ea413d49803580abb6cb27971b481b7788a78d35117a88",
|
||||
SchnorrSigHashType::Single, None, None, None
|
||||
SchnorrSighashType::Single, None, None, None
|
||||
);
|
||||
|
||||
test_taproot_sighash(
|
||||
|
@ -871,7 +871,7 @@ mod tests {
|
|||
"0107af4e00000000002251202c36d243dfc06cb56a248e62df27ecba7417307511a81ae61aa41c597a929c69",
|
||||
0,
|
||||
"bf9c83f26c6dd16449e4921f813f551c4218e86f2ec906ca8611175b41b566df",
|
||||
SchnorrSigHashType::SinglePlusAnyoneCanPay, None, None, None
|
||||
SchnorrSighashType::SinglePlusAnyoneCanPay, None, None, None
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -882,7 +882,7 @@ mod tests {
|
|||
"01ea49260000000000225120ab5e9800806bf18cb246edcf5fe63441208fe955a4b5a35bbff65f5db622a010",
|
||||
0,
|
||||
"3b003000add359a364a156e73e02846782a59d0d95ca8c4638aaad99f2ef915c",
|
||||
SchnorrSigHashType::SinglePlusAnyoneCanPay,
|
||||
SchnorrSighashType::SinglePlusAnyoneCanPay,
|
||||
Some("507b979802e62d397acb29f56743a791894b99372872fc5af06a4f6e8d242d0615cda53062bb20e6ec79756fe39183f0c128adfe85559a8fa042b042c018aa8010143799e44f0893c40e1e"),
|
||||
None,
|
||||
None,
|
||||
|
@ -896,7 +896,7 @@ mod tests {
|
|||
"011bec34000000000022512028055142ea437db73382e991861446040b61dd2185c4891d7daf6893d79f7182",
|
||||
0,
|
||||
"d66de5274a60400c7b08c86ba6b7f198f40660079edf53aca89d2a9501317f2e",
|
||||
SchnorrSigHashType::All,
|
||||
SchnorrSighashType::All,
|
||||
None,
|
||||
Some("20cc4e1107aea1d170c5ff5b6817e1303010049724fb3caa7941792ea9d29b3e2bacab"),
|
||||
None,
|
||||
|
@ -910,7 +910,7 @@ mod tests {
|
|||
"011bec34000000000022512028055142ea437db73382e991861446040b61dd2185c4891d7daf6893d79f7182",
|
||||
0,
|
||||
"d66de5274a60400c7b08c86ba6b7f198f40660079edf53aca89d2a9501317f2e",
|
||||
SchnorrSigHashType::All,
|
||||
SchnorrSighashType::All,
|
||||
None,
|
||||
None,
|
||||
Some("15a2530514e399f8b5cf0b3d3112cf5b289eaa3e308ba2071b58392fdc6da68a"),
|
||||
|
@ -924,7 +924,7 @@ mod tests {
|
|||
"011458360000000000225120a7baec3fb9f84614e3899fcc010c638f80f13539344120e1f4d8b68a9a011a13",
|
||||
0,
|
||||
"a0042aa434f9a75904b64043f2a283f8b4c143c7f4f7f49a6cbe5b9f745f4c15",
|
||||
SchnorrSigHashType::All,
|
||||
SchnorrSighashType::All,
|
||||
Some("50a6272b470e1460e3332ade7bb14b81671c564fb6245761bd5bd531394b28860e0b3808ab229fb51791fb6ae6fa82d915b2efb8f6df83ae1f5ab3db13e30928875e2a22b749d89358de481f19286cd4caa792ce27f9559082d227a731c5486882cc707f83da361c51b7aadd9a0cf68fe7480c410fa137b454482d9a1ebf0f96d760b4d61426fc109c6e8e99a508372c45caa7b000a41f8251305da3f206c1849985ba03f3d9592832b4053afbd23ab25d0465df0bc25a36c223aacf8e04ec736a418c72dc319e4da3e972e349713ca600965e7c665f2090d5a70e241ac164115a1f5639f28b1773327715ca307ace64a2de7f0e3df70a2ffee3857689f909c0dad46d8a20fa373a4cc6eed6d4c9806bf146f0d76baae1"),
|
||||
Some("7520ab9160dd8299dc1367659be3e8f66781fe440d52940c7f8d314a89b9f2698d406ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac"),
|
||||
None,
|
||||
|
@ -939,33 +939,33 @@ mod tests {
|
|||
input: vec![TxIn::default()],
|
||||
output: vec![],
|
||||
};
|
||||
let mut c = SigHashCache::new(&dumb_tx);
|
||||
let mut c = SighashCache::new(&dumb_tx);
|
||||
|
||||
// 1.29 fixes
|
||||
let empty_vec = vec![];
|
||||
let empty_prevouts : Prevouts<TxOut> = Prevouts::All(&empty_vec);
|
||||
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)
|
||||
);
|
||||
let two = vec![TxOut::default(), TxOut::default()];
|
||||
let too_many_prevouts = Prevouts::All(&two);
|
||||
assert_eq!(
|
||||
c.taproot_signature_hash(0, &too_many_prevouts, None, None, SchnorrSigHashType::All),
|
||||
c.taproot_signature_hash(0, &too_many_prevouts, None, None, SchnorrSighashType::All),
|
||||
Err(Error::PrevoutsSize)
|
||||
);
|
||||
let tx_out = TxOut::default();
|
||||
let prevout = Prevouts::One(1, &tx_out);
|
||||
assert_eq!(
|
||||
c.taproot_signature_hash(0, &prevout, None, None, SchnorrSigHashType::All),
|
||||
c.taproot_signature_hash(0, &prevout, None, None, SchnorrSighashType::All),
|
||||
Err(Error::PrevoutKind)
|
||||
);
|
||||
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)
|
||||
);
|
||||
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 {
|
||||
index: 10,
|
||||
inputs_size: 1
|
||||
|
@ -973,7 +973,7 @@ mod tests {
|
|||
);
|
||||
let prevout = Prevouts::One(0, &tx_out);
|
||||
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 {
|
||||
index: 0,
|
||||
outputs_size: 0
|
||||
|
@ -1000,7 +1000,7 @@ mod tests {
|
|||
prevout_hex: &str,
|
||||
input_index: usize,
|
||||
expected_hash: &str,
|
||||
sighash_type: SchnorrSigHashType,
|
||||
sighash_type: SchnorrSighashType,
|
||||
annex_hex: Option<&str>,
|
||||
script_hex: Option<&str>,
|
||||
script_leaf_hash: Option<&str>,
|
||||
|
@ -1039,9 +1039,9 @@ mod tests {
|
|||
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)
|
||||
.unwrap();
|
||||
let expected = Vec::from_hex(expected_hash).unwrap();
|
||||
|
@ -1065,7 +1065,7 @@ mod tests {
|
|||
}
|
||||
|
||||
// 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_outputs_hash = key_path["intermediary"]["hashOutputs"].as_str().unwrap();
|
||||
let expected_prevouts_hash = key_path["intermediary"]["hashPrevouts"].as_str().unwrap();
|
||||
|
@ -1087,18 +1087,18 @@ mod tests {
|
|||
} else {
|
||||
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_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_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 (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 {
|
||||
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)
|
||||
};
|
||||
|
||||
|
@ -1117,7 +1117,7 @@ mod tests {
|
|||
None,
|
||||
hash_ty
|
||||
).unwrap();
|
||||
let sig_hash = cache.taproot_signature_hash(
|
||||
let sighash = cache.taproot_signature_hash(
|
||||
tx_ind,
|
||||
&Prevouts::All(&utxos),
|
||||
None,
|
||||
|
@ -1125,13 +1125,13 @@ mod tests {
|
|||
hash_ty
|
||||
).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]);
|
||||
|
||||
assert_eq!(expected_internal_pk, internal_key);
|
||||
assert_eq!(expected_tweak, tweak);
|
||||
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_key_spend_sig, key_spend_sig);
|
||||
|
||||
|
@ -1148,18 +1148,18 @@ mod tests {
|
|||
#[test]
|
||||
fn sighashtype_fromstr_display() {
|
||||
let sighashtypes = vec![
|
||||
("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),
|
||||
("SIGHASH_RESERVED", SchnorrSigHashType::Reserved),
|
||||
("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),
|
||||
("SIGHASH_RESERVED", SchnorrSighashType::Reserved),
|
||||
];
|
||||
for (s, sht) in sighashtypes {
|
||||
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![
|
||||
"SIGHASH_ALL | SIGHASH_ANYONECANPAY",
|
||||
|
@ -1176,7 +1176,7 @@ mod tests {
|
|||
"SigHash_NONE",
|
||||
];
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue