Merge rust-bitcoin/rust-bitcoin#1565: Reduce usage of `FromHex`
32ca6cc320
Remove hex_from_slice and display Sighash forwards (Tobin C. Harding)a308e1e2ea
Remove FromHex for all types except Vec and array (Tobin C. Harding)3e70c01826
Manually format a bunch of vecs (Tobin C. Harding)83e1c40c4d
Remove script:: prefix from unambiguous types (Tobin C. Harding)5ab5c264d2
Use fully qualified path in macro (Tobin C. Harding)7e85452cd9
hashes: Implement std::error::Error (Tobin C. Harding)5e3abc5e11
Fix feature gating on unit tests (Tobin C. Harding)3344cf6be2
Favour $reverse instead of $reversed (Tobin C. Harding) Pull request description: This work started out, as the branch name suggests, as an effort to use the `hex_lit` crate. But once I got to this stage it seems that the `hex!` macro we have provides different, useful, functionality than the `hex_lit::hex!` macro (it allows usage with non-consts). So I'm unsure if we want to remove it now. - Patches 1 - 6 are preparatory clean ups - Patch 7 reduces usage of `FromHex`, please see git log for full description - Patch 8 removes `hex_from_slice` and fixes a bug in how we display `Sighash` ACKs for top commit: apoelstra: ACK32ca6cc320
Kixunil: ACK32ca6cc320
Tree-SHA512: 11b45b39ec2fc0f837d7395b5fb86de7cc44641fd51cf7e93394a635e6a8fb1c7ac441a6070d5516dae60e084c04cc6e8b605a5167093f964679e445ef60c271
This commit is contained in:
commit
f52301151c
|
@ -37,13 +37,12 @@ use bitcoin::bip32::{
|
||||||
ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey, Fingerprint, IntoDerivationPath,
|
ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey, Fingerprint, IntoDerivationPath,
|
||||||
};
|
};
|
||||||
use bitcoin::consensus::encode;
|
use bitcoin::consensus::encode;
|
||||||
use bitcoin::hashes::hex::FromHex;
|
|
||||||
use bitcoin::locktime::absolute;
|
use bitcoin::locktime::absolute;
|
||||||
use bitcoin::psbt::{self, Input, Psbt, PsbtSighashType};
|
use bitcoin::psbt::{self, Input, Psbt, PsbtSighashType};
|
||||||
use bitcoin::secp256k1::{Secp256k1, Signing, Verification};
|
use bitcoin::secp256k1::{Secp256k1, Signing, Verification};
|
||||||
use bitcoin::{
|
use bitcoin::{
|
||||||
Address, Amount, Network, OutPoint, PublicKey, ScriptBuf, Sequence, Transaction, TxIn, TxOut,
|
Address, Amount, Network, OutPoint, PublicKey, ScriptBuf, Sequence, Transaction, TxIn, TxOut,
|
||||||
Txid, Witness,
|
Witness,
|
||||||
};
|
};
|
||||||
|
|
||||||
type Result<T> = std::result::Result<T, Error>;
|
type Result<T> = std::result::Result<T, Error>;
|
||||||
|
@ -189,7 +188,7 @@ impl WatchOnly {
|
||||||
lock_time: absolute::LockTime::ZERO,
|
lock_time: absolute::LockTime::ZERO,
|
||||||
input: vec![TxIn {
|
input: vec![TxIn {
|
||||||
previous_output: OutPoint {
|
previous_output: OutPoint {
|
||||||
txid: Txid::from_hex(INPUT_UTXO_TXID)?,
|
txid: INPUT_UTXO_TXID.parse()?,
|
||||||
vout: INPUT_UTXO_VOUT,
|
vout: INPUT_UTXO_VOUT,
|
||||||
},
|
},
|
||||||
script_sig: ScriptBuf::new(),
|
script_sig: ScriptBuf::new(),
|
||||||
|
|
|
@ -81,7 +81,6 @@ use std::str::FromStr;
|
||||||
use bitcoin::bip32::{ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey, Fingerprint};
|
use bitcoin::bip32::{ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey, Fingerprint};
|
||||||
use bitcoin::consensus::encode;
|
use bitcoin::consensus::encode;
|
||||||
use bitcoin::constants::COIN_VALUE;
|
use bitcoin::constants::COIN_VALUE;
|
||||||
use bitcoin::hashes::hex::FromHex;
|
|
||||||
use bitcoin::hashes::Hash;
|
use bitcoin::hashes::Hash;
|
||||||
use bitcoin::key::XOnlyPublicKey;
|
use bitcoin::key::XOnlyPublicKey;
|
||||||
use bitcoin::opcodes::all::{OP_CHECKSIG, OP_CLTV, OP_DROP};
|
use bitcoin::opcodes::all::{OP_CHECKSIG, OP_CLTV, OP_DROP};
|
||||||
|
@ -93,7 +92,7 @@ use bitcoin::taproot::{
|
||||||
LeafVersion, TapLeafHash, TapSighashHash, TaprootBuilder, TaprootSpendInfo,
|
LeafVersion, TapLeafHash, TapSighashHash, TaprootBuilder, TaprootSpendInfo,
|
||||||
};
|
};
|
||||||
use bitcoin::{
|
use bitcoin::{
|
||||||
absolute, script, Address, Amount, Network, OutPoint, ScriptBuf, Transaction, TxIn, TxOut, Txid, Witness,
|
absolute, script, Address, Amount, Network, OutPoint, ScriptBuf, Transaction, TxIn, TxOut, Witness,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
@ -239,7 +238,7 @@ fn generate_bip86_key_spend_tx(
|
||||||
lock_time: absolute::LockTime::ZERO,
|
lock_time: absolute::LockTime::ZERO,
|
||||||
input: vec![TxIn {
|
input: vec![TxIn {
|
||||||
previous_output: OutPoint {
|
previous_output: OutPoint {
|
||||||
txid: Txid::from_hex(input_utxo.txid)?,
|
txid: input_utxo.txid.parse()?,
|
||||||
vout: input_utxo.vout,
|
vout: input_utxo.vout,
|
||||||
},
|
},
|
||||||
script_sig: ScriptBuf::new(),
|
script_sig: ScriptBuf::new(),
|
||||||
|
@ -290,7 +289,7 @@ fn generate_bip86_key_spend_tx(
|
||||||
vout,
|
vout,
|
||||||
&sighash::Prevouts::All(&[TxOut {
|
&sighash::Prevouts::All(&[TxOut {
|
||||||
value: from_amount,
|
value: from_amount,
|
||||||
script_pubkey: ScriptBuf::from_str(input_utxo.script_pubkey)?,
|
script_pubkey: ScriptBuf::from_hex(input_utxo.script_pubkey)?,
|
||||||
}]),
|
}]),
|
||||||
hash_ty,
|
hash_ty,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -41,9 +41,9 @@ use crate::blockdata::constants::{
|
||||||
MAX_SCRIPT_ELEMENT_SIZE, PUBKEY_ADDRESS_PREFIX_MAIN, PUBKEY_ADDRESS_PREFIX_TEST,
|
MAX_SCRIPT_ELEMENT_SIZE, PUBKEY_ADDRESS_PREFIX_MAIN, PUBKEY_ADDRESS_PREFIX_TEST,
|
||||||
SCRIPT_ADDRESS_PREFIX_MAIN, SCRIPT_ADDRESS_PREFIX_TEST,
|
SCRIPT_ADDRESS_PREFIX_MAIN, SCRIPT_ADDRESS_PREFIX_TEST,
|
||||||
};
|
};
|
||||||
|
use crate::blockdata::opcodes;
|
||||||
use crate::blockdata::opcodes::all::*;
|
use crate::blockdata::opcodes::all::*;
|
||||||
use crate::blockdata::script::Instruction;
|
use crate::blockdata::script::{self, Instruction, Script, ScriptBuf};
|
||||||
use crate::blockdata::{opcodes, script};
|
|
||||||
use crate::crypto::key::PublicKey;
|
use crate::crypto::key::PublicKey;
|
||||||
use crate::crypto::schnorr::{TapTweak, TweakedPublicKey, UntweakedPublicKey};
|
use crate::crypto::schnorr::{TapTweak, TweakedPublicKey, UntweakedPublicKey};
|
||||||
use crate::error::ParseIntError;
|
use crate::error::ParseIntError;
|
||||||
|
@ -432,7 +432,7 @@ impl WitnessProgram {
|
||||||
|
|
||||||
impl Payload {
|
impl Payload {
|
||||||
/// Constructs a [Payload] from an output script (`scriptPubkey`).
|
/// Constructs a [Payload] from an output script (`scriptPubkey`).
|
||||||
pub fn from_script(script: &script::Script) -> Result<Payload, Error> {
|
pub fn from_script(script: &Script) -> Result<Payload, Error> {
|
||||||
Ok(if script.is_p2pkh() {
|
Ok(if script.is_p2pkh() {
|
||||||
let mut hash_inner = [0u8; 20];
|
let mut hash_inner = [0u8; 20];
|
||||||
hash_inner.copy_from_slice(&script.as_bytes()[3..23]);
|
hash_inner.copy_from_slice(&script.as_bytes()[3..23]);
|
||||||
|
@ -455,12 +455,12 @@ impl Payload {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a script pubkey spending to this [Payload].
|
/// Generates a script pubkey spending to this [Payload].
|
||||||
pub fn script_pubkey(&self) -> script::ScriptBuf {
|
pub fn script_pubkey(&self) -> ScriptBuf {
|
||||||
match *self {
|
match *self {
|
||||||
Payload::PubkeyHash(ref hash) => script::ScriptBuf::new_p2pkh(hash),
|
Payload::PubkeyHash(ref hash) => ScriptBuf::new_p2pkh(hash),
|
||||||
Payload::ScriptHash(ref hash) => script::ScriptBuf::new_p2sh(hash),
|
Payload::ScriptHash(ref hash) => ScriptBuf::new_p2sh(hash),
|
||||||
Payload::WitnessProgram(ref prog) =>
|
Payload::WitnessProgram(ref prog) =>
|
||||||
script::ScriptBuf::new_witness_program(prog)
|
ScriptBuf::new_witness_program(prog)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,7 +470,7 @@ impl Payload {
|
||||||
|
|
||||||
/// Creates a pay to script hash P2SH payload from a script
|
/// Creates a pay to script hash P2SH payload from a script
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn p2sh(script: &script::Script) -> Result<Payload, Error> {
|
pub fn p2sh(script: &Script) -> Result<Payload, Error> {
|
||||||
if script.len() > MAX_SCRIPT_ELEMENT_SIZE {
|
if script.len() > MAX_SCRIPT_ELEMENT_SIZE {
|
||||||
return Err(Error::ExcessiveScriptSize);
|
return Err(Error::ExcessiveScriptSize);
|
||||||
}
|
}
|
||||||
|
@ -496,7 +496,7 @@ impl Payload {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a witness pay to script hash payload.
|
/// Create a witness pay to script hash payload.
|
||||||
pub fn p2wsh(script: &script::Script) -> Payload {
|
pub fn p2wsh(script: &Script) -> Payload {
|
||||||
let prog = WitnessProgram::new(
|
let prog = WitnessProgram::new(
|
||||||
WitnessVersion::V0,
|
WitnessVersion::V0,
|
||||||
script.wscript_hash().as_ref().to_vec()
|
script.wscript_hash().as_ref().to_vec()
|
||||||
|
@ -505,7 +505,7 @@ impl Payload {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a pay to script payload that embeds a witness pay to script hash address
|
/// Create a pay to script payload that embeds a witness pay to script hash address
|
||||||
pub fn p2shwsh(script: &script::Script) -> Payload {
|
pub fn p2shwsh(script: &Script) -> Payload {
|
||||||
let ws =
|
let ws =
|
||||||
script::Builder::new().push_int(0).push_slice(script.wscript_hash().as_ref()).into_script();
|
script::Builder::new().push_int(0).push_slice(script.wscript_hash().as_ref()).into_script();
|
||||||
|
|
||||||
|
@ -820,7 +820,7 @@ impl Address {
|
||||||
/// This address type was introduced with BIP16 and is the popular type to implement multi-sig
|
/// This address type was introduced with BIP16 and is the popular type to implement multi-sig
|
||||||
/// these days.
|
/// these days.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn p2sh(script: &script::Script, network: Network) -> Result<Address, Error> {
|
pub fn p2sh(script: &Script, network: Network) -> Result<Address, Error> {
|
||||||
Ok(Address::new(network, Payload::p2sh(script)?))
|
Ok(Address::new(network, Payload::p2sh(script)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -845,14 +845,14 @@ impl Address {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a witness pay to script hash address.
|
/// Creates a witness pay to script hash address.
|
||||||
pub fn p2wsh(script: &script::Script, network: Network) -> Address {
|
pub fn p2wsh(script: &Script, network: Network) -> Address {
|
||||||
Address::new(network, Payload::p2wsh(script))
|
Address::new(network, Payload::p2wsh(script))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a pay to script address that embeds a witness pay to script hash address.
|
/// Creates a pay to script address that embeds a witness pay to script hash address.
|
||||||
///
|
///
|
||||||
/// This is a segwit address type that looks familiar (as p2sh) to legacy clients.
|
/// This is a segwit address type that looks familiar (as p2sh) to legacy clients.
|
||||||
pub fn p2shwsh(script: &script::Script, network: Network) -> Address {
|
pub fn p2shwsh(script: &Script, network: Network) -> Address {
|
||||||
Address::new(network, Payload::p2shwsh(script))
|
Address::new(network, Payload::p2shwsh(script))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -905,12 +905,12 @@ impl Address {
|
||||||
pub fn is_standard(&self) -> bool { self.address_type().is_some() }
|
pub fn is_standard(&self) -> bool { self.address_type().is_some() }
|
||||||
|
|
||||||
/// Constructs an [`Address`] from an output script (`scriptPubkey`).
|
/// Constructs an [`Address`] from an output script (`scriptPubkey`).
|
||||||
pub fn from_script(script: &script::Script, network: Network) -> Result<Address, Error> {
|
pub fn from_script(script: &Script, network: Network) -> Result<Address, Error> {
|
||||||
Ok(Address::new(network, Payload::from_script(script)?))
|
Ok(Address::new(network, Payload::from_script(script)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a script pubkey spending to this address.
|
/// Generates a script pubkey spending to this address.
|
||||||
pub fn script_pubkey(&self) -> script::ScriptBuf { self.payload.script_pubkey() }
|
pub fn script_pubkey(&self) -> ScriptBuf { self.payload.script_pubkey() }
|
||||||
|
|
||||||
/// Creates a URI string *bitcoin:address* optimized to be encoded in QR codes.
|
/// Creates a URI string *bitcoin:address* optimized to be encoded in QR codes.
|
||||||
///
|
///
|
||||||
|
@ -1133,7 +1133,7 @@ mod tests {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::crypto::key::PublicKey;
|
use crate::crypto::key::PublicKey;
|
||||||
use crate::internal_macros::{hex, hex_into, hex_script};
|
use crate::internal_macros::hex;
|
||||||
use crate::network::constants::Network::{Bitcoin, Testnet};
|
use crate::network::constants::Network::{Bitcoin, Testnet};
|
||||||
|
|
||||||
fn roundtrips(addr: &Address) {
|
fn roundtrips(addr: &Address) {
|
||||||
|
@ -1160,11 +1160,11 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_p2pkh_address_58() {
|
fn test_p2pkh_address_58() {
|
||||||
let addr = Address::new(Bitcoin, Payload::PubkeyHash(hex_into!("162c5ea71c0b23f5b9022ef047c4a86470a5b070")));
|
let addr = Address::new(Bitcoin, Payload::PubkeyHash("162c5ea71c0b23f5b9022ef047c4a86470a5b070".parse().unwrap()));
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
addr.script_pubkey(),
|
addr.script_pubkey(),
|
||||||
hex_script!("76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac")
|
ScriptBuf::from_hex("76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac").unwrap()
|
||||||
);
|
);
|
||||||
assert_eq!(&addr.to_string(), "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM");
|
assert_eq!(&addr.to_string(), "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM");
|
||||||
assert_eq!(addr.address_type(), Some(AddressType::P2pkh));
|
assert_eq!(addr.address_type(), Some(AddressType::P2pkh));
|
||||||
|
@ -1173,11 +1173,11 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_p2pkh_from_key() {
|
fn test_p2pkh_from_key() {
|
||||||
let key = hex_into!("048d5141948c1702e8c95f438815794b87f706a8d4cd2bffad1dc1570971032c9b6042a0431ded2478b5c9cf2d81c124a5e57347a3c63ef0e7716cf54d613ba183");
|
let key = "048d5141948c1702e8c95f438815794b87f706a8d4cd2bffad1dc1570971032c9b6042a0431ded2478b5c9cf2d81c124a5e57347a3c63ef0e7716cf54d613ba183".parse::<PublicKey>().unwrap();
|
||||||
let addr = Address::p2pkh(&key, Bitcoin);
|
let addr = Address::p2pkh(&key, Bitcoin);
|
||||||
assert_eq!(&addr.to_string(), "1QJVDzdqb1VpbDK7uDeyVXy9mR27CJiyhY");
|
assert_eq!(&addr.to_string(), "1QJVDzdqb1VpbDK7uDeyVXy9mR27CJiyhY");
|
||||||
|
|
||||||
let key = hex_into!("03df154ebfcf29d29cc10d5c2565018bce2d9edbab267c31d2caf44a63056cf99f");
|
let key = "03df154ebfcf29d29cc10d5c2565018bce2d9edbab267c31d2caf44a63056cf99f".parse::<PublicKey>().unwrap();
|
||||||
let addr = Address::p2pkh(&key, Testnet);
|
let addr = Address::p2pkh(&key, Testnet);
|
||||||
assert_eq!(&addr.to_string(), "mqkhEMH6NCeYjFybv7pvFC22MFeaNT9AQC");
|
assert_eq!(&addr.to_string(), "mqkhEMH6NCeYjFybv7pvFC22MFeaNT9AQC");
|
||||||
assert_eq!(addr.address_type(), Some(AddressType::P2pkh));
|
assert_eq!(addr.address_type(), Some(AddressType::P2pkh));
|
||||||
|
@ -1186,11 +1186,11 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_p2sh_address_58() {
|
fn test_p2sh_address_58() {
|
||||||
let addr = Address::new(Bitcoin, Payload::ScriptHash(hex_into!("162c5ea71c0b23f5b9022ef047c4a86470a5b070")));
|
let addr = Address::new(Bitcoin, Payload::ScriptHash("162c5ea71c0b23f5b9022ef047c4a86470a5b070".parse().unwrap()));
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
addr.script_pubkey(),
|
addr.script_pubkey(),
|
||||||
hex_script!("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087")
|
ScriptBuf::from_hex("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087").unwrap(),
|
||||||
);
|
);
|
||||||
assert_eq!(&addr.to_string(), "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k");
|
assert_eq!(&addr.to_string(), "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k");
|
||||||
assert_eq!(addr.address_type(), Some(AddressType::P2sh));
|
assert_eq!(addr.address_type(), Some(AddressType::P2sh));
|
||||||
|
@ -1199,7 +1199,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_p2sh_parse() {
|
fn test_p2sh_parse() {
|
||||||
let script = hex_script!("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae");
|
let script = ScriptBuf::from_hex("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae").unwrap();
|
||||||
let addr = Address::p2sh(&script, Testnet).unwrap();
|
let addr = Address::p2sh(&script, Testnet).unwrap();
|
||||||
assert_eq!(&addr.to_string(), "2N3zXjbwdTcPsJiy8sUK9FhWJhqQCxA8Jjr");
|
assert_eq!(&addr.to_string(), "2N3zXjbwdTcPsJiy8sUK9FhWJhqQCxA8Jjr");
|
||||||
assert_eq!(addr.address_type(), Some(AddressType::P2sh));
|
assert_eq!(addr.address_type(), Some(AddressType::P2sh));
|
||||||
|
@ -1208,15 +1208,14 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_p2sh_parse_for_large_script() {
|
fn test_p2sh_parse_for_large_script() {
|
||||||
let script = hex_script!("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123");
|
let script = ScriptBuf::from_hex("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123").unwrap();
|
||||||
assert_eq!(Address::p2sh(&script, Testnet), Err(Error::ExcessiveScriptSize));
|
assert_eq!(Address::p2sh(&script, Testnet), Err(Error::ExcessiveScriptSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_p2wpkh() {
|
fn test_p2wpkh() {
|
||||||
// stolen from Bitcoin transaction: b3c8c2b6cfc335abbcb2c7823a8453f55d64b2b5125a9a61e8737230cdb8ce20
|
// stolen from Bitcoin transaction: b3c8c2b6cfc335abbcb2c7823a8453f55d64b2b5125a9a61e8737230cdb8ce20
|
||||||
let mut key =
|
let mut key = "033bc8c83c52df5712229a2f72206d90192366c36428cb0c12b6af98324d97bfbc".parse::<PublicKey>().unwrap();
|
||||||
hex_into!("033bc8c83c52df5712229a2f72206d90192366c36428cb0c12b6af98324d97bfbc");
|
|
||||||
let addr = Address::p2wpkh(&key, Bitcoin).unwrap();
|
let addr = Address::p2wpkh(&key, Bitcoin).unwrap();
|
||||||
assert_eq!(&addr.to_string(), "bc1qvzvkjn4q3nszqxrv3nraga2r822xjty3ykvkuw");
|
assert_eq!(&addr.to_string(), "bc1qvzvkjn4q3nszqxrv3nraga2r822xjty3ykvkuw");
|
||||||
assert_eq!(addr.address_type(), Some(AddressType::P2wpkh));
|
assert_eq!(addr.address_type(), Some(AddressType::P2wpkh));
|
||||||
|
@ -1230,7 +1229,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_p2wsh() {
|
fn test_p2wsh() {
|
||||||
// stolen from Bitcoin transaction 5df912fda4becb1c29e928bec8d64d93e9ba8efa9b5b405bd683c86fd2c65667
|
// stolen from Bitcoin transaction 5df912fda4becb1c29e928bec8d64d93e9ba8efa9b5b405bd683c86fd2c65667
|
||||||
let script = hex_script!("52210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae");
|
let script = ScriptBuf::from_hex("52210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae").unwrap();
|
||||||
let addr = Address::p2wsh(&script, Bitcoin);
|
let addr = Address::p2wsh(&script, Bitcoin);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&addr.to_string(),
|
&addr.to_string(),
|
||||||
|
@ -1243,8 +1242,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_p2shwpkh() {
|
fn test_p2shwpkh() {
|
||||||
// stolen from Bitcoin transaction: ad3fd9c6b52e752ba21425435ff3dd361d6ac271531fc1d2144843a9f550ad01
|
// stolen from Bitcoin transaction: ad3fd9c6b52e752ba21425435ff3dd361d6ac271531fc1d2144843a9f550ad01
|
||||||
let mut key =
|
let mut key = "026c468be64d22761c30cd2f12cbc7de255d592d7904b1bab07236897cc4c2e766".parse::<PublicKey>().unwrap();
|
||||||
hex_into!("026c468be64d22761c30cd2f12cbc7de255d592d7904b1bab07236897cc4c2e766");
|
|
||||||
let addr = Address::p2shwpkh(&key, Bitcoin).unwrap();
|
let addr = Address::p2shwpkh(&key, Bitcoin).unwrap();
|
||||||
assert_eq!(&addr.to_string(), "3QBRmWNqqBGme9er7fMkGqtZtp4gjMFxhE");
|
assert_eq!(&addr.to_string(), "3QBRmWNqqBGme9er7fMkGqtZtp4gjMFxhE");
|
||||||
assert_eq!(addr.address_type(), Some(AddressType::P2sh));
|
assert_eq!(addr.address_type(), Some(AddressType::P2sh));
|
||||||
|
@ -1258,7 +1256,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_p2shwsh() {
|
fn test_p2shwsh() {
|
||||||
// stolen from Bitcoin transaction f9ee2be4df05041d0e0a35d7caa3157495ca4f93b233234c9967b6901dacf7a9
|
// stolen from Bitcoin transaction f9ee2be4df05041d0e0a35d7caa3157495ca4f93b233234c9967b6901dacf7a9
|
||||||
let script = hex_script!("522103e5529d8eaa3d559903adb2e881eb06c86ac2574ffa503c45f4e942e2a693b33e2102e5f10fcdcdbab211e0af6a481f5532536ec61a5fdbf7183770cf8680fe729d8152ae");
|
let script = ScriptBuf::from_hex("522103e5529d8eaa3d559903adb2e881eb06c86ac2574ffa503c45f4e942e2a693b33e2102e5f10fcdcdbab211e0af6a481f5532536ec61a5fdbf7183770cf8680fe729d8152ae").unwrap();
|
||||||
let addr = Address::p2shwsh(&script, Bitcoin);
|
let addr = Address::p2shwsh(&script, Bitcoin);
|
||||||
assert_eq!(&addr.to_string(), "36EqgNnsWW94SreZgBWc1ANC6wpFZwirHr");
|
assert_eq!(&addr.to_string(), "36EqgNnsWW94SreZgBWc1ANC6wpFZwirHr");
|
||||||
assert_eq!(addr.address_type(), Some(AddressType::P2sh));
|
assert_eq!(addr.address_type(), Some(AddressType::P2sh));
|
||||||
|
@ -1417,7 +1415,7 @@ mod tests {
|
||||||
assert_eq!(addr.to_string(), into.to_string());
|
assert_eq!(addr.to_string(), into.to_string());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
into.script_pubkey(),
|
into.script_pubkey(),
|
||||||
hex_script!("76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac")
|
ScriptBuf::from_hex("76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac").unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
let addr = Address::from_str("33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k").unwrap().assume_checked();
|
let addr = Address::from_str("33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k").unwrap().assume_checked();
|
||||||
|
@ -1430,7 +1428,7 @@ mod tests {
|
||||||
assert_eq!(addr.to_string(), into.to_string());
|
assert_eq!(addr.to_string(), into.to_string());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
into.script_pubkey(),
|
into.script_pubkey(),
|
||||||
hex_script!("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087")
|
ScriptBuf::from_hex("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087").unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
let addr: Address<NetworkUnchecked> =
|
let addr: Address<NetworkUnchecked> =
|
||||||
|
@ -1458,7 +1456,7 @@ mod tests {
|
||||||
assert_eq!(addr.to_string(), into.to_string());
|
assert_eq!(addr.to_string(), into.to_string());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
into.script_pubkey(),
|
into.script_pubkey(),
|
||||||
hex_script!("00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262")
|
ScriptBuf::from_hex("00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262").unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
let addr = Address::from_str("bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl").unwrap().assume_checked();
|
let addr = Address::from_str("bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl").unwrap().assume_checked();
|
||||||
|
@ -1471,7 +1469,7 @@ mod tests {
|
||||||
assert_eq!(addr.to_string(), into.to_string());
|
assert_eq!(addr.to_string(), into.to_string());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
into.script_pubkey(),
|
into.script_pubkey(),
|
||||||
hex_script!("001454d26dddb59c7073c6a197946ea1841951fa7a74")
|
ScriptBuf::from_hex("001454d26dddb59c7073c6a197946ea1841951fa7a74").unwrap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1690,10 +1688,10 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fail_address_from_script() {
|
fn test_fail_address_from_script() {
|
||||||
let bad_p2wpkh = hex_script!("0014dbc5b0a8f9d4353b4b54c3db48846bb15abfec");
|
let bad_p2wpkh = ScriptBuf::from_hex("0014dbc5b0a8f9d4353b4b54c3db48846bb15abfec").unwrap();
|
||||||
let bad_p2wsh =
|
let bad_p2wsh =
|
||||||
hex_script!("00202d4fa2eb233d008cc83206fa2f4f2e60199000f5b857a835e3172323385623");
|
ScriptBuf::from_hex("00202d4fa2eb233d008cc83206fa2f4f2e60199000f5b857a835e3172323385623").unwrap();
|
||||||
let invalid_segwitv0_script = hex_script!("001161458e330389cd0437ee9fe3641d70cc18");
|
let invalid_segwitv0_script = ScriptBuf::from_hex("001161458e330389cd0437ee9fe3641d70cc18").unwrap();
|
||||||
let expected = Err(Error::UnrecognizedScript);
|
let expected = Err(Error::UnrecognizedScript);
|
||||||
|
|
||||||
assert_eq!(Address::from_script(&bad_p2wpkh, Network::Bitcoin), expected);
|
assert_eq!(Address::from_script(&bad_p2wpkh, Network::Bitcoin), expected);
|
||||||
|
|
|
@ -561,7 +561,6 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::consensus::encode::deserialize;
|
use crate::consensus::encode::deserialize;
|
||||||
use crate::hash_types::BlockHash;
|
use crate::hash_types::BlockHash;
|
||||||
use crate::hashes::hex::FromHex;
|
|
||||||
use crate::ScriptBuf;
|
use crate::ScriptBuf;
|
||||||
use crate::internal_macros::hex;
|
use crate::internal_macros::hex;
|
||||||
|
|
||||||
|
@ -572,16 +571,16 @@ mod test {
|
||||||
|
|
||||||
let testdata = serde_json::from_str::<Value>(data).unwrap().as_array().unwrap().clone();
|
let testdata = serde_json::from_str::<Value>(data).unwrap().as_array().unwrap().clone();
|
||||||
for t in testdata.iter().skip(1) {
|
for t in testdata.iter().skip(1) {
|
||||||
let block_hash = BlockHash::from_hex(t.get(1).unwrap().as_str().unwrap()).unwrap();
|
let block_hash = t.get(1).unwrap().as_str().unwrap().parse::<BlockHash>().unwrap();
|
||||||
let block: Block =
|
let block: Block =
|
||||||
deserialize(&hex!(t.get(2).unwrap().as_str().unwrap())).unwrap();
|
deserialize(&hex!(t.get(2).unwrap().as_str().unwrap())).unwrap();
|
||||||
assert_eq!(block.block_hash(), block_hash);
|
assert_eq!(block.block_hash(), block_hash);
|
||||||
let scripts = t.get(3).unwrap().as_array().unwrap();
|
let scripts = t.get(3).unwrap().as_array().unwrap();
|
||||||
let previous_filter_header =
|
let previous_filter_header =
|
||||||
FilterHeader::from_hex(t.get(4).unwrap().as_str().unwrap()).unwrap();
|
t.get(4).unwrap().as_str().unwrap().parse::<FilterHeader>().unwrap();
|
||||||
let filter_content = hex!(t.get(5).unwrap().as_str().unwrap());
|
let filter_content = hex!(t.get(5).unwrap().as_str().unwrap());
|
||||||
let filter_header =
|
let filter_header =
|
||||||
FilterHeader::from_hex(t.get(6).unwrap().as_str().unwrap()).unwrap();
|
t.get(6).unwrap().as_str().unwrap().parse::<FilterHeader>().unwrap();
|
||||||
|
|
||||||
let mut txmap = HashMap::new();
|
let mut txmap = HashMap::new();
|
||||||
let mut si = scripts.iter();
|
let mut si = scripts.iter();
|
||||||
|
|
|
@ -673,21 +673,11 @@ impl fmt::UpperHex for Script {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl hex::FromHex for ScriptBuf {
|
|
||||||
#[inline]
|
|
||||||
fn from_byte_iter<I>(iter: I) -> Result<Self, hex::Error>
|
|
||||||
where
|
|
||||||
I: Iterator<Item=Result<u8, hex::Error>> + ExactSizeIterator + DoubleEndedIterator,
|
|
||||||
{
|
|
||||||
Vec::from_byte_iter(iter).map(ScriptBuf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl core::str::FromStr for ScriptBuf {
|
impl core::str::FromStr for ScriptBuf {
|
||||||
type Err = hex::Error;
|
type Err = hex::Error;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_str(s: &str) -> Result<Self, hex::Error> {
|
fn from_str(s: &str) -> Result<Self, hex::Error> {
|
||||||
hex::FromHex::from_hex(s)
|
ScriptBuf::from_hex(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1198,7 +1188,15 @@ impl ScriptBuf {
|
||||||
.into_script()
|
.into_script()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts byte vector into script.
|
/// Creates a [`ScriptBuf`] from a hex string.
|
||||||
|
pub fn from_hex(s: &str) -> Result<Self, hex::Error> {
|
||||||
|
use crate::hashes::hex::FromHex;
|
||||||
|
|
||||||
|
let v = Vec::from_hex(s)?;
|
||||||
|
Ok(ScriptBuf::from_bytes(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a [`ScriptBuf`] from a byte vector.
|
||||||
///
|
///
|
||||||
/// This method doesn't (re)allocate.
|
/// This method doesn't (re)allocate.
|
||||||
pub fn from_bytes(bytes: Vec<u8>) -> Self {
|
pub fn from_bytes(bytes: Vec<u8>) -> Self {
|
||||||
|
@ -2057,7 +2055,7 @@ mod test {
|
||||||
use crate::blockdata::opcodes;
|
use crate::blockdata::opcodes;
|
||||||
use crate::crypto::key::PublicKey;
|
use crate::crypto::key::PublicKey;
|
||||||
use crate::psbt::serialize::Serialize;
|
use crate::psbt::serialize::Serialize;
|
||||||
use crate::internal_macros::{hex, hex_script};
|
use crate::internal_macros::hex;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn script() {
|
fn script() {
|
||||||
|
@ -2401,11 +2399,11 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn script_hashes() {
|
fn script_hashes() {
|
||||||
let script = hex_script!("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac");
|
let script = ScriptBuf::from_hex("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").unwrap();
|
||||||
assert_eq!(script.script_hash().to_string(), "8292bcfbef1884f73c813dfe9c82fd7e814291ea");
|
assert_eq!(script.script_hash().to_string(), "8292bcfbef1884f73c813dfe9c82fd7e814291ea");
|
||||||
assert_eq!(script.wscript_hash().to_string(), "3e1525eb183ad4f9b3c5fa3175bdca2a52e947b135bbb90383bf9f6408e2c324");
|
assert_eq!(script.wscript_hash().to_string(), "3e1525eb183ad4f9b3c5fa3175bdca2a52e947b135bbb90383bf9f6408e2c324");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hex_script!("20d85a959b0290bf19bb89ed43c916be835475d013da4b362117393e25a48229b8ac").tapscript_leaf_hash().to_string(),
|
ScriptBuf::from_hex("20d85a959b0290bf19bb89ed43c916be835475d013da4b362117393e25a48229b8ac").unwrap().tapscript_leaf_hash().to_string(),
|
||||||
"5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21"
|
"5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2413,18 +2411,18 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn provably_unspendable_test() {
|
fn provably_unspendable_test() {
|
||||||
// p2pk
|
// p2pk
|
||||||
assert!(!hex_script!("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").is_provably_unspendable());
|
assert!(!ScriptBuf::from_hex("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").unwrap().is_provably_unspendable());
|
||||||
assert!(!hex_script!("4104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac").is_provably_unspendable());
|
assert!(!ScriptBuf::from_hex("4104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac").unwrap().is_provably_unspendable());
|
||||||
// p2pkhash
|
// p2pkhash
|
||||||
assert!(!hex_script!("76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac").is_provably_unspendable());
|
assert!(!ScriptBuf::from_hex("76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac").unwrap().is_provably_unspendable());
|
||||||
assert!(hex_script!("6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87").is_provably_unspendable());
|
assert!(ScriptBuf::from_hex("6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87").unwrap().is_provably_unspendable());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn op_return_test() {
|
fn op_return_test() {
|
||||||
assert!(hex_script!("6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87").is_op_return());
|
assert!(ScriptBuf::from_hex("6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87").unwrap().is_op_return());
|
||||||
assert!(!hex_script!("76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac").is_op_return());
|
assert!(!ScriptBuf::from_hex("76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac").unwrap().is_op_return());
|
||||||
assert!(!hex_script!("").is_op_return());
|
assert!(!ScriptBuf::from_hex("").unwrap().is_op_return());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -2432,7 +2430,7 @@ mod test {
|
||||||
fn script_json_serialize() {
|
fn script_json_serialize() {
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
|
||||||
let original = hex_script!("827651a0698faaa9a8a7a687");
|
let original = ScriptBuf::from_hex("827651a0698faaa9a8a7a687").unwrap();
|
||||||
let json = serde_json::to_value(&original).unwrap();
|
let json = serde_json::to_value(&original).unwrap();
|
||||||
assert_eq!(json, serde_json::Value::String("827651a0698faaa9a8a7a687".to_owned()));
|
assert_eq!(json, serde_json::Value::String("827651a0698faaa9a8a7a687".to_owned()));
|
||||||
let des = serde_json::from_value::<ScriptBuf>(json).unwrap();
|
let des = serde_json::from_value::<ScriptBuf>(json).unwrap();
|
||||||
|
@ -2441,77 +2439,77 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn script_asm() {
|
fn script_asm() {
|
||||||
assert_eq!(hex_script!("6363636363686868686800").to_asm_string(),
|
assert_eq!(ScriptBuf::from_hex("6363636363686868686800").unwrap().to_asm_string(),
|
||||||
"OP_IF OP_IF OP_IF OP_IF OP_IF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_0");
|
"OP_IF OP_IF OP_IF OP_IF OP_IF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_0");
|
||||||
assert_eq!(hex_script!("6363636363686868686800").to_asm_string(),
|
assert_eq!(ScriptBuf::from_hex("6363636363686868686800").unwrap().to_asm_string(),
|
||||||
"OP_IF OP_IF OP_IF OP_IF OP_IF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_0");
|
"OP_IF OP_IF OP_IF OP_IF OP_IF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_0");
|
||||||
assert_eq!(hex_script!("2102715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699ac").to_asm_string(),
|
assert_eq!(ScriptBuf::from_hex("2102715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699ac").unwrap().to_asm_string(),
|
||||||
"OP_PUSHBYTES_33 02715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699 OP_CHECKSIG");
|
"OP_PUSHBYTES_33 02715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699 OP_CHECKSIG");
|
||||||
// Elements Alpha peg-out transaction with some signatures removed for brevity. Mainly to test PUSHDATA1
|
// Elements Alpha peg-out transaction with some signatures removed for brevity. Mainly to test PUSHDATA1
|
||||||
assert_eq!(hex_script!("0047304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401004cf1552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae").to_asm_string(),
|
assert_eq!(ScriptBuf::from_hex("0047304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401004cf1552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae").unwrap().to_asm_string(),
|
||||||
"OP_0 OP_PUSHBYTES_71 304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401 OP_0 OP_PUSHDATA1 552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae");
|
"OP_0 OP_PUSHBYTES_71 304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401 OP_0 OP_PUSHDATA1 552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae");
|
||||||
// Various weird scripts found in transaction 6d7ed9914625c73c0288694a6819196a27ef6c08f98e1270d975a8e65a3dc09a
|
// Various weird scripts found in transaction 6d7ed9914625c73c0288694a6819196a27ef6c08f98e1270d975a8e65a3dc09a
|
||||||
// which triggerred overflow bugs on 32-bit machines in script formatting in the past.
|
// which triggerred overflow bugs on 32-bit machines in script formatting in the past.
|
||||||
assert_eq!(hex_script!("01").to_asm_string(),
|
assert_eq!(ScriptBuf::from_hex("01").unwrap().to_asm_string(),
|
||||||
"OP_PUSHBYTES_1 <push past end>");
|
"OP_PUSHBYTES_1 <push past end>");
|
||||||
assert_eq!(hex_script!("0201").to_asm_string(),
|
assert_eq!(ScriptBuf::from_hex("0201").unwrap().to_asm_string(),
|
||||||
"OP_PUSHBYTES_2 <push past end>");
|
"OP_PUSHBYTES_2 <push past end>");
|
||||||
assert_eq!(hex_script!("4c").to_asm_string(),
|
assert_eq!(ScriptBuf::from_hex("4c").unwrap().to_asm_string(),
|
||||||
"<unexpected end>");
|
"<unexpected end>");
|
||||||
assert_eq!(hex_script!("4c0201").to_asm_string(),
|
assert_eq!(ScriptBuf::from_hex("4c0201").unwrap().to_asm_string(),
|
||||||
"OP_PUSHDATA1 <push past end>");
|
"OP_PUSHDATA1 <push past end>");
|
||||||
assert_eq!(hex_script!("4d").to_asm_string(),
|
assert_eq!(ScriptBuf::from_hex("4d").unwrap().to_asm_string(),
|
||||||
"<unexpected end>");
|
"<unexpected end>");
|
||||||
assert_eq!(hex_script!("4dffff01").to_asm_string(),
|
assert_eq!(ScriptBuf::from_hex("4dffff01").unwrap().to_asm_string(),
|
||||||
"OP_PUSHDATA2 <push past end>");
|
"OP_PUSHDATA2 <push past end>");
|
||||||
assert_eq!(hex_script!("4effffffff01").to_asm_string(),
|
assert_eq!(ScriptBuf::from_hex("4effffffff01").unwrap().to_asm_string(),
|
||||||
"OP_PUSHDATA4 <push past end>");
|
"OP_PUSHDATA4 <push past end>");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn script_buf_collect() {
|
fn script_buf_collect() {
|
||||||
assert_eq!(&core::iter::empty::<Instruction<'_>>().collect::<ScriptBuf>(), Script::empty());
|
assert_eq!(&core::iter::empty::<Instruction<'_>>().collect::<ScriptBuf>(), Script::empty());
|
||||||
let script = hex_script!("0047304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401004cf1552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae");
|
let script = ScriptBuf::from_hex("0047304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401004cf1552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae").unwrap();
|
||||||
assert_eq!(script.instructions().collect::<Result<ScriptBuf, _>>().unwrap(), script);
|
assert_eq!(script.instructions().collect::<Result<ScriptBuf, _>>().unwrap(), script);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn script_p2sh_p2p2k_template() {
|
fn script_p2sh_p2p2k_template() {
|
||||||
// random outputs I picked out of the mempool
|
// random outputs I picked out of the mempool
|
||||||
assert!(hex_script!("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").is_p2pkh());
|
assert!(ScriptBuf::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap().is_p2pkh());
|
||||||
assert!(!hex_script!("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").is_p2sh());
|
assert!(!ScriptBuf::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap().is_p2sh());
|
||||||
assert!(!hex_script!("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ad").is_p2pkh());
|
assert!(!ScriptBuf::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ad").unwrap().is_p2pkh());
|
||||||
assert!(!hex_script!("").is_p2pkh());
|
assert!(!ScriptBuf::from_hex("").unwrap().is_p2pkh());
|
||||||
assert!(hex_script!("a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87").is_p2sh());
|
assert!(ScriptBuf::from_hex("a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87").unwrap().is_p2sh());
|
||||||
assert!(!hex_script!("a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87").is_p2pkh());
|
assert!(!ScriptBuf::from_hex("a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87").unwrap().is_p2pkh());
|
||||||
assert!(!hex_script!("a314acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87").is_p2sh());
|
assert!(!ScriptBuf::from_hex("a314acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87").unwrap().is_p2sh());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn script_p2pk() {
|
fn script_p2pk() {
|
||||||
assert!(hex_script!("21021aeaf2f8638a129a3156fbe7e5ef635226b0bafd495ff03afe2c843d7e3a4b51ac").is_p2pk());
|
assert!(ScriptBuf::from_hex("21021aeaf2f8638a129a3156fbe7e5ef635226b0bafd495ff03afe2c843d7e3a4b51ac").unwrap().is_p2pk());
|
||||||
assert!(hex_script!("410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac").is_p2pk());
|
assert!(ScriptBuf::from_hex("410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac").unwrap().is_p2pk());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn p2sh_p2wsh_conversion() {
|
fn p2sh_p2wsh_conversion() {
|
||||||
// Test vectors taken from Core tests/data/script_tests.json
|
// Test vectors taken from Core tests/data/script_tests.json
|
||||||
// bare p2wsh
|
// bare p2wsh
|
||||||
let redeem_script = hex_script!("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac");
|
let redeem_script = ScriptBuf::from_hex("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac").unwrap();
|
||||||
let expected_witout = hex_script!("0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64");
|
let expected_witout = ScriptBuf::from_hex("0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64").unwrap();
|
||||||
assert!(redeem_script.to_v0_p2wsh().is_v0_p2wsh());
|
assert!(redeem_script.to_v0_p2wsh().is_v0_p2wsh());
|
||||||
assert_eq!(redeem_script.to_v0_p2wsh(), expected_witout);
|
assert_eq!(redeem_script.to_v0_p2wsh(), expected_witout);
|
||||||
|
|
||||||
// p2sh
|
// p2sh
|
||||||
let redeem_script = hex_script!("0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8");
|
let redeem_script = ScriptBuf::from_hex("0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8").unwrap();
|
||||||
let expected_p2shout = hex_script!("a91491b24bf9f5288532960ac687abb035127b1d28a587");
|
let expected_p2shout = ScriptBuf::from_hex("a91491b24bf9f5288532960ac687abb035127b1d28a587").unwrap();
|
||||||
assert!(redeem_script.to_p2sh().is_p2sh());
|
assert!(redeem_script.to_p2sh().is_p2sh());
|
||||||
assert_eq!(redeem_script.to_p2sh(), expected_p2shout);
|
assert_eq!(redeem_script.to_p2sh(), expected_p2shout);
|
||||||
|
|
||||||
// p2sh-p2wsh
|
// p2sh-p2wsh
|
||||||
let redeem_script = hex_script!("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac");
|
let redeem_script = ScriptBuf::from_hex("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac").unwrap();
|
||||||
let expected_witout = hex_script!("0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64");
|
let expected_witout = ScriptBuf::from_hex("0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64").unwrap();
|
||||||
let expected_out = hex_script!("a914f386c2ba255cc56d20cfa6ea8b062f8b5994551887");
|
let expected_out = ScriptBuf::from_hex("a914f386c2ba255cc56d20cfa6ea8b062f8b5994551887").unwrap();
|
||||||
assert!(redeem_script.to_p2sh().is_p2sh());
|
assert!(redeem_script.to_p2sh().is_p2sh());
|
||||||
assert!(redeem_script.to_p2sh().to_v0_p2wsh().is_v0_p2wsh());
|
assert!(redeem_script.to_p2sh().to_v0_p2wsh().is_v0_p2wsh());
|
||||||
assert_eq!(redeem_script.to_v0_p2wsh(), expected_witout);
|
assert_eq!(redeem_script.to_v0_p2wsh(), expected_witout);
|
||||||
|
@ -2528,12 +2526,12 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_iterator() {
|
fn test_iterator() {
|
||||||
let zero = hex_script!("00");
|
let zero = ScriptBuf::from_hex("00").unwrap();
|
||||||
let zeropush = hex_script!("0100");
|
let zeropush = ScriptBuf::from_hex("0100").unwrap();
|
||||||
|
|
||||||
let nonminimal = hex_script!("4c0169b2"); // PUSHDATA1 for no reason
|
let nonminimal = ScriptBuf::from_hex("4c0169b2").unwrap(); // PUSHDATA1 for no reason
|
||||||
let minimal = hex_script!("0169b2"); // minimal
|
let minimal = ScriptBuf::from_hex("0169b2").unwrap(); // minimal
|
||||||
let nonminimal_alt = hex_script!("026900b2"); // non-minimal number but minimal push (should be OK)
|
let nonminimal_alt = ScriptBuf::from_hex("026900b2").unwrap(); // non-minimal number but minimal push (should be OK)
|
||||||
|
|
||||||
let v_zero: Result<Vec<_>, Error> = zero.instruction_indices_minimal().collect();
|
let v_zero: Result<Vec<_>, Error> = zero.instruction_indices_minimal().collect();
|
||||||
let v_zeropush: Result<Vec<_>, Error> = zeropush.instruction_indices_minimal().collect();
|
let v_zeropush: Result<Vec<_>, Error> = zeropush.instruction_indices_minimal().collect();
|
||||||
|
|
|
@ -22,7 +22,6 @@ use core::convert::TryFrom;
|
||||||
use bitcoin_internals::write_err;
|
use bitcoin_internals::write_err;
|
||||||
|
|
||||||
use crate::hashes::{self, Hash, sha256d};
|
use crate::hashes::{self, Hash, sha256d};
|
||||||
use crate::hashes::hex::FromHex;
|
|
||||||
|
|
||||||
use crate::blockdata::constants::WITNESS_SCALE_FACTOR;
|
use crate::blockdata::constants::WITNESS_SCALE_FACTOR;
|
||||||
#[cfg(feature="bitcoinconsensus")] use crate::blockdata::script;
|
#[cfg(feature="bitcoinconsensus")] use crate::blockdata::script;
|
||||||
|
@ -175,7 +174,7 @@ impl core::str::FromStr for OutPoint {
|
||||||
return Err(ParseOutPointError::Format);
|
return Err(ParseOutPointError::Format);
|
||||||
}
|
}
|
||||||
Ok(OutPoint {
|
Ok(OutPoint {
|
||||||
txid: Txid::from_hex(&s[..colon]).map_err(ParseOutPointError::Txid)?,
|
txid: s[..colon].parse().map_err(ParseOutPointError::Txid)?,
|
||||||
vout: parse_vout(&s[colon+1..])?,
|
vout: parse_vout(&s[colon+1..])?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1163,8 +1162,6 @@ mod tests {
|
||||||
use crate::hashes::hex::FromHex;
|
use crate::hashes::hex::FromHex;
|
||||||
use crate::internal_macros::hex;
|
use crate::internal_macros::hex;
|
||||||
|
|
||||||
use crate::hash_types::*;
|
|
||||||
|
|
||||||
const SOME_TX: &str = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000";
|
const SOME_TX: &str = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000";
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1193,20 +1190,20 @@ mod tests {
|
||||||
assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:+42"),
|
assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:+42"),
|
||||||
Err(ParseOutPointError::VoutNotCanonical));
|
Err(ParseOutPointError::VoutNotCanonical));
|
||||||
assert_eq!(OutPoint::from_str("i don't care:1"),
|
assert_eq!(OutPoint::from_str("i don't care:1"),
|
||||||
Err(ParseOutPointError::Txid(Txid::from_hex("i don't care").unwrap_err())));
|
Err(ParseOutPointError::Txid("i don't care".parse::<Txid>().unwrap_err())));
|
||||||
assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c945X:1"),
|
assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c945X:1"),
|
||||||
Err(ParseOutPointError::Txid(Txid::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c945X").unwrap_err())));
|
Err(ParseOutPointError::Txid("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c945X".parse::<Txid>().unwrap_err())));
|
||||||
assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:lol"),
|
assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:lol"),
|
||||||
Err(ParseOutPointError::Vout(crate::parse::int::<u32, _>("lol").unwrap_err())));
|
Err(ParseOutPointError::Vout(crate::parse::int::<u32, _>("lol").unwrap_err())));
|
||||||
|
|
||||||
assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:42"),
|
assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:42"),
|
||||||
Ok(OutPoint{
|
Ok(OutPoint{
|
||||||
txid: Txid::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(),
|
txid: "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456".parse().unwrap(),
|
||||||
vout: 42,
|
vout: 42,
|
||||||
}));
|
}));
|
||||||
assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0"),
|
assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0"),
|
||||||
Ok(OutPoint{
|
Ok(OutPoint{
|
||||||
txid: Txid::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(),
|
txid: "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456".parse().unwrap(),
|
||||||
vout: 0,
|
vout: 0,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ See [`hashes::Hash::DISPLAY_BACKWARD`] for more details.
|
||||||
");
|
");
|
||||||
hash_newtype!(Wtxid, sha256d::Hash, 32, doc="A bitcoin witness transaction ID.");
|
hash_newtype!(Wtxid, sha256d::Hash, 32, doc="A bitcoin witness transaction ID.");
|
||||||
hash_newtype!(BlockHash, sha256d::Hash, 32, doc="A bitcoin block hash.");
|
hash_newtype!(BlockHash, sha256d::Hash, 32, doc="A bitcoin block hash.");
|
||||||
hash_newtype!(Sighash, sha256d::Hash, 32, doc="Hash of the transaction according to the signature algorithm");
|
hash_newtype!(Sighash, sha256d::Hash, 32, doc="Hash of the transaction according to the signature algorithm", false);
|
||||||
impl secp256k1::ThirtyTwoByteHash for Sighash {
|
impl secp256k1::ThirtyTwoByteHash for Sighash {
|
||||||
fn into_32(self) -> [u8; 32] {
|
fn into_32(self) -> [u8; 32] {
|
||||||
use hashes::Hash;
|
use hashes::Hash;
|
||||||
|
|
|
@ -51,60 +51,9 @@ pub(crate) use test_macros::*;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_macros {
|
mod test_macros {
|
||||||
use crate::hashes::hex::FromHex;
|
|
||||||
use crate::PublicKey;
|
|
||||||
|
|
||||||
/// Trait used to create a value from hex string for testing purposes.
|
|
||||||
pub(crate) trait TestFromHex {
|
|
||||||
/// Produces the value from hex.
|
|
||||||
///
|
|
||||||
/// ## Panics
|
|
||||||
///
|
|
||||||
/// The function panics if the hex or the value is invalid.
|
|
||||||
fn test_from_hex(hex: &str) -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: FromHex> TestFromHex for T {
|
|
||||||
fn test_from_hex(hex: &str) -> Self { Self::from_hex(hex).unwrap() }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TestFromHex for PublicKey {
|
|
||||||
fn test_from_hex(hex: &str) -> Self {
|
|
||||||
PublicKey::from_slice(&Vec::from_hex(hex).unwrap()).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! hex (($hex:expr) => (<Vec<u8> as hashes::hex::FromHex>::from_hex($hex).unwrap()));
|
macro_rules! hex (($hex:expr) => (<Vec<u8> as hashes::hex::FromHex>::from_hex($hex).unwrap()));
|
||||||
pub(crate) use hex;
|
pub(crate) use hex;
|
||||||
|
|
||||||
macro_rules! hex_into {
|
|
||||||
($hex:expr) => {
|
|
||||||
$crate::internal_macros::hex_into!(_, $hex)
|
|
||||||
};
|
|
||||||
($type:ty, $hex:expr) => {
|
|
||||||
<$type as $crate::internal_macros::TestFromHex>::test_from_hex($hex)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
pub(crate) use hex_into;
|
|
||||||
|
|
||||||
// Script is commonly used in places where inference may fail
|
|
||||||
macro_rules! hex_script (($hex:expr) => ($crate::internal_macros::hex_into!($crate::ScriptBuf, $hex)));
|
|
||||||
pub(crate) use hex_script;
|
|
||||||
|
|
||||||
// For types that can't use TestFromHex due to coherence rules or reversed hex
|
|
||||||
macro_rules! hex_from_slice {
|
|
||||||
($hex:expr) => {
|
|
||||||
$crate::internal_macros::hex_from_slice!(_, $hex)
|
|
||||||
};
|
|
||||||
($type:ty, $hex:expr) => {
|
|
||||||
<$type>::from_slice(
|
|
||||||
&<$crate::prelude::Vec<u8> as $crate::hashes::hex::FromHex>::from_hex($hex)
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
pub(crate) use hex_from_slice;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implements several traits for byte-based newtypes.
|
/// Implements several traits for byte-based newtypes.
|
||||||
|
|
|
@ -32,8 +32,7 @@
|
||||||
//! assert!(mb.extract_matches(&mut matches, &mut index).is_ok());
|
//! assert!(mb.extract_matches(&mut matches, &mut index).is_ok());
|
||||||
//! assert_eq!(1, matches.len());
|
//! assert_eq!(1, matches.len());
|
||||||
//! assert_eq!(
|
//! assert_eq!(
|
||||||
//! Txid::from_hex(
|
//! "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2".parse::<Txid>().unwrap(),
|
||||||
//! "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2").unwrap(),
|
|
||||||
//! matches[0]
|
//! matches[0]
|
||||||
//! );
|
//! );
|
||||||
//! assert_eq!(1, index.len());
|
//! assert_eq!(1, index.len());
|
||||||
|
@ -163,7 +162,7 @@ impl PartialMerkleTree {
|
||||||
/// "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2",
|
/// "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2",
|
||||||
/// ]
|
/// ]
|
||||||
/// .iter()
|
/// .iter()
|
||||||
/// .map(|hex| Txid::from_hex(hex).unwrap())
|
/// .map(|hex| hex.parse::<Txid>().unwrap())
|
||||||
/// .collect();
|
/// .collect();
|
||||||
///
|
///
|
||||||
/// // Select the second transaction
|
/// // Select the second transaction
|
||||||
|
@ -426,8 +425,7 @@ impl MerkleBlock {
|
||||||
/// let block: Block = bitcoin::consensus::deserialize(&block_bytes).unwrap();
|
/// let block: Block = bitcoin::consensus::deserialize(&block_bytes).unwrap();
|
||||||
///
|
///
|
||||||
/// // Create a merkle block containing a single transaction
|
/// // Create a merkle block containing a single transaction
|
||||||
/// let txid = Txid::from_hex(
|
/// let txid = "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2".parse::<Txid>().unwrap();
|
||||||
/// "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2").unwrap();
|
|
||||||
/// let match_txids: Vec<Txid> = vec![txid].into_iter().collect();
|
/// let match_txids: Vec<Txid> = vec![txid].into_iter().collect();
|
||||||
/// let mb = MerkleBlock::from_block_with_predicate(&block, |t| match_txids.contains(t));
|
/// let mb = MerkleBlock::from_block_with_predicate(&block, |t| match_txids.contains(t));
|
||||||
///
|
///
|
||||||
|
@ -506,7 +504,6 @@ mod tests {
|
||||||
use crate::consensus::encode::{deserialize, serialize};
|
use crate::consensus::encode::{deserialize, serialize};
|
||||||
#[cfg(feature = "rand-std")]
|
#[cfg(feature = "rand-std")]
|
||||||
use crate::hash_types::TxMerkleNode;
|
use crate::hash_types::TxMerkleNode;
|
||||||
use crate::hashes::hex::FromHex;
|
|
||||||
#[cfg(feature = "rand-std")]
|
#[cfg(feature = "rand-std")]
|
||||||
use crate::hashes::Hash;
|
use crate::hashes::Hash;
|
||||||
use crate::internal_macros::hex;
|
use crate::internal_macros::hex;
|
||||||
|
@ -551,7 +548,7 @@ mod tests {
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
// Create some fake tx ids
|
// Create some fake tx ids
|
||||||
let tx_ids = (1..=tx_count)
|
let tx_ids = (1..=tx_count)
|
||||||
.map(|i| Txid::from_hex(&format!("{:064x}", i)).unwrap())
|
.map(|i| format!("{:064x}", i).parse::<Txid>().unwrap())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
// Calculate the merkle root and height
|
// Calculate the merkle root and height
|
||||||
|
@ -625,7 +622,7 @@ mod tests {
|
||||||
// Create some fake tx ids with the last 2 hashes repeating
|
// Create some fake tx ids with the last 2 hashes repeating
|
||||||
let txids: Vec<Txid> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 10]
|
let txids: Vec<Txid> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 10]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|i| Txid::from_hex(&format!("{:064x}", i)).unwrap())
|
.map(|i| format!("{:064x}", i).parse::<Txid>().unwrap())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let matches =
|
let matches =
|
||||||
|
@ -670,7 +667,7 @@ mod tests {
|
||||||
"f9fc751cb7dc372406a9f8d738d5e6f8f63bab71986a39cf36ee70ee17036d07",
|
"f9fc751cb7dc372406a9f8d738d5e6f8f63bab71986a39cf36ee70ee17036d07",
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|hex| Txid::from_hex(hex).unwrap())
|
.map(|hex| hex.parse::<Txid>().unwrap())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let txid1 = txids[0];
|
let txid1 = txids[0];
|
||||||
|
@ -704,7 +701,7 @@ mod tests {
|
||||||
let block = get_block_13b8a();
|
let block = get_block_13b8a();
|
||||||
let txids: Vec<Txid> = ["c0ffee00003bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20"]
|
let txids: Vec<Txid> = ["c0ffee00003bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20"]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|hex| Txid::from_hex(hex).unwrap())
|
.map(|hex| hex.parse::<Txid>().unwrap())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let merkle_block = MerkleBlock::from_block_with_predicate(&block, |t| txids.contains(t));
|
let merkle_block = MerkleBlock::from_block_with_predicate(&block, |t| txids.contains(t));
|
||||||
|
|
|
@ -143,8 +143,7 @@ impl_consensus_encoding!(Reject, message, ccode, reason, hash);
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{Reject, RejectReason, VersionMessage};
|
use super::{Reject, RejectReason, VersionMessage};
|
||||||
use crate::consensus::encode::{deserialize, serialize};
|
use crate::consensus::encode::{deserialize, serialize};
|
||||||
use crate::hashes::hex::FromHex;
|
use crate::hashes::sha256d;
|
||||||
use crate::hashes::sha256d::Hash;
|
|
||||||
use crate::internal_macros::hex;
|
use crate::internal_macros::hex;
|
||||||
use crate::network::constants::ServiceFlags;
|
use crate::network::constants::ServiceFlags;
|
||||||
|
|
||||||
|
@ -184,7 +183,7 @@ mod tests {
|
||||||
assert_eq!(RejectReason::Duplicate, conflict.ccode);
|
assert_eq!(RejectReason::Duplicate, conflict.ccode);
|
||||||
assert_eq!("txn-mempool-conflict", conflict.reason);
|
assert_eq!("txn-mempool-conflict", conflict.reason);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Hash::from_hex("0470f4f2dc4191221b59884bcffaaf00932748ab46356a80413c0b86d354df05")
|
"0470f4f2dc4191221b59884bcffaaf00932748ab46356a80413c0b86d354df05".parse::<sha256d::Hash>()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
conflict.hash
|
conflict.hash
|
||||||
);
|
);
|
||||||
|
@ -194,7 +193,7 @@ mod tests {
|
||||||
assert_eq!(RejectReason::NonStandard, nonfinal.ccode);
|
assert_eq!(RejectReason::NonStandard, nonfinal.ccode);
|
||||||
assert_eq!("non-final", nonfinal.reason);
|
assert_eq!("non-final", nonfinal.reason);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Hash::from_hex("0b46a539138b5fde4e341b37f2d945c23d41193b30caa7fcbd8bdb836cbe9b25")
|
"0b46a539138b5fde4e341b37f2d945c23d41193b30caa7fcbd8bdb836cbe9b25".parse::<sha256d::Hash>()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
nonfinal.hash
|
nonfinal.hash
|
||||||
);
|
);
|
||||||
|
|
|
@ -812,9 +812,7 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use crate::blockdata::locktime::absolute;
|
use crate::blockdata::locktime::absolute;
|
||||||
use crate::hashes::hex::FromHex;
|
|
||||||
use crate::hashes::{sha256, hash160, Hash, ripemd160};
|
use crate::hashes::{sha256, hash160, Hash, ripemd160};
|
||||||
use crate::hash_types::Txid;
|
|
||||||
use crate::psbt::serialize::{Serialize, Deserialize};
|
use crate::psbt::serialize::{Serialize, Deserialize};
|
||||||
|
|
||||||
use secp256k1::{Secp256k1, self};
|
use secp256k1::{Secp256k1, self};
|
||||||
|
@ -827,7 +825,7 @@ mod tests {
|
||||||
use crate::bip32::{ChildNumber, ExtendedPrivKey, ExtendedPubKey, KeySource};
|
use crate::bip32::{ChildNumber, ExtendedPrivKey, ExtendedPubKey, KeySource};
|
||||||
use crate::psbt::map::{Output, Input};
|
use crate::psbt::map::{Output, Input};
|
||||||
use crate::psbt::raw;
|
use crate::psbt::raw;
|
||||||
use crate::internal_macros::{hex, hex_script};
|
use crate::internal_macros::hex;
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use crate::blockdata::witness::Witness;
|
use crate::blockdata::witness::Witness;
|
||||||
|
@ -891,8 +889,8 @@ mod tests {
|
||||||
hd_keypaths.insert(pk.public_key, (fprint, dpath.into()));
|
hd_keypaths.insert(pk.public_key, (fprint, dpath.into()));
|
||||||
|
|
||||||
let expected: Output = Output {
|
let expected: Output = Output {
|
||||||
redeem_script: Some(hex_script!("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac")),
|
redeem_script: Some(ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap()),
|
||||||
witness_script: Some(hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787")),
|
witness_script: Some(ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap()),
|
||||||
bip32_derivation: hd_keypaths,
|
bip32_derivation: hd_keypaths,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
@ -908,29 +906,25 @@ mod tests {
|
||||||
unsigned_tx: Transaction {
|
unsigned_tx: Transaction {
|
||||||
version: 2,
|
version: 2,
|
||||||
lock_time: absolute::LockTime::from_consensus(1257139),
|
lock_time: absolute::LockTime::from_consensus(1257139),
|
||||||
input: vec![TxIn {
|
input: vec![
|
||||||
|
TxIn {
|
||||||
previous_output: OutPoint {
|
previous_output: OutPoint {
|
||||||
txid: Txid::from_hex(
|
txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126".parse().unwrap(),
|
||||||
"f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126",
|
|
||||||
).unwrap(),
|
|
||||||
vout: 0,
|
vout: 0,
|
||||||
},
|
},
|
||||||
script_sig: ScriptBuf::new(),
|
script_sig: ScriptBuf::new(),
|
||||||
sequence: Sequence::ENABLE_LOCKTIME_NO_RBF,
|
sequence: Sequence::ENABLE_LOCKTIME_NO_RBF,
|
||||||
witness: Witness::default(),
|
witness: Witness::default(),
|
||||||
}],
|
}
|
||||||
|
],
|
||||||
output: vec![
|
output: vec![
|
||||||
TxOut {
|
TxOut {
|
||||||
value: 99999699,
|
value: 99999699,
|
||||||
script_pubkey: hex_script!(
|
script_pubkey: ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(),
|
||||||
"76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac"
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
TxOut {
|
TxOut {
|
||||||
value: 100000000,
|
value: 100000000,
|
||||||
script_pubkey: hex_script!(
|
script_pubkey: ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(),
|
||||||
"a9143545e6e33b832c47050f24d3eeb93c9c03948bc787"
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -974,25 +968,26 @@ mod tests {
|
||||||
//! Create a full PSBT value with various fields filled and make sure it can be JSONized.
|
//! Create a full PSBT value with various fields filled and make sure it can be JSONized.
|
||||||
use crate::hashes::sha256d;
|
use crate::hashes::sha256d;
|
||||||
use crate::psbt::map::Input;
|
use crate::psbt::map::Input;
|
||||||
use crate::sighash::EcdsaSighashType;
|
|
||||||
|
|
||||||
// create some values to use in the PSBT
|
// create some values to use in the PSBT
|
||||||
let tx = Transaction {
|
let tx = Transaction {
|
||||||
version: 1,
|
version: 1,
|
||||||
lock_time: absolute::LockTime::ZERO,
|
lock_time: absolute::LockTime::ZERO,
|
||||||
input: vec![TxIn {
|
input: vec![
|
||||||
|
TxIn {
|
||||||
previous_output: OutPoint {
|
previous_output: OutPoint {
|
||||||
txid: Txid::from_hex("e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389").unwrap(),
|
txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse().unwrap(),
|
||||||
vout: 1,
|
vout: 1,
|
||||||
},
|
},
|
||||||
script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"),
|
script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(),
|
||||||
sequence: Sequence::MAX,
|
sequence: Sequence::MAX,
|
||||||
witness: Witness::from_slice(&[hex!("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105")]),
|
witness: Witness::from_slice(&[hex!("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105")]),
|
||||||
}],
|
}
|
||||||
|
],
|
||||||
output: vec![
|
output: vec![
|
||||||
TxOut {
|
TxOut {
|
||||||
value: 190303501938,
|
value: 190303501938,
|
||||||
script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"),
|
script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@ -1032,13 +1027,14 @@ mod tests {
|
||||||
proprietary: proprietary.clone(),
|
proprietary: proprietary.clone(),
|
||||||
unknown: unknown.clone(),
|
unknown: unknown.clone(),
|
||||||
|
|
||||||
inputs: vec![Input {
|
inputs: vec![
|
||||||
|
Input {
|
||||||
non_witness_utxo: Some(tx),
|
non_witness_utxo: Some(tx),
|
||||||
witness_utxo: Some(TxOut {
|
witness_utxo: Some(TxOut {
|
||||||
value: 190303501938,
|
value: 190303501938,
|
||||||
script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"),
|
script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
|
||||||
}),
|
}),
|
||||||
sighash_type: Some("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse::<EcdsaSighashType>().unwrap().into()),
|
sighash_type: Some("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse::<PsbtSighashType>().unwrap()),
|
||||||
redeem_script: Some(vec![0x51].into()),
|
redeem_script: Some(vec![0x51].into()),
|
||||||
witness_script: None,
|
witness_script: None,
|
||||||
partial_sigs: vec![(
|
partial_sigs: vec![(
|
||||||
|
@ -1054,13 +1050,16 @@ mod tests {
|
||||||
proprietary: proprietary.clone(),
|
proprietary: proprietary.clone(),
|
||||||
unknown: unknown.clone(),
|
unknown: unknown.clone(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}],
|
}
|
||||||
outputs: vec![Output {
|
],
|
||||||
|
outputs: vec![
|
||||||
|
Output {
|
||||||
bip32_derivation: keypaths,
|
bip32_derivation: keypaths,
|
||||||
proprietary,
|
proprietary,
|
||||||
unknown,
|
unknown,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}],
|
}
|
||||||
|
],
|
||||||
};
|
};
|
||||||
let encoded = serde_json::to_string(&psbt).unwrap();
|
let encoded = serde_json::to_string(&psbt).unwrap();
|
||||||
let decoded: PartiallySignedTransaction = serde_json::from_str(&encoded).unwrap();
|
let decoded: PartiallySignedTransaction = serde_json::from_str(&encoded).unwrap();
|
||||||
|
@ -1068,12 +1067,11 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod bip_vectors {
|
mod bip_vectors {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
#[cfg(feature = "base64")]
|
#[cfg(feature = "base64")]
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::hashes::hex::FromHex;
|
|
||||||
use crate::hash_types::Txid;
|
|
||||||
|
|
||||||
use crate::blockdata::script::ScriptBuf;
|
use crate::blockdata::script::ScriptBuf;
|
||||||
use crate::blockdata::transaction::{Transaction, TxIn, TxOut, OutPoint, Sequence};
|
use crate::blockdata::transaction::{Transaction, TxIn, TxOut, OutPoint, Sequence};
|
||||||
use crate::blockdata::locktime::absolute;
|
use crate::blockdata::locktime::absolute;
|
||||||
|
@ -1082,7 +1080,6 @@ mod tests {
|
||||||
use crate::sighash::EcdsaSighashType;
|
use crate::sighash::EcdsaSighashType;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use crate::blockdata::witness::Witness;
|
use crate::blockdata::witness::Witness;
|
||||||
use crate::internal_macros::{hex, hex_script};
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic(expected = "InvalidMagic")]
|
#[should_panic(expected = "InvalidMagic")]
|
||||||
|
@ -1166,25 +1163,25 @@ mod tests {
|
||||||
unsigned_tx: Transaction {
|
unsigned_tx: Transaction {
|
||||||
version: 2,
|
version: 2,
|
||||||
lock_time: absolute::LockTime::from_consensus(1257139),
|
lock_time: absolute::LockTime::from_consensus(1257139),
|
||||||
input: vec![TxIn {
|
input: vec![
|
||||||
|
TxIn {
|
||||||
previous_output: OutPoint {
|
previous_output: OutPoint {
|
||||||
txid: Txid::from_hex(
|
txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126".parse().unwrap(),
|
||||||
"f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126",
|
|
||||||
).unwrap(),
|
|
||||||
vout: 0,
|
vout: 0,
|
||||||
},
|
},
|
||||||
script_sig: ScriptBuf::new(),
|
script_sig: ScriptBuf::new(),
|
||||||
sequence: Sequence::ENABLE_LOCKTIME_NO_RBF,
|
sequence: Sequence::ENABLE_LOCKTIME_NO_RBF,
|
||||||
witness: Witness::default(),
|
witness: Witness::default(),
|
||||||
}],
|
}
|
||||||
|
],
|
||||||
output: vec![
|
output: vec![
|
||||||
TxOut {
|
TxOut {
|
||||||
value: 99999699,
|
value: 99999699,
|
||||||
script_pubkey: hex_script!("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac"),
|
script_pubkey: ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(),
|
||||||
},
|
},
|
||||||
TxOut {
|
TxOut {
|
||||||
value: 100000000,
|
value: 100000000,
|
||||||
script_pubkey: hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787"),
|
script_pubkey: ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -1193,18 +1190,18 @@ mod tests {
|
||||||
proprietary: BTreeMap::new(),
|
proprietary: BTreeMap::new(),
|
||||||
unknown: BTreeMap::new(),
|
unknown: BTreeMap::new(),
|
||||||
|
|
||||||
inputs: vec![Input {
|
inputs: vec![
|
||||||
|
Input {
|
||||||
non_witness_utxo: Some(Transaction {
|
non_witness_utxo: Some(Transaction {
|
||||||
version: 1,
|
version: 1,
|
||||||
lock_time: absolute::LockTime::ZERO,
|
lock_time: absolute::LockTime::ZERO,
|
||||||
input: vec![TxIn {
|
input: vec![
|
||||||
|
TxIn {
|
||||||
previous_output: OutPoint {
|
previous_output: OutPoint {
|
||||||
txid: Txid::from_hex(
|
txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse().unwrap(),
|
||||||
"e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389",
|
|
||||||
).unwrap(),
|
|
||||||
vout: 1,
|
vout: 1,
|
||||||
},
|
},
|
||||||
script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"),
|
script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(),
|
||||||
sequence: Sequence::MAX,
|
sequence: Sequence::MAX,
|
||||||
witness: Witness::from_slice(&[
|
witness: Witness::from_slice(&[
|
||||||
hex!("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01"),
|
hex!("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01"),
|
||||||
|
@ -1213,31 +1210,31 @@ mod tests {
|
||||||
},
|
},
|
||||||
TxIn {
|
TxIn {
|
||||||
previous_output: OutPoint {
|
previous_output: OutPoint {
|
||||||
txid: Txid::from_hex(
|
txid: "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886".parse().unwrap(),
|
||||||
"b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886",
|
|
||||||
).unwrap(),
|
|
||||||
vout: 1,
|
vout: 1,
|
||||||
},
|
},
|
||||||
script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"),
|
script_sig: ScriptBuf::from_hex("160014fe3e9ef1a745e974d902c4355943abcb34bd5353").unwrap(),
|
||||||
sequence: Sequence::MAX,
|
sequence: Sequence::MAX,
|
||||||
witness: Witness::from_slice(&[
|
witness: Witness::from_slice(&[
|
||||||
hex!("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01"),
|
hex!("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01"),
|
||||||
hex!("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3"),
|
hex!("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3"),
|
||||||
]),
|
]),
|
||||||
}],
|
}
|
||||||
|
],
|
||||||
output: vec![
|
output: vec![
|
||||||
TxOut {
|
TxOut {
|
||||||
value: 200000000,
|
value: 200000000,
|
||||||
script_pubkey: hex_script!("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac"),
|
script_pubkey: ScriptBuf::from_hex("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac").unwrap(),
|
||||||
},
|
},
|
||||||
TxOut {
|
TxOut {
|
||||||
value: 190303501938,
|
value: 190303501938,
|
||||||
script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"),
|
script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},],
|
},
|
||||||
|
],
|
||||||
outputs: vec![
|
outputs: vec![
|
||||||
Output {
|
Output {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -1271,7 +1268,7 @@ mod tests {
|
||||||
assert!(&psbt.inputs[0].final_script_sig.is_some());
|
assert!(&psbt.inputs[0].final_script_sig.is_some());
|
||||||
|
|
||||||
let redeem_script = psbt.inputs[1].redeem_script.as_ref().unwrap();
|
let redeem_script = psbt.inputs[1].redeem_script.as_ref().unwrap();
|
||||||
let expected_out = hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787");
|
let expected_out = ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap();
|
||||||
|
|
||||||
assert!(redeem_script.is_v0_p2wpkh());
|
assert!(redeem_script.is_v0_p2wpkh());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -1317,7 +1314,7 @@ mod tests {
|
||||||
assert!(&psbt.inputs[1].final_script_sig.is_none());
|
assert!(&psbt.inputs[1].final_script_sig.is_none());
|
||||||
|
|
||||||
let redeem_script = psbt.inputs[1].redeem_script.as_ref().unwrap();
|
let redeem_script = psbt.inputs[1].redeem_script.as_ref().unwrap();
|
||||||
let expected_out = hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787");
|
let expected_out = ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap();
|
||||||
|
|
||||||
assert!(redeem_script.is_v0_p2wpkh());
|
assert!(redeem_script.is_v0_p2wpkh());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -1341,7 +1338,7 @@ mod tests {
|
||||||
assert!(&psbt.inputs[0].final_script_sig.is_none());
|
assert!(&psbt.inputs[0].final_script_sig.is_none());
|
||||||
|
|
||||||
let redeem_script = psbt.inputs[0].redeem_script.as_ref().unwrap();
|
let redeem_script = psbt.inputs[0].redeem_script.as_ref().unwrap();
|
||||||
let expected_out = hex_script!("a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87");
|
let expected_out = ScriptBuf::from_hex("a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87").unwrap();
|
||||||
|
|
||||||
assert!(redeem_script.is_v0_p2wsh());
|
assert!(redeem_script.is_v0_p2wsh());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -1362,7 +1359,7 @@ mod tests {
|
||||||
let tx = &psbt.unsigned_tx;
|
let tx = &psbt.unsigned_tx;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tx.txid(),
|
tx.txid(),
|
||||||
Txid::from_hex("75c5c9665a570569ad77dd1279e6fd4628a093c4dcbf8d41532614044c14c115").unwrap(),
|
"75c5c9665a570569ad77dd1279e6fd4628a093c4dcbf8d41532614044c14c115".parse().unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut unknown: BTreeMap<raw::Key, Vec<u8>> = BTreeMap::new();
|
let mut unknown: BTreeMap<raw::Key, Vec<u8>> = BTreeMap::new();
|
||||||
|
@ -1400,7 +1397,7 @@ mod tests {
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
assert_eq!(err.to_string(), "hash parse error");
|
assert_eq!(err.to_string(), "hash parse error");
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
assert_eq!(err.to_string(), "hash parse error: bad slice length 33 (expected 32)");
|
assert_eq!(err.to_string(), "hash parse error: invalid slice length 33 (expected 32)");
|
||||||
let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b094289756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb01010000").unwrap_err();
|
let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b094289756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb01010000").unwrap_err();
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
assert_eq!(err.to_string(), "invalid Schnorr signature");
|
assert_eq!(err.to_string(), "invalid Schnorr signature");
|
||||||
|
@ -1486,25 +1483,25 @@ mod tests {
|
||||||
unsigned_tx: Transaction {
|
unsigned_tx: Transaction {
|
||||||
version: 2,
|
version: 2,
|
||||||
lock_time: absolute::LockTime::from_consensus(1257139),
|
lock_time: absolute::LockTime::from_consensus(1257139),
|
||||||
input: vec![TxIn {
|
input: vec![
|
||||||
|
TxIn {
|
||||||
previous_output: OutPoint {
|
previous_output: OutPoint {
|
||||||
txid: Txid::from_hex(
|
txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126".parse().unwrap(),
|
||||||
"f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126",
|
|
||||||
).unwrap(),
|
|
||||||
vout: 0,
|
vout: 0,
|
||||||
},
|
},
|
||||||
script_sig: ScriptBuf::new(),
|
script_sig: ScriptBuf::new(),
|
||||||
sequence: Sequence::ENABLE_LOCKTIME_NO_RBF,
|
sequence: Sequence::ENABLE_LOCKTIME_NO_RBF,
|
||||||
witness: Witness::default(),
|
witness: Witness::default(),
|
||||||
}],
|
}
|
||||||
|
],
|
||||||
output: vec![
|
output: vec![
|
||||||
TxOut {
|
TxOut {
|
||||||
value: 99999699,
|
value: 99999699,
|
||||||
script_pubkey: hex_script!("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac"),
|
script_pubkey: ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(),
|
||||||
},
|
},
|
||||||
TxOut {
|
TxOut {
|
||||||
value: 100000000,
|
value: 100000000,
|
||||||
script_pubkey: hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787"),
|
script_pubkey: ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -1513,18 +1510,18 @@ mod tests {
|
||||||
proprietary: Default::default(),
|
proprietary: Default::default(),
|
||||||
unknown: BTreeMap::new(),
|
unknown: BTreeMap::new(),
|
||||||
|
|
||||||
inputs: vec![Input {
|
inputs: vec![
|
||||||
|
Input {
|
||||||
non_witness_utxo: Some(Transaction {
|
non_witness_utxo: Some(Transaction {
|
||||||
version: 1,
|
version: 1,
|
||||||
lock_time: absolute::LockTime::ZERO,
|
lock_time: absolute::LockTime::ZERO,
|
||||||
input: vec![TxIn {
|
input: vec![
|
||||||
|
TxIn {
|
||||||
previous_output: OutPoint {
|
previous_output: OutPoint {
|
||||||
txid: Txid::from_hex(
|
txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse().unwrap(),
|
||||||
"e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389",
|
|
||||||
).unwrap(),
|
|
||||||
vout: 1,
|
vout: 1,
|
||||||
},
|
},
|
||||||
script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"),
|
script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(),
|
||||||
sequence: Sequence::MAX,
|
sequence: Sequence::MAX,
|
||||||
witness: Witness::from_slice(&[
|
witness: Witness::from_slice(&[
|
||||||
hex!("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01"),
|
hex!("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01"),
|
||||||
|
@ -1533,31 +1530,31 @@ mod tests {
|
||||||
},
|
},
|
||||||
TxIn {
|
TxIn {
|
||||||
previous_output: OutPoint {
|
previous_output: OutPoint {
|
||||||
txid: Txid::from_hex(
|
txid: "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886".parse().unwrap(),
|
||||||
"b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886",
|
|
||||||
).unwrap(),
|
|
||||||
vout: 1,
|
vout: 1,
|
||||||
},
|
},
|
||||||
script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"),
|
script_sig: ScriptBuf::from_hex("160014fe3e9ef1a745e974d902c4355943abcb34bd5353").unwrap(),
|
||||||
sequence: Sequence::MAX,
|
sequence: Sequence::MAX,
|
||||||
witness: Witness::from_slice(&[
|
witness: Witness::from_slice(&[
|
||||||
hex!("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01"),
|
hex!("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01"),
|
||||||
hex!("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3"),
|
hex!("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3"),
|
||||||
]),
|
]),
|
||||||
}],
|
}
|
||||||
|
],
|
||||||
output: vec![
|
output: vec![
|
||||||
TxOut {
|
TxOut {
|
||||||
value: 200000000,
|
value: 200000000,
|
||||||
script_pubkey: hex_script!("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac"),
|
script_pubkey: ScriptBuf::from_hex("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac").unwrap(),
|
||||||
},
|
},
|
||||||
TxOut {
|
TxOut {
|
||||||
value: 190303501938,
|
value: 190303501938,
|
||||||
script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"),
|
script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},],
|
},
|
||||||
|
],
|
||||||
outputs: vec![
|
outputs: vec![
|
||||||
Output {
|
Output {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -1656,16 +1653,16 @@ mod tests {
|
||||||
unsigned_tx: Transaction {
|
unsigned_tx: Transaction {
|
||||||
version: 2,
|
version: 2,
|
||||||
lock_time: absolute::LockTime::from_consensus(1257139),
|
lock_time: absolute::LockTime::from_consensus(1257139),
|
||||||
input: vec![TxIn {
|
input: vec![
|
||||||
|
TxIn {
|
||||||
previous_output: OutPoint {
|
previous_output: OutPoint {
|
||||||
txid: Txid::from_hex(
|
txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126".parse().unwrap(),
|
||||||
"f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126",
|
|
||||||
).unwrap(),
|
|
||||||
vout: 0,
|
vout: 0,
|
||||||
},
|
},
|
||||||
sequence: Sequence::ENABLE_LOCKTIME_NO_RBF,
|
sequence: Sequence::ENABLE_LOCKTIME_NO_RBF,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}],
|
}
|
||||||
|
],
|
||||||
output: vec![
|
output: vec![
|
||||||
TxOut {
|
TxOut {
|
||||||
value: output_0_val,
|
value: output_0_val,
|
||||||
|
@ -1682,15 +1679,15 @@ mod tests {
|
||||||
proprietary: BTreeMap::new(),
|
proprietary: BTreeMap::new(),
|
||||||
unknown: BTreeMap::new(),
|
unknown: BTreeMap::new(),
|
||||||
|
|
||||||
inputs: vec![Input {
|
inputs: vec![
|
||||||
|
Input {
|
||||||
non_witness_utxo: Some(Transaction {
|
non_witness_utxo: Some(Transaction {
|
||||||
version: 1,
|
version: 1,
|
||||||
lock_time: absolute::LockTime::ZERO,
|
lock_time: absolute::LockTime::ZERO,
|
||||||
input: vec![TxIn {
|
input: vec![
|
||||||
|
TxIn {
|
||||||
previous_output: OutPoint {
|
previous_output: OutPoint {
|
||||||
txid: Txid::from_hex(
|
txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse().unwrap(),
|
||||||
"e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389",
|
|
||||||
).unwrap(),
|
|
||||||
vout: 1,
|
vout: 1,
|
||||||
},
|
},
|
||||||
sequence: Sequence::MAX,
|
sequence: Sequence::MAX,
|
||||||
|
@ -1698,14 +1695,13 @@ mod tests {
|
||||||
},
|
},
|
||||||
TxIn {
|
TxIn {
|
||||||
previous_output: OutPoint {
|
previous_output: OutPoint {
|
||||||
txid: Txid::from_hex(
|
txid: "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886".parse().unwrap(),
|
||||||
"b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886",
|
|
||||||
).unwrap(),
|
|
||||||
vout: 1,
|
vout: 1,
|
||||||
},
|
},
|
||||||
sequence: Sequence::MAX,
|
sequence: Sequence::MAX,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}],
|
}
|
||||||
|
],
|
||||||
output: vec![
|
output: vec![
|
||||||
TxOut {
|
TxOut {
|
||||||
value: prev_output_val,
|
value: prev_output_val,
|
||||||
|
@ -1718,7 +1714,8 @@ mod tests {
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},],
|
},
|
||||||
|
],
|
||||||
outputs: vec![
|
outputs: vec![
|
||||||
Output {
|
Output {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
|
@ -436,7 +436,6 @@ fn key_source_len(key_source: &KeySource) -> usize {
|
||||||
mod tests {
|
mod tests {
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
|
|
||||||
use crate::hashes::hex::FromHex;
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
// Composes tree matching a given depth map, filled with dumb script leafs,
|
// Composes tree matching a given depth map, filled with dumb script leafs,
|
||||||
|
|
|
@ -1057,7 +1057,7 @@ mod tests {
|
||||||
use crate::hash_types::Sighash;
|
use crate::hash_types::Sighash;
|
||||||
use crate::hashes::hex::FromHex;
|
use crate::hashes::hex::FromHex;
|
||||||
use crate::hashes::{Hash, HashEngine};
|
use crate::hashes::{Hash, HashEngine};
|
||||||
use crate::internal_macros::{hex, hex_from_slice, hex_script};
|
use crate::internal_macros::hex;
|
||||||
use crate::network::constants::Network;
|
use crate::network::constants::Network;
|
||||||
use crate::taproot::{TapLeafHash, TapSighashHash};
|
use crate::taproot::{TapLeafHash, TapSighashHash};
|
||||||
|
|
||||||
|
@ -1347,7 +1347,7 @@ mod tests {
|
||||||
let script_inner = ScriptBuf::from_hex(script_hex).unwrap();
|
let script_inner = ScriptBuf::from_hex(script_hex).unwrap();
|
||||||
Some(ScriptPath::with_defaults(&script_inner).leaf_hash())
|
Some(ScriptPath::with_defaults(&script_inner).leaf_hash())
|
||||||
}
|
}
|
||||||
(_, Some(script_leaf_hash)) => Some(TapLeafHash::from_hex(script_leaf_hash).unwrap()),
|
(_, Some(script_leaf_hash)) => Some(script_leaf_hash.parse::<TapLeafHash>().unwrap()),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
// All our tests use the default `0xFFFFFFFF` codeseparator value
|
// All our tests use the default `0xFFFFFFFF` codeseparator value
|
||||||
|
@ -1621,24 +1621,22 @@ mod tests {
|
||||||
let mut cache = SighashCache::new(&tx);
|
let mut cache = SighashCache::new(&tx);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.segwit_signature_hash(1, &witness_script, value, EcdsaSighashType::All).unwrap(),
|
cache.segwit_signature_hash(1, &witness_script, value, EcdsaSighashType::All).unwrap(),
|
||||||
hex_from_slice!(
|
"c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670".parse::<Sighash>().unwrap(),
|
||||||
Sighash,
|
|
||||||
"c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670"
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let cache = cache.segwit_cache();
|
let cache = cache.segwit_cache();
|
||||||
|
// Parse hex into Vec because BIP143 test vector displays forwards but our sha256d::Hash displays backwards.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.prevouts,
|
cache.prevouts.into_inner().as_ref(),
|
||||||
hex_from_slice!("96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37")
|
&Vec::from_hex("96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37").unwrap()[..],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.sequences,
|
cache.sequences.into_inner().as_ref(),
|
||||||
hex_from_slice!("52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b")
|
&Vec::from_hex("52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b").unwrap()[..],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.outputs,
|
cache.outputs.into_inner().as_ref(),
|
||||||
hex_from_slice!("863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5")
|
&Vec::from_hex("863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5").unwrap()[..],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1659,24 +1657,22 @@ mod tests {
|
||||||
let mut cache = SighashCache::new(&tx);
|
let mut cache = SighashCache::new(&tx);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.segwit_signature_hash(0, &witness_script, value, EcdsaSighashType::All).unwrap(),
|
cache.segwit_signature_hash(0, &witness_script, value, EcdsaSighashType::All).unwrap(),
|
||||||
hex_from_slice!(
|
"64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6".parse::<Sighash>().unwrap(),
|
||||||
Sighash,
|
|
||||||
"64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6"
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let cache = cache.segwit_cache();
|
let cache = cache.segwit_cache();
|
||||||
|
// Parse hex into Vec because BIP143 test vector displays forwards but our sha256d::Hash displays backwards.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.prevouts,
|
cache.prevouts.into_inner().as_ref(),
|
||||||
hex_from_slice!("b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a")
|
&Vec::from_hex("b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a").unwrap()[..],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.sequences,
|
cache.sequences.into_inner().as_ref(),
|
||||||
hex_from_slice!("18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198")
|
&Vec::from_hex("18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198").unwrap()[..],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.outputs,
|
cache.outputs.into_inner().as_ref(),
|
||||||
hex_from_slice!("de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83")
|
&Vec::from_hex("de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83").unwrap()[..],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1689,37 +1685,35 @@ mod tests {
|
||||||
05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000"),
|
05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000"),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
let witness_script = hex_script!(
|
let witness_script = ScriptBuf::from_hex(
|
||||||
"56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28\
|
"56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28\
|
||||||
bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b\
|
bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b\
|
||||||
9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58\
|
9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58\
|
||||||
c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b1486\
|
c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b1486\
|
||||||
2c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b\
|
2c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b\
|
||||||
56ae"
|
56ae"
|
||||||
);
|
).unwrap();
|
||||||
let value = 987654321;
|
let value = 987654321;
|
||||||
|
|
||||||
let mut cache = SighashCache::new(&tx);
|
let mut cache = SighashCache::new(&tx);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.segwit_signature_hash(0, &witness_script, value, EcdsaSighashType::All).unwrap(),
|
cache.segwit_signature_hash(0, &witness_script, value, EcdsaSighashType::All).unwrap(),
|
||||||
hex_from_slice!(
|
"185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c".parse::<Sighash>().unwrap(),
|
||||||
Sighash,
|
|
||||||
"185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c"
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let cache = cache.segwit_cache();
|
let cache = cache.segwit_cache();
|
||||||
|
// Parse hex into Vec because BIP143 test vector displays forwards but our sha256d::Hash displays backwards.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.prevouts,
|
cache.prevouts.into_inner().as_ref(),
|
||||||
hex_from_slice!("74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0")
|
&Vec::from_hex("74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0").unwrap()[..],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.sequences,
|
cache.sequences.into_inner().as_ref(),
|
||||||
hex_from_slice!("3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044")
|
&Vec::from_hex("3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044").unwrap()[..],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.outputs,
|
cache.outputs.into_inner().as_ref(),
|
||||||
hex_from_slice!("bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc")
|
&Vec::from_hex("bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc").unwrap()[..],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1394,7 +1394,7 @@ mod test {
|
||||||
builder = process_script_trees(leaf, builder, leaves, depth + 1);
|
builder = process_script_trees(leaf, builder, leaves, depth + 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let script = ScriptBuf::from_str(v["script"].as_str().unwrap()).unwrap();
|
let script = ScriptBuf::from_hex(v["script"].as_str().unwrap()).unwrap();
|
||||||
let ver =
|
let ver =
|
||||||
LeafVersion::from_consensus(v["leafVersion"].as_u64().unwrap() as u8).unwrap();
|
LeafVersion::from_consensus(v["leafVersion"].as_u64().unwrap() as u8).unwrap();
|
||||||
leaves.push((script.clone(), ver));
|
leaves.push((script.clone(), ver));
|
||||||
|
@ -1446,7 +1446,7 @@ mod test {
|
||||||
let expected_tweak =
|
let expected_tweak =
|
||||||
TapTweakHash::from_str(arr["intermediary"]["tweak"].as_str().unwrap()).unwrap();
|
TapTweakHash::from_str(arr["intermediary"]["tweak"].as_str().unwrap()).unwrap();
|
||||||
let expected_spk =
|
let expected_spk =
|
||||||
ScriptBuf::from_str(arr["expected"]["scriptPubKey"].as_str().unwrap()).unwrap();
|
ScriptBuf::from_hex(arr["expected"]["scriptPubKey"].as_str().unwrap()).unwrap();
|
||||||
let expected_addr =
|
let expected_addr =
|
||||||
Address::from_str(arr["expected"]["bip350Address"].as_str().unwrap()).unwrap().assume_checked();
|
Address::from_str(arr["expected"]["bip350Address"].as_str().unwrap()).unwrap().assume_checked();
|
||||||
|
|
||||||
|
|
|
@ -13,14 +13,14 @@ use bitcoin::psbt::{Psbt, PsbtSighashType};
|
||||||
use bitcoin::secp256k1::{self, Secp256k1};
|
use bitcoin::secp256k1::{self, Secp256k1};
|
||||||
use bitcoin::{
|
use bitcoin::{
|
||||||
absolute, Amount, Denomination, Network, OutPoint, PrivateKey, PublicKey, ScriptBuf, Sequence,
|
absolute, Amount, Denomination, Network, OutPoint, PrivateKey, PublicKey, ScriptBuf, Sequence,
|
||||||
Transaction, TxIn, TxOut, Txid, Witness,
|
Transaction, TxIn, TxOut, Witness,
|
||||||
};
|
};
|
||||||
|
|
||||||
const NETWORK: Network = Network::Testnet;
|
const NETWORK: Network = Network::Testnet;
|
||||||
|
|
||||||
macro_rules! hex_script {
|
macro_rules! hex_script {
|
||||||
($s:expr) => {
|
($s:expr) => {
|
||||||
<ScriptBuf as FromStr>::from_str($s).unwrap()
|
<ScriptBuf>::from_hex($s).unwrap()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ fn create_transaction() -> Transaction {
|
||||||
input: vec![
|
input: vec![
|
||||||
TxIn {
|
TxIn {
|
||||||
previous_output: OutPoint {
|
previous_output: OutPoint {
|
||||||
txid: Txid::from_hex(input_0.txid).expect("failed to parse txid"),
|
txid: input_0.txid.parse().expect("failed to parse txid"),
|
||||||
vout: input_0.index,
|
vout: input_0.index,
|
||||||
},
|
},
|
||||||
script_sig: ScriptBuf::new(),
|
script_sig: ScriptBuf::new(),
|
||||||
|
@ -175,7 +175,7 @@ fn create_transaction() -> Transaction {
|
||||||
},
|
},
|
||||||
TxIn {
|
TxIn {
|
||||||
previous_output: OutPoint {
|
previous_output: OutPoint {
|
||||||
txid: Txid::from_hex(input_1.txid).expect("failed to parse txid"),
|
txid: input_1.txid.parse().expect("failed to parse txid"),
|
||||||
vout: input_1.index,
|
vout: input_1.index,
|
||||||
},
|
},
|
||||||
script_sig: ScriptBuf::new(),
|
script_sig: ScriptBuf::new(),
|
||||||
|
@ -188,14 +188,14 @@ fn create_transaction() -> Transaction {
|
||||||
value: Amount::from_str_in(output_0.amount, Denomination::Bitcoin)
|
value: Amount::from_str_in(output_0.amount, Denomination::Bitcoin)
|
||||||
.expect("failed to parse amount")
|
.expect("failed to parse amount")
|
||||||
.to_sat(),
|
.to_sat(),
|
||||||
script_pubkey: ScriptBuf::from_str(output_0.script_pubkey)
|
script_pubkey: ScriptBuf::from_hex(output_0.script_pubkey)
|
||||||
.expect("failed to parse script"),
|
.expect("failed to parse script"),
|
||||||
},
|
},
|
||||||
TxOut {
|
TxOut {
|
||||||
value: Amount::from_str_in(output_1.amount, Denomination::Bitcoin)
|
value: Amount::from_str_in(output_1.amount, Denomination::Bitcoin)
|
||||||
.expect("failed to parse amount")
|
.expect("failed to parse amount")
|
||||||
.to_sat(),
|
.to_sat(),
|
||||||
script_pubkey: ScriptBuf::from_str(output_1.script_pubkey)
|
script_pubkey: ScriptBuf::from_hex(output_1.script_pubkey)
|
||||||
.expect("failed to parse script"),
|
.expect("failed to parse script"),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -226,13 +226,10 @@ fn serde_regression_psbt() {
|
||||||
lock_time: absolute::LockTime::ZERO,
|
lock_time: absolute::LockTime::ZERO,
|
||||||
input: vec![TxIn {
|
input: vec![TxIn {
|
||||||
previous_output: OutPoint {
|
previous_output: OutPoint {
|
||||||
txid: Txid::from_hex(
|
txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse::<Txid>().unwrap(),
|
||||||
"e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389",
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
vout: 1,
|
vout: 1,
|
||||||
},
|
},
|
||||||
script_sig: ScriptBuf::from_str("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(),
|
script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(),
|
||||||
sequence: Sequence::from_consensus(4294967295),
|
sequence: Sequence::from_consensus(4294967295),
|
||||||
witness: Witness::from_slice(&[Vec::from_hex(
|
witness: Witness::from_slice(&[Vec::from_hex(
|
||||||
"03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105",
|
"03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105",
|
||||||
|
@ -241,7 +238,7 @@ fn serde_regression_psbt() {
|
||||||
}],
|
}],
|
||||||
output: vec![TxOut {
|
output: vec![TxOut {
|
||||||
value: 190303501938,
|
value: 190303501938,
|
||||||
script_pubkey: ScriptBuf::from_str("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587")
|
script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587")
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
|
@ -286,7 +283,7 @@ fn serde_regression_psbt() {
|
||||||
non_witness_utxo: Some(tx),
|
non_witness_utxo: Some(tx),
|
||||||
witness_utxo: Some(TxOut {
|
witness_utxo: Some(TxOut {
|
||||||
value: 190303501938,
|
value: 190303501938,
|
||||||
script_pubkey: ScriptBuf::from_str("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
|
script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
|
||||||
}),
|
}),
|
||||||
sighash_type: Some(PsbtSighashType::from(EcdsaSighashType::from_str("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY").unwrap())),
|
sighash_type: Some(PsbtSighashType::from(EcdsaSighashType::from_str("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY").unwrap())),
|
||||||
redeem_script: Some(vec![0x51].into()),
|
redeem_script: Some(vec![0x51].into()),
|
||||||
|
|
|
@ -26,8 +26,22 @@ pub enum Error {
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match *self {
|
use self::Error::*;
|
||||||
Error::InvalidLength(ell, ell2) => write!(f, "bad slice length {} (expected {})", ell2, ell),
|
|
||||||
|
match self {
|
||||||
|
InvalidLength(ref ell, ref ell2) => write!(f, "invalid slice length {} (expected {})", ell2, ell),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
|
impl std::error::Error for Error {
|
||||||
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
|
use self::Error::*;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
InvalidLength(_, _) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ use core::str;
|
||||||
use core::ops::Index;
|
use core::ops::Index;
|
||||||
use core::slice::SliceIndex;
|
use core::slice::SliceIndex;
|
||||||
|
|
||||||
use crate::{Error, hex, ripemd160, sha256};
|
use crate::{Error, ripemd160, sha256};
|
||||||
|
|
||||||
crate::internal_macros::hash_type! {
|
crate::internal_macros::hash_type! {
|
||||||
160,
|
160,
|
||||||
|
@ -52,7 +52,6 @@ mod tests {
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
fn test() {
|
fn test() {
|
||||||
use crate::{hash160, Hash, HashEngine};
|
use crate::{hash160, Hash, HashEngine};
|
||||||
use crate::hex::FromHex;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
@ -87,7 +86,7 @@ mod tests {
|
||||||
for test in tests {
|
for test in tests {
|
||||||
// Hash through high-level API, check hex encoding/decoding
|
// Hash through high-level API, check hex encoding/decoding
|
||||||
let hash = hash160::Hash::hash(&test.input[..]);
|
let hash = hash160::Hash::hash(&test.input[..]);
|
||||||
assert_eq!(hash, hash160::Hash::from_hex(test.output_str).expect("parse hex"));
|
assert_eq!(hash, test.output_str.parse::<hash160::Hash>().expect("parse hex"));
|
||||||
assert_eq!(&hash[..], &test.output[..]);
|
assert_eq!(&hash[..], &test.output[..]);
|
||||||
assert_eq!(&hash.to_string(), &test.output_str);
|
assert_eq!(&hash.to_string(), &test.output_str);
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ use std::io;
|
||||||
use core2::io;
|
use core2::io;
|
||||||
|
|
||||||
use core::{fmt, str};
|
use core::{fmt, str};
|
||||||
use crate::Hash;
|
|
||||||
|
|
||||||
/// Hex decoding error.
|
/// Hex decoding error.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
@ -47,6 +46,18 @@ impl fmt::Display for Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
|
impl std::error::Error for Error {
|
||||||
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
|
use self::Error::*;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
InvalidChar(_) | OddLengthString(_) | InvalidLength(_, _) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Trait for objects that can be deserialized from hex strings.
|
/// Trait for objects that can be deserialized from hex strings.
|
||||||
pub trait FromHex: Sized {
|
pub trait FromHex: Sized {
|
||||||
/// Produces an object from a byte iterator.
|
/// Produces an object from a byte iterator.
|
||||||
|
@ -60,20 +71,6 @@ pub trait FromHex: Sized {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Hash> FromHex for T {
|
|
||||||
fn from_byte_iter<I>(iter: I) -> Result<Self, Error>
|
|
||||||
where
|
|
||||||
I: Iterator<Item = Result<u8, Error>> + ExactSizeIterator + DoubleEndedIterator,
|
|
||||||
{
|
|
||||||
let inner = if Self::DISPLAY_BACKWARD {
|
|
||||||
T::Inner::from_byte_iter(iter.rev())?
|
|
||||||
} else {
|
|
||||||
T::Inner::from_byte_iter(iter)?
|
|
||||||
};
|
|
||||||
Ok(Hash::from_inner(inner))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Iterator over a hex-encoded string slice which decodes hex and yields bytes.
|
/// Iterator over a hex-encoded string slice which decodes hex and yields bytes.
|
||||||
pub struct HexIterator<'a> {
|
pub struct HexIterator<'a> {
|
||||||
/// The `Bytes` iterator whose next two bytes will be decoded to yield
|
/// The `Bytes` iterator whose next two bytes will be decoded to yield
|
||||||
|
@ -204,13 +201,12 @@ impl_fromhex_array!(384);
|
||||||
impl_fromhex_array!(512);
|
impl_fromhex_array!(512);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
||||||
use internals::hex::exts::DisplayHex;
|
use internals::hex::exts::DisplayHex;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
||||||
fn hex_roundtrip() {
|
fn hex_roundtrip() {
|
||||||
let expected = "0123456789abcdef";
|
let expected = "0123456789abcdef";
|
||||||
let expected_up = "0123456789ABCDEF";
|
let expected_up = "0123456789ABCDEF";
|
||||||
|
@ -232,7 +228,6 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
||||||
fn hex_error() {
|
fn hex_error() {
|
||||||
let oddlen = "0123456789abcdef0";
|
let oddlen = "0123456789abcdef0";
|
||||||
let badchar1 = "Z123456789abcdef";
|
let badchar1 = "Z123456789abcdef";
|
||||||
|
|
|
@ -18,26 +18,12 @@
|
||||||
//!
|
//!
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::{error, io};
|
use std::io;
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
use core2::{error, io};
|
use core2::io;
|
||||||
|
|
||||||
use crate::{Error, HashEngine, hex, sha1, sha256, sha512, ripemd160, siphash24, hmac};
|
use crate::{HashEngine, sha1, sha256, sha512, ripemd160, siphash24, hmac};
|
||||||
|
|
||||||
impl error::Error for Error {
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
fn cause(&self) -> Option<&error::Error> { None }
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
fn description(&self) -> &str { "`std::error::description` is deprecated" }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl error::Error for hex::Error {
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
fn cause(&self) -> Option<&error::Error> { None }
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
fn description(&self) -> &str { "`std::error::description` is deprecated" }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl io::Write for sha1::HashEngine {
|
impl io::Write for sha1::HashEngine {
|
||||||
fn flush(&mut self) -> io::Result<()> { Ok(()) }
|
fn flush(&mut self) -> io::Result<()> { Ok(()) }
|
||||||
|
|
|
@ -53,7 +53,7 @@ pub(crate) use arr_newtype_fmt_impl;
|
||||||
/// Arguments:
|
/// Arguments:
|
||||||
///
|
///
|
||||||
/// * `$bits` - number of bits this hash type has
|
/// * `$bits` - number of bits this hash type has
|
||||||
/// * `$reversed` - `bool` - `true` if the hash type should be displayed backwards, `false`
|
/// * `$reverse` - `bool` - `true` if the hash type should be displayed backwards, `false`
|
||||||
/// otherwise.
|
/// otherwise.
|
||||||
/// * `$gen: $gent` - generic type(s) and trait bound(s)
|
/// * `$gen: $gent` - generic type(s) and trait bound(s)
|
||||||
///
|
///
|
||||||
|
@ -67,7 +67,7 @@ pub(crate) use arr_newtype_fmt_impl;
|
||||||
/// `internal_new` is required so that types with more than one field are constructible.
|
/// `internal_new` is required so that types with more than one field are constructible.
|
||||||
/// `internal_engine` is required to initialize the engine for given hash type.
|
/// `internal_engine` is required to initialize the engine for given hash type.
|
||||||
macro_rules! hash_trait_impls {
|
macro_rules! hash_trait_impls {
|
||||||
($bits:expr, $reversed:expr $(, $gen:ident: $gent:ident)*) => {
|
($bits:expr, $reverse:expr $(, $gen:ident: $gent:ident)*) => {
|
||||||
impl<$($gen: $gent),*> Hash<$($gen),*> {
|
impl<$($gen: $gent),*> Hash<$($gen),*> {
|
||||||
/// Displays hex forwards, regardless of how this type would display it naturally.
|
/// Displays hex forwards, regardless of how this type would display it naturally.
|
||||||
///
|
///
|
||||||
|
@ -87,9 +87,17 @@ macro_rules! hash_trait_impls {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<$($gen: $gent),*> str::FromStr for Hash<$($gen),*> {
|
impl<$($gen: $gent),*> str::FromStr for Hash<$($gen),*> {
|
||||||
type Err = hex::Error;
|
type Err = $crate::hex::Error;
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
hex::FromHex::from_hex(s)
|
use $crate::hex::{FromHex, HexIterator};
|
||||||
|
use $crate::Hash;
|
||||||
|
|
||||||
|
let inner: [u8; $bits / 8] = if $reverse {
|
||||||
|
FromHex::from_byte_iter(HexIterator::new(s)?.rev())?
|
||||||
|
} else {
|
||||||
|
FromHex::from_byte_iter(HexIterator::new(s)?)?
|
||||||
|
};
|
||||||
|
Ok(Self::from_inner(inner))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +119,7 @@ macro_rules! hash_trait_impls {
|
||||||
type Inner = [u8; $bits / 8];
|
type Inner = [u8; $bits / 8];
|
||||||
|
|
||||||
const LEN: usize = $bits / 8;
|
const LEN: usize = $bits / 8;
|
||||||
const DISPLAY_BACKWARD: bool = $reversed;
|
const DISPLAY_BACKWARD: bool = $reverse;
|
||||||
|
|
||||||
fn engine() -> Self::Engine {
|
fn engine() -> Self::Engine {
|
||||||
Self::internal_engine()
|
Self::internal_engine()
|
||||||
|
@ -159,14 +167,14 @@ pub(crate) use hash_trait_impls;
|
||||||
/// Arguments:
|
/// Arguments:
|
||||||
///
|
///
|
||||||
/// * `$bits` - the number of bits of the hash type
|
/// * `$bits` - the number of bits of the hash type
|
||||||
/// * `$reversed` - `true` if the hash should be displayed backwards, `false` otherwise
|
/// * `$reverse` - `true` if the hash should be displayed backwards, `false` otherwise
|
||||||
/// * `$doc` - doc string to put on the type
|
/// * `$doc` - doc string to put on the type
|
||||||
/// * `$schemars` - a literal that goes into `schema_with`.
|
/// * `$schemars` - a literal that goes into `schema_with`.
|
||||||
///
|
///
|
||||||
/// The `from_engine` free-standing function is still required with this macro. See the doc of
|
/// The `from_engine` free-standing function is still required with this macro. See the doc of
|
||||||
/// [`hash_trait_impls`].
|
/// [`hash_trait_impls`].
|
||||||
macro_rules! hash_type {
|
macro_rules! hash_type {
|
||||||
($bits:expr, $reversed:expr, $doc:literal, $schemars:literal) => {
|
($bits:expr, $reverse:expr, $doc:literal, $schemars:literal) => {
|
||||||
#[doc = $doc]
|
#[doc = $doc]
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
#[cfg_attr(feature = "schemars", derive(crate::schemars::JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(crate::schemars::JsonSchema))]
|
||||||
|
@ -186,7 +194,7 @@ macro_rules! hash_type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::internal_macros::hash_trait_impls!($bits, $reversed);
|
crate::internal_macros::hash_trait_impls!($bits, $reverse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub(crate) use hash_type;
|
pub(crate) use hash_type;
|
||||||
|
|
|
@ -25,7 +25,7 @@ use core::convert::TryInto;
|
||||||
use core::ops::Index;
|
use core::ops::Index;
|
||||||
use core::slice::SliceIndex;
|
use core::slice::SliceIndex;
|
||||||
|
|
||||||
use crate::{Error, HashEngine as _, hex};
|
use crate::{Error, HashEngine as _};
|
||||||
|
|
||||||
crate::internal_macros::hash_type! {
|
crate::internal_macros::hash_type! {
|
||||||
160,
|
160,
|
||||||
|
@ -408,7 +408,6 @@ mod tests {
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
fn test() {
|
fn test() {
|
||||||
use crate::{Hash, HashEngine, ripemd160};
|
use crate::{Hash, HashEngine, ripemd160};
|
||||||
use crate::hex::FromHex;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Test {
|
struct Test {
|
||||||
|
@ -470,7 +469,7 @@ mod tests {
|
||||||
for test in tests {
|
for test in tests {
|
||||||
// Hash through high-level API, check hex encoding/decoding
|
// Hash through high-level API, check hex encoding/decoding
|
||||||
let hash = ripemd160::Hash::hash(test.input.as_bytes());
|
let hash = ripemd160::Hash::hash(test.input.as_bytes());
|
||||||
assert_eq!(hash, ripemd160::Hash::from_hex(test.output_str).expect("parse hex"));
|
assert_eq!(hash, test.output_str.parse::<ripemd160::Hash>().expect("parse hex"));
|
||||||
assert_eq!(&hash[..], &test.output[..]);
|
assert_eq!(&hash[..], &test.output[..]);
|
||||||
assert_eq!(&hash.to_string(), &test.output_str);
|
assert_eq!(&hash.to_string(), &test.output_str);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ use core::convert::TryInto;
|
||||||
use core::ops::Index;
|
use core::ops::Index;
|
||||||
use core::slice::SliceIndex;
|
use core::slice::SliceIndex;
|
||||||
|
|
||||||
use crate::{Error, HashEngine as _, hex};
|
use crate::{Error, HashEngine as _};
|
||||||
|
|
||||||
crate::internal_macros::hash_type! {
|
crate::internal_macros::hash_type! {
|
||||||
160,
|
160,
|
||||||
|
@ -146,7 +146,6 @@ mod tests {
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
fn test() {
|
fn test() {
|
||||||
use crate::{sha1, Hash, HashEngine};
|
use crate::{sha1, Hash, HashEngine};
|
||||||
use crate::hex::FromHex;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Test {
|
struct Test {
|
||||||
|
@ -196,7 +195,7 @@ mod tests {
|
||||||
for test in tests {
|
for test in tests {
|
||||||
// Hash through high-level API, check hex encoding/decoding
|
// Hash through high-level API, check hex encoding/decoding
|
||||||
let hash = sha1::Hash::hash(test.input.as_bytes());
|
let hash = sha1::Hash::hash(test.input.as_bytes());
|
||||||
assert_eq!(hash, sha1::Hash::from_hex(test.output_str).expect("parse hex"));
|
assert_eq!(hash, test.output_str.parse::<sha1::Hash>().expect("parse hex"));
|
||||||
assert_eq!(&hash[..], &test.output[..]);
|
assert_eq!(&hash[..], &test.output[..]);
|
||||||
assert_eq!(&hash.to_string(), &test.output_str);
|
assert_eq!(&hash.to_string(), &test.output_str);
|
||||||
|
|
||||||
|
|
|
@ -326,8 +326,6 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
fn test() {
|
fn test() {
|
||||||
use crate::hex::FromHex;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Test {
|
struct Test {
|
||||||
input: &'static str,
|
input: &'static str,
|
||||||
|
@ -372,7 +370,7 @@ mod tests {
|
||||||
for test in tests {
|
for test in tests {
|
||||||
// Hash through high-level API, check hex encoding/decoding
|
// Hash through high-level API, check hex encoding/decoding
|
||||||
let hash = sha256::Hash::hash(test.input.as_bytes());
|
let hash = sha256::Hash::hash(test.input.as_bytes());
|
||||||
assert_eq!(hash, sha256::Hash::from_hex(test.output_str).expect("parse hex"));
|
assert_eq!(hash, test.output_str.parse::<sha256::Hash>().expect("parse hex"));
|
||||||
assert_eq!(&hash[..], &test.output[..]);
|
assert_eq!(&hash[..], &test.output[..]);
|
||||||
assert_eq!(&hash.to_string(), &test.output_str);
|
assert_eq!(&hash.to_string(), &test.output_str);
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ use core::str;
|
||||||
use core::ops::Index;
|
use core::ops::Index;
|
||||||
use core::slice::SliceIndex;
|
use core::slice::SliceIndex;
|
||||||
|
|
||||||
use crate::{Error, hex, sha256};
|
use crate::{Error, sha256};
|
||||||
|
|
||||||
crate::internal_macros::hash_type! {
|
crate::internal_macros::hash_type! {
|
||||||
256,
|
256,
|
||||||
|
@ -43,13 +43,10 @@ fn from_engine(e: sha256::HashEngine) -> Hash {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::sha256;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
fn test() {
|
fn test() {
|
||||||
use crate::{sha256d, Hash, HashEngine};
|
use crate::{sha256, sha256d, Hash, HashEngine};
|
||||||
use crate::hex::FromHex;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Test {
|
struct Test {
|
||||||
|
@ -75,7 +72,7 @@ mod tests {
|
||||||
for test in tests {
|
for test in tests {
|
||||||
// Hash through high-level API, check hex encoding/decoding
|
// Hash through high-level API, check hex encoding/decoding
|
||||||
let hash = sha256d::Hash::hash(test.input.as_bytes());
|
let hash = sha256d::Hash::hash(test.input.as_bytes());
|
||||||
assert_eq!(hash, sha256d::Hash::from_hex(test.output_str).expect("parse hex"));
|
assert_eq!(hash, test.output_str.parse::<sha256d::Hash>().expect("parse hex"));
|
||||||
assert_eq!(&hash[..], &test.output[..]);
|
assert_eq!(&hash[..], &test.output[..]);
|
||||||
assert_eq!(&hash.to_string(), &test.output_str);
|
assert_eq!(&hash.to_string(), &test.output_str);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ use core::marker::PhantomData;
|
||||||
use core::ops::Index;
|
use core::ops::Index;
|
||||||
use core::slice::SliceIndex;
|
use core::slice::SliceIndex;
|
||||||
|
|
||||||
use crate::{Error, hex, sha256};
|
use crate::{Error, sha256};
|
||||||
|
|
||||||
type HashEngine = sha256::HashEngine;
|
type HashEngine = sha256::HashEngine;
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ use core::convert::TryInto;
|
||||||
use core::ops::Index;
|
use core::ops::Index;
|
||||||
use core::slice::SliceIndex;
|
use core::slice::SliceIndex;
|
||||||
|
|
||||||
use crate::{Error, HashEngine as _, hex};
|
use crate::{Error, HashEngine as _};
|
||||||
|
|
||||||
crate::internal_macros::hash_trait_impls!(512, false);
|
crate::internal_macros::hash_trait_impls!(512, false);
|
||||||
|
|
||||||
|
@ -311,7 +311,6 @@ mod tests {
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
fn test() {
|
fn test() {
|
||||||
use crate::{sha512, Hash, HashEngine};
|
use crate::{sha512, Hash, HashEngine};
|
||||||
use crate::hex::FromHex;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Test {
|
struct Test {
|
||||||
|
@ -369,7 +368,7 @@ mod tests {
|
||||||
for test in tests {
|
for test in tests {
|
||||||
// Hash through high-level API, check hex encoding/decoding
|
// Hash through high-level API, check hex encoding/decoding
|
||||||
let hash = sha512::Hash::hash(test.input.as_bytes());
|
let hash = sha512::Hash::hash(test.input.as_bytes());
|
||||||
assert_eq!(hash, sha512::Hash::from_hex(test.output_str).expect("parse hex"));
|
assert_eq!(hash, test.output_str.parse::<sha512::Hash>().expect("parse hex"));
|
||||||
assert_eq!(&hash[..], &test.output[..]);
|
assert_eq!(&hash[..], &test.output[..]);
|
||||||
assert_eq!(&hash.to_string(), &test.output_str);
|
assert_eq!(&hash.to_string(), &test.output_str);
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ use core::str;
|
||||||
use core::ops::Index;
|
use core::ops::Index;
|
||||||
use core::slice::SliceIndex;
|
use core::slice::SliceIndex;
|
||||||
|
|
||||||
use crate::{hex, sha512, sha512::BLOCK_SIZE, Error};
|
use crate::{sha512, sha512::BLOCK_SIZE, Error};
|
||||||
|
|
||||||
/// Engine to compute SHA512/256 hash function.
|
/// Engine to compute SHA512/256 hash function.
|
||||||
///
|
///
|
||||||
|
@ -89,7 +89,6 @@ mod tests {
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
fn test() {
|
fn test() {
|
||||||
use crate::{sha512_256, Hash, HashEngine};
|
use crate::{sha512_256, Hash, HashEngine};
|
||||||
use crate::hex::FromHex;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Test {
|
struct Test {
|
||||||
|
@ -155,7 +154,7 @@ mod tests {
|
||||||
for test in tests {
|
for test in tests {
|
||||||
// Hash through high-level API, check hex encoding/decoding
|
// Hash through high-level API, check hex encoding/decoding
|
||||||
let hash = sha512_256::Hash::hash(test.input.as_bytes());
|
let hash = sha512_256::Hash::hash(test.input.as_bytes());
|
||||||
assert_eq!(hash, sha512_256::Hash::from_hex(test.output_str).expect("parse hex"));
|
assert_eq!(hash, test.output_str.parse::<sha512_256::Hash>().expect("parse hex"));
|
||||||
assert_eq!(&hash[..], &test.output[..]);
|
assert_eq!(&hash[..], &test.output[..]);
|
||||||
assert_eq!(&hash.to_string(), &test.output_str);
|
assert_eq!(&hash.to_string(), &test.output_str);
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ use core::{cmp, mem, ptr, str};
|
||||||
use core::ops::Index;
|
use core::ops::Index;
|
||||||
use core::slice::SliceIndex;
|
use core::slice::SliceIndex;
|
||||||
|
|
||||||
use crate::{Error, Hash as _, HashEngine as _, hex};
|
use crate::{Error, Hash as _, HashEngine as _};
|
||||||
|
|
||||||
crate::internal_macros::hash_type! {
|
crate::internal_macros::hash_type! {
|
||||||
64,
|
64,
|
||||||
|
|
|
@ -196,7 +196,15 @@ macro_rules! hash_newtype {
|
||||||
impl $crate::_export::_core::str::FromStr for $newtype {
|
impl $crate::_export::_core::str::FromStr for $newtype {
|
||||||
type Err = $crate::hex::Error;
|
type Err = $crate::hex::Error;
|
||||||
fn from_str(s: &str) -> $crate::_export::_core::result::Result<$newtype, Self::Err> {
|
fn from_str(s: &str) -> $crate::_export::_core::result::Result<$newtype, Self::Err> {
|
||||||
$crate::hex::FromHex::from_hex(s)
|
use $crate::hex::{HexIterator, FromHex};
|
||||||
|
use $crate::Hash;
|
||||||
|
|
||||||
|
let inner: <$hash as Hash>::Inner = if $reverse {
|
||||||
|
FromHex::from_byte_iter(HexIterator::new(s)?.rev())?
|
||||||
|
} else {
|
||||||
|
FromHex::from_byte_iter(HexIterator::new(s)?)?
|
||||||
|
};
|
||||||
|
Ok($newtype(<$hash>::from_inner(inner)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue