From fb7ff46ccc293e3b5d68d7b62340cd488171fcfe Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 8 Nov 2022 08:25:08 +1100 Subject: [PATCH 1/9] Improve crate root re-exports When we moved to edition 2018 the use of `extern` became unnecessary and we moved to using `pub use` for re-exports. It was observed however that `pub extern crate` is more readable. Improve crate root re-exports by doing: - Use `pub extern crate foo` to re-export foo. - Fix docs attribute for optional dependency `bitcoinconsensus`. - Re-order to how rustfmt would put them. --- bitcoin/src/lib.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/bitcoin/src/lib.rs b/bitcoin/src/lib.rs index a9abadcb..9d0a17ca 100644 --- a/bitcoin/src/lib.rs +++ b/bitcoin/src/lib.rs @@ -63,20 +63,18 @@ extern crate test; #[macro_use] extern crate alloc; -// Re-export dependencies we control. -#[cfg(feature = "bitcoinconsensus")] -pub use bitcoinconsensus; -pub use {bech32, bitcoin_hashes as hashes, secp256k1}; - -// Re-export base64 when enabled #[cfg(feature = "base64")] #[cfg_attr(docsrs, doc(cfg(feature = "base64")))] -pub use base64; - -// Re-export hashbrown when enabled +pub extern crate base64; +pub extern crate bech32; +pub extern crate bitcoin_hashes as hashes; +#[cfg(feature = "bitcoinconsensus")] +#[cfg_attr(docsrs, doc(cfg(feature = "bitcoinconsensus")))] +pub extern crate bitcoinconsensus; #[cfg(feature = "hashbrown")] #[cfg_attr(docsrs, doc(cfg(feature = "hashbrown")))] -pub use hashbrown; +pub extern crate hashbrown; +pub extern crate secp256k1; #[cfg(feature = "serde")] #[macro_use] From 308a12b7cf7dc38b451577b16096a5aeeeb829da Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 27 Oct 2022 13:21:29 +1100 Subject: [PATCH 2/9] Exclude array from formatting Direct `rustfmt` to exclude formatting of a 32 byte array currently in 4 rows of 8 columns for obvious reasons. --- bitcoin/src/sighash.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/bitcoin/src/sighash.rs b/bitcoin/src/sighash.rs index 1a24cd91..247df36f 100644 --- a/bitcoin/src/sighash.rs +++ b/bitcoin/src/sighash.rs @@ -22,6 +22,7 @@ use crate::prelude::*; use crate::util::taproot::{TapLeafHash, TAPROOT_ANNEX_PREFIX, TapSighashHash, LeafVersion}; /// Used for signature hash for invalid use of SIGHASH_SINGLE. +#[rustfmt::skip] pub(crate) const UINT256_ONE: [u8; 32] = [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, From ff5a80dbd3888240812c644c622a560d161bcc44 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 16 Nov 2022 10:10:54 +1100 Subject: [PATCH 3/9] Exclude formatting of function fmt_satoshi_in This function is called in a long but clear manner, skip it when formatting. --- bitcoin/src/amount.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bitcoin/src/amount.rs b/bitcoin/src/amount.rs index 5425da0c..731a660b 100644 --- a/bitcoin/src/amount.rs +++ b/bitcoin/src/amount.rs @@ -600,6 +600,7 @@ impl Amount { /// Format the value of this [Amount] in the given denomination. /// /// Does not include the denomination. + #[rustfmt::skip] pub fn fmt_value_in(self, f: &mut dyn fmt::Write, denom: Denomination) -> fmt::Result { fmt_satoshi_in(self.to_sat(), false, f, denom, false, FormatOptions::default()) } @@ -808,10 +809,13 @@ impl Display { } impl fmt::Display for Display { + #[rustfmt::skip] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let format_options = FormatOptions::from_formatter(f); match &self.style { - DisplayStyle::FixedDenomination { show_denomination, denomination } => fmt_satoshi_in(self.sats_abs, self.is_negative, f, *denomination, *show_denomination, format_options), + DisplayStyle::FixedDenomination { show_denomination, denomination } => { + fmt_satoshi_in(self.sats_abs, self.is_negative, f, *denomination, *show_denomination, format_options) + }, DisplayStyle::DynamicDenomination if self.sats_abs >= Amount::ONE_BTC.to_sat() => { fmt_satoshi_in(self.sats_abs, self.is_negative, f, Denomination::Bitcoin, true, format_options) }, @@ -971,8 +975,8 @@ impl SignedAmount { /// Format the value of this [SignedAmount] in the given denomination. /// /// Does not include the denomination. + #[rustfmt::skip] pub fn fmt_value_in(self, f: &mut dyn fmt::Write, denom: Denomination) -> fmt::Result { - fmt_satoshi_in(self.to_sat_abs(), self.is_negative(), f, denom, false, FormatOptions::default()) } From b2e74bc0504ca651fbed122362df0e3491f3d626 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 16 Nov 2022 10:16:01 +1100 Subject: [PATCH 4/9] Exclude long function call Skip formatting `taproot_signature_hash` function calls in test code. --- bitcoin/src/sighash.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/bitcoin/src/sighash.rs b/bitcoin/src/sighash.rs index 247df36f..dc26f6a6 100644 --- a/bitcoin/src/sighash.rs +++ b/bitcoin/src/sighash.rs @@ -1269,6 +1269,7 @@ mod tests { } #[test] + #[rustfmt::skip] // Allow long function call `taproot_signature_hash`. fn test_sighash_errors() { let dumb_tx = Transaction { version: 0, From 1ecf09359ba901cb9c07b5c9dc624f1767430f97 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 18 Nov 2022 13:09:28 +1100 Subject: [PATCH 5/9] Add local variable to reduce line length In order to reduce the line length introduce a local variable `align`. Refactor only, no logic changes. --- bitcoin/src/amount.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bitcoin/src/amount.rs b/bitcoin/src/amount.rs index 731a660b..bf04205a 100644 --- a/bitcoin/src/amount.rs +++ b/bitcoin/src/amount.rs @@ -413,7 +413,8 @@ fn fmt_satoshi_in( } let width = options.width.unwrap_or(0); - let (left_pad, pad_right) = match (num_width < width, options.sign_aware_zero_pad, options.align.unwrap_or(fmt::Alignment::Right)) { + let align = options.align.unwrap_or(fmt::Alignment::Right); + let (left_pad, pad_right) = match (num_width < width, options.sign_aware_zero_pad, align) { (false, _, _) => (0, 0), // Alignment is always right (ignored) when zero-padding (true, true, _) | (true, false, fmt::Alignment::Right) => (width - num_width, 0), From 408d7737fb31641e51b3207e838672e81a9df3a4 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 16 Nov 2022 10:22:16 +1100 Subject: [PATCH 6/9] Run cargo fmt Run the command `cargo +nightly fmt` to fix formatting issues. No other changes other than those introduced by `rustfmt`. --- bitcoin/examples/bip32.rs | 2 +- bitcoin/examples/ecdsa-psbt.rs | 8 +- bitcoin/examples/taproot-psbt.rs | 10 +- bitcoin/src/address.rs | 6 +- bitcoin/src/amount.rs | 405 ++++++++++++++----------------- bitcoin/src/bip152.rs | 11 +- bitcoin/src/lib.rs | 4 +- bitcoin/src/sighash.rs | 380 ++++++++++++++++------------- 8 files changed, 413 insertions(+), 413 deletions(-) diff --git a/bitcoin/examples/bip32.rs b/bitcoin/examples/bip32.rs index fadae07f..738d9268 100644 --- a/bitcoin/examples/bip32.rs +++ b/bitcoin/examples/bip32.rs @@ -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() { diff --git a/bitcoin/examples/ecdsa-psbt.rs b/bitcoin/examples/ecdsa-psbt.rs index 60a0a129..d92ce878 100644 --- a/bitcoin/examples/ecdsa-psbt.rs +++ b/bitcoin/examples/ecdsa-psbt.rs @@ -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, diff --git a/bitcoin/examples/taproot-psbt.rs b/bitcoin/examples/taproot-psbt.rs index c3ba70bd..cff2c028 100644 --- a/bitcoin/examples/taproot-psbt.rs +++ b/bitcoin/examples/taproot-psbt.rs @@ -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> { diff --git a/bitcoin/src/address.rs b/bitcoin/src/address.rs index dee8ddd6..5e08125d 100644 --- a/bitcoin/src/address.rs +++ b/bitcoin/src/address.rs @@ -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 for WitnessVersion { fn try_from(opcode: opcodes::All) -> Result { 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), } diff --git a/bitcoin/src/amount.rs b/bitcoin/src/amount.rs index bf04205a..06868876 100644 --- a/bitcoin/src/amount.rs +++ b/bitcoin/src/amount.rs @@ -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 { - 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 { @@ -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 { - self.0.checked_mul(rhs).map(Amount) - } + pub fn checked_mul(self, rhs: u64) -> Option { 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 { - self.0.checked_div(rhs).map(Amount) - } + pub fn checked_div(self, rhs: u64) -> Option { self.0.checked_div(rhs).map(Amount) } /// Checked remainder. /// Returns [None] if overflow occurred. - pub fn checked_rem(self, rhs: u64) -> Option { - self.0.checked_rem(rhs).map(Amount) - } + pub fn checked_rem(self, rhs: u64) -> Option { self.0.checked_rem(rhs).map(Amount) } /// Convert to a signed amount. pub fn to_signed(self) -> Result { @@ -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 for Amount { @@ -726,9 +703,7 @@ impl ops::Rem for Amount { } impl ops::RemAssign 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 for Amount { @@ -740,31 +715,23 @@ impl ops::Mul for Amount { } impl ops::MulAssign 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 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 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 { - Amount::from_str_with_denomination(s) - } + fn from_str(s: &str) -> Result { 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 { @@ -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 { - self.0.checked_abs().map(SignedAmount) - } + pub fn checked_abs(self) -> Option { 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 for SignedAmount { @@ -1144,9 +1082,7 @@ impl ops::Rem for SignedAmount { } impl ops::RemAssign 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 for SignedAmount { @@ -1158,9 +1094,7 @@ impl ops::Mul for SignedAmount { } impl ops::MulAssign 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 for SignedAmount { @@ -1172,17 +1106,13 @@ impl ops::Div for SignedAmount { } impl ops::DivAssign 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 { - SignedAmount::from_str_with_denomination(s) - } + fn from_str(s: &str) -> Result { SignedAmount::from_str_with_denomination(s) } } impl core::iter::Sum for SignedAmount { @@ -1199,18 +1129,21 @@ pub trait CheckedSum: private::SumSeal { fn checked_sum(self) -> Option; } -impl CheckedSum for T where T: Iterator { +impl CheckedSum for T +where + T: Iterator, +{ fn checked_sum(mut self) -> Option { 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 CheckedSum for T where T: Iterator { +impl CheckedSum for T +where + T: Iterator, +{ fn checked_sum(mut self) -> Option { let first = Some(self.next().unwrap_or_default()); @@ -1224,8 +1157,8 @@ mod private { /// Used to seal the `CheckedSum` trait pub trait SumSeal {} - impl SumSeal for T where T: Iterator {} - impl SumSeal for T where T: Iterator {} + impl SumSeal for T where T: Iterator {} + impl SumSeal for T where T: Iterator {} } #[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(self, s: S) -> Result { 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(self, s: S) -> Result { 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: &A, s: S) -> Result { @@ -1353,11 +1284,13 @@ pub mod serde { //! Serialize and deserialize [`Option`](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: &Option, 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: &A, s: S) -> Result { @@ -1417,11 +1351,13 @@ pub mod serde { //! Serialize and deserialize [Option] 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: &Option, 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::()); assert_eq!(SignedAmount::from_sat(0), vec![].into_iter().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().sum::(); 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::(); 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), } } diff --git a/bitcoin/src/bip152.rs b/bitcoin/src/bip152.rs index 943f47a3..c8d3b993 100644 --- a/bitcoin/src/bip152.rs +++ b/bitcoin/src/bip152.rs @@ -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 { diff --git a/bitcoin/src/lib.rs b/bitcoin/src/lib.rs index 9d0a17ca..b4b47106 100644 --- a/bitcoin/src/lib.rs +++ b/bitcoin/src/lib.rs @@ -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"))] diff --git a/bitcoin/src/sighash.rs b/bitcoin/src/sighash.rs index dc26f6a6..65e5aced 100644 --- a/bitcoin/src/sighash.rs +++ b/bitcoin/src/sighash.rs @@ -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> { +pub struct SighashCache> { /// Access to transaction required for transaction introspection. Moreover, type /// `T: Deref` 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 { +pub enum Prevouts<'u, T> +where + T: 'u + Borrow, +{ /// `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 { +impl<'u, T> Prevouts<'u, T> +where + T: Borrow, +{ 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 { 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 { 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> 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> 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 { - use SchnorrSighashType::*; + use SchnorrSighashType::*; Ok(match hash_ty { 0x00 => Default, @@ -498,12 +497,7 @@ impl> SighashCache { /// 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> SighashCache { // 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> SighashCache { // 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> SighashCache { && 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> SighashCache { 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> SighashCache { 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> SighashCache { 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> SighashCache { 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> SighashCache { sighash_type: u32, ) -> Result { 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> SighashCache { 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> SighashCache { }) } - fn taproot_cache>(&mut self, prevouts: &[T]) -> &TaprootCache - { + fn taproot_cache>(&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> SighashCache { } } -impl> SighashCache { +impl> SighashCache { /// 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> SighashCache { } impl From 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::::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::::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::::from_hex(&sig_str[128..]).unwrap()[0]).unwrap(); + let hash_ty = SchnorrSighashType::from_consensus_u8( + Vec::::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") + ); } } From 81f69e846b3786b7f82c75e55dc3b3933ffa0ad6 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 27 Oct 2022 13:31:55 +1100 Subject: [PATCH 7/9] Exclude from formatting stuff in the network module In preparation for formatting the `network` module; improve the formatting, and direct `rustfmt` to skip formatting, on a bunch of byte arrays. --- bitcoin/src/network/message.rs | 83 +++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 36 deletions(-) diff --git a/bitcoin/src/network/message.rs b/bitcoin/src/network/message.rs index a64df614..008a871e 100644 --- a/bitcoin/src/network/message.rs +++ b/bitcoin/src/network/message.rs @@ -574,45 +574,51 @@ mod test { } #[test] + #[rustfmt::skip] fn serialize_verack_test() { assert_eq!(serialize(&RawNetworkMessage { magic: Magic::from(Network::Bitcoin), payload: NetworkMessage::Verack }), - vec![0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x61, - 0x63, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]); + vec![0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x61, + 0x63, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]); } #[test] + #[rustfmt::skip] fn serialize_ping_test() { assert_eq!(serialize(&RawNetworkMessage { magic: Magic::from(Network::Bitcoin), payload: NetworkMessage::Ping(100) }), - vec![0xf9, 0xbe, 0xb4, 0xd9, 0x70, 0x69, 0x6e, 0x67, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x24, 0x67, 0xf1, 0x1d, - 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + vec![0xf9, 0xbe, 0xb4, 0xd9, 0x70, 0x69, 0x6e, 0x67, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x24, 0x67, 0xf1, 0x1d, + 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); } #[test] + #[rustfmt::skip] fn serialize_mempool_test() { assert_eq!(serialize(&RawNetworkMessage { magic: Magic::from(Network::Bitcoin), payload: NetworkMessage::MemPool }), - vec![0xf9, 0xbe, 0xb4, 0xd9, 0x6d, 0x65, 0x6d, 0x70, - 0x6f, 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]); + vec![0xf9, 0xbe, 0xb4, 0xd9, 0x6d, 0x65, 0x6d, 0x70, + 0x6f, 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]); } #[test] + #[rustfmt::skip] fn serialize_getaddr_test() { assert_eq!(serialize(&RawNetworkMessage { magic: Magic::from(Network::Bitcoin), payload: NetworkMessage::GetAddr }), - vec![0xf9, 0xbe, 0xb4, 0xd9, 0x67, 0x65, 0x74, 0x61, - 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]); + vec![0xf9, 0xbe, 0xb4, 0xd9, 0x67, 0x65, 0x74, 0x61, + 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]); } #[test] fn deserialize_getaddr_test() { - let msg = deserialize( - &[0xf9, 0xbe, 0xb4, 0xd9, 0x67, 0x65, 0x74, 0x61, - 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]); + #[rustfmt::skip] + let msg = deserialize(&[ + 0xf9, 0xbe, 0xb4, 0xd9, 0x67, 0x65, 0x74, 0x61, + 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2 + ]); let preimage = RawNetworkMessage { magic: Magic::from(Network::Bitcoin), payload: NetworkMessage::GetAddr }; assert!(msg.is_ok()); let msg : RawNetworkMessage = msg.unwrap(); @@ -622,23 +628,25 @@ mod test { #[test] fn deserialize_version_test() { - let msg = deserialize::( - &[ 0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x66, 0x00, 0x00, 0x00, 0xbe, 0x61, 0xb8, 0x27, - 0x7f, 0x11, 0x01, 0x00, 0x0d, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x4d, 0x5c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x5b, 0xf0, 0x8c, 0x80, 0xb4, 0xbd, 0x0d, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfa, 0xa9, 0x95, 0x59, 0xcc, 0x68, 0xa1, 0xc1, - 0x10, 0x2f, 0x53, 0x61, 0x74, 0x6f, 0x73, 0x68, - 0x69, 0x3a, 0x30, 0x2e, 0x31, 0x37, 0x2e, 0x31, - 0x2f, 0x93, 0x8c, 0x08, 0x00, 0x01 ]); + #[rustfmt::skip] + let msg = deserialize::(&[ + 0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x00, 0x00, 0x00, 0xbe, 0x61, 0xb8, 0x27, + 0x7f, 0x11, 0x01, 0x00, 0x0d, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x4d, 0x5c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x5b, 0xf0, 0x8c, 0x80, 0xb4, 0xbd, 0x0d, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfa, 0xa9, 0x95, 0x59, 0xcc, 0x68, 0xa1, 0xc1, + 0x10, 0x2f, 0x53, 0x61, 0x74, 0x6f, 0x73, 0x68, + 0x69, 0x3a, 0x30, 0x2e, 0x31, 0x37, 0x2e, 0x31, + 0x2f, 0x93, 0x8c, 0x08, 0x00, 0x01 + ]); assert!(msg.is_ok()); let msg = msg.unwrap(); @@ -658,7 +666,9 @@ mod test { #[test] fn deserialize_partial_message_test() { - let data = [ 0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x73, + #[rustfmt::skip] + let data = [ + 0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0xbe, 0x61, 0xb8, 0x27, 0x7f, 0x11, 0x01, 0x00, 0x0d, 0x04, 0x00, 0x00, @@ -673,7 +683,8 @@ mod test { 0xfa, 0xa9, 0x95, 0x59, 0xcc, 0x68, 0xa1, 0xc1, 0x10, 0x2f, 0x53, 0x61, 0x74, 0x6f, 0x73, 0x68, 0x69, 0x3a, 0x30, 0x2e, 0x31, 0x37, 0x2e, 0x31, - 0x2f, 0x93, 0x8c, 0x08, 0x00, 0x01, 0, 0 ]; + 0x2f, 0x93, 0x8c, 0x08, 0x00, 0x01, 0x00, 0x00 + ]; let msg = deserialize_partial::(&data); assert!(msg.is_ok()); From dc33c7999f5b461c996be2fe11c4481e7ed8ceb9 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 27 Oct 2022 13:35:00 +1100 Subject: [PATCH 8/9] Enable formatting of the network module Remove the exclude for the `bitcoin/src/network/` directory from the `rustfmt` config file. Do not run formatter as part of this change, this allows the actual formatting change to be verified more easily. --- rustfmt.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt.toml b/rustfmt.toml index 466114a8..0beedbe1 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -2,7 +2,6 @@ ignore = [ "bitcoin/src/blockdata", "bitcoin/src/consensus", - "bitcoin/src/network", "bitcoin/src/psbt", "bitcoin/src/util", ] From e04a7a926dfa5e943f1db3cec97eab9b19c10269 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 16 Nov 2022 10:23:01 +1100 Subject: [PATCH 9/9] network: Run cargo fmt We just removed the `bitcoin/src/network/` exclude from `rustfmt` config file. Run the command `cargo +nightly fmt`. No other changes than those introduced by `rustfmt`. --- bitcoin/src/network/address.rs | 246 +++++++---- bitcoin/src/network/constants.rs | 126 ++---- bitcoin/src/network/message.rs | 400 +++++++++++------- bitcoin/src/network/message_blockdata.rs | 47 +- bitcoin/src/network/message_bloom.rs | 6 +- bitcoin/src/network/message_compact_blocks.rs | 2 +- bitcoin/src/network/message_network.rs | 50 ++- bitcoin/src/network/mod.rs | 4 +- 8 files changed, 524 insertions(+), 357 deletions(-) diff --git a/bitcoin/src/network/address.rs b/bitcoin/src/network/address.rs index 76234df7..2015970d 100644 --- a/bitcoin/src/network/address.rs +++ b/bitcoin/src/network/address.rs @@ -7,14 +7,13 @@ //! network addresses in Bitcoin messages. //! -use crate::prelude::*; - use core::{fmt, iter}; -use std::net::{SocketAddr, Ipv6Addr, SocketAddrV4, SocketAddrV6, Ipv4Addr, ToSocketAddrs}; +use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; +use crate::consensus::encode::{self, Decodable, Encodable, ReadExt, VarInt, WriteExt}; use crate::io; use crate::network::constants::ServiceFlags; -use crate::consensus::encode::{self, Decodable, Encodable, VarInt, ReadExt, WriteExt}; +use crate::prelude::*; /// A message which can be sent on the Bitcoin network #[derive(Clone, PartialEq, Eq, Hash)] @@ -24,17 +23,17 @@ pub struct Address { /// Network byte-order ipv6 address, or ipv4-mapped ipv6 address pub address: [u16; 8], /// Network port - pub port: u16 + pub port: u16, } const ONION: [u16; 3] = [0xFD87, 0xD87E, 0xEB43]; impl Address { /// Create an address message for a socket - pub fn new(socket :&SocketAddr, services: ServiceFlags) -> Address { + pub fn new(socket: &SocketAddr, services: ServiceFlags) -> Address { let (address, port) = match *socket { SocketAddr::V4(addr) => (addr.ip().to_ipv6_mapped().segments(), addr.port()), - SocketAddr::V6(addr) => (addr.ip().segments(), addr.port()) + SocketAddr::V6(addr) => (addr.ip().segments(), addr.port()), }; Address { address, port, services } } @@ -47,7 +46,8 @@ impl Address { if addr[0..3] == ONION { return Err(io::Error::from(io::ErrorKind::AddrNotAvailable)); } - let ipv6 = Ipv6Addr::new(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]); + let ipv6 = + Ipv6Addr::new(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]); if let Some(ipv4) = ipv6.to_ipv4() { Ok(SocketAddr::V4(SocketAddrV4::new(ipv4, self.port))) } else { @@ -79,7 +79,7 @@ impl Decodable for Address { Ok(Address { services: Decodable::consensus_decode(r)?, address: read_be_address(r)?, - port: u16::swap_bytes(Decodable::consensus_decode(r)?) + port: u16::swap_bytes(Decodable::consensus_decode(r)?), }) } } @@ -101,10 +101,16 @@ impl fmt::Debug for Address { let ipv6 = Ipv6Addr::from(self.address); match ipv6.to_ipv4() { - Some(addr) => write!(f, "Address {{services: {}, address: {}, port: {}}}", - self.services, addr, self.port), - None => write!(f, "Address {{services: {}, address: {}, port: {}}}", - self.services, ipv6, self.port) + Some(addr) => write!( + f, + "Address {{services: {}, address: {}, port: {}}}", + self.services, addr, self.port + ), + None => write!( + f, + "Address {{services: {}, address: {}, port: {}}}", + self.services, ipv6, self.port + ), } } } @@ -137,7 +143,11 @@ pub enum AddrV2 { impl Encodable for AddrV2 { fn consensus_encode(&self, e: &mut W) -> Result { - fn encode_addr(w: &mut W, network: u8, bytes: &[u8]) -> Result { + fn encode_addr( + w: &mut W, + network: u8, + bytes: &[u8], + ) -> Result { let len = network.consensus_encode(w)? + VarInt(bytes.len() as u64).consensus_encode(w)? + bytes.len(); @@ -151,7 +161,7 @@ impl Encodable for AddrV2 { AddrV2::TorV3(ref bytes) => encode_addr(e, 4, bytes)?, AddrV2::I2p(ref bytes) => encode_addr(e, 5, bytes)?, AddrV2::Cjdns(ref addr) => encode_addr(e, 6, &addr.octets())?, - AddrV2::Unknown(network, ref bytes) => encode_addr(e, network, bytes)? + AddrV2::Unknown(network, ref bytes) => encode_addr(e, network, bytes)?, }) } } @@ -170,43 +180,49 @@ impl Decodable for AddrV2 { } let addr: [u8; 4] = Decodable::consensus_decode(r)?; AddrV2::Ipv4(Ipv4Addr::new(addr[0], addr[1], addr[2], addr[3])) - }, + } 2 => { if len != 16 { return Err(encode::Error::ParseFailed("Invalid IPv6 address")); } let addr: [u16; 8] = read_be_address(r)?; if addr[0..3] == ONION { - return Err(encode::Error::ParseFailed("OnionCat address sent with IPv6 network id")); + return Err(encode::Error::ParseFailed( + "OnionCat address sent with IPv6 network id", + )); } if addr[0..6] == [0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFFF] { - return Err(encode::Error::ParseFailed("IPV4 wrapped address sent with IPv6 network id")); + return Err(encode::Error::ParseFailed( + "IPV4 wrapped address sent with IPv6 network id", + )); } - AddrV2::Ipv6(Ipv6Addr::new(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7])) - }, + AddrV2::Ipv6(Ipv6Addr::new( + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + )) + } 3 => { if len != 10 { return Err(encode::Error::ParseFailed("Invalid TorV2 address")); } let id = Decodable::consensus_decode(r)?; AddrV2::TorV2(id) - }, + } 4 => { if len != 32 { return Err(encode::Error::ParseFailed("Invalid TorV3 address")); } let pubkey = Decodable::consensus_decode(r)?; AddrV2::TorV3(pubkey) - }, + } 5 => { if len != 32 { return Err(encode::Error::ParseFailed("Invalid I2P address")); } let hash = Decodable::consensus_decode(r)?; AddrV2::I2p(hash) - }, + } 6 => { - if len != 16 { + if len != 16 { return Err(encode::Error::ParseFailed("Invalid CJDNS address")); } let addr: [u16; 8] = read_be_address(r)?; @@ -214,8 +230,10 @@ impl Decodable for AddrV2 { if addr[0] != u16::from_be_bytes([0xFC, 0x00]) { return Err(encode::Error::ParseFailed("Invalid CJDNS address")); } - AddrV2::Cjdns(Ipv6Addr::new(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7])) - }, + AddrV2::Cjdns(Ipv6Addr::new( + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + )) + } _ => { // len already checked above to be <= 512 let mut addr = vec![0u8; len as usize]; @@ -236,7 +254,7 @@ pub struct AddrV2Message { /// Network ID + Network Address pub addr: AddrV2, /// Network port, 0 if not applicable - pub port: u16 + pub port: u16, } impl AddrV2Message { @@ -287,22 +305,26 @@ impl ToSocketAddrs for AddrV2Message { #[cfg(test)] mod test { use core::str::FromStr; - use super::{AddrV2Message, AddrV2, Address}; - use crate::network::constants::ServiceFlags; - use std::net::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr}; - use crate::hashes::hex::FromHex; + use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; + use super::{AddrV2, AddrV2Message, Address}; use crate::consensus::encode::{deserialize, serialize}; + use crate::hashes::hex::FromHex; + use crate::network::constants::ServiceFlags; #[test] fn serialize_address_test() { - assert_eq!(serialize(&Address { - services: ServiceFlags::NETWORK, - address: [0, 0, 0, 0, 0, 0xffff, 0x0a00, 0x0001], - port: 8333 - }), - vec![1u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1, 0x20, 0x8d]); + assert_eq!( + serialize(&Address { + services: ServiceFlags::NETWORK, + address: [0, 0, 0, 0, 0, 0xffff, 0x0a00, 0x0001], + port: 8333 + }), + vec![ + 1u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1, + 0x20, 0x8d + ] + ); } #[test] @@ -329,41 +351,47 @@ mod test { #[test] fn deserialize_address_test() { - let mut addr: Result = deserialize(&[1u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, - 0, 1, 0x20, 0x8d]); + let mut addr: Result = deserialize(&[ + 1u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1, + 0x20, 0x8d, + ]); assert!(addr.is_ok()); let full = addr.unwrap(); assert!(match full.socket_addr().unwrap() { - SocketAddr::V4(_) => true, - _ => false - } - ); + SocketAddr::V4(_) => true, + _ => false, + }); assert_eq!(full.services, ServiceFlags::NETWORK); assert_eq!(full.address, [0, 0, 0, 0, 0, 0xffff, 0x0a00, 0x0001]); assert_eq!(full.port, 8333); - addr = deserialize(&[1u8, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1]); + addr = deserialize(&[ + 1u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1, + ]); assert!(addr.is_err()); } #[test] - fn test_socket_addr () { - let s4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(111,222,123,4)), 5555); + fn test_socket_addr() { + let s4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(111, 222, 123, 4)), 5555); let a4 = Address::new(&s4, ServiceFlags::NETWORK | ServiceFlags::WITNESS); assert_eq!(a4.socket_addr().unwrap(), s4); - let s6 = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444, - 0x5555, 0x6666, 0x7777, 0x8888)), 9999); + let s6 = SocketAddr::new( + IpAddr::V6(Ipv6Addr::new( + 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888, + )), + 9999, + ); let a6 = Address::new(&s6, ServiceFlags::NETWORK | ServiceFlags::WITNESS); assert_eq!(a6.socket_addr().unwrap(), s6); } #[test] - fn onion_test () { + fn onion_test() { let onionaddr = SocketAddr::new( - IpAddr::V6( - Ipv6Addr::from_str("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").unwrap()), 1111); + IpAddr::V6(Ipv6Addr::from_str("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").unwrap()), + 1111, + ); let addr = Address::new(&onionaddr, ServiceFlags::NONE); assert!(addr.socket_addr().is_err()); } @@ -375,17 +403,32 @@ mod test { let ip = AddrV2::Ipv4(Ipv4Addr::new(1, 2, 3, 4)); assert_eq!(serialize(&ip), Vec::from_hex("010401020304").unwrap()); - let ip = AddrV2::Ipv6(Ipv6Addr::from_str("1a1b:2a2b:3a3b:4a4b:5a5b:6a6b:7a7b:8a8b").unwrap()); + let ip = + AddrV2::Ipv6(Ipv6Addr::from_str("1a1b:2a2b:3a3b:4a4b:5a5b:6a6b:7a7b:8a8b").unwrap()); assert_eq!(serialize(&ip), Vec::from_hex("02101a1b2a2b3a3b4a4b5a5b6a6b7a7b8a8b").unwrap()); let ip = AddrV2::TorV2(FromHex::from_hex("f1f2f3f4f5f6f7f8f9fa").unwrap()); assert_eq!(serialize(&ip), Vec::from_hex("030af1f2f3f4f5f6f7f8f9fa").unwrap()); - let ip = AddrV2::TorV3(FromHex::from_hex("53cd5648488c4707914182655b7664034e09e66f7e8cbf1084e654eb56c5bd88").unwrap()); - assert_eq!(serialize(&ip), Vec::from_hex("042053cd5648488c4707914182655b7664034e09e66f7e8cbf1084e654eb56c5bd88").unwrap()); + let ip = AddrV2::TorV3( + FromHex::from_hex("53cd5648488c4707914182655b7664034e09e66f7e8cbf1084e654eb56c5bd88") + .unwrap(), + ); + assert_eq!( + serialize(&ip), + Vec::from_hex("042053cd5648488c4707914182655b7664034e09e66f7e8cbf1084e654eb56c5bd88") + .unwrap() + ); - let ip = AddrV2::I2p(FromHex::from_hex("a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87").unwrap()); - assert_eq!(serialize(&ip), Vec::from_hex("0520a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87").unwrap()); + let ip = AddrV2::I2p( + FromHex::from_hex("a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87") + .unwrap(), + ); + assert_eq!( + serialize(&ip), + Vec::from_hex("0520a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87") + .unwrap() + ); let ip = AddrV2::Cjdns(Ipv6Addr::from_str("fc00:1:2:3:4:5:6:7").unwrap()); assert_eq!(serialize(&ip), Vec::from_hex("0610fc000001000200030004000500060007").unwrap()); @@ -412,17 +455,27 @@ mod test { assert!(deserialize::(&Vec::from_hex("01fd010201020304").unwrap()).is_err()); // Valid IPv6. - let ip: AddrV2 = deserialize(&Vec::from_hex("02100102030405060708090a0b0c0d0e0f10").unwrap()).unwrap(); - assert_eq!(ip, AddrV2::Ipv6(Ipv6Addr::from_str("102:304:506:708:90a:b0c:d0e:f10").unwrap())); + let ip: AddrV2 = + deserialize(&Vec::from_hex("02100102030405060708090a0b0c0d0e0f10").unwrap()).unwrap(); + assert_eq!( + ip, + AddrV2::Ipv6(Ipv6Addr::from_str("102:304:506:708:90a:b0c:d0e:f10").unwrap()) + ); // Invalid IPv6, with bogus length. assert!(deserialize::(&Vec::from_hex("020400").unwrap()).is_err()); // Invalid IPv6, contains embedded IPv4. - assert!(deserialize::(&Vec::from_hex("021000000000000000000000ffff01020304").unwrap()).is_err()); + assert!(deserialize::( + &Vec::from_hex("021000000000000000000000ffff01020304").unwrap() + ) + .is_err()); // Invalid IPv6, contains embedded TORv2. - assert!(deserialize::(&Vec::from_hex("0210fd87d87eeb430102030405060708090a").unwrap()).is_err()); + assert!(deserialize::( + &Vec::from_hex("0210fd87d87eeb430102030405060708090a").unwrap() + ) + .is_err()); // Valid TORv2. let ip: AddrV2 = deserialize(&Vec::from_hex("030af1f2f3f4f5f6f7f8f9fa").unwrap()).unwrap(); @@ -432,31 +485,61 @@ mod test { assert!(deserialize::(&Vec::from_hex("030700").unwrap()).is_err()); // Valid TORv3. - let ip: AddrV2 = deserialize(&Vec::from_hex("042079bcc625184b05194975c28b66b66b0469f7f6556fb1ac3189a79b40dda32f1f").unwrap()).unwrap(); - assert_eq!(ip, AddrV2::TorV3(FromHex::from_hex("79bcc625184b05194975c28b66b66b0469f7f6556fb1ac3189a79b40dda32f1f").unwrap())); + let ip: AddrV2 = deserialize( + &Vec::from_hex("042079bcc625184b05194975c28b66b66b0469f7f6556fb1ac3189a79b40dda32f1f") + .unwrap(), + ) + .unwrap(); + assert_eq!( + ip, + AddrV2::TorV3( + FromHex::from_hex( + "79bcc625184b05194975c28b66b66b0469f7f6556fb1ac3189a79b40dda32f1f" + ) + .unwrap() + ) + ); // Invalid TORv3, with bogus length. assert!(deserialize::(&Vec::from_hex("040000").unwrap()).is_err()); // Valid I2P. - let ip: AddrV2 = deserialize(&Vec::from_hex("0520a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87").unwrap()).unwrap(); - assert_eq!(ip, AddrV2::I2p(FromHex::from_hex("a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87").unwrap())); + let ip: AddrV2 = deserialize( + &Vec::from_hex("0520a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87") + .unwrap(), + ) + .unwrap(); + assert_eq!( + ip, + AddrV2::I2p( + FromHex::from_hex( + "a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87" + ) + .unwrap() + ) + ); // Invalid I2P, with bogus length. assert!(deserialize::(&Vec::from_hex("050300").unwrap()).is_err()); // Valid CJDNS. - let ip: AddrV2 = deserialize(&Vec::from_hex("0610fc000001000200030004000500060007").unwrap()).unwrap(); + let ip: AddrV2 = + deserialize(&Vec::from_hex("0610fc000001000200030004000500060007").unwrap()).unwrap(); assert_eq!(ip, AddrV2::Cjdns(Ipv6Addr::from_str("fc00:1:2:3:4:5:6:7").unwrap())); // Invalid CJDNS, incorrect marker - assert!(deserialize::(&Vec::from_hex("0610fd000001000200030004000500060007").unwrap()).is_err()); + assert!(deserialize::( + &Vec::from_hex("0610fd000001000200030004000500060007").unwrap() + ) + .is_err()); // Invalid CJDNS, with bogus length. assert!(deserialize::(&Vec::from_hex("060100").unwrap()).is_err()); // Unknown, with extreme length. - assert!(deserialize::(&Vec::from_hex("aafe0000000201020304050607").unwrap()).is_err()); + assert!( + deserialize::(&Vec::from_hex("aafe0000000201020304050607").unwrap()).is_err() + ); // Unknown, with reasonable length. let ip: AddrV2 = deserialize(&Vec::from_hex("aa0401020304").unwrap()).unwrap(); @@ -472,10 +555,25 @@ mod test { let raw = Vec::from_hex("0261bc6649019902abab208d79627683fd4804010409090909208d").unwrap(); let addresses: Vec = deserialize(&raw).unwrap(); - assert_eq!(addresses, vec![ - AddrV2Message{services: ServiceFlags::NETWORK, time: 0x4966bc61, port: 8333, addr: AddrV2::Unknown(153, Vec::from_hex("abab").unwrap())}, - AddrV2Message{services: ServiceFlags::NETWORK_LIMITED | ServiceFlags::WITNESS | ServiceFlags::COMPACT_FILTERS, time: 0x83766279, port: 8333, addr: AddrV2::Ipv4(Ipv4Addr::new(9, 9, 9, 9))}, - ]); + assert_eq!( + addresses, + vec![ + AddrV2Message { + services: ServiceFlags::NETWORK, + time: 0x4966bc61, + port: 8333, + addr: AddrV2::Unknown(153, Vec::from_hex("abab").unwrap()) + }, + AddrV2Message { + services: ServiceFlags::NETWORK_LIMITED + | ServiceFlags::WITNESS + | ServiceFlags::COMPACT_FILTERS, + time: 0x83766279, + port: 8333, + addr: AddrV2::Ipv4(Ipv4Addr::new(9, 9, 9, 9)) + }, + ] + ); assert_eq!(serialize(&addresses), raw); } diff --git a/bitcoin/src/network/constants.rs b/bitcoin/src/network/constants.rs index 3cff507f..a8025ee3 100644 --- a/bitcoin/src/network/constants.rs +++ b/bitcoin/src/network/constants.rs @@ -26,19 +26,20 @@ //! assert_eq!(&bytes[..], &[0xF9, 0xBE, 0xB4, 0xD9]); //! ``` -use core::{fmt, ops, convert::TryFrom, borrow::Borrow, borrow::BorrowMut}; +use core::borrow::{Borrow, BorrowMut}; +use core::convert::TryFrom; use core::str::FromStr; +use core::{fmt, ops}; +use bitcoin_internals::{debug_from_display, write_err}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use bitcoin_internals::{debug_from_display, write_err}; - +use crate::consensus::encode::{self, Decodable, Encodable}; +use crate::error::impl_std_error; +use crate::hashes::hex::{Error, FromHex}; use crate::io; use crate::prelude::{String, ToOwned}; -use crate::consensus::encode::{self, Encodable, Decodable}; -use crate::hashes::hex::{FromHex, Error}; -use crate::error::impl_std_error; /// Version of the protocol as appearing in network message headers /// This constant is used to signal to other peers which features you support. @@ -86,9 +87,7 @@ impl Network { /// assert_eq!(Ok(Network::Bitcoin), Network::try_from(Magic::from_bytes([0xF9, 0xBE, 0xB4, 0xD9]))); /// assert_eq!(None, Network::from_magic(Magic::from_bytes([0xFF, 0xFF, 0xFF, 0xFF]))); /// ``` - pub fn from_magic(magic: Magic) -> Option { - Network::try_from(magic).ok() - } + pub fn from_magic(magic: Magic) -> Option { Network::try_from(magic).ok() } /// Return the network magic bytes, which should be encoded little-endian /// at the start of every message @@ -101,9 +100,7 @@ impl Network { /// let network = Network::Bitcoin; /// assert_eq!(network.magic(), Magic::from_bytes([0xF9, 0xBE, 0xB4, 0xD9])); /// ``` - pub fn magic(self) -> Magic { - Magic::from(self) - } + pub fn magic(self) -> Magic { Magic::from(self) } } /// An error in parsing network string. @@ -129,7 +126,7 @@ impl FromStr for Network { "testnet" => Testnet, "signet" => Signet, "regtest" => Regtest, - _ => return Err(ParseNetworkError(s.to_owned())) + _ => return Err(ParseNetworkError(s.to_owned())), }; Ok(network) } @@ -164,14 +161,10 @@ impl Magic { pub const REGTEST: Self = Self([0xFA, 0xBF, 0xB5, 0xDA]); /// Create network magic from bytes. - pub fn from_bytes(bytes: [u8; 4]) -> Magic { - Magic(bytes) - } + pub fn from_bytes(bytes: [u8; 4]) -> Magic { Magic(bytes) } /// Get network magic bytes. - pub fn to_bytes(self) -> [u8; 4] { - self.0 - } + pub fn to_bytes(self) -> [u8; 4] { self.0 } } /// An error in parsing magic bytes. @@ -180,7 +173,7 @@ pub struct ParseMagicError { /// The error that occurred when parsing the string. error: Error, /// The byte string that failed to parse. - magic: String + magic: String, } impl FromStr for Magic { @@ -189,7 +182,7 @@ impl FromStr for Magic { fn from_str(s: &str) -> Result { match <[u8; 4]>::from_hex(s) { Ok(magic) => Ok(Magic::from_bytes(magic)), - Err(e) => Err(ParseMagicError { error: e, magic: s.to_owned() }) + Err(e) => Err(ParseMagicError { error: e, magic: s.to_owned() }), } } } @@ -201,7 +194,7 @@ impl From for Magic { Network::Bitcoin => Magic::BITCOIN, Network::Testnet => Magic::TESTNET, Network::Signet => Magic::SIGNET, - Network::Regtest => Magic::REGTEST + Network::Regtest => Magic::REGTEST, } } } @@ -220,7 +213,7 @@ impl TryFrom for Network { Magic::TESTNET => Ok(Network::Testnet), Magic::SIGNET => Ok(Network::Signet), Magic::REGTEST => Ok(Network::Regtest), - _ => Err(UnknownMagic(magic)) + _ => Err(UnknownMagic(magic)), } } } @@ -260,51 +253,35 @@ impl Decodable for Magic { } impl AsRef<[u8]> for Magic { - fn as_ref(&self) -> &[u8] { - &self.0 - } + fn as_ref(&self) -> &[u8] { &self.0 } } impl AsRef<[u8; 4]> for Magic { - fn as_ref(&self) -> &[u8; 4] { - &self.0 - } + fn as_ref(&self) -> &[u8; 4] { &self.0 } } impl AsMut<[u8]> for Magic { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0 - } + fn as_mut(&mut self) -> &mut [u8] { &mut self.0 } } impl AsMut<[u8; 4]> for Magic { - fn as_mut(&mut self) -> &mut [u8; 4] { - &mut self.0 - } + fn as_mut(&mut self) -> &mut [u8; 4] { &mut self.0 } } impl Borrow<[u8]> for Magic { - fn borrow(&self) -> &[u8] { - &self.0 - } + fn borrow(&self) -> &[u8] { &self.0 } } impl Borrow<[u8; 4]> for Magic { - fn borrow(&self) -> &[u8; 4] { - &self.0 - } + fn borrow(&self) -> &[u8; 4] { &self.0 } } impl BorrowMut<[u8]> for Magic { - fn borrow_mut(&mut self) -> &mut [u8] { - &mut self.0 - } + fn borrow_mut(&mut self) -> &mut [u8] { &mut self.0 } } impl BorrowMut<[u8; 4]> for Magic { - fn borrow_mut(&mut self) -> &mut [u8; 4] { - &mut self.0 - } + fn borrow_mut(&mut self) -> &mut [u8; 4] { &mut self.0 } } impl fmt::Display for ParseMagicError { @@ -376,26 +353,18 @@ impl ServiceFlags { } /// Check whether [ServiceFlags] are included in this one. - pub fn has(self, flags: ServiceFlags) -> bool { - (self.0 | flags.0) == self.0 - } + pub fn has(self, flags: ServiceFlags) -> bool { (self.0 | flags.0) == self.0 } /// Gets the integer representation of this [`ServiceFlags`]. - pub fn to_u64(self) -> u64 { - self.0 - } + pub fn to_u64(self) -> u64 { self.0 } } impl fmt::LowerHex for ServiceFlags { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::LowerHex::fmt(&self.0, f) - } + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) } } impl fmt::UpperHex for ServiceFlags { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::UpperHex::fmt(&self.0, f) - } + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) } } impl fmt::Display for ServiceFlags { @@ -415,7 +384,7 @@ impl fmt::Display for ServiceFlags { write!(f, stringify!($f))?; flags.remove(ServiceFlags::$f); } - } + }; } write!(f, "ServiceFlags(")?; write_flag!(NETWORK); @@ -436,43 +405,31 @@ impl fmt::Display for ServiceFlags { } impl From for ServiceFlags { - fn from(f: u64) -> Self { - ServiceFlags(f) - } + fn from(f: u64) -> Self { ServiceFlags(f) } } impl From for u64 { - fn from(flags: ServiceFlags) -> Self { - flags.0 - } + fn from(flags: ServiceFlags) -> Self { flags.0 } } impl ops::BitOr for ServiceFlags { type Output = Self; - fn bitor(mut self, rhs: Self) -> Self { - self.add(rhs) - } + fn bitor(mut self, rhs: Self) -> Self { self.add(rhs) } } impl ops::BitOrAssign for ServiceFlags { - fn bitor_assign(&mut self, rhs: Self) { - self.add(rhs); - } + fn bitor_assign(&mut self, rhs: Self) { self.add(rhs); } } impl ops::BitXor for ServiceFlags { type Output = Self; - fn bitxor(mut self, rhs: Self) -> Self { - self.remove(rhs) - } + fn bitxor(mut self, rhs: Self) -> Self { self.remove(rhs) } } impl ops::BitXorAssign for ServiceFlags { - fn bitxor_assign(&mut self, rhs: Self) { - self.remove(rhs); - } + fn bitxor_assign(&mut self, rhs: Self) { self.remove(rhs); } } impl Encodable for ServiceFlags { @@ -491,11 +448,12 @@ impl Decodable for ServiceFlags { #[cfg(test)] mod tests { - use super::{Network, ServiceFlags, Magic}; - use crate::consensus::encode::{deserialize, serialize}; use std::convert::TryFrom; use std::str::FromStr; + use super::{Magic, Network, ServiceFlags}; + use crate::consensus::encode::{deserialize, serialize}; + #[test] fn serialize_test() { assert_eq!(serialize(&Network::Bitcoin.magic()), &[0xf9, 0xbe, 0xb4, 0xd9]); @@ -507,7 +465,6 @@ mod tests { assert_eq!(deserialize(&[0x0b, 0x11, 0x09, 0x07]).ok(), Some(Network::Testnet.magic())); assert_eq!(deserialize(&[0x0a, 0x03, 0xcf, 0x40]).ok(), Some(Network::Signet.magic())); assert_eq!(deserialize(&[0xfa, 0xbf, 0xb5, 0xda]).ok(), Some(Network::Regtest.magic())); - } #[test] @@ -568,7 +525,12 @@ mod tests { #[cfg(feature = "serde")] fn serde_roundtrip() { use Network::*; - let tests = vec![(Bitcoin, "bitcoin"), (Testnet, "testnet"), (Signet, "signet"), (Regtest, "regtest")]; + let tests = vec![ + (Bitcoin, "bitcoin"), + (Testnet, "testnet"), + (Signet, "signet"), + (Regtest, "regtest"), + ]; for tc in tests { let network = tc.0; diff --git a/bitcoin/src/network/message.rs b/bitcoin/src/network/message.rs index 008a871e..22479796 100644 --- a/bitcoin/src/network/message.rs +++ b/bitcoin/src/network/message.rs @@ -7,24 +7,22 @@ //! are used for (de)serializing Bitcoin objects for transmission on the network. //! -use crate::prelude::*; - -use core::{fmt, iter}; use core::convert::TryFrom; +use core::{fmt, iter}; -use crate::io; use io::Read as _; -use crate::blockdata::block; -use crate::blockdata::transaction; -use crate::network::address::{Address, AddrV2Message}; -use crate::network::{message_network, message_bloom}; -use crate::network::message_blockdata; -use crate::network::message_filter; -use crate::network::message_compact_blocks; -use crate::network::constants::Magic; + +use crate::blockdata::{block, transaction}; use crate::consensus::encode::{CheckedData, Decodable, Encodable, VarInt}; use crate::consensus::{encode, serialize}; +use crate::io; use crate::merkle_tree::MerkleBlock; +use crate::network::address::{AddrV2Message, Address}; +use crate::network::constants::Magic; +use crate::network::{ + message_blockdata, message_bloom, message_compact_blocks, message_filter, message_network, +}; +use crate::prelude::*; /// The maximum number of [super::message_blockdata::Inventory] items in an `inv` message. /// @@ -95,15 +93,11 @@ impl core::str::FromStr for CommandString { } impl fmt::Display for CommandString { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(self.0.as_ref()) - } + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(self.0.as_ref()) } } impl AsRef for CommandString { - fn as_ref(&self) -> &str { - self.0.as_ref() - } + fn as_ref(&self) -> &str { self.0.as_ref() } } impl Encodable for CommandString { @@ -121,11 +115,13 @@ impl Decodable for CommandString { #[inline] fn consensus_decode(r: &mut R) -> Result { let rawbytes: [u8; 12] = Decodable::consensus_decode(r)?; - let rv = iter::FromIterator::from_iter( - rawbytes - .iter() - .filter_map(|&u| if u > 0 { Some(u as char) } else { None }) - ); + let rv = iter::FromIterator::from_iter(rawbytes.iter().filter_map(|&u| { + if u > 0 { + Some(u as char) + } else { + None + } + })); Ok(CommandString(rv)) } } @@ -140,7 +136,12 @@ pub struct CommandStringError { impl fmt::Display for CommandStringError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "the command string '{}' has length {} which is larger than 12", self.cow, self.cow.len()) + write!( + f, + "the command string '{}' has length {} which is larger than 12", + self.cow, + self.cow.len() + ) } } @@ -152,7 +153,7 @@ pub struct RawNetworkMessage { /// Magic bytes to identify the network these messages are meant for pub magic: Magic, /// The actual message data - pub payload: NetworkMessage + pub payload: NetworkMessage, } /// A Network message payload. Proper documentation is available on at @@ -241,7 +242,7 @@ pub enum NetworkMessage { command: CommandString, /// The payload of this message. payload: Vec, - } + }, } impl NetworkMessage { @@ -253,25 +254,25 @@ impl NetworkMessage { pub fn cmd(&self) -> &'static str { match *self { NetworkMessage::Version(_) => "version", - NetworkMessage::Verack => "verack", - NetworkMessage::Addr(_) => "addr", - NetworkMessage::Inv(_) => "inv", + NetworkMessage::Verack => "verack", + NetworkMessage::Addr(_) => "addr", + NetworkMessage::Inv(_) => "inv", NetworkMessage::GetData(_) => "getdata", NetworkMessage::NotFound(_) => "notfound", NetworkMessage::GetBlocks(_) => "getblocks", NetworkMessage::GetHeaders(_) => "getheaders", - NetworkMessage::MemPool => "mempool", - NetworkMessage::Tx(_) => "tx", - NetworkMessage::Block(_) => "block", + NetworkMessage::MemPool => "mempool", + NetworkMessage::Tx(_) => "tx", + NetworkMessage::Block(_) => "block", NetworkMessage::Headers(_) => "headers", NetworkMessage::SendHeaders => "sendheaders", - NetworkMessage::GetAddr => "getaddr", - NetworkMessage::Ping(_) => "ping", - NetworkMessage::Pong(_) => "pong", + NetworkMessage::GetAddr => "getaddr", + NetworkMessage::Ping(_) => "ping", + NetworkMessage::Pong(_) => "pong", NetworkMessage::MerkleBlock(_) => "merkleblock", NetworkMessage::FilterLoad(_) => "filterload", - NetworkMessage::FilterAdd(_) => "filteradd", - NetworkMessage::FilterClear => "filterclear", + NetworkMessage::FilterAdd(_) => "filteradd", + NetworkMessage::FilterClear => "filterclear", NetworkMessage::GetCFilters(_) => "getcfilters", NetworkMessage::CFilter(_) => "cfilter", NetworkMessage::GetCFHeaders(_) => "getcfheaders", @@ -282,8 +283,8 @@ impl NetworkMessage { NetworkMessage::CmpctBlock(_) => "cmpctblock", NetworkMessage::GetBlockTxn(_) => "getblocktxn", NetworkMessage::BlockTxn(_) => "blocktxn", - NetworkMessage::Alert(_) => "alert", - NetworkMessage::Reject(_) => "reject", + NetworkMessage::Alert(_) => "alert", + NetworkMessage::Reject(_) => "reject", NetworkMessage::FeeFilter(_) => "feefilter", NetworkMessage::WtxidRelay => "wtxidrelay", NetworkMessage::AddrV2(_) => "addrv2", @@ -296,7 +297,7 @@ impl NetworkMessage { pub fn command(&self) -> CommandString { match *self { NetworkMessage::Unknown { command: ref c, .. } => c.clone(), - _ => CommandString::try_from_static(self.cmd()).expect("cmd returns valid commands") + _ => CommandString::try_from_static(self.cmd()).expect("cmd returns valid commands"), } } } @@ -307,14 +308,10 @@ impl RawNetworkMessage { /// This returns `"unknown"` for [NetworkMessage::Unknown], /// regardless of the actual command in the unknown message. /// Use the [Self::command] method to get the command for unknown messages. - pub fn cmd(&self) -> &'static str { - self.payload.cmd() - } + pub fn cmd(&self) -> &'static str { self.payload.cmd() } /// Return the CommandString for the message command. - pub fn command(&self) -> CommandString { - self.payload.command() - } + pub fn command(&self) -> CommandString { self.payload.command() } } struct HeaderSerializationWrapper<'a>(&'a Vec); @@ -339,20 +336,20 @@ impl Encodable for RawNetworkMessage { len += self.command().consensus_encode(w)?; len += CheckedData(match self.payload { NetworkMessage::Version(ref dat) => serialize(dat), - NetworkMessage::Addr(ref dat) => serialize(dat), - NetworkMessage::Inv(ref dat) => serialize(dat), + NetworkMessage::Addr(ref dat) => serialize(dat), + NetworkMessage::Inv(ref dat) => serialize(dat), NetworkMessage::GetData(ref dat) => serialize(dat), NetworkMessage::NotFound(ref dat) => serialize(dat), NetworkMessage::GetBlocks(ref dat) => serialize(dat), NetworkMessage::GetHeaders(ref dat) => serialize(dat), - NetworkMessage::Tx(ref dat) => serialize(dat), - NetworkMessage::Block(ref dat) => serialize(dat), + NetworkMessage::Tx(ref dat) => serialize(dat), + NetworkMessage::Block(ref dat) => serialize(dat), NetworkMessage::Headers(ref dat) => serialize(&HeaderSerializationWrapper(dat)), - NetworkMessage::Ping(ref dat) => serialize(dat), - NetworkMessage::Pong(ref dat) => serialize(dat), - NetworkMessage::MerkleBlock(ref dat) => serialize(dat), - NetworkMessage::FilterLoad(ref dat) => serialize(dat), - NetworkMessage::FilterAdd(ref dat) => serialize(dat), + NetworkMessage::Ping(ref dat) => serialize(dat), + NetworkMessage::Pong(ref dat) => serialize(dat), + NetworkMessage::MerkleBlock(ref dat) => serialize(dat), + NetworkMessage::FilterLoad(ref dat) => serialize(dat), + NetworkMessage::FilterAdd(ref dat) => serialize(dat), NetworkMessage::GetCFilters(ref dat) => serialize(dat), NetworkMessage::CFilter(ref dat) => serialize(dat), NetworkMessage::GetCFHeaders(ref dat) => serialize(dat), @@ -363,7 +360,7 @@ impl Encodable for RawNetworkMessage { NetworkMessage::CmpctBlock(ref dat) => serialize(dat), NetworkMessage::GetBlockTxn(ref dat) => serialize(dat), NetworkMessage::BlockTxn(ref dat) => serialize(dat), - NetworkMessage::Alert(ref dat) => serialize(dat), + NetworkMessage::Alert(ref dat) => serialize(dat), NetworkMessage::Reject(ref dat) => serialize(dat), NetworkMessage::FeeFilter(ref data) => serialize(data), NetworkMessage::AddrV2(ref dat) => serialize(dat), @@ -375,7 +372,8 @@ impl Encodable for RawNetworkMessage { | NetworkMessage::FilterClear | NetworkMessage::SendAddrV2 => vec![], NetworkMessage::Unknown { payload: ref data, .. } => serialize(data), - }).consensus_encode(w)?; + }) + .consensus_encode(w)?; Ok(len) } } @@ -384,7 +382,9 @@ struct HeaderDeserializationWrapper(Vec); impl Decodable for HeaderDeserializationWrapper { #[inline] - fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + fn consensus_decode_from_finite_reader( + r: &mut R, + ) -> Result { let len = VarInt::consensus_decode(r)?.0; // should be above usual number of items to avoid // allocation @@ -392,7 +392,9 @@ impl Decodable for HeaderDeserializationWrapper { for _ in 0..len { ret.push(Decodable::consensus_decode(r)?); if u8::consensus_decode(r)? != 0u8 { - return Err(encode::Error::ParseFailed("Headers message should not contain transactions")); + return Err(encode::Error::ParseFailed( + "Headers message should not contain transactions", + )); } } Ok(HeaderDeserializationWrapper(ret)) @@ -405,60 +407,99 @@ impl Decodable for HeaderDeserializationWrapper { } impl Decodable for RawNetworkMessage { - fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + fn consensus_decode_from_finite_reader( + r: &mut R, + ) -> Result { let magic = Decodable::consensus_decode_from_finite_reader(r)?; let cmd = CommandString::consensus_decode_from_finite_reader(r)?; let raw_payload = CheckedData::consensus_decode_from_finite_reader(r)?.0; let mut mem_d = io::Cursor::new(raw_payload); let payload = match &cmd.0[..] { - "version" => NetworkMessage::Version(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "verack" => NetworkMessage::Verack, - "addr" => NetworkMessage::Addr(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "inv" => NetworkMessage::Inv(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "getdata" => NetworkMessage::GetData(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "notfound" => NetworkMessage::NotFound(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "getblocks" => NetworkMessage::GetBlocks(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "getheaders" => NetworkMessage::GetHeaders(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "version" => + NetworkMessage::Version(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "verack" => NetworkMessage::Verack, + "addr" => + NetworkMessage::Addr(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "inv" => + NetworkMessage::Inv(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "getdata" => + NetworkMessage::GetData(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "notfound" => NetworkMessage::NotFound(Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + )?), + "getblocks" => NetworkMessage::GetBlocks( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "getheaders" => NetworkMessage::GetHeaders( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), "mempool" => NetworkMessage::MemPool, - "block" => NetworkMessage::Block(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "block" => + NetworkMessage::Block(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), "headers" => NetworkMessage::Headers( - HeaderDeserializationWrapper::consensus_decode_from_finite_reader(&mut mem_d)?.0 + HeaderDeserializationWrapper::consensus_decode_from_finite_reader(&mut mem_d)?.0, ), "sendheaders" => NetworkMessage::SendHeaders, "getaddr" => NetworkMessage::GetAddr, - "ping" => NetworkMessage::Ping(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "pong" => NetworkMessage::Pong(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "merkleblock" => NetworkMessage::MerkleBlock(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "filterload" => NetworkMessage::FilterLoad(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "filteradd" => NetworkMessage::FilterAdd(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "ping" => + NetworkMessage::Ping(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "pong" => + NetworkMessage::Pong(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "merkleblock" => NetworkMessage::MerkleBlock( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "filterload" => NetworkMessage::FilterLoad( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "filteradd" => NetworkMessage::FilterAdd( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), "filterclear" => NetworkMessage::FilterClear, - "tx" => NetworkMessage::Tx(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "getcfilters" => NetworkMessage::GetCFilters(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "cfilter" => NetworkMessage::CFilter(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "getcfheaders" => NetworkMessage::GetCFHeaders(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "cfheaders" => NetworkMessage::CFHeaders(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "getcfcheckpt" => NetworkMessage::GetCFCheckpt(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "cfcheckpt" => NetworkMessage::CFCheckpt(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "reject" => NetworkMessage::Reject(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "alert" => NetworkMessage::Alert(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "feefilter" => NetworkMessage::FeeFilter(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "sendcmpct" => NetworkMessage::SendCmpct(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "cmpctblock" => NetworkMessage::CmpctBlock(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "getblocktxn" => NetworkMessage::GetBlockTxn(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), - "blocktxn" => NetworkMessage::BlockTxn(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "tx" => NetworkMessage::Tx(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "getcfilters" => NetworkMessage::GetCFilters( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "cfilter" => + NetworkMessage::CFilter(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "getcfheaders" => NetworkMessage::GetCFHeaders( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "cfheaders" => NetworkMessage::CFHeaders( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "getcfcheckpt" => NetworkMessage::GetCFCheckpt( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "cfcheckpt" => NetworkMessage::CFCheckpt( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "reject" => + NetworkMessage::Reject(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "alert" => + NetworkMessage::Alert(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "feefilter" => NetworkMessage::FeeFilter( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "sendcmpct" => NetworkMessage::SendCmpct( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "cmpctblock" => NetworkMessage::CmpctBlock( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "getblocktxn" => NetworkMessage::GetBlockTxn( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "blocktxn" => NetworkMessage::BlockTxn(Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + )?), "wtxidrelay" => NetworkMessage::WtxidRelay, - "addrv2" => NetworkMessage::AddrV2(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "addrv2" => + NetworkMessage::AddrV2(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), "sendaddrv2" => NetworkMessage::SendAddrV2, - _ => NetworkMessage::Unknown { - command: cmd, - payload: mem_d.into_inner(), - } + _ => NetworkMessage::Unknown { command: cmd, payload: mem_d.into_inner() }, }; - Ok(RawNetworkMessage { - magic, - payload, - }) + Ok(RawNetworkMessage { magic, payload }) } #[inline] @@ -469,29 +510,28 @@ impl Decodable for RawNetworkMessage { #[cfg(test)] mod test { - use super::*; - use std::net::Ipv4Addr; - use super::{RawNetworkMessage, NetworkMessage, CommandString}; - use crate::network::constants::{ServiceFlags, Magic, Network}; + + use super::message_network::{Reject, RejectReason, VersionMessage}; + use super::{CommandString, NetworkMessage, RawNetworkMessage, *}; + use crate::bip152::BlockTransactionsRequest; + use crate::blockdata::block::{self, Block}; + use crate::blockdata::script::Script; + use crate::blockdata::transaction::Transaction; use crate::consensus::encode::{deserialize, deserialize_partial, serialize}; use crate::hashes::hex::FromHex; use crate::hashes::sha256d::Hash; use crate::hashes::Hash as HashTrait; - use crate::network::address::{Address, AddrV2, AddrV2Message}; - use super::message_network::{Reject, RejectReason, VersionMessage}; - use crate::network::message_blockdata::{Inventory, GetBlocksMessage, GetHeadersMessage}; - use crate::blockdata::block::{self, Block}; - use crate::network::message_filter::{GetCFilters, CFilter, GetCFHeaders, CFHeaders, GetCFCheckpt, CFCheckpt}; - use crate::blockdata::transaction::Transaction; - use crate::blockdata::script::Script; - use crate::network::message_bloom::{FilterAdd, FilterLoad, BloomFlags}; + use crate::network::address::{AddrV2, AddrV2Message, Address}; + use crate::network::constants::{Magic, Network, ServiceFlags}; + use crate::network::message_blockdata::{GetBlocksMessage, GetHeadersMessage, Inventory}; + use crate::network::message_bloom::{BloomFlags, FilterAdd, FilterLoad}; use crate::network::message_compact_blocks::{GetBlockTxn, SendCmpct}; - use crate::bip152::BlockTransactionsRequest; + use crate::network::message_filter::{ + CFCheckpt, CFHeaders, CFilter, GetCFCheckpt, GetCFHeaders, GetCFilters, + }; - fn hash(slice: [u8;32]) -> Hash { - Hash::from_slice(&slice).unwrap() - } + fn hash(slice: [u8; 32]) -> Hash { Hash::from_slice(&slice).unwrap() } #[test] fn full_round_ser_der_raw_network_message_test() { @@ -500,21 +540,32 @@ mod test { let tx: Transaction = deserialize(&Vec::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap()).unwrap(); let block: Block = deserialize(&include_bytes!("../../tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw")[..]).unwrap(); let header: block::Header = deserialize(&Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap()).unwrap(); - let script: Script = deserialize(&Vec::from_hex("1976a91431a420903c05a0a7de2de40c9f02ebedbacdc17288ac").unwrap()).unwrap(); + let script: Script = deserialize( + &Vec::from_hex("1976a91431a420903c05a0a7de2de40c9f02ebedbacdc17288ac").unwrap(), + ) + .unwrap(); let merkle_block: MerkleBlock = deserialize(&Vec::from_hex("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630100000001b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f19630101").unwrap()).unwrap(); let cmptblock = deserialize(&Vec::from_hex("00000030d923ad36ff2d955abab07f8a0a6e813bc6e066b973e780c5e36674cad5d1cd1f6e265f2a17a0d35cbe701fe9d06e2c6324cfe135f6233e8b767bfa3fb4479b71115dc562ffff7f2006000000000000000000000000010002000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0302ee00ffffffff0100f9029500000000015100000000").unwrap()).unwrap(); let blocktxn = deserialize(&Vec::from_hex("2e93c0cff39ff605020072d96bc3a8d20b8447e294d08092351c8583e08d9b5a01020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0402dc0000ffffffff0200f90295000000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()).unwrap(); - let msgs = vec![ NetworkMessage::Version(version_msg), NetworkMessage::Verack, - NetworkMessage::Addr(vec![(45, Address::new(&([123,255,000,100], 833).into(), ServiceFlags::NETWORK))]), + NetworkMessage::Addr(vec![( + 45, + Address::new(&([123, 255, 000, 100], 833).into(), ServiceFlags::NETWORK), + )]), NetworkMessage::Inv(vec![Inventory::Block(hash([8u8; 32]).into())]), NetworkMessage::GetData(vec![Inventory::Transaction(hash([45u8; 32]).into())]), NetworkMessage::NotFound(vec![Inventory::Error]), - NetworkMessage::GetBlocks(GetBlocksMessage::new(vec![hash([1u8; 32]).into(), hash([4u8; 32]).into()], hash([5u8; 32]).into())), - NetworkMessage::GetHeaders(GetHeadersMessage::new(vec![hash([10u8; 32]).into(), hash([40u8; 32]).into()], hash([50u8; 32]).into())), + NetworkMessage::GetBlocks(GetBlocksMessage::new( + vec![hash([1u8; 32]).into(), hash([4u8; 32]).into()], + hash([5u8; 32]).into(), + )), + NetworkMessage::GetHeaders(GetHeadersMessage::new( + vec![hash([10u8; 32]).into(), hash([40u8; 32]).into()], + hash([50u8; 32]).into(), + )), NetworkMessage::MemPool, NetworkMessage::Tx(tx), NetworkMessage::Block(block), @@ -524,39 +575,86 @@ mod test { NetworkMessage::Ping(15), NetworkMessage::Pong(23), NetworkMessage::MerkleBlock(merkle_block), - NetworkMessage::FilterLoad(FilterLoad {filter: Vec::from_hex("03614e9b050000000000000001").unwrap(), hash_funcs: 1, tweak: 2, flags: BloomFlags::All}), - NetworkMessage::FilterAdd(FilterAdd {data: script.as_bytes().to_vec()}), - NetworkMessage::FilterAdd(FilterAdd {data: hash([29u8; 32]).to_vec()}), + NetworkMessage::FilterLoad(FilterLoad { + filter: Vec::from_hex("03614e9b050000000000000001").unwrap(), + hash_funcs: 1, + tweak: 2, + flags: BloomFlags::All, + }), + NetworkMessage::FilterAdd(FilterAdd { data: script.as_bytes().to_vec() }), + NetworkMessage::FilterAdd(FilterAdd { data: hash([29u8; 32]).to_vec() }), NetworkMessage::FilterClear, - NetworkMessage::GetCFilters(GetCFilters{filter_type: 2, start_height: 52, stop_hash: hash([42u8; 32]).into()}), - NetworkMessage::CFilter(CFilter{filter_type: 7, block_hash: hash([25u8; 32]).into(), filter: vec![1,2,3]}), - NetworkMessage::GetCFHeaders(GetCFHeaders{filter_type: 4, start_height: 102, stop_hash: hash([47u8; 32]).into()}), - NetworkMessage::CFHeaders(CFHeaders{filter_type: 13, stop_hash: hash([53u8; 32]).into(), previous_filter_header: hash([12u8; 32]).into(), filter_hashes: vec![hash([4u8; 32]).into(), hash([12u8; 32]).into()]}), - NetworkMessage::GetCFCheckpt(GetCFCheckpt{filter_type: 17, stop_hash: hash([25u8; 32]).into()}), - NetworkMessage::CFCheckpt(CFCheckpt{filter_type: 27, stop_hash: hash([77u8; 32]).into(), filter_headers: vec![hash([3u8; 32]).into(), hash([99u8; 32]).into()]}), - NetworkMessage::Alert(vec![45,66,3,2,6,8,9,12,3,130]), - NetworkMessage::Reject(Reject{message: "Test reject".into(), ccode: RejectReason::Duplicate, reason: "Cause".into(), hash: hash([255u8; 32])}), + NetworkMessage::GetCFilters(GetCFilters { + filter_type: 2, + start_height: 52, + stop_hash: hash([42u8; 32]).into(), + }), + NetworkMessage::CFilter(CFilter { + filter_type: 7, + block_hash: hash([25u8; 32]).into(), + filter: vec![1, 2, 3], + }), + NetworkMessage::GetCFHeaders(GetCFHeaders { + filter_type: 4, + start_height: 102, + stop_hash: hash([47u8; 32]).into(), + }), + NetworkMessage::CFHeaders(CFHeaders { + filter_type: 13, + stop_hash: hash([53u8; 32]).into(), + previous_filter_header: hash([12u8; 32]).into(), + filter_hashes: vec![hash([4u8; 32]).into(), hash([12u8; 32]).into()], + }), + NetworkMessage::GetCFCheckpt(GetCFCheckpt { + filter_type: 17, + stop_hash: hash([25u8; 32]).into(), + }), + NetworkMessage::CFCheckpt(CFCheckpt { + filter_type: 27, + stop_hash: hash([77u8; 32]).into(), + filter_headers: vec![hash([3u8; 32]).into(), hash([99u8; 32]).into()], + }), + NetworkMessage::Alert(vec![45, 66, 3, 2, 6, 8, 9, 12, 3, 130]), + NetworkMessage::Reject(Reject { + message: "Test reject".into(), + ccode: RejectReason::Duplicate, + reason: "Cause".into(), + hash: hash([255u8; 32]), + }), NetworkMessage::FeeFilter(1000), NetworkMessage::WtxidRelay, - NetworkMessage::AddrV2(vec![AddrV2Message{ addr: AddrV2::Ipv4(Ipv4Addr::new(127, 0, 0, 1)), port: 0, services: ServiceFlags::NONE, time: 0 }]), + NetworkMessage::AddrV2(vec![AddrV2Message { + addr: AddrV2::Ipv4(Ipv4Addr::new(127, 0, 0, 1)), + port: 0, + services: ServiceFlags::NONE, + time: 0, + }]), NetworkMessage::SendAddrV2, NetworkMessage::CmpctBlock(cmptblock), - NetworkMessage::GetBlockTxn(GetBlockTxn { txs_request: BlockTransactionsRequest { block_hash: hash([11u8; 32]).into(), indexes: vec![0, 1, 2, 3, 10, 3002] } }), + NetworkMessage::GetBlockTxn(GetBlockTxn { + txs_request: BlockTransactionsRequest { + block_hash: hash([11u8; 32]).into(), + indexes: vec![0, 1, 2, 3, 10, 3002], + }, + }), NetworkMessage::BlockTxn(blocktxn), - NetworkMessage::SendCmpct(SendCmpct{send_compact: true, version: 8333}), + NetworkMessage::SendCmpct(SendCmpct { send_compact: true, version: 8333 }), ]; for msg in msgs { - let raw_msg = RawNetworkMessage {magic: Magic::from_bytes([57, 0, 0, 0]), payload: msg}; + let raw_msg = + RawNetworkMessage { magic: Magic::from_bytes([57, 0, 0, 0]), payload: msg }; assert_eq!(deserialize::(&serialize(&raw_msg)).unwrap(), raw_msg); } - } #[test] fn commandstring_test() { // Test converting. - assert_eq!(CommandString::try_from_static("AndrewAndrew").unwrap().as_ref(), "AndrewAndrew"); + assert_eq!( + CommandString::try_from_static("AndrewAndrew").unwrap().as_ref(), + "AndrewAndrew" + ); assert!(CommandString::try_from_static("AndrewAndrewA").is_err()); // Test serializing. @@ -564,12 +662,14 @@ mod test { assert_eq!(serialize(&cs), vec![0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]); // Test deserializing - let cs: Result = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]); + let cs: Result = + deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]); assert!(cs.is_ok()); assert_eq!(cs.as_ref().unwrap().to_string(), "Andrew".to_owned()); assert_eq!(cs.unwrap(), CommandString::try_from_static("Andrew").unwrap()); - let short_cs: Result = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0]); + let short_cs: Result = + deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0]); assert!(short_cs.is_err()); } @@ -592,7 +692,6 @@ mod test { 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); } - #[test] #[rustfmt::skip] fn serialize_mempool_test() { @@ -619,9 +718,12 @@ mod test { 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2 ]); - let preimage = RawNetworkMessage { magic: Magic::from(Network::Bitcoin), payload: NetworkMessage::GetAddr }; + let preimage = RawNetworkMessage { + magic: Magic::from(Network::Bitcoin), + payload: NetworkMessage::GetAddr, + }; assert!(msg.is_ok()); - let msg : RawNetworkMessage = msg.unwrap(); + let msg: RawNetworkMessage = msg.unwrap(); assert_eq!(preimage.magic, msg.magic); assert_eq!(preimage.payload, msg.payload); } @@ -653,7 +755,13 @@ mod test { assert_eq!(msg.magic, Magic::from(Network::Bitcoin)); if let NetworkMessage::Version(version_msg) = msg.payload { assert_eq!(version_msg.version, 70015); - assert_eq!(version_msg.services, ServiceFlags::NETWORK | ServiceFlags::BLOOM | ServiceFlags::WITNESS | ServiceFlags::NETWORK_LIMITED); + assert_eq!( + version_msg.services, + ServiceFlags::NETWORK + | ServiceFlags::BLOOM + | ServiceFlags::WITNESS + | ServiceFlags::NETWORK_LIMITED + ); assert_eq!(version_msg.timestamp, 1548554224); assert_eq!(version_msg.nonce, 13952548347456104954); assert_eq!(version_msg.user_agent, "/Satoshi:0.17.1/"); @@ -693,7 +801,13 @@ mod test { assert_eq!(msg.magic, Magic::from(Network::Bitcoin)); if let NetworkMessage::Version(version_msg) = msg.payload { assert_eq!(version_msg.version, 70015); - assert_eq!(version_msg.services, ServiceFlags::NETWORK | ServiceFlags::BLOOM | ServiceFlags::WITNESS | ServiceFlags::NETWORK_LIMITED); + assert_eq!( + version_msg.services, + ServiceFlags::NETWORK + | ServiceFlags::BLOOM + | ServiceFlags::WITNESS + | ServiceFlags::NETWORK_LIMITED + ); assert_eq!(version_msg.timestamp, 1548554224); assert_eq!(version_msg.nonce, 13952548347456104954); assert_eq!(version_msg.user_agent, "/Satoshi:0.17.1/"); diff --git a/bitcoin/src/network/message_blockdata.rs b/bitcoin/src/network/message_blockdata.rs index 0e51748f..8521616d 100644 --- a/bitcoin/src/network/message_blockdata.rs +++ b/bitcoin/src/network/message_blockdata.rs @@ -7,16 +7,13 @@ //! Bitcoin data (blocks and transactions) around. //! -use crate::prelude::*; - -use crate::io; - -use crate::hashes::{Hash as _, sha256d}; - -use crate::network::constants; use crate::consensus::encode::{self, Decodable, Encodable}; use crate::hash_types::{BlockHash, Txid, Wtxid}; +use crate::hashes::{sha256d, Hash as _}; use crate::internal_macros::impl_consensus_encoding; +use crate::io; +use crate::network::constants; +use crate::prelude::*; /// An inventory item. #[derive(PartialEq, Eq, Clone, Debug, Copy, Hash, PartialOrd, Ord)] @@ -41,7 +38,7 @@ pub enum Inventory { inv_type: u32, /// The hash of the inventory item hash: [u8; 32], - } + }, } impl Encodable for Inventory { @@ -50,7 +47,7 @@ impl Encodable for Inventory { macro_rules! encode_inv { ($code:expr, $item:expr) => { u32::consensus_encode(&$code, w)? + $item.consensus_encode(w)? - } + }; } Ok(match *self { Inventory::Error => encode_inv!(0, sha256d::Hash::all_zeros()), @@ -77,10 +74,7 @@ impl Decodable for Inventory { 5 => Inventory::WTx(Decodable::consensus_decode(r)?), 0x40000001 => Inventory::WitnessTransaction(Decodable::consensus_decode(r)?), 0x40000002 => Inventory::WitnessBlock(Decodable::consensus_decode(r)?), - tp => Inventory::Unknown { - inv_type: tp, - hash: Decodable::consensus_decode(r)?, - } + tp => Inventory::Unknown { inv_type: tp, hash: Decodable::consensus_decode(r)? }, }) } } @@ -110,17 +104,13 @@ pub struct GetHeadersMessage { /// if possible and block 1 otherwise. pub locator_hashes: Vec, /// References the header to stop at, or zero to just fetch the maximum 2000 headers - pub stop_hash: BlockHash + pub stop_hash: BlockHash, } impl GetBlocksMessage { /// Construct a new `getblocks` message pub fn new(locator_hashes: Vec, stop_hash: BlockHash) -> GetBlocksMessage { - GetBlocksMessage { - version: constants::PROTOCOL_VERSION, - locator_hashes, - stop_hash, - } + GetBlocksMessage { version: constants::PROTOCOL_VERSION, locator_hashes, stop_hash } } } @@ -129,11 +119,7 @@ impl_consensus_encoding!(GetBlocksMessage, version, locator_hashes, stop_hash); impl GetHeadersMessage { /// Construct a new `getheaders` message pub fn new(locator_hashes: Vec, stop_hash: BlockHash) -> GetHeadersMessage { - GetHeadersMessage { - version: constants::PROTOCOL_VERSION, - locator_hashes, - stop_hash, - } + GetHeadersMessage { version: constants::PROTOCOL_VERSION, locator_hashes, stop_hash } } } @@ -141,16 +127,17 @@ impl_consensus_encoding!(GetHeadersMessage, version, locator_hashes, stop_hash); #[cfg(test)] mod tests { - use super::{Vec, GetHeadersMessage, GetBlocksMessage}; - + use super::{GetBlocksMessage, GetHeadersMessage, Vec}; + use crate::consensus::encode::{deserialize, serialize}; use crate::hashes::hex::FromHex; use crate::hashes::Hash; - use crate::consensus::encode::{deserialize, serialize}; #[test] fn getblocks_message_test() { let from_sat = Vec::from_hex("72110100014a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b0000000000000000000000000000000000000000000000000000000000000000").unwrap(); - let genhash = Vec::from_hex("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b").unwrap(); + let genhash = + Vec::from_hex("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b") + .unwrap(); let decode: Result = deserialize(&from_sat); assert!(decode.is_ok()); @@ -166,7 +153,9 @@ mod tests { #[test] fn getheaders_message_test() { let from_sat = Vec::from_hex("72110100014a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b0000000000000000000000000000000000000000000000000000000000000000").unwrap(); - let genhash = Vec::from_hex("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b").unwrap(); + let genhash = + Vec::from_hex("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b") + .unwrap(); let decode: Result = deserialize(&from_sat); assert!(decode.is_ok()); diff --git a/bitcoin/src/network/message_bloom.rs b/bitcoin/src/network/message_bloom.rs index 31430869..e3dcbe18 100644 --- a/bitcoin/src/network/message_bloom.rs +++ b/bitcoin/src/network/message_bloom.rs @@ -5,11 +5,11 @@ //! This module describes BIP37 Connection Bloom filtering network messages. //! -use crate::consensus::encode; -use crate::consensus::{Decodable, Encodable, ReadExt}; -use crate::internal_macros::impl_consensus_encoding; use std::io; +use crate::consensus::{encode, Decodable, Encodable, ReadExt}; +use crate::internal_macros::impl_consensus_encoding; + /// `filterload` message sets the current bloom filter #[derive(Clone, PartialEq, Eq, Debug)] pub struct FilterLoad { diff --git a/bitcoin/src/network/message_compact_blocks.rs b/bitcoin/src/network/message_compact_blocks.rs index 6a92a15d..8827e543 100644 --- a/bitcoin/src/network/message_compact_blocks.rs +++ b/bitcoin/src/network/message_compact_blocks.rs @@ -2,8 +2,8 @@ //! BIP152 Compact Blocks network messages //! -use crate::internal_macros::impl_consensus_encoding; use crate::bip152; +use crate::internal_macros::impl_consensus_encoding; /// sendcmpct message #[derive(PartialEq, Eq, Clone, Debug, Copy, PartialOrd, Ord, Hash)] diff --git a/bitcoin/src/network/message_network.rs b/bitcoin/src/network/message_network.rs index 1db65b82..b8ac228e 100644 --- a/bitcoin/src/network/message_network.rs +++ b/bitcoin/src/network/message_network.rs @@ -7,16 +7,13 @@ //! capabilities. //! -use crate::prelude::*; - -use crate::io; - -use crate::network::address::Address; -use crate::network::constants::{self, ServiceFlags}; -use crate::consensus::{Encodable, Decodable, ReadExt}; -use crate::consensus::encode; +use crate::consensus::{encode, Decodable, Encodable, ReadExt}; use crate::hashes::sha256d; use crate::internal_macros::impl_consensus_encoding; +use crate::io; +use crate::network::address::Address; +use crate::network::constants::{self, ServiceFlags}; +use crate::prelude::*; /// Some simple messages @@ -42,7 +39,7 @@ pub struct VersionMessage { /// Whether the receiving peer should relay messages to the sender; used /// if the sender is bandwidth-limited and would like to support bloom /// filtering. Defaults to false. - pub relay: bool + pub relay: bool, } impl VersionMessage { @@ -70,9 +67,18 @@ impl VersionMessage { } } -impl_consensus_encoding!(VersionMessage, version, services, timestamp, - receiver, sender, nonce, - user_agent, start_height, relay); +impl_consensus_encoding!( + VersionMessage, + version, + services, + timestamp, + receiver, + sender, + nonce, + user_agent, + start_height, + relay +); /// message rejection reason as a code #[derive(PartialEq, Eq, Clone, Copy, Debug)] @@ -92,7 +98,7 @@ pub enum RejectReason { /// insufficient fee Fee = 0x42, /// checkpoint - Checkpoint = 0x43 + Checkpoint = 0x43, } impl Encodable for RejectReason { @@ -113,7 +119,7 @@ impl Decodable for RejectReason { 0x41 => RejectReason::Dust, 0x42 => RejectReason::Fee, 0x43 => RejectReason::Checkpoint, - _ => return Err(encode::Error::ParseFailed("unknown reject code")) + _ => return Err(encode::Error::ParseFailed("unknown reject code")), }) } } @@ -128,23 +134,19 @@ pub struct Reject { /// reason of rejectection pub reason: Cow<'static, str>, /// reference to rejected item - pub hash: sha256d::Hash + pub hash: sha256d::Hash, } impl_consensus_encoding!(Reject, message, ccode, reason, hash); #[cfg(test)] mod tests { - use super::VersionMessage; - use super::Reject; - use super::RejectReason; - + use super::{Reject, RejectReason, VersionMessage}; + use crate::consensus::encode::{deserialize, serialize}; use crate::hashes::hex::FromHex; use crate::hashes::sha256d::Hash; use crate::network::constants::ServiceFlags; - use crate::consensus::encode::{deserialize, serialize}; - #[test] fn version_message_test() { // This message is from my satoshi node, morning of May 27 2014 @@ -181,7 +183,8 @@ mod tests { assert_eq!(RejectReason::Duplicate, conflict.ccode); assert_eq!("txn-mempool-conflict", conflict.reason); assert_eq!( - Hash::from_hex("0470f4f2dc4191221b59884bcffaaf00932748ab46356a80413c0b86d354df05").unwrap(), + Hash::from_hex("0470f4f2dc4191221b59884bcffaaf00932748ab46356a80413c0b86d354df05") + .unwrap(), conflict.hash ); @@ -190,7 +193,8 @@ mod tests { assert_eq!(RejectReason::NonStandard, nonfinal.ccode); assert_eq!("non-final", nonfinal.reason); assert_eq!( - Hash::from_hex("0b46a539138b5fde4e341b37f2d945c23d41193b30caa7fcbd8bdb836cbe9b25").unwrap(), + Hash::from_hex("0b46a539138b5fde4e341b37f2d945c23d41193b30caa7fcbd8bdb836cbe9b25") + .unwrap(), nonfinal.hash ); diff --git a/bitcoin/src/network/mod.rs b/bitcoin/src/network/mod.rs index dfefbb6f..0450156f 100644 --- a/bitcoin/src/network/mod.rs +++ b/bitcoin/src/network/mod.rs @@ -29,7 +29,7 @@ pub mod message_bloom; pub mod message_compact_blocks; #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -pub mod message_network; +pub mod message_filter; #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -pub mod message_filter; +pub mod message_network;