Run cargo fmt

Run the command `cargo +nightly fmt` to fix formatting issues. No other
changes other than those introduced by `rustfmt`.
This commit is contained in:
Tobin C. Harding 2022-11-16 10:22:16 +11:00
parent 1ecf09359b
commit 408d7737fb
8 changed files with 413 additions and 413 deletions

View File

@ -4,10 +4,10 @@ use std::str::FromStr;
use std::{env, process};
use bitcoin::address::Address;
use bitcoin::bip32::{ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey};
use bitcoin::hashes::hex::FromHex;
use bitcoin::secp256k1::ffi::types::AlignedType;
use bitcoin::secp256k1::Secp256k1;
use bitcoin::bip32::{ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey};
use bitcoin::PublicKey;
fn main() {

View File

@ -33,14 +33,14 @@ use std::collections::BTreeMap;
use std::fmt;
use std::str::FromStr;
use bitcoin::consensus::encode;
use bitcoin::hashes::hex::FromHex;
use bitcoin::locktime::absolute;
use bitcoin::secp256k1::{Secp256k1, Signing, Verification};
use bitcoin::bip32::{
ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey, Fingerprint, IntoDerivationPath,
};
use bitcoin::consensus::encode;
use bitcoin::hashes::hex::FromHex;
use bitcoin::locktime::absolute;
use bitcoin::psbt::{self, Input, Psbt, PsbtSighashType};
use bitcoin::secp256k1::{Secp256k1, Signing, Verification};
use bitcoin::{
Address, Amount, Network, OutPoint, PublicKey, Script, Sequence, Transaction, TxIn, TxOut,
Txid, Witness,

View File

@ -78,6 +78,7 @@ const UTXO_3: P2trUtxo = P2trUtxo {
use std::collections::BTreeMap;
use std::str::FromStr;
use bitcoin::bip32::{ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey, Fingerprint};
use bitcoin::consensus::encode;
use bitcoin::constants::COIN_VALUE;
use bitcoin::hashes::hex::FromHex;
@ -87,16 +88,13 @@ use bitcoin::psbt::serialize::Serialize;
use bitcoin::psbt::{self, Input, Output, Psbt, PsbtSighashType};
use bitcoin::schnorr::TapTweak;
use bitcoin::secp256k1::{Message, Secp256k1};
use bitcoin::bip32::{
ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey, Fingerprint,
};
use bitcoin::sighash::{self, SighashCache, SchnorrSighashType};
use bitcoin::sighash::{self, SchnorrSighashType, SighashCache};
use bitcoin::util::taproot::{
LeafVersion, TapLeafHash, TapSighashHash, TaprootBuilder, TaprootSpendInfo,
};
use bitcoin::{
absolute, script, Address, Amount, OutPoint, SchnorrSig, Script,
Transaction, TxIn, TxOut, Txid, Witness, XOnlyPublicKey,
absolute, script, Address, Amount, OutPoint, SchnorrSig, Script, Transaction, TxIn, TxOut,
Txid, Witness, XOnlyPublicKey,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {

View File

@ -34,9 +34,9 @@ use crate::blockdata::constants::{
MAX_SCRIPT_ELEMENT_SIZE, PUBKEY_ADDRESS_PREFIX_MAIN, PUBKEY_ADDRESS_PREFIX_TEST,
SCRIPT_ADDRESS_PREFIX_MAIN, SCRIPT_ADDRESS_PREFIX_TEST,
};
use crate::blockdata::opcodes::all::*;
use crate::blockdata::script::Instruction;
use crate::blockdata::{opcodes, script};
use crate::blockdata::opcodes::all::*;
use crate::error::ParseIntError;
use crate::hash_types::{PubkeyHash, ScriptHash};
use crate::hashes::{sha256, Hash, HashEngine};
@ -324,9 +324,7 @@ impl TryFrom<opcodes::All> for WitnessVersion {
fn try_from(opcode: opcodes::All) -> Result<Self, Self::Error> {
match opcode.to_u8() {
0 => Ok(WitnessVersion::V0),
version
if version >= OP_PUSHNUM_1.to_u8()
&& version <= OP_PUSHNUM_16.to_u8() =>
version if version >= OP_PUSHNUM_1.to_u8() && version <= OP_PUSHNUM_16.to_u8() =>
WitnessVersion::try_from(version - OP_PUSHNUM_1.to_u8() + 1),
_ => Err(Error::MalformedWitnessVersion),
}

View File

@ -6,10 +6,12 @@
//! We refer to the documentation on the types for more information.
//!
use crate::prelude::*;
use core::{ops, default, str::FromStr, cmp::Ordering};
use core::cmp::Ordering;
use core::fmt::{self, Write};
use core::str::FromStr;
use core::{default, ops};
use crate::prelude::*;
/// A set of denominations in which amounts can be expressed.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
@ -63,9 +65,7 @@ impl Denomination {
}
impl fmt::Display for Denomination {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(self.as_str())
}
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(self.as_str()) }
}
impl FromStr for Denomination {
@ -79,18 +79,17 @@ impl FromStr for Denomination {
///
/// Due to ambiguity between mega and milli, pico and peta we prohibit usage of leading capital 'M', 'P'.
fn from_str(s: &str) -> Result<Self, Self::Err> {
use self::ParseAmountError::*;
use self::Denomination as D;
use self::ParseAmountError::*;
let starts_with_uppercase = || s.starts_with(char::is_uppercase);
match denomination_from_str(s) {
None => Err(UnknownDenomination(s.to_owned())),
Some(D::MilliBitcoin) | Some(D::PicoBitcoin) | Some(D::MilliSatoshi) if starts_with_uppercase() => {
Err(PossiblyConfusingDenomination(s.to_owned()))
}
Some(D::NanoBitcoin) | Some(D::MicroBitcoin) if starts_with_uppercase() => {
Err(UnknownDenomination(s.to_owned()))
}
Some(D::MilliBitcoin) | Some(D::PicoBitcoin) | Some(D::MilliSatoshi)
if starts_with_uppercase() =>
Err(PossiblyConfusingDenomination(s.to_owned())),
Some(D::NanoBitcoin) | Some(D::MicroBitcoin) if starts_with_uppercase() =>
Err(UnknownDenomination(s.to_owned())),
Some(d) => Ok(d),
}
}
@ -157,7 +156,7 @@ pub enum ParseAmountError {
/// The denomination was unknown.
UnknownDenomination(String),
/// The denomination has multiple possible interpretations.
PossiblyConfusingDenomination(String)
PossiblyConfusingDenomination(String),
}
impl fmt::Display for ParseAmountError {
@ -169,7 +168,8 @@ impl fmt::Display for ParseAmountError {
ParseAmountError::InvalidFormat => f.write_str("invalid number format"),
ParseAmountError::InputTooLarge => f.write_str("input string was too large"),
ParseAmountError::InvalidCharacter(c) => write!(f, "invalid character in input: {}", c),
ParseAmountError::UnknownDenomination(ref d) => write!(f, "unknown denomination: {}", d),
ParseAmountError::UnknownDenomination(ref d) =>
write!(f, "unknown denomination: {}", d),
ParseAmountError::PossiblyConfusingDenomination(ref d) => {
let (letter, upper, lower) = match d.chars().next() {
Some('M') => ('M', "Mega", "milli"),
@ -191,13 +191,13 @@ impl std::error::Error for ParseAmountError {
match *self {
Negative
| TooBig
| TooPrecise
| InvalidFormat
| InputTooLarge
| InvalidCharacter(_)
| UnknownDenomination(_)
| PossiblyConfusingDenomination(_) => None
| TooBig
| TooPrecise
| InvalidFormat
| InputTooLarge
| InvalidCharacter(_)
| UnknownDenomination(_)
| PossiblyConfusingDenomination(_) => None,
}
}
}
@ -337,9 +337,7 @@ fn dec_width(mut num: u64) -> usize {
}
// NIH due to MSRV, impl copied from `core::i8::unsigned_abs` (introduced in Rust 1.51.1).
fn unsigned_abs(x: i8) -> u8 {
x.wrapping_abs() as u8
}
fn unsigned_abs(x: i8) -> u8 { x.wrapping_abs() as u8 }
fn repeat_char(f: &mut dyn fmt::Write, c: char, count: usize) -> fmt::Result {
for _ in 0..count {
@ -372,7 +370,7 @@ fn fmt_satoshi_in(
exp = precision as usize;
}
trailing_decimal_zeros = options.precision.unwrap_or(0);
},
}
Ordering::Less => {
let precision = unsigned_abs(precision);
let divisor = 10u64.pow(precision.into());
@ -391,7 +389,7 @@ fn fmt_satoshi_in(
// compute requested precision
let opt_precision = options.precision.unwrap_or(0);
trailing_decimal_zeros = opt_precision.saturating_sub(norm_nb_decimals);
},
}
Ordering::Equal => trailing_decimal_zeros = options.precision.unwrap_or(0),
}
let total_decimals = norm_nb_decimals + trailing_decimal_zeros;
@ -420,7 +418,8 @@ fn fmt_satoshi_in(
(true, true, _) | (true, false, fmt::Alignment::Right) => (width - num_width, 0),
(true, false, fmt::Alignment::Left) => (0, width - num_width),
// If the required padding is odd it needs to be skewed to the left
(true, false, fmt::Alignment::Center) => ((width - num_width) / 2, (width - num_width + 1) / 2),
(true, false, fmt::Alignment::Center) =>
((width - num_width) / 2, (width - num_width + 1) / 2),
};
if !options.sign_aware_zero_pad {
@ -488,24 +487,16 @@ impl Amount {
pub const MAX_MONEY: Amount = Amount(21_000_000 * 100_000_000);
/// Create an [Amount] with satoshi precision and the given number of satoshis.
pub const fn from_sat(satoshi: u64) -> Amount {
Amount(satoshi)
}
pub const fn from_sat(satoshi: u64) -> Amount { Amount(satoshi) }
/// Gets the number of satoshis in this [`Amount`].
pub fn to_sat(self) -> u64 {
self.0
}
pub fn to_sat(self) -> u64 { self.0 }
/// The maximum value of an [Amount].
pub fn max_value() -> Amount {
Amount(u64::max_value())
}
pub fn max_value() -> Amount { Amount(u64::max_value()) }
/// The minimum value of an [Amount].
pub fn min_value() -> Amount {
Amount(u64::min_value())
}
pub fn min_value() -> Amount { Amount(u64::min_value()) }
/// Convert from a value expressing bitcoins to an [Amount].
pub fn from_btc(btc: f64) -> Result<Amount, ParseAmountError> {
@ -559,9 +550,7 @@ impl Amount {
/// let amount = Amount::from_sat(100_000);
/// assert_eq!(amount.to_btc(), amount.to_float_in(Denomination::Bitcoin))
/// ```
pub fn to_btc(self) -> f64 {
self.to_float_in(Denomination::Bitcoin)
}
pub fn to_btc(self) -> f64 { self.to_float_in(Denomination::Bitcoin) }
/// Convert this [Amount] in floating-point notation with a given
/// denomination.
@ -582,7 +571,7 @@ impl Amount {
Display {
sats_abs: self.to_sat(),
is_negative: false,
style: DisplayStyle::FixedDenomination { denomination, show_denomination: false, },
style: DisplayStyle::FixedDenomination { denomination, show_denomination: false },
}
}
@ -640,23 +629,17 @@ impl Amount {
/// Checked multiplication.
/// Returns [None] if overflow occurred.
pub fn checked_mul(self, rhs: u64) -> Option<Amount> {
self.0.checked_mul(rhs).map(Amount)
}
pub fn checked_mul(self, rhs: u64) -> Option<Amount> { self.0.checked_mul(rhs).map(Amount) }
/// Checked integer division.
/// Be aware that integer division loses the remainder if no exact division
/// can be made.
/// Returns [None] if overflow occurred.
pub fn checked_div(self, rhs: u64) -> Option<Amount> {
self.0.checked_div(rhs).map(Amount)
}
pub fn checked_div(self, rhs: u64) -> Option<Amount> { self.0.checked_div(rhs).map(Amount) }
/// Checked remainder.
/// Returns [None] if overflow occurred.
pub fn checked_rem(self, rhs: u64) -> Option<Amount> {
self.0.checked_rem(rhs).map(Amount)
}
pub fn checked_rem(self, rhs: u64) -> Option<Amount> { self.0.checked_rem(rhs).map(Amount) }
/// Convert to a signed amount.
pub fn to_signed(self) -> Result<SignedAmount, ParseAmountError> {
@ -669,9 +652,7 @@ impl Amount {
}
impl default::Default for Amount {
fn default() -> Self {
Amount::ZERO
}
fn default() -> Self { Amount::ZERO }
}
impl fmt::Debug for Amount {
@ -698,9 +679,7 @@ impl ops::Add for Amount {
}
impl ops::AddAssign for Amount {
fn add_assign(&mut self, other: Amount) {
*self = *self + other
}
fn add_assign(&mut self, other: Amount) { *self = *self + other }
}
impl ops::Sub for Amount {
@ -712,9 +691,7 @@ impl ops::Sub for Amount {
}
impl ops::SubAssign for Amount {
fn sub_assign(&mut self, other: Amount) {
*self = *self - other
}
fn sub_assign(&mut self, other: Amount) { *self = *self - other }
}
impl ops::Rem<u64> for Amount {
@ -726,9 +703,7 @@ impl ops::Rem<u64> for Amount {
}
impl ops::RemAssign<u64> for Amount {
fn rem_assign(&mut self, modulus: u64) {
*self = *self % modulus
}
fn rem_assign(&mut self, modulus: u64) { *self = *self % modulus }
}
impl ops::Mul<u64> for Amount {
@ -740,31 +715,23 @@ impl ops::Mul<u64> for Amount {
}
impl ops::MulAssign<u64> for Amount {
fn mul_assign(&mut self, rhs: u64) {
*self = *self * rhs
}
fn mul_assign(&mut self, rhs: u64) { *self = *self * rhs }
}
impl ops::Div<u64> for Amount {
type Output = Amount;
fn div(self, rhs: u64) -> Self::Output {
self.checked_div(rhs).expect("Amount division error")
}
fn div(self, rhs: u64) -> Self::Output { self.checked_div(rhs).expect("Amount division error") }
}
impl ops::DivAssign<u64> for Amount {
fn div_assign(&mut self, rhs: u64) {
*self = *self / rhs
}
fn div_assign(&mut self, rhs: u64) { *self = *self / rhs }
}
impl FromStr for Amount {
type Err = ParseAmountError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Amount::from_str_with_denomination(s)
}
fn from_str(s: &str) -> Result<Self, Self::Err> { Amount::from_str_with_denomination(s) }
}
impl core::iter::Sum for Amount {
@ -829,7 +796,7 @@ impl fmt::Display for Display {
#[derive(Clone, Debug)]
enum DisplayStyle {
FixedDenomination { denomination: Denomination, show_denomination: bool, },
FixedDenomination { denomination: Denomination, show_denomination: bool },
DynamicDenomination,
}
@ -861,24 +828,16 @@ impl SignedAmount {
pub const MAX_MONEY: SignedAmount = SignedAmount(21_000_000 * 100_000_000);
/// Create an [SignedAmount] with satoshi precision and the given number of satoshis.
pub const fn from_sat(satoshi: i64) -> SignedAmount {
SignedAmount(satoshi)
}
pub const fn from_sat(satoshi: i64) -> SignedAmount { SignedAmount(satoshi) }
/// Gets the number of satoshis in this [`SignedAmount`].
pub fn to_sat(self) -> i64 {
self.0
}
pub fn to_sat(self) -> i64 { self.0 }
/// The maximum value of an [SignedAmount].
pub fn max_value() -> SignedAmount {
SignedAmount(i64::max_value())
}
pub fn max_value() -> SignedAmount { SignedAmount(i64::max_value()) }
/// The minimum value of an [SignedAmount].
pub fn min_value() -> SignedAmount {
SignedAmount(i64::min_value())
}
pub fn min_value() -> SignedAmount { SignedAmount(i64::min_value()) }
/// Convert from a value expressing bitcoins to an [SignedAmount].
pub fn from_btc(btc: f64) -> Result<SignedAmount, ParseAmountError> {
@ -927,9 +886,7 @@ impl SignedAmount {
/// Equivalent to `to_float_in(Denomination::Bitcoin)`.
///
/// Please be aware of the risk of using floating-point numbers.
pub fn to_btc(self) -> f64 {
self.to_float_in(Denomination::Bitcoin)
}
pub fn to_btc(self) -> f64 { self.to_float_in(Denomination::Bitcoin) }
/// Convert this [SignedAmount] in floating-point notation with a given
/// denomination.
@ -948,16 +905,14 @@ impl SignedAmount {
/// Returns the absolute value as satoshis.
///
/// This is the implementation of `unsigned_abs()` copied from `core` to support older MSRV.
fn to_sat_abs(self) -> u64 {
self.to_sat().wrapping_abs() as u64
}
fn to_sat_abs(self) -> u64 { self.to_sat().wrapping_abs() as u64 }
/// Create an object that implements [`fmt::Display`] using specified denomination.
pub fn display_in(self, denomination: Denomination) -> Display {
Display {
sats_abs: self.to_sat_abs(),
is_negative: self.is_negative(),
style: DisplayStyle::FixedDenomination { denomination, show_denomination: false, },
style: DisplayStyle::FixedDenomination { denomination, show_denomination: false },
}
}
@ -1002,37 +957,26 @@ impl SignedAmount {
// Some arithmetic that doesn't fit in `core::ops` traits.
/// Get the absolute value of this [SignedAmount].
pub fn abs(self) -> SignedAmount {
SignedAmount(self.0.abs())
}
pub fn abs(self) -> SignedAmount { SignedAmount(self.0.abs()) }
/// Returns a number representing sign of this [SignedAmount].
///
/// - `0` if the amount is zero
/// - `1` if the amount is positive
/// - `-1` if the amount is negative
pub fn signum(self) -> i64 {
self.0.signum()
}
pub fn signum(self) -> i64 { self.0.signum() }
/// Returns `true` if this [SignedAmount] is positive and `false` if
/// this [SignedAmount] is zero or negative.
pub fn is_positive(self) -> bool {
self.0.is_positive()
}
pub fn is_positive(self) -> bool { self.0.is_positive() }
/// Returns `true` if this [SignedAmount] is negative and `false` if
/// this [SignedAmount] is zero or positive.
pub fn is_negative(self) -> bool {
self.0.is_negative()
}
pub fn is_negative(self) -> bool { self.0.is_negative() }
/// Get the absolute value of this [SignedAmount].
/// Returns [None] if overflow occurred. (`self == min_value()`)
pub fn checked_abs(self) -> Option<SignedAmount> {
self.0.checked_abs().map(SignedAmount)
}
pub fn checked_abs(self) -> Option<SignedAmount> { self.0.checked_abs().map(SignedAmount) }
/// Checked addition.
/// Returns [None] if overflow occurred.
@ -1087,9 +1031,7 @@ impl SignedAmount {
}
impl default::Default for SignedAmount {
fn default() -> Self {
SignedAmount::ZERO
}
fn default() -> Self { SignedAmount::ZERO }
}
impl fmt::Debug for SignedAmount {
@ -1116,9 +1058,7 @@ impl ops::Add for SignedAmount {
}
impl ops::AddAssign for SignedAmount {
fn add_assign(&mut self, other: SignedAmount) {
*self = *self + other
}
fn add_assign(&mut self, other: SignedAmount) { *self = *self + other }
}
impl ops::Sub for SignedAmount {
@ -1130,9 +1070,7 @@ impl ops::Sub for SignedAmount {
}
impl ops::SubAssign for SignedAmount {
fn sub_assign(&mut self, other: SignedAmount) {
*self = *self - other
}
fn sub_assign(&mut self, other: SignedAmount) { *self = *self - other }
}
impl ops::Rem<i64> for SignedAmount {
@ -1144,9 +1082,7 @@ impl ops::Rem<i64> for SignedAmount {
}
impl ops::RemAssign<i64> for SignedAmount {
fn rem_assign(&mut self, modulus: i64) {
*self = *self % modulus
}
fn rem_assign(&mut self, modulus: i64) { *self = *self % modulus }
}
impl ops::Mul<i64> for SignedAmount {
@ -1158,9 +1094,7 @@ impl ops::Mul<i64> for SignedAmount {
}
impl ops::MulAssign<i64> for SignedAmount {
fn mul_assign(&mut self, rhs: i64) {
*self = *self * rhs
}
fn mul_assign(&mut self, rhs: i64) { *self = *self * rhs }
}
impl ops::Div<i64> for SignedAmount {
@ -1172,17 +1106,13 @@ impl ops::Div<i64> for SignedAmount {
}
impl ops::DivAssign<i64> for SignedAmount {
fn div_assign(&mut self, rhs: i64) {
*self = *self / rhs
}
fn div_assign(&mut self, rhs: i64) { *self = *self / rhs }
}
impl FromStr for SignedAmount {
type Err = ParseAmountError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
SignedAmount::from_str_with_denomination(s)
}
fn from_str(s: &str) -> Result<Self, Self::Err> { SignedAmount::from_str_with_denomination(s) }
}
impl core::iter::Sum for SignedAmount {
@ -1199,18 +1129,21 @@ pub trait CheckedSum<R>: private::SumSeal<R> {
fn checked_sum(self) -> Option<R>;
}
impl<T> CheckedSum<Amount> for T where T: Iterator<Item=Amount> {
impl<T> CheckedSum<Amount> for T
where
T: Iterator<Item = Amount>,
{
fn checked_sum(mut self) -> Option<Amount> {
let first = Some(self.next().unwrap_or_default());
self.fold(
first,
|acc, item| acc.and_then(|acc| acc.checked_add(item))
)
self.fold(first, |acc, item| acc.and_then(|acc| acc.checked_add(item)))
}
}
impl<T> CheckedSum<SignedAmount> for T where T: Iterator<Item=SignedAmount> {
impl<T> CheckedSum<SignedAmount> for T
where
T: Iterator<Item = SignedAmount>,
{
fn checked_sum(mut self) -> Option<SignedAmount> {
let first = Some(self.next().unwrap_or_default());
@ -1224,8 +1157,8 @@ mod private {
/// Used to seal the `CheckedSum` trait
pub trait SumSeal<A> {}
impl<T> SumSeal<Amount> for T where T: Iterator<Item=Amount> {}
impl<T> SumSeal<SignedAmount> for T where T: Iterator<Item=SignedAmount> {}
impl<T> SumSeal<Amount> for T where T: Iterator<Item = Amount> {}
impl<T> SumSeal<SignedAmount> for T where T: Iterator<Item = SignedAmount> {}
}
#[cfg(feature = "serde")]
@ -1252,6 +1185,7 @@ pub mod serde {
//! ```
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::amount::{Amount, Denomination, SignedAmount};
/// This trait is used only to avoid code duplication and naming collisions
@ -1295,9 +1229,7 @@ pub mod serde {
}
impl SerdeAmountForOpt for Amount {
fn type_prefix() -> &'static str {
"u"
}
fn type_prefix() -> &'static str { "u" }
fn ser_sat_opt<S: Serializer>(self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_some(&self.to_sat())
}
@ -1323,9 +1255,7 @@ pub mod serde {
}
impl SerdeAmountForOpt for SignedAmount {
fn type_prefix() -> &'static str {
"i"
}
fn type_prefix() -> &'static str { "i" }
fn ser_sat_opt<S: Serializer>(self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_some(&self.to_sat())
}
@ -1339,6 +1269,7 @@ pub mod serde {
//! Use with `#[serde(with = "amount::serde::as_sat")]`.
use serde::{Deserializer, Serializer};
use crate::amount::serde::SerdeAmount;
pub fn serialize<A: SerdeAmount, S: Serializer>(a: &A, s: S) -> Result<S::Ok, S::Error> {
@ -1353,11 +1284,13 @@ pub mod serde {
//! Serialize and deserialize [`Option<Amount>`](crate::Amount) as real numbers denominated in satoshi.
//! Use with `#[serde(default, with = "amount::serde::as_sat::opt")]`.
use serde::{Deserializer, Serializer, de};
use crate::amount::serde::SerdeAmountForOpt;
use core::fmt;
use core::marker::PhantomData;
use serde::{de, Deserializer, Serializer};
use crate::amount::serde::SerdeAmountForOpt;
pub fn serialize<A: SerdeAmountForOpt, S: Serializer>(
a: &Option<A>,
s: S,
@ -1403,6 +1336,7 @@ pub mod serde {
//! Use with `#[serde(with = "amount::serde::as_btc")]`.
use serde::{Deserializer, Serializer};
use crate::amount::serde::SerdeAmount;
pub fn serialize<A: SerdeAmount, S: Serializer>(a: &A, s: S) -> Result<S::Ok, S::Error> {
@ -1417,11 +1351,13 @@ pub mod serde {
//! Serialize and deserialize [Option<Amount>] as JSON numbers denominated in BTC.
//! Use with `#[serde(default, with = "amount::serde::as_btc::opt")]`.
use serde::{Deserializer, Serializer, de};
use crate::amount::serde::SerdeAmountForOpt;
use core::fmt;
use core::marker::PhantomData;
use serde::{de, Deserializer, Serializer};
use crate::amount::serde::SerdeAmountForOpt;
pub fn serialize<A: SerdeAmountForOpt, S: Serializer>(
a: &Option<A>,
s: S,
@ -1465,14 +1401,15 @@ pub mod serde {
#[cfg(test)]
mod tests {
use super::*;
use core::str::FromStr;
#[cfg(feature = "std")]
use std::panic;
use core::str::FromStr;
#[cfg(feature = "serde")]
use serde_test;
use super::*;
#[test]
fn add_sub_mul_div() {
let sat = Amount::from_sat;
@ -1613,13 +1550,22 @@ mod tests {
// make sure satoshi > i64::max_value() is checked.
let amount = Amount::from_sat(i64::max_value() as u64);
assert_eq!(Amount::from_str_in(&amount.to_string_in(sat), sat), Ok(amount));
assert_eq!(Amount::from_str_in(&(amount+Amount(1)).to_string_in(sat), sat), Err(E::TooBig));
assert_eq!(
Amount::from_str_in(&(amount + Amount(1)).to_string_in(sat), sat),
Err(E::TooBig)
);
assert_eq!(p("12.000", Denomination::MilliSatoshi), Err(E::TooPrecise));
// exactly 50 chars.
assert_eq!(p("100000000000000.0000000000000000000000000000000000", Denomination::Bitcoin), Err(E::TooBig));
assert_eq!(
p("100000000000000.0000000000000000000000000000000000", Denomination::Bitcoin),
Err(E::TooBig)
);
// more than 50 chars.
assert_eq!(p("100000000000000.00000000000000000000000000000000000", Denomination::Bitcoin), Err(E::InputTooLarge));
assert_eq!(
p("100000000000000.00000000000000000000000000000000000", Denomination::Bitcoin),
Err(E::InputTooLarge)
);
}
#[test]
@ -1834,9 +1780,9 @@ mod tests {
let ua = Amount::from_sat;
assert_eq!(Amount::max_value().to_signed(), Err(E::TooBig));
assert_eq!(ua(i64::max_value() as u64).to_signed(), Ok(sa(i64::max_value())));
assert_eq!(ua(i64::max_value() as u64).to_signed(), Ok(sa(i64::max_value())));
assert_eq!(ua(0).to_signed(), Ok(sa(0)));
assert_eq!(ua(1).to_signed(), Ok( sa(1)));
assert_eq!(ua(1).to_signed(), Ok(sa(1)));
assert_eq!(ua(1).to_signed(), Ok(sa(1)));
assert_eq!(ua(i64::max_value() as u64 + 1).to_signed(), Err(E::TooBig));
@ -1845,7 +1791,10 @@ mod tests {
assert_eq!(sa(0).to_unsigned().unwrap().to_signed(), Ok(sa(0)));
assert_eq!(sa(1).to_unsigned().unwrap().to_signed(), Ok(sa(1)));
assert_eq!(sa(i64::max_value()).to_unsigned().unwrap().to_signed(), Ok(sa(i64::max_value())));
assert_eq!(
sa(i64::max_value()).to_unsigned().unwrap().to_signed(),
Ok(sa(i64::max_value()))
);
}
#[test]
@ -1907,34 +1856,73 @@ mod tests {
assert_eq!("2535830000", Amount::from_sat(253583).to_string_in(D::PicoBitcoin));
assert_eq!("-100000000", SignedAmount::from_sat(-10_000).to_string_in(D::PicoBitcoin));
assert_eq!("0.50", format!("{:.2}", Amount::from_sat(50).display_in(D::Bit)));
assert_eq!("-0.50", format!("{:.2}", SignedAmount::from_sat(-50).display_in(D::Bit)));
assert_eq!("0.10000000", format!("{:.8}", Amount::from_sat(100_000_00).display_in(D::Bitcoin)));
assert_eq!(
"0.10000000",
format!("{:.8}", Amount::from_sat(100_000_00).display_in(D::Bitcoin))
);
assert_eq!("-100.00", format!("{:.2}", SignedAmount::from_sat(-10_000).display_in(D::Bit)));
assert_eq!(ua_str(&ua_sat(0).to_string_in(D::Satoshi), D::Satoshi), Ok(ua_sat(0)));
assert_eq!(ua_str(&ua_sat(500).to_string_in(D::Bitcoin), D::Bitcoin), Ok(ua_sat(500)));
assert_eq!(ua_str(&ua_sat(21_000_000).to_string_in(D::Bit), D::Bit), Ok(ua_sat(21_000_000)));
assert_eq!(ua_str(&ua_sat(1).to_string_in(D::MicroBitcoin), D::MicroBitcoin), Ok(ua_sat(1)));
assert_eq!(ua_str(&ua_sat(1_000_000_000_000).to_string_in(D::MilliBitcoin), D::MilliBitcoin), Ok(ua_sat(1_000_000_000_000)));
assert_eq!(ua_str(&ua_sat(u64::max_value()).to_string_in(D::MilliBitcoin), D::MilliBitcoin), Err(ParseAmountError::TooBig));
assert_eq!(
ua_str(&ua_sat(21_000_000).to_string_in(D::Bit), D::Bit),
Ok(ua_sat(21_000_000))
);
assert_eq!(
ua_str(&ua_sat(1).to_string_in(D::MicroBitcoin), D::MicroBitcoin),
Ok(ua_sat(1))
);
assert_eq!(
ua_str(&ua_sat(1_000_000_000_000).to_string_in(D::MilliBitcoin), D::MilliBitcoin),
Ok(ua_sat(1_000_000_000_000))
);
assert_eq!(
ua_str(&ua_sat(u64::max_value()).to_string_in(D::MilliBitcoin), D::MilliBitcoin),
Err(ParseAmountError::TooBig)
);
assert_eq!(sa_str(&sa_sat(-1).to_string_in(D::MicroBitcoin), D::MicroBitcoin), Ok(sa_sat(-1)));
assert_eq!(
sa_str(&sa_sat(-1).to_string_in(D::MicroBitcoin), D::MicroBitcoin),
Ok(sa_sat(-1))
);
assert_eq!(sa_str(&sa_sat(i64::max_value()).to_string_in(D::Satoshi), D::MicroBitcoin), Err(ParseAmountError::TooBig));
assert_eq!(
sa_str(&sa_sat(i64::max_value()).to_string_in(D::Satoshi), D::MicroBitcoin),
Err(ParseAmountError::TooBig)
);
// Test an overflow bug in `abs()`
assert_eq!(sa_str(&sa_sat(i64::min_value()).to_string_in(D::Satoshi), D::MicroBitcoin), Err(ParseAmountError::TooBig));
assert_eq!(sa_str(&sa_sat(-1).to_string_in(D::NanoBitcoin), D::NanoBitcoin), Ok(sa_sat(-1)));
assert_eq!(sa_str(&sa_sat(i64::max_value()).to_string_in(D::Satoshi), D::NanoBitcoin), Err(ParseAmountError::TooPrecise));
assert_eq!(sa_str(&sa_sat(i64::min_value()).to_string_in(D::Satoshi), D::NanoBitcoin), Err(ParseAmountError::TooPrecise));
assert_eq!(sa_str(&sa_sat(-1).to_string_in(D::PicoBitcoin), D::PicoBitcoin), Ok(sa_sat(-1)));
assert_eq!(sa_str(&sa_sat(i64::max_value()).to_string_in(D::Satoshi), D::PicoBitcoin), Err(ParseAmountError::TooPrecise));
assert_eq!(sa_str(&sa_sat(i64::min_value()).to_string_in(D::Satoshi), D::PicoBitcoin), Err(ParseAmountError::TooPrecise));
assert_eq!(
sa_str(&sa_sat(i64::min_value()).to_string_in(D::Satoshi), D::MicroBitcoin),
Err(ParseAmountError::TooBig)
);
assert_eq!(
sa_str(&sa_sat(-1).to_string_in(D::NanoBitcoin), D::NanoBitcoin),
Ok(sa_sat(-1))
);
assert_eq!(
sa_str(&sa_sat(i64::max_value()).to_string_in(D::Satoshi), D::NanoBitcoin),
Err(ParseAmountError::TooPrecise)
);
assert_eq!(
sa_str(&sa_sat(i64::min_value()).to_string_in(D::Satoshi), D::NanoBitcoin),
Err(ParseAmountError::TooPrecise)
);
assert_eq!(
sa_str(&sa_sat(-1).to_string_in(D::PicoBitcoin), D::PicoBitcoin),
Ok(sa_sat(-1))
);
assert_eq!(
sa_str(&sa_sat(i64::max_value()).to_string_in(D::Satoshi), D::PicoBitcoin),
Err(ParseAmountError::TooPrecise)
);
assert_eq!(
sa_str(&sa_sat(i64::min_value()).to_string_in(D::Satoshi), D::PicoBitcoin),
Err(ParseAmountError::TooPrecise)
);
}
#[test]
@ -1958,7 +1946,6 @@ mod tests {
#[cfg(feature = "serde")]
#[test]
fn serde_as_sat() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(crate = "actual_serde")]
struct T {
@ -1969,10 +1956,7 @@ mod tests {
}
serde_test::assert_tokens(
&T {
amt: Amount::from_sat(123456789),
samt: SignedAmount::from_sat(-123456789),
},
&T { amt: Amount::from_sat(123456789), samt: SignedAmount::from_sat(-123456789) },
&[
serde_test::Token::Struct { name: "T", len: 2 },
serde_test::Token::Str("amt"),
@ -2039,15 +2023,12 @@ mod tests {
amt: Some(Amount::from_sat(2_500_000_00)),
samt: Some(SignedAmount::from_sat(-2_500_000_00)),
};
let without = T {
amt: None,
samt: None,
};
let without = T { amt: None, samt: None };
// Test Roundtripping
for s in [&with, &without].iter() {
let v = serde_json::to_string(s).unwrap();
let w : T = serde_json::from_str(&v).unwrap();
let w: T = serde_json::from_str(&v).unwrap();
assert_eq!(w, **s);
}
@ -2084,15 +2065,12 @@ mod tests {
amt: Some(Amount::from_sat(2_500_000_00)),
samt: Some(SignedAmount::from_sat(-2_500_000_00)),
};
let without = T {
amt: None,
samt: None,
};
let without = T { amt: None, samt: None };
// Test Roundtripping
for s in [&with, &without].iter() {
let v = serde_json::to_string(s).unwrap();
let w : T = serde_json::from_str(&v).unwrap();
let w: T = serde_json::from_str(&v).unwrap();
assert_eq!(w, **s);
}
@ -2115,18 +2093,14 @@ mod tests {
assert_eq!(Amount::from_sat(0), vec![].into_iter().sum::<Amount>());
assert_eq!(SignedAmount::from_sat(0), vec![].into_iter().sum::<SignedAmount>());
let amounts = vec![
Amount::from_sat(42),
Amount::from_sat(1337),
Amount::from_sat(21)
];
let amounts = vec![Amount::from_sat(42), Amount::from_sat(1337), Amount::from_sat(21)];
let sum = amounts.into_iter().sum::<Amount>();
assert_eq!(Amount::from_sat(1400), sum);
let amounts = vec![
SignedAmount::from_sat(-42),
SignedAmount::from_sat(1337),
SignedAmount::from_sat(21)
SignedAmount::from_sat(21),
];
let sum = amounts.into_iter().sum::<SignedAmount>();
assert_eq!(SignedAmount::from_sat(1316), sum);
@ -2137,26 +2111,19 @@ mod tests {
assert_eq!(Some(Amount::from_sat(0)), vec![].into_iter().checked_sum());
assert_eq!(Some(SignedAmount::from_sat(0)), vec![].into_iter().checked_sum());
let amounts = vec![
Amount::from_sat(42),
Amount::from_sat(1337),
Amount::from_sat(21)
];
let amounts = vec![Amount::from_sat(42), Amount::from_sat(1337), Amount::from_sat(21)];
let sum = amounts.into_iter().checked_sum();
assert_eq!(Some(Amount::from_sat(1400)), sum);
let amounts = vec![
Amount::from_sat(u64::max_value()),
Amount::from_sat(1337),
Amount::from_sat(21)
];
let amounts =
vec![Amount::from_sat(u64::max_value()), Amount::from_sat(1337), Amount::from_sat(21)];
let sum = amounts.into_iter().checked_sum();
assert_eq!(None, sum);
let amounts = vec![
SignedAmount::from_sat(i64::min_value()),
SignedAmount::from_sat(-1),
SignedAmount::from_sat(21)
SignedAmount::from_sat(21),
];
let sum = amounts.into_iter().checked_sum();
assert_eq!(None, sum);
@ -2164,7 +2131,7 @@ mod tests {
let amounts = vec![
SignedAmount::from_sat(i64::max_value()),
SignedAmount::from_sat(1),
SignedAmount::from_sat(21)
SignedAmount::from_sat(21),
];
let sum = amounts.into_iter().checked_sum();
assert_eq!(None, sum);
@ -2172,7 +2139,7 @@ mod tests {
let amounts = vec![
SignedAmount::from_sat(42),
SignedAmount::from_sat(3301),
SignedAmount::from_sat(21)
SignedAmount::from_sat(21),
];
let sum = amounts.into_iter().checked_sum();
assert_eq!(Some(SignedAmount::from_sat(3364)), sum);
@ -2181,7 +2148,10 @@ mod tests {
#[test]
fn denomination_string_acceptable_forms() {
// Non-exhaustive list of valid forms.
let valid = vec!["BTC", "btc", "mBTC", "mbtc", "uBTC", "ubtc", "SATOSHI","Satoshi", "Satoshis", "satoshis", "SAT", "Sat", "sats", "bit", "bits", "nBTC", "pBTC"];
let valid = vec![
"BTC", "btc", "mBTC", "mbtc", "uBTC", "ubtc", "SATOSHI", "Satoshi", "Satoshis",
"satoshis", "SAT", "Sat", "sats", "bit", "bits", "nBTC", "pBTC",
];
for denom in valid.iter() {
assert!(Denomination::from_str(denom).is_ok());
}
@ -2190,11 +2160,12 @@ mod tests {
#[test]
fn disallow_confusing_forms() {
// Non-exhaustive list of confusing forms.
let confusing = vec!["Msat", "Msats", "MSAT", "MSATS", "MSat", "MSats", "MBTC", "Mbtc", "PBTC"];
let confusing =
vec!["Msat", "Msats", "MSAT", "MSATS", "MSat", "MSats", "MBTC", "Mbtc", "PBTC"];
for denom in confusing.iter() {
match Denomination::from_str(denom) {
match Denomination::from_str(denom) {
Ok(_) => panic!("from_str should error for {}", denom),
Err(ParseAmountError::PossiblyConfusingDenomination(_)) => {},
Err(ParseAmountError::PossiblyConfusingDenomination(_)) => {}
Err(e) => panic!("unexpected error: {}", e),
}
}
@ -2205,9 +2176,9 @@ mod tests {
// Non-exhaustive list of unknown forms.
let unknown = vec!["NBTC", "UBTC", "ABC", "abc"];
for denom in unknown.iter() {
match Denomination::from_str(denom) {
match Denomination::from_str(denom) {
Ok(_) => panic!("from_str should error for {}", denom),
Err(ParseAmountError::UnknownDenomination(_)) => {},
Err(ParseAmountError::UnknownDenomination(_)) => {}
Err(e) => panic!("unexpected error: {}", e),
}
}

View File

@ -16,7 +16,7 @@ use crate::consensus::encode::{self, Decodable, Encodable, VarInt};
use crate::hashes::{sha256, siphash24, Hash};
use crate::internal_macros::{impl_bytes_newtype, impl_consensus_encoding};
use crate::prelude::*;
use crate::{io, block, Block, BlockHash, Transaction};
use crate::{block, io, Block, BlockHash, Transaction};
/// A BIP-152 error
#[derive(Clone, PartialEq, Eq, Debug, Copy, PartialOrd, Ord, Hash)]
@ -111,7 +111,10 @@ impl ShortId {
// 2. Running SipHash-2-4 with the input being the transaction ID and the keys (k0/k1)
// set to the first two little-endian 64-bit integers from the above hash, respectively.
(u64::from_le_bytes(h[0..8].try_into().expect("8 byte slice")), u64::from_le_bytes(h[8..16].try_into().expect("8 byte slice")))
(
u64::from_le_bytes(h[0..8].try_into().expect("8 byte slice")),
u64::from_le_bytes(h[8..16].try_into().expect("8 byte slice")),
)
}
/// Calculate the short ID with the given (w)txid and using the provided SipHash keys.
@ -374,8 +377,8 @@ mod test {
use crate::consensus::encode::{deserialize, serialize};
use crate::hashes::hex::FromHex;
use crate::{
CompactTarget, OutPoint, Script, Sequence,
Transaction, TxIn, TxMerkleNode, TxOut, Txid, Witness,
CompactTarget, OutPoint, Script, Sequence, Transaction, TxIn, TxMerkleNode, TxOut, Txid,
Witness,
};
fn dummy_tx(nonce: &[u8]) -> Transaction {

View File

@ -114,6 +114,7 @@ use std::io;
use core2::io;
pub use crate::address::{Address, AddressType};
pub use crate::amount::{Amount, Denomination, SignedAmount};
pub use crate::blockdata::block::{self, Block};
pub use crate::blockdata::locktime::{self, absolute, relative};
pub use crate::blockdata::script::{self, Script};
@ -123,12 +124,11 @@ pub use crate::blockdata::{constants, opcodes};
pub use crate::consensus::encode::VarInt;
pub use crate::error::Error;
pub use crate::hash_types::*;
pub use crate::merkle_tree::MerkleBlock;
pub use crate::network::constants::Network;
pub use crate::pow::{CompactTarget, Target, Work};
pub use crate::amount::{Amount, Denomination, SignedAmount};
pub use crate::util::ecdsa::{self, EcdsaSig, EcdsaSigError};
pub use crate::util::key::{KeyPair, PrivateKey, PublicKey, XOnlyPublicKey};
pub use crate::merkle_tree::MerkleBlock;
pub use crate::util::schnorr::{self, SchnorrSig, SchnorrSigError};
#[cfg(not(feature = "std"))]

View File

@ -8,18 +8,18 @@
//! and legacy (before Bip143).
//!
use core::{str, fmt};
use core::borrow::Borrow;
use core::ops::{Deref, DerefMut};
use core::{fmt, str};
use crate::{io, Script, Transaction, TxIn, TxOut, Sequence, Sighash};
use crate::blockdata::transaction::EncodeSigningDataResult;
use crate::blockdata::witness::Witness;
use crate::consensus::{encode, Encodable};
use crate::error::impl_std_error;
use crate::hashes::{sha256, sha256d, Hash};
use crate::prelude::*;
use crate::util::taproot::{TapLeafHash, TAPROOT_ANNEX_PREFIX, TapSighashHash, LeafVersion};
use crate::util::taproot::{LeafVersion, TapLeafHash, TapSighashHash, TAPROOT_ANNEX_PREFIX};
use crate::{io, Script, Sequence, Sighash, Transaction, TxIn, TxOut};
/// Used for signature hash for invalid use of SIGHASH_SINGLE.
#[rustfmt::skip]
@ -32,7 +32,7 @@ pub(crate) const UINT256_ONE: [u8; 32] = [
/// Efficiently calculates signature hash message for legacy, segwit and taproot inputs.
#[derive(Debug)]
pub struct SighashCache<T: Deref<Target=Transaction>> {
pub struct SighashCache<T: Deref<Target = Transaction>> {
/// Access to transaction required for transaction introspection. Moreover, type
/// `T: Deref<Target=Transaction>` allows us to use borrowed and mutable borrowed types,
/// the latter in particular is necessary for [`SighashCache::witness_mut`].
@ -77,7 +77,10 @@ struct TaprootCache {
/// Contains outputs of previous transactions. In the case [`SchnorrSighashType`] variant is
/// `SIGHASH_ANYONECANPAY`, [`Prevouts::One`] may be used.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Prevouts<'u, T> where T: 'u + Borrow<TxOut> {
pub enum Prevouts<'u, T>
where
T: 'u + Borrow<TxOut>,
{
/// `One` variant allows provision of the single prevout needed. It's useful, for example, when
/// modifier `SIGHASH_ANYONECANPAY` is provided, only prevout of the current input is needed.
/// The first `usize` argument is the input index this [`TxOut`] is referring to.
@ -150,7 +153,7 @@ impl str::FromStr for SchnorrSighashType {
"SIGHASH_ALL|SIGHASH_ANYONECANPAY" => Ok(SchnorrSighashType::AllPlusAnyoneCanPay),
"SIGHASH_NONE|SIGHASH_ANYONECANPAY" => Ok(SchnorrSighashType::NonePlusAnyoneCanPay),
"SIGHASH_SINGLE|SIGHASH_ANYONECANPAY" => Ok(SchnorrSighashType::SinglePlusAnyoneCanPay),
_ => Err(SighashTypeParseError{ unrecognized: s.to_owned() }),
_ => Err(SighashTypeParseError { unrecognized: s.to_owned() }),
}
}
}
@ -233,7 +236,10 @@ impl std::error::Error for Error {
}
}
impl<'u, T> Prevouts<'u, T> where T: Borrow<TxOut> {
impl<'u, T> Prevouts<'u, T>
where
T: Borrow<TxOut>,
{
fn check_all(&self, tx: &Transaction) -> Result<(), Error> {
if let Prevouts::All(prevouts) = self {
if prevouts.len() != tx.input.len() {
@ -252,17 +258,14 @@ impl<'u, T> Prevouts<'u, T> where T: Borrow<TxOut> {
fn get(&self, input_index: usize) -> Result<&TxOut, Error> {
match self {
Prevouts::One(index, prevout) => {
Prevouts::One(index, prevout) =>
if input_index == *index {
Ok(prevout.borrow())
} else {
Err(Error::PrevoutIndex)
}
}
Prevouts::All(prevouts) => prevouts
.get(input_index)
.map(|x| x.borrow())
.ok_or(Error::PrevoutIndex),
},
Prevouts::All(prevouts) =>
prevouts.get(input_index).map(|x| x.borrow()).ok_or(Error::PrevoutIndex),
}
}
}
@ -270,20 +273,18 @@ impl<'u, T> Prevouts<'u, T> where T: Borrow<TxOut> {
impl<'s> ScriptPath<'s> {
/// Creates a new `ScriptPath` structure.
pub fn new(script: &'s Script, leaf_version: LeafVersion) -> Self {
ScriptPath {
script,
leaf_version,
}
ScriptPath { script, leaf_version }
}
/// Creates a new `ScriptPath` structure using default leaf version value.
pub fn with_defaults(script: &'s Script) -> Self {
Self::new(script, LeafVersion::TapScript)
}
pub fn with_defaults(script: &'s Script) -> Self { Self::new(script, LeafVersion::TapScript) }
/// Computes the leaf hash for this `ScriptPath`.
pub fn leaf_hash(&self) -> TapLeafHash {
let mut enc = TapLeafHash::engine();
self.leaf_version.to_consensus().consensus_encode(&mut enc).expect("Writing to hash enging should never fail");
self.leaf_version
.to_consensus()
.consensus_encode(&mut enc)
.expect("Writing to hash enging should never fail");
self.script.consensus_encode(&mut enc).expect("Writing to hash enging should never fail");
TapLeafHash::from_engine(enc)
@ -291,9 +292,7 @@ impl<'s> ScriptPath<'s> {
}
impl<'s> From<ScriptPath<'s>> for TapLeafHash {
fn from(script_path: ScriptPath<'s>) -> TapLeafHash {
script_path.leaf_hash()
}
fn from(script_path: ScriptPath<'s>) -> TapLeafHash { script_path.leaf_hash() }
}
/// Hashtype of an input's signature, encoded in the last byte of the signature.
@ -303,20 +302,20 @@ impl<'s> From<ScriptPath<'s>> for TapLeafHash {
#[derive(PartialEq, Eq, Debug, Copy, Clone, Hash)]
pub enum EcdsaSighashType {
/// 0x1: Sign all outputs.
All = 0x01,
All = 0x01,
/// 0x2: Sign no outputs --- anyone can choose the destination.
None = 0x02,
None = 0x02,
/// 0x3: Sign the output whose index matches this input's index. If none exists,
/// sign the hash `0000000000000000000000000000000000000000000000000000000000000001`.
/// (This rule is probably an unintentional C++ism, but it's consensus so we have
/// to follow it.)
Single = 0x03,
Single = 0x03,
/// 0x81: Sign all outputs but only this input.
AllPlusAnyoneCanPay = 0x81,
AllPlusAnyoneCanPay = 0x81,
/// 0x82: Sign no outputs and only this input.
NonePlusAnyoneCanPay = 0x82,
NonePlusAnyoneCanPay = 0x82,
/// 0x83: Sign one output and only this input (see `Single` for what "one output" means).
SinglePlusAnyoneCanPay = 0x83
SinglePlusAnyoneCanPay = 0x83,
}
#[cfg(feature = "serde")]
crate::serde_utils::serde_string_impl!(EcdsaSighashType, "a EcdsaSighashType data");
@ -360,7 +359,7 @@ impl EcdsaSighashType {
EcdsaSighashType::Single => (EcdsaSighashType::Single, false),
EcdsaSighashType::AllPlusAnyoneCanPay => (EcdsaSighashType::All, true),
EcdsaSighashType::NonePlusAnyoneCanPay => (EcdsaSighashType::None, true),
EcdsaSighashType::SinglePlusAnyoneCanPay => (EcdsaSighashType::Single, true)
EcdsaSighashType::SinglePlusAnyoneCanPay => (EcdsaSighashType::Single, true),
}
}
@ -389,7 +388,7 @@ impl EcdsaSighashType {
0x83 => EcdsaSighashType::SinglePlusAnyoneCanPay,
// catchalls
x if x & 0x80 == 0x80 => EcdsaSighashType::AllPlusAnyoneCanPay,
_ => EcdsaSighashType::All
_ => EcdsaSighashType::All,
}
}
@ -407,7 +406,7 @@ impl EcdsaSighashType {
0x81 => Ok(EcdsaSighashType::AllPlusAnyoneCanPay),
0x82 => Ok(EcdsaSighashType::NonePlusAnyoneCanPay),
0x83 => Ok(EcdsaSighashType::SinglePlusAnyoneCanPay),
non_standard => Err(NonStandardSighashType(non_standard))
non_standard => Err(NonStandardSighashType(non_standard)),
}
}
@ -446,7 +445,7 @@ impl SchnorrSighashType {
/// Constructs a [`SchnorrSighashType`] from a raw `u8`.
pub fn from_consensus_u8(hash_ty: u8) -> Result<Self, Error> {
use SchnorrSighashType::*;
use SchnorrSighashType::*;
Ok(match hash_ty {
0x00 => Default,
@ -498,12 +497,7 @@ impl<R: Deref<Target = Transaction>> SighashCache<R> {
/// sighashes to be valid, no fields in the transaction may change except for script_sig and
/// witness.
pub fn new(tx: R) -> Self {
SighashCache {
tx,
common_cache: None,
taproot_cache: None,
segwit_cache: None,
}
SighashCache { tx, common_cache: None, taproot_cache: None, segwit_cache: None }
}
/// Encodes the BIP341 signing data for any flag type into a given object implementing a
@ -542,15 +536,9 @@ impl<R: Deref<Target = Transaction>> SighashCache<R> {
// sha_sequences (32): the SHA256 of the serialization of all input nSequence.
if !anyone_can_pay {
self.common_cache().prevouts.consensus_encode(&mut writer)?;
self.taproot_cache(prevouts.get_all()?)
.amounts
.consensus_encode(&mut writer)?;
self.taproot_cache(prevouts.get_all()?)
.script_pubkeys
.consensus_encode(&mut writer)?;
self.common_cache()
.sequences
.consensus_encode(&mut writer)?;
self.taproot_cache(prevouts.get_all()?).amounts.consensus_encode(&mut writer)?;
self.taproot_cache(prevouts.get_all()?).script_pubkeys.consensus_encode(&mut writer)?;
self.common_cache().sequences.consensus_encode(&mut writer)?;
}
// If hash_type & 3 does not equal SIGHASH_NONE or SIGHASH_SINGLE:
@ -577,21 +565,14 @@ impl<R: Deref<Target = Transaction>> SighashCache<R> {
// scriptPubKey (35): scriptPubKey of the previous output spent by this input, serialized as script inside CTxOut. Its size is always 35 bytes.
// nSequence (4): nSequence of this input.
if anyone_can_pay {
let txin =
&self
.tx
.input
.get(input_index)
.ok_or(Error::IndexOutOfInputsBounds {
index: input_index,
inputs_size: self.tx.input.len(),
})?;
let txin = &self.tx.input.get(input_index).ok_or(Error::IndexOutOfInputsBounds {
index: input_index,
inputs_size: self.tx.input.len(),
})?;
let previous_output = prevouts.get(input_index)?;
txin.previous_output.consensus_encode(&mut writer)?;
previous_output.value.consensus_encode(&mut writer)?;
previous_output
.script_pubkey
.consensus_encode(&mut writer)?;
previous_output.script_pubkey.consensus_encode(&mut writer)?;
txin.sequence.consensus_encode(&mut writer)?;
} else {
(input_index as u32).consensus_encode(&mut writer)?;
@ -726,23 +707,16 @@ impl<R: Deref<Target = Transaction>> SighashCache<R> {
&& sighash != EcdsaSighashType::Single
&& sighash != EcdsaSighashType::None
{
self.segwit_cache()
.sequences
.consensus_encode(&mut writer)?;
self.segwit_cache().sequences.consensus_encode(&mut writer)?;
} else {
zero_hash.consensus_encode(&mut writer)?;
}
{
let txin =
&self
.tx
.input
.get(input_index)
.ok_or(Error::IndexOutOfInputsBounds {
index: input_index,
inputs_size: self.tx.input.len(),
})?;
let txin = &self.tx.input.get(input_index).ok_or(Error::IndexOutOfInputsBounds {
index: input_index,
inputs_size: self.tx.input.len(),
})?;
txin.previous_output.consensus_encode(&mut writer)?;
script_code.consensus_encode(&mut writer)?;
@ -836,7 +810,8 @@ impl<R: Deref<Target = Transaction>> SighashCache<R> {
script_pubkey: &Script,
sighash_type: u32,
) -> Result<(), io::Error> {
let (sighash, anyone_can_pay) = EcdsaSighashType::from_consensus(sighash_type).split_anyonecanpay_flag();
let (sighash, anyone_can_pay) =
EcdsaSighashType::from_consensus(sighash_type).split_anyonecanpay_flag();
// Build tx to sign
let mut tx = Transaction {
@ -858,8 +833,19 @@ impl<R: Deref<Target = Transaction>> SighashCache<R> {
for (n, input) in self_.input.iter().enumerate() {
tx.input.push(TxIn {
previous_output: input.previous_output,
script_sig: if n == input_index { script_pubkey.clone() } else { Script::new() },
sequence: if n != input_index && (sighash == EcdsaSighashType::Single || sighash == EcdsaSighashType::None) { Sequence::ZERO } else { input.sequence },
script_sig: if n == input_index {
script_pubkey.clone()
} else {
Script::new()
},
sequence: if n != input_index
&& (sighash == EcdsaSighashType::Single
|| sighash == EcdsaSighashType::None)
{
Sequence::ZERO
} else {
input.sequence
},
witness: Witness::default(),
});
}
@ -868,14 +854,24 @@ impl<R: Deref<Target = Transaction>> SighashCache<R> {
tx.output = match sighash {
EcdsaSighashType::All => self_.output.clone(),
EcdsaSighashType::Single => {
let output_iter = self_.output.iter()
.take(input_index + 1) // sign all outputs up to and including this one, but erase
.enumerate() // all of them except for this one
.map(|(n, out)| if n == input_index { out.clone() } else { TxOut::default() });
let output_iter = self_
.output
.iter()
.take(input_index + 1) // sign all outputs up to and including this one, but erase
.enumerate() // all of them except for this one
.map(
|(n, out)| {
if n == input_index {
out.clone()
} else {
TxOut::default()
}
},
);
output_iter.collect()
}
EcdsaSighashType::None => vec![],
_ => unreachable!()
_ => unreachable!(),
};
// hash the result
tx.consensus_encode(&mut writer)?;
@ -889,8 +885,9 @@ impl<R: Deref<Target = Transaction>> SighashCache<R> {
writer,
input_index,
script_pubkey,
sighash_type
).map_err(|e| Error::Io(e.kind()))
sighash_type,
)
.map_err(|e| Error::Io(e.kind())),
)
}
@ -920,8 +917,10 @@ impl<R: Deref<Target = Transaction>> SighashCache<R> {
sighash_type: u32,
) -> Result<Sighash, Error> {
let mut enc = Sighash::engine();
if self.legacy_encode_signing_data_to(&mut enc, input_index, script_pubkey, sighash_type)
.is_sighash_single_bug()? {
if self
.legacy_encode_signing_data_to(&mut enc, input_index, script_pubkey, sighash_type)
.is_sighash_single_bug()?
{
Ok(Sighash::from_inner(UINT256_ONE))
} else {
Ok(Sighash::from_engine(enc))
@ -941,9 +940,7 @@ impl<R: Deref<Target = Transaction>> SighashCache<R> {
let mut enc_prevouts = sha256::Hash::engine();
let mut enc_sequences = sha256::Hash::engine();
for txin in tx.input.iter() {
txin.previous_output
.consensus_encode(&mut enc_prevouts)
.unwrap();
txin.previous_output.consensus_encode(&mut enc_prevouts).unwrap();
txin.sequence.consensus_encode(&mut enc_sequences).unwrap();
}
CommonCache {
@ -979,18 +976,13 @@ impl<R: Deref<Target = Transaction>> SighashCache<R> {
})
}
fn taproot_cache<T: Borrow<TxOut>>(&mut self, prevouts: &[T]) -> &TaprootCache
{
fn taproot_cache<T: Borrow<TxOut>>(&mut self, prevouts: &[T]) -> &TaprootCache {
self.taproot_cache.get_or_insert_with(|| {
let mut enc_amounts = sha256::Hash::engine();
let mut enc_script_pubkeys = sha256::Hash::engine();
for prevout in prevouts {
prevout.borrow().value.consensus_encode(&mut enc_amounts).unwrap();
prevout
.borrow()
.script_pubkey
.consensus_encode(&mut enc_script_pubkeys)
.unwrap();
prevout.borrow().script_pubkey.consensus_encode(&mut enc_script_pubkeys).unwrap();
}
TaprootCache {
amounts: sha256::Hash::from_engine(enc_amounts),
@ -1000,7 +992,7 @@ impl<R: Deref<Target = Transaction>> SighashCache<R> {
}
}
impl<R: DerefMut<Target=Transaction>> SighashCache<R> {
impl<R: DerefMut<Target = Transaction>> SighashCache<R> {
/// When the `SighashCache` is initialized with a mutable reference to a transaction instead of
/// a regular reference, this method is available to allow modification to the witnesses.
///
@ -1026,9 +1018,7 @@ impl<R: DerefMut<Target=Transaction>> SighashCache<R> {
}
impl From<io::Error> for Error {
fn from(e: io::Error) -> Self {
Error::Io(e.kind())
}
fn from(e: io::Error) -> Self { Error::Io(e.kind()) }
}
/// The `Annex` struct is a slice wrapper enforcing first byte is `0x50`.
@ -1046,9 +1036,7 @@ impl<'a> Annex<'a> {
}
/// Returns the Annex bytes data (including first byte `0x50`).
pub fn as_bytes(&self) -> &[u8] {
self.0
}
pub fn as_bytes(&self) -> &[u8] { self.0 }
}
impl<'a> Encodable for Annex<'a> {
@ -1064,23 +1052,22 @@ fn is_invalid_use_of_sighash_single(sighash: u32, input_index: usize, output_len
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr;
use secp256k1::{self, SecretKey, XOnlyPublicKey};
use crate::{Script, Transaction, TxIn, TxOut, Address};
use super::*;
use crate::blockdata::locktime::absolute;
use crate::consensus::deserialize;
use crate::hash_types::Sighash;
use crate::hashes::hex::{FromHex, ToHex};
use crate::hashes::{Hash, HashEngine};
use crate::hash_types::Sighash;
use crate::internal_macros::{hex_into, hex_script, hex_decode, hex_from_slice};
use crate::internal_macros::{hex_decode, hex_from_slice, hex_into, hex_script};
use crate::network::constants::Network;
use crate::util::key::PublicKey;
use crate::sighash::{Annex, Error, Prevouts, ScriptPath, SighashCache};
use crate::util::taproot::{TapTweakHash, TapSighashHash, TapBranchHash, TapLeafHash};
use crate::util::key::PublicKey;
use crate::util::taproot::{TapBranchHash, TapLeafHash, TapSighashHash, TapTweakHash};
use crate::{Address, Script, Transaction, TxIn, TxOut};
extern crate serde_json;
@ -1108,9 +1095,16 @@ mod tests {
#[cfg(feature = "serde")]
fn legacy_sighash() {
use serde_json::Value;
use crate::sighash::SighashCache;
fn run_test_sighash(tx: &str, script: &str, input_index: usize, hash_type: i64, expected_result: &str) {
fn run_test_sighash(
tx: &str,
script: &str,
input_index: usize,
hash_type: i64,
expected_result: &str,
) {
let tx: Transaction = deserialize(&Vec::from_hex(tx).unwrap()[..]).unwrap();
let script = Script::from(Vec::from_hex(script).unwrap());
let mut raw_expected = Vec::from_hex(expected_result).unwrap();
@ -1357,14 +1351,12 @@ mod tests {
None => None,
};
let leaf_hash = match (script_hex, script_leaf_hash) {
let leaf_hash = match (script_hex, script_leaf_hash) {
(Some(script_hex), _) => {
let script_inner = Script::from_hex(script_hex).unwrap();
Some(ScriptPath::with_defaults(&script_inner).leaf_hash())
}
(_, Some(script_leaf_hash)) => {
Some(TapLeafHash::from_hex(script_leaf_hash).unwrap())
}
(_, Some(script_leaf_hash)) => Some(TapLeafHash::from_hex(script_leaf_hash).unwrap()),
_ => None,
};
// All our tests use the default `0xFFFFFFFF` codeseparator value
@ -1389,18 +1381,18 @@ mod tests {
#[test]
fn bip_341_sighash_tests() {
let data = bip_341_read_json();
assert!(data["version"].as_u64().unwrap() == 1u64);
let secp = &secp256k1::Secp256k1::new();
let key_path = &data["keyPathSpending"].as_array().unwrap()[0];
let raw_unsigned_tx = hex_decode!(Transaction, key_path["given"]["rawUnsignedTx"].as_str().unwrap());
let raw_unsigned_tx =
hex_decode!(Transaction, key_path["given"]["rawUnsignedTx"].as_str().unwrap());
let mut utxos = vec![];
for utxo in key_path["given"]["utxosSpent"].as_array().unwrap() {
let spk = hex_script!(utxo["scriptPubKey"].as_str().unwrap());
let amt = utxo["amountSats"].as_u64().unwrap();
utxos.push(TxOut {value: amt, script_pubkey: spk });
utxos.push(TxOut { value: amt, script_pubkey: spk });
}
// Test intermediary
@ -1420,24 +1412,41 @@ mod tests {
for inp in key_path["inputSpending"].as_array().unwrap() {
let tx_ind = inp["given"]["txinIndex"].as_u64().unwrap() as usize;
let internal_priv_key = hex_from_slice!(SecretKey, inp["given"]["internalPrivkey"].as_str().unwrap());
let internal_priv_key =
hex_from_slice!(SecretKey, inp["given"]["internalPrivkey"].as_str().unwrap());
let merkle_root = if inp["given"]["merkleRoot"].is_null() {
None
} else {
Some(hex_into!(TapBranchHash, inp["given"]["merkleRoot"].as_str().unwrap()))
};
let hash_ty = SchnorrSighashType::from_consensus_u8(inp["given"]["hashType"].as_u64().unwrap() as u8).unwrap();
let hash_ty = SchnorrSighashType::from_consensus_u8(
inp["given"]["hashType"].as_u64().unwrap() as u8,
)
.unwrap();
let expected_internal_pk = hex_from_slice!(XOnlyPublicKey, inp["intermediary"]["internalPubkey"].as_str().unwrap());
let expected_tweak = hex_into!(TapTweakHash, inp["intermediary"]["tweak"].as_str().unwrap());
let expected_tweaked_priv_key = hex_from_slice!(SecretKey, inp["intermediary"]["tweakedPrivkey"].as_str().unwrap());
let expected_sig_msg = Vec::<u8>::from_hex(inp["intermediary"]["sigMsg"].as_str().unwrap()).unwrap();
let expected_sighash = hex_into!(TapSighashHash, inp["intermediary"]["sigHash"].as_str().unwrap());
let expected_internal_pk = hex_from_slice!(
XOnlyPublicKey,
inp["intermediary"]["internalPubkey"].as_str().unwrap()
);
let expected_tweak =
hex_into!(TapTweakHash, inp["intermediary"]["tweak"].as_str().unwrap());
let expected_tweaked_priv_key =
hex_from_slice!(SecretKey, inp["intermediary"]["tweakedPrivkey"].as_str().unwrap());
let expected_sig_msg =
Vec::<u8>::from_hex(inp["intermediary"]["sigMsg"].as_str().unwrap()).unwrap();
let expected_sighash =
hex_into!(TapSighashHash, inp["intermediary"]["sigHash"].as_str().unwrap());
let sig_str = inp["expected"]["witness"][0].as_str().unwrap();
let (expected_key_spend_sig, expected_hash_ty) = if sig_str.len() == 128 {
(secp256k1::schnorr::Signature::from_str(sig_str).unwrap(), SchnorrSighashType::Default)
(
secp256k1::schnorr::Signature::from_str(sig_str).unwrap(),
SchnorrSighashType::Default,
)
} else {
let hash_ty = SchnorrSighashType::from_consensus_u8(Vec::<u8>::from_hex(&sig_str[128..]).unwrap()[0]).unwrap();
let hash_ty = SchnorrSighashType::from_consensus_u8(
Vec::<u8>::from_hex(&sig_str[128..]).unwrap()[0],
)
.unwrap();
(secp256k1::schnorr::Signature::from_str(&sig_str[..128]).unwrap(), hash_ty)
};
@ -1447,21 +1456,19 @@ mod tests {
let tweak = TapTweakHash::from_key_and_tweak(internal_key, merkle_root);
let tweaked_keypair = keypair.add_xonly_tweak(secp, &tweak.to_scalar()).unwrap();
let mut sig_msg = Vec::new();
cache.taproot_encode_signing_data_to(
&mut sig_msg,
tx_ind,
&Prevouts::All(&utxos),
None,
None,
hash_ty
).unwrap();
let sighash = cache.taproot_signature_hash(
tx_ind,
&Prevouts::All(&utxos),
None,
None,
hash_ty
).unwrap();
cache
.taproot_encode_signing_data_to(
&mut sig_msg,
tx_ind,
&Prevouts::All(&utxos),
None,
None,
hash_ty,
)
.unwrap();
let sighash = cache
.taproot_signature_hash(tx_ind, &Prevouts::All(&utxos), None, None, hash_ty)
.unwrap();
let msg = secp256k1::Message::from(sighash);
let key_spend_sig = secp.sign_schnorr_with_aux_rand(&msg, &tweaked_keypair, &[0u8; 32]);
@ -1513,7 +1520,10 @@ mod tests {
"SigHash_NONE",
];
for s in sht_mistakes {
assert_eq!(SchnorrSighashType::from_str(s).unwrap_err().to_string(), format!("Unrecognized SIGHASH string '{}'", s));
assert_eq!(
SchnorrSighashType::from_str(s).unwrap_err().to_string(),
format!("Unrecognized SIGHASH string '{}'", s)
);
}
}
@ -1533,25 +1543,32 @@ mod tests {
).unwrap()[..],
).unwrap();
let witness_script = p2pkh_hex("025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357");
let witness_script =
p2pkh_hex("025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357");
let value = 600_000_000;
let mut cache = SighashCache::new(&tx);
assert_eq!(
cache.segwit_signature_hash(1, &witness_script, value, EcdsaSighashType::All).unwrap(),
hex_from_slice!(Sighash, "c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670")
hex_from_slice!(
Sighash,
"c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670"
)
);
let cache = cache.segwit_cache();
assert_eq!(cache.prevouts, hex_from_slice!(
"96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37"
));
assert_eq!(cache.sequences, hex_from_slice!(
"52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b"
));
assert_eq!(cache.outputs, hex_from_slice!(
"863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5"
));
assert_eq!(
cache.prevouts,
hex_from_slice!("96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37")
);
assert_eq!(
cache.sequences,
hex_from_slice!("52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b")
);
assert_eq!(
cache.outputs,
hex_from_slice!("863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5")
);
}
#[test]
@ -1564,25 +1581,32 @@ mod tests {
).unwrap()[..],
).unwrap();
let witness_script = p2pkh_hex("03ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a26873");
let witness_script =
p2pkh_hex("03ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a26873");
let value = 1_000_000_000;
let mut cache = SighashCache::new(&tx);
assert_eq!(
cache.segwit_signature_hash(0, &witness_script, value, EcdsaSighashType::All).unwrap(),
hex_from_slice!(Sighash, "64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6")
hex_from_slice!(
Sighash,
"64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6"
)
);
let cache = cache.segwit_cache();
assert_eq!(cache.prevouts, hex_from_slice!(
"b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a"
));
assert_eq!(cache.sequences, hex_from_slice!(
"18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198"
));
assert_eq!(cache.outputs, hex_from_slice!(
"de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83"
));
assert_eq!(
cache.prevouts,
hex_from_slice!("b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a")
);
assert_eq!(
cache.sequences,
hex_from_slice!("18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198")
);
assert_eq!(
cache.outputs,
hex_from_slice!("de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83")
);
}
#[test]
@ -1607,18 +1631,24 @@ mod tests {
let mut cache = SighashCache::new(&tx);
assert_eq!(
cache.segwit_signature_hash(0, &witness_script, value, EcdsaSighashType::All).unwrap(),
hex_from_slice!(Sighash, "185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c")
hex_from_slice!(
Sighash,
"185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c"
)
);
let cache = cache.segwit_cache();
assert_eq!(cache.prevouts, hex_from_slice!(
"74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0"
));
assert_eq!(cache.sequences, hex_from_slice!(
"3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044"
));
assert_eq!(cache.outputs, hex_from_slice!(
"bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc"
));
assert_eq!(
cache.prevouts,
hex_from_slice!("74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0")
);
assert_eq!(
cache.sequences,
hex_from_slice!("3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044")
);
assert_eq!(
cache.outputs,
hex_from_slice!("bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc")
);
}
}