From cb9893c4a974e3bed8288871d8e93d5aab087c32 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 16 Aug 2022 15:07:59 +1000 Subject: [PATCH 1/2] Add Target and Difficulty types Currently we use the `Uint256` type to represent two proof of work integers, namely target and difficulty (work). It would be nice to not have a public integer type that is not fully implemented (i.e., does not implement arithmetic etc as do integer types in stdlib). Instead of implementing all the stdlib functions we can instead add two new wrapper types, since these are not general purpose integers they do not need to implement anything we do not need to use. - Add a `pow` module. - Put a modified version of `Uint256` to `pow`. - Add two new wrapper types `Target` and `Difficulty`. - Only implement methods that we use on each type. Note this patch does not remove the original `Uint256`, that will be done as a separate patch. --- .github/workflows/fuzz.yml | 2 +- bitcoin/src/blockdata/block.rs | 124 +-- bitcoin/src/blockdata/constants.rs | 21 +- bitcoin/src/consensus/params.rs | 41 +- bitcoin/src/lib.rs | 2 + bitcoin/src/pow.rs | 1536 ++++++++++++++++++++++++++++ bitcoin/src/util/bip152.rs | 6 +- bitcoin/src/util/endian.rs | 24 - bitcoin/src/util/mod.rs | 22 - bitcoin/src/util/uint.rs | 817 --------------- fuzz/Cargo.toml | 4 - fuzz/fuzz_targets/uint128_fuzz.rs | 113 -- 12 files changed, 1588 insertions(+), 1124 deletions(-) create mode 100644 bitcoin/src/pow.rs delete mode 100644 bitcoin/src/util/uint.rs delete mode 100644 fuzz/fuzz_targets/uint128_fuzz.rs diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index 92b61597..d60940df 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -10,7 +10,7 @@ jobs: strategy: fail-fast: false matrix: - fuzz_target: [deser_net_msg, deserialize_address, deserialize_amount, deserialize_block, deserialize_psbt, deserialize_script, deserialize_transaction, deserialize_prefilled_transaction, deserialize_witness, outpoint_string, uint128_fuzz, script_bytes_to_asm_fmt] + fuzz_target: [deser_net_msg, deserialize_address, deserialize_amount, deserialize_block, deserialize_psbt, deserialize_script, deserialize_transaction, deserialize_prefilled_transaction, deserialize_witness, outpoint_string, script_bytes_to_asm_fmt] steps: - name: Install test dependencies run: sudo apt-get update -y && sudo apt-get install -y binutils-dev libunwind8-dev libcurl4-openssl-dev libelf-dev libdw-dev cmake gcc libiberty-dev diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs index b09dd6a7..1dd8a290 100644 --- a/bitcoin/src/blockdata/block.rs +++ b/bitcoin/src/blockdata/block.rs @@ -18,12 +18,11 @@ use crate::util::Error::{BlockBadTarget, BlockBadProofOfWork}; use crate::util::hash::bitcoin_merkle_root; use crate::hashes::{Hash, HashEngine}; use crate::hash_types::{Wtxid, BlockHash, TxMerkleNode, WitnessMerkleNode, WitnessCommitment}; -use crate::util::uint::Uint256; use crate::consensus::{encode, Encodable, Decodable}; -use crate::network::constants::Network; use crate::blockdata::transaction::Transaction; -use crate::blockdata::constants::{max_target, WITNESS_SCALE_FACTOR}; +use crate::blockdata::constants::WITNESS_SCALE_FACTOR; use crate::blockdata::script; +use crate::pow::{CompactTarget, Target, Work}; use crate::VarInt; use crate::internal_macros::impl_consensus_encoding; use crate::io; @@ -50,9 +49,8 @@ pub struct BlockHeader { pub merkle_root: TxMerkleNode, /// The timestamp of the block, as claimed by the miner. pub time: u32, - /// The target value below which the blockhash must lie, encoded as a - /// a float (with well-defined rounding, of course). - pub bits: u32, + /// The target value below which the blockhash must lie. + pub bits: CompactTarget, /// The nonce, selected to obtain a low enough blockhash. pub nonce: u32, } @@ -67,91 +65,33 @@ impl BlockHeader { BlockHash::from_engine(engine) } - /// Computes the target [0, T] that a blockhash must land in to be valid. - pub fn target(&self) -> Uint256 { - Self::u256_from_compact_target(self.bits) - } - - /// Computes the target value in [`Uint256`] format, from a compact representation. - /// - /// [`Uint256`]: ../../util/uint/struct.Uint256.html - /// - /// ``` - /// use bitcoin::block::BlockHeader; - /// - /// assert_eq!(0x1d00ffff, - /// BlockHeader::compact_target_from_u256( - /// &BlockHeader::u256_from_compact_target(0x1d00ffff) - /// ) - /// ); - /// ``` - pub fn u256_from_compact_target(bits: u32) -> Uint256 { - // This is a floating-point "compact" encoding originally used by - // OpenSSL, which satoshi put into consensus code, so we're stuck - // with it. The exponent needs to have 3 subtracted from it, hence - // this goofy decoding code: - let (mant, expt) = { - let unshifted_expt = bits >> 24; - if unshifted_expt <= 3 { - ((bits & 0xFFFFFF) >> (8 * (3 - unshifted_expt as usize)), 0) - } else { - (bits & 0xFFFFFF, 8 * ((bits >> 24) - 3)) - } - }; - - // The mantissa is signed but may not be negative - if mant > 0x7FFFFF { - Default::default() - } else { - Uint256::from_u64(mant as u64).unwrap() << (expt as usize) - } - } - - /// Computes the target value in float format from Uint256 format. - pub fn compact_target_from_u256(value: &Uint256) -> u32 { - let mut size = (value.bits() + 7) / 8; - let mut compact = if size <= 3 { - (value.low_u64() << (8 * (3 - size))) as u32 - } else { - let bn = *value >> (8 * (size - 3)); - bn.low_u32() - }; - - if (compact & 0x00800000) != 0 { - compact >>= 8; - size += 1; - } - - compact | (size << 24) as u32 + /// Computes the target (range [0, T] inclusive) that a blockhash must land in to be valid. + pub fn target(&self) -> Target { + self.bits.into() } /// Computes the popular "difficulty" measure for mining. - pub fn difficulty(&self, network: Network) -> u64 { - (max_target(network) / self.target()).low_u64() + pub fn difficulty(&self) -> u128 { + self.target().difficulty() } /// Checks that the proof-of-work for the block is valid, returning the block hash. - pub fn validate_pow(&self, required_target: &Uint256) -> Result { - let target = &self.target(); + pub fn validate_pow(&self, required_target: Target) -> Result { + let target = self.target(); if target != required_target { return Err(BlockBadTarget); } let block_hash = self.block_hash(); - let mut ret = [0u64; 4]; - util::endian::bytes_to_u64_slice_le(block_hash.as_inner(), &mut ret); - let hash = &Uint256(ret); - if hash <= target { Ok(block_hash) } else { Err(BlockBadProofOfWork) } + if target.is_met_by(block_hash) { + Ok(block_hash) + } else { + Err(BlockBadProofOfWork) + } } /// Returns the total work of the block. - pub fn work(&self) -> Uint256 { - // 2**256 / (target + 1) == ~target / (target+1) + 1 (eqn shamelessly stolen from bitcoind) - let mut ret = !self.target(); - let mut ret1 = self.target(); - ret1.increment(); - ret = ret / ret1; - ret.increment(); - ret + pub fn work(&self) -> Work { + self.target().to_work() } } @@ -451,13 +391,13 @@ impl From<&Block> for BlockHash { #[cfg(test)] mod tests { + use super::*; + use crate::hashes::hex::FromHex; use crate::blockdata::block::{Block, BlockHeader, BlockVersion}; use crate::consensus::encode::{deserialize, serialize}; - use crate::util::uint::Uint256; use crate::util::Error::{BlockBadTarget, BlockBadProofOfWork}; - use crate::network::constants::Network; #[test] fn test_coinbase_and_bip34() { @@ -487,7 +427,7 @@ mod tests { let prevhash = Vec::from_hex("4ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000").unwrap(); let merkle = Vec::from_hex("bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c").unwrap(); - let work = Uint256([0x100010001u64, 0, 0, 0]); + let work = Work::from(0x100010001_u128); let decode: Result = deserialize(&some_block); let bad_decode: Result = deserialize(&cutoff_block); @@ -500,11 +440,11 @@ mod tests { assert_eq!(real_decode.header.merkle_root, real_decode.compute_merkle_root().unwrap()); assert_eq!(serialize(&real_decode.header.merkle_root), merkle); assert_eq!(real_decode.header.time, 1231965655); - assert_eq!(real_decode.header.bits, 486604799); + assert_eq!(real_decode.header.bits, CompactTarget::from_consensus(486604799)); assert_eq!(real_decode.header.nonce, 2067413810); assert_eq!(real_decode.header.work(), work); - assert_eq!(real_decode.header.validate_pow(&real_decode.header.target()).unwrap(), real_decode.block_hash()); - assert_eq!(real_decode.header.difficulty(Network::Bitcoin), 1); + assert_eq!(real_decode.header.validate_pow(real_decode.header.target()).unwrap(), real_decode.block_hash()); + assert_eq!(real_decode.header.difficulty(), 1); // [test] TODO: check the transaction data assert_eq!(real_decode.size(), some_block.len()); @@ -526,7 +466,7 @@ mod tests { let prevhash = Vec::from_hex("2aa2f2ca794ccbd40c16e2f3333f6b8b683f9e7179b2c4d74906000000000000").unwrap(); let merkle = Vec::from_hex("10bc26e70a2f672ad420a6153dd0c28b40a6002c55531bfc99bf8994a8e8f67e").unwrap(); - let work = Uint256([0x257c3becdacc64u64, 0, 0, 0]); + let work = Work::from(0x257c3becdacc64_u64); assert!(decode.is_ok()); let real_decode = decode.unwrap(); @@ -535,11 +475,11 @@ mod tests { assert_eq!(serialize(&real_decode.header.merkle_root), merkle); assert_eq!(real_decode.header.merkle_root, real_decode.compute_merkle_root().unwrap()); assert_eq!(real_decode.header.time, 1472004949); - assert_eq!(real_decode.header.bits, 0x1a06d450); + assert_eq!(real_decode.header.bits, CompactTarget::from_consensus(0x1a06d450)); assert_eq!(real_decode.header.nonce, 1879759182); assert_eq!(real_decode.header.work(), work); - assert_eq!(real_decode.header.validate_pow(&real_decode.header.target()).unwrap(), real_decode.block_hash()); - assert_eq!(real_decode.header.difficulty(Network::Testnet), 2456598); + assert_eq!(real_decode.header.validate_pow(real_decode.header.target()).unwrap(), real_decode.block_hash()); + assert_eq!(real_decode.header.difficulty(), 2456598); // [test] TODO: check the transaction data assert_eq!(real_decode.size(), segwit_block.len()); @@ -570,10 +510,10 @@ mod tests { fn validate_pow_test() { let some_header = Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap(); let some_header: BlockHeader = deserialize(&some_header).expect("Can't deserialize correct block header"); - assert_eq!(some_header.validate_pow(&some_header.target()).unwrap(), some_header.block_hash()); + assert_eq!(some_header.validate_pow(some_header.target()).unwrap(), some_header.block_hash()); // test with zero target - match some_header.validate_pow(&Uint256::default()) { + match some_header.validate_pow(Target::default()) { Err(BlockBadTarget) => (), _ => panic!("unexpected result from validate_pow"), } @@ -581,7 +521,7 @@ mod tests { // test with modified header let mut invalid_header: BlockHeader = some_header; invalid_header.version.0 += 1; - match invalid_header.validate_pow(&invalid_header.target()) { + match invalid_header.validate_pow(invalid_header.target()) { Err(BlockBadProofOfWork) => (), _ => panic!("unexpected result from validate_pow"), } @@ -593,7 +533,7 @@ mod tests { let header: BlockHeader = deserialize(&some_header).expect("Can't deserialize correct block header"); - assert_eq!(header.bits, BlockHeader::compact_target_from_u256(&header.target())); + assert_eq!(header.bits, header.target().to_compact_lossy()); } #[test] diff --git a/bitcoin/src/blockdata/constants.rs b/bitcoin/src/blockdata/constants.rs index a5648c84..fb3943e3 100644 --- a/bitcoin/src/blockdata/constants.rs +++ b/bitcoin/src/blockdata/constants.rs @@ -21,7 +21,7 @@ use crate::blockdata::transaction::{OutPoint, Transaction, TxOut, TxIn, Sequence use crate::blockdata::block::{Block, BlockHeader, BlockVersion}; use crate::blockdata::witness::Witness; use crate::network::constants::Network; -use crate::util::uint::Uint256; +use crate::pow::CompactTarget; use crate::internal_macros::{impl_array_newtype, impl_bytes_newtype}; /// How many satoshis are in "one bitcoin" @@ -55,11 +55,6 @@ pub const SUBSIDY_HALVING_INTERVAL: u32 = 210_000; /// Maximum allowed value for an integer in Script. pub const MAX_SCRIPTNUM_VALUE: u32 = 0x80000000; // 2^31 -/// In Bitcoind this is insanely described as ~((u256)0 >> 32) -pub fn max_target(_: Network) -> Uint256 { - Uint256::from_u64(0xFFFF).unwrap() << 208 -} - /// The maximum value allowed in an output (useful for sanity checking, /// since keeping everything below this value should prevent overflows /// if you are doing anything remotely sane with monetary values). @@ -119,7 +114,7 @@ pub fn genesis_block(network: Network) -> Block { prev_blockhash: Hash::all_zeros(), merkle_root, time: 1231006505, - bits: 0x1d00ffff, + bits: CompactTarget::from_consensus(0x1d00ffff), nonce: 2083236893 }, txdata, @@ -132,7 +127,7 @@ pub fn genesis_block(network: Network) -> Block { prev_blockhash: Hash::all_zeros(), merkle_root, time: 1296688602, - bits: 0x1d00ffff, + bits: CompactTarget::from_consensus(0x1d00ffff), nonce: 414098458 }, txdata, @@ -145,7 +140,7 @@ pub fn genesis_block(network: Network) -> Block { prev_blockhash: Hash::all_zeros(), merkle_root, time: 1598918400, - bits: 0x1e0377ae, + bits: CompactTarget::from_consensus(0x1e0377ae), nonce: 52613770 }, txdata, @@ -158,7 +153,7 @@ pub fn genesis_block(network: Network) -> Block { prev_blockhash: Hash::all_zeros(), merkle_root, time: 1296688602, - bits: 0x207fffff, + bits: CompactTarget::from_consensus(0x207fffff), nonce: 2 }, txdata, @@ -232,7 +227,7 @@ mod test { assert_eq!(gen.header.merkle_root.to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); assert_eq!(gen.header.time, 1231006505); - assert_eq!(gen.header.bits, 0x1d00ffff); + assert_eq!(gen.header.bits, CompactTarget::from_consensus(0x1d00ffff)); assert_eq!(gen.header.nonce, 2083236893); assert_eq!(gen.header.block_hash().to_hex(), "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"); } @@ -244,7 +239,7 @@ mod test { assert_eq!(gen.header.prev_blockhash, Hash::all_zeros()); assert_eq!(gen.header.merkle_root.to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); assert_eq!(gen.header.time, 1296688602); - assert_eq!(gen.header.bits, 0x1d00ffff); + assert_eq!(gen.header.bits, CompactTarget::from_consensus(0x1d00ffff)); assert_eq!(gen.header.nonce, 414098458); assert_eq!(gen.header.block_hash().to_hex(), "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"); } @@ -256,7 +251,7 @@ mod test { assert_eq!(gen.header.prev_blockhash, Hash::all_zeros()); assert_eq!(gen.header.merkle_root.to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); assert_eq!(gen.header.time, 1598918400); - assert_eq!(gen.header.bits, 0x1e0377ae); + assert_eq!(gen.header.bits, CompactTarget::from_consensus(0x1e0377ae)); assert_eq!(gen.header.nonce, 52613770); assert_eq!(gen.header.block_hash().to_hex(), "00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6"); } diff --git a/bitcoin/src/consensus/params.rs b/bitcoin/src/consensus/params.rs index 09feebed..dc4909d4 100644 --- a/bitcoin/src/consensus/params.rs +++ b/bitcoin/src/consensus/params.rs @@ -8,36 +8,7 @@ //! use crate::network::constants::Network; -use crate::util::uint::Uint256; - -/// Lowest possible difficulty for Mainnet. See comment on Params::pow_limit for more info. -const MAX_BITS_BITCOIN: Uint256 = Uint256([ - 0x0000000000000000u64, - 0x0000000000000000u64, - 0x0000000000000000u64, - 0x00000000ffff0000u64, -]); -/// Lowest possible difficulty for Testnet. See comment on Params::pow_limit for more info. -const MAX_BITS_TESTNET: Uint256 = Uint256([ - 0x0000000000000000u64, - 0x0000000000000000u64, - 0x0000000000000000u64, - 0x00000000ffff0000u64, -]); -/// Lowest possible difficulty for Signet. See comment on Params::pow_limit for more info. -const MAX_BITS_SIGNET: Uint256 = Uint256([ - 0x0000000000000000u64, - 0x0000000000000000u64, - 0x0000000000000000u64, - 0x00000377ae000000u64, -]); -/// Lowest possible difficulty for Regtest. See comment on Params::pow_limit for more info. -const MAX_BITS_REGTEST: Uint256 = Uint256([ - 0x0000000000000000u64, - 0x0000000000000000u64, - 0x0000000000000000u64, - 0x7fffff0000000000u64, -]); +use crate::pow::Work; /// Parameters that influence chain consensus. #[non_exhaustive] @@ -67,7 +38,7 @@ pub struct Params { /// Still, this should not affect consensus as the only place where the non-compact form of /// this is used in Bitcoin Core's consensus algorithm is in comparison and there are no /// compact-expressible values between Bitcoin Core's and the limit expressed here. - pub pow_limit: Uint256, + pub pow_limit: Work, /// Expected amount of time to mine one block. pub pow_target_spacing: u64, /// Difficulty recalculation interval. @@ -90,7 +61,7 @@ impl Params { bip66_height: 363725, // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931 rule_change_activation_threshold: 1916, // 95% miner_confirmation_window: 2016, - pow_limit: MAX_BITS_BITCOIN, + pow_limit: Work::MAINNET_MIN, pow_target_spacing: 10 * 60, // 10 minutes. pow_target_timespan: 14 * 24 * 60 * 60, // 2 weeks. allow_min_difficulty_blocks: false, @@ -104,7 +75,7 @@ impl Params { bip66_height: 330776, // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182 rule_change_activation_threshold: 1512, // 75% miner_confirmation_window: 2016, - pow_limit: MAX_BITS_TESTNET, + pow_limit: Work::TESTNET_MIN, pow_target_spacing: 10 * 60, // 10 minutes. pow_target_timespan: 14 * 24 * 60 * 60, // 2 weeks. allow_min_difficulty_blocks: true, @@ -118,7 +89,7 @@ impl Params { bip66_height: 1, rule_change_activation_threshold: 1916, // 95% miner_confirmation_window: 2016, - pow_limit: MAX_BITS_SIGNET, + pow_limit: Work::SIGNET_MIN, pow_target_spacing: 10 * 60, // 10 minutes. pow_target_timespan: 14 * 24 * 60 * 60, // 2 weeks. allow_min_difficulty_blocks: false, @@ -132,7 +103,7 @@ impl Params { bip66_height: 1251, // used only in rpc tests rule_change_activation_threshold: 108, // 75% miner_confirmation_window: 144, - pow_limit: MAX_BITS_REGTEST, + pow_limit: Work::REGTEST_MIN, pow_target_spacing: 10 * 60, // 10 minutes. pow_target_timespan: 14 * 24 * 60 * 60, // 2 weeks. allow_min_difficulty_blocks: true, diff --git a/bitcoin/src/lib.rs b/bitcoin/src/lib.rs index bb55562f..2e039e22 100644 --- a/bitcoin/src/lib.rs +++ b/bitcoin/src/lib.rs @@ -87,6 +87,7 @@ pub mod consensus; pub mod error; pub mod hash_types; pub mod policy; +pub mod pow; pub mod sign_message; pub mod util; @@ -106,6 +107,7 @@ pub use crate::blockdata::{constants, opcodes}; pub use crate::consensus::encode::VarInt; pub use crate::hash_types::*; pub use crate::network::constants::Network; +pub use crate::pow::{CompactTarget, Target, Work}; pub use crate::util::amount::{Amount, Denomination, SignedAmount}; pub use crate::util::ecdsa::{self, EcdsaSig, EcdsaSigError}; pub use crate::util::key::{KeyPair, PrivateKey, PublicKey, XOnlyPublicKey}; diff --git a/bitcoin/src/pow.rs b/bitcoin/src/pow.rs new file mode 100644 index 00000000..c1bd127c --- /dev/null +++ b/bitcoin/src/pow.rs @@ -0,0 +1,1536 @@ +// Rust Bitcoin Library - Written by the rust-bitcoin developers. +// SPDX-License-Identifier: CC0-1.0 + +//! Proof-of-work related integer types. +//! +//! Provides the [`Work`] and [`Target`] types that are use in proof-of-work calculations. The +//! functions here are designed to be fast, by that we mean it is safe to use them to check headers. +//! + +use core::fmt::{self, LowerHex, UpperHex}; +use core::ops::{Add, Div, Mul, Not, Rem, Shl, Shr, Sub}; + +use crate::consensus::encode::{self, Decodable, Encodable}; +#[cfg(doc)] +use crate::consensus::Params; +use crate::hash_types::BlockHash; +use crate::io::{self, Read, Write}; + +/// Implements $int * $ty. Requires `u64::from($int)`. +macro_rules! impl_int_mul { + ($ty:ident, $($int:ident),+ $(,)?) => { + $( + impl Mul<$ty> for $int { + + type Output = $ty; + #[inline] + fn mul(self, rhs: $ty) -> $ty { $ty(self.mul(rhs.0)) } + } + )+ + }; +} + +/// Implement traits and methods shared by `Target` and `Work`. +macro_rules! do_impl { + ($ty:ident) => { + impl $ty { + /// Creates `Self` from a big-endian byte array. + #[inline] + pub fn from_be_bytes(bytes: [u8; 32]) -> $ty { $ty(U256::from_be_bytes(bytes)) } + + /// Creates `Self` from a little-endian byte array. + #[inline] + pub fn from_le_bytes(bytes: [u8; 32]) -> $ty { $ty(U256::from_le_bytes(bytes)) } + + /// Converts `self` to a big-endian byte array. + #[inline] + pub fn to_be_bytes(self) -> [u8; 32] { self.0.to_be_bytes() } + + /// Converts `self` to a little-endian byte array. + #[inline] + pub fn to_le_bytes(self) -> [u8; 32] { self.0.to_le_bytes() } + } + + impl fmt::Display for $ty { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) } + } + + impl fmt::LowerHex for $ty { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) } + } + + impl fmt::UpperHex for $ty { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) } + } + + impl> Mul for $ty { + type Output = $ty; + #[inline] + fn mul(self, rhs: T) -> Self { $ty(self.0 * rhs) } + } + + impl_int_mul!($ty, u8, u16, u32, u64); + + impl> Div for $ty { + type Output = $ty; + #[inline] + fn div(self, rhs: T) -> Self { + let rhs = U256::from(rhs.into()); + $ty(self.0 / rhs) + } + } + }; +} + +/// A 256 bit integer representing work. +/// +/// Work is a measure of how difficult it is to find a hash below a given [`Target`]. +/// +/// ref: +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +pub struct Work(U256); + +impl Work { + /// Lowest possible work value for Mainnet. See comment on [`Params::pow_limit`] for more info. + pub const MAINNET_MIN: Work = Work(U256(0x0000_0000_ffff_0000_0000_0000_0000_0000_u128, 0)); + + /// Lowest possible work value for Testnet. See comment on [`Params::pow_limit`] for more info. + pub const TESTNET_MIN: Work = Work(U256(0x0000_0000_ffff_0000_0000_0000_0000_0000_u128, 0)); + + /// Lowest possible work value for Signet. See comment on [`Params::pow_limit`] for more info. + pub const SIGNET_MIN: Work = Work(U256(0x0000_0377_ae00_0000_0000_0000_0000_0000_u128, 0)); + + /// Lowest possible work value for Regtest. See comment on [`Params::pow_limit`] for more info. + pub const REGTEST_MIN: Work = Work(U256(0x7fff_ff00_0000_0000_0000_0000_0000_0000_u128, 0)); + + /// Converts this [`Work`] to [`Target`]. + pub fn to_target(self) -> Target { Target(self.0.inverse()) } +} +do_impl!(Work); + +impl Add for Work { + type Output = Work; + fn add(self, rhs: Self) -> Self { Work(self.0 + rhs.0) } +} + +impl Sub for Work { + type Output = Work; + fn sub(self, rhs: Self) -> Self { Work(self.0 - rhs.0) } +} + +/// A 256 bit integer representing target. +/// +/// The SHA-256 hash of a block's header must be lower than or equal to the current target for the +/// block to be accepted by the network. The lower the target, the more difficult it is to generate +/// a block. (See also [`Work`].) +/// +/// ref: +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +pub struct Target(U256); + +impl Target { + // When parsing nBits, Bitcoin Core converts a negative target threshold into a target of zero. + const ZERO: Target = Target(U256::ZERO); + /// The maximum possible target. + /// + /// This value is used to calculate difficulty, which is defined as how difficult the current + /// target makes it to find a block relative to how difficult it would be at the highest + /// possible target. Remember highest target == lowest difficulty. + /// + /// ref: + // In Bitcoind this is ~(u256)0 >> 32 stored as a floating-point type so it gets truncated, hence + // the low 208 bits are all zero. + pub const MAX: Self = Target(U256(0xFFFF_u128 << (208 - 128), 0)); + + /// The maximum possible target (see [`Target::MAX`]). + /// + /// This is provided for consistency with Rust 1.41.1, newer code should use [`Target::MAX`]. + pub fn max_value() -> Self { Target::MAX } + + /// Computes the [`Target`] value from a compact representation. + /// + /// ref: + pub fn from_compact(c: CompactTarget) -> Target { + let bits = c.0; + // This is a floating-point "compact" encoding originally used by + // OpenSSL, which satoshi put into consensus code, so we're stuck + // with it. The exponent needs to have 3 subtracted from it, hence + // this goofy decoding code. 3 is due to 3 bytes in the mantissa. + let (mant, expt) = { + let unshifted_expt = bits >> 24; + if unshifted_expt <= 3 { + ((bits & 0xFFFFFF) >> (8 * (3 - unshifted_expt as usize)), 0) + } else { + (bits & 0xFFFFFF, 8 * ((bits >> 24) - 3)) + } + }; + + // The mantissa is signed but may not be negative. + if mant > 0x7F_FFFF { + Target::ZERO + } else { + Target(U256::from(mant) << expt) + } + } + + /// Computes the compact value from a [`Target`] representation. + /// + /// The compact form is by definition lossy, this means that + /// `t == Target::from_compact(t.to_compact_lossy())` does not always hold. + pub fn to_compact_lossy(self) -> CompactTarget { + let mut size = (self.0.bits() + 7) / 8; + let mut compact = if size <= 3 { + (self.0.low_u64() << (8 * (3 - size))) as u32 + } else { + let bn = self.0 >> (8 * (size - 3)); + bn.low_u32() + }; + + if (compact & 0x0080_0000) != 0 { + compact >>= 8; + size += 1; + } + + CompactTarget(compact | (size << 24) as u32) + } + + /// Returns true if block hash is less than or equal to this [`Target`]. + /// + /// Proof-of-work validity for a block requires the hash of the block to be less than or equal + /// to the target. + pub fn is_met_by(&self, hash: BlockHash) -> bool { + use crate::hashes::Hash; + let hash = U256::from_le_bytes(hash.into_inner()); + hash <= self.0 + } + + /// Converts this [`Target`] to [`Work`]. + /// + /// "Work" is defined as the work done to mine a block with this target value (recorded in the + /// block header in compact form as nBits). This is not the same as the difficulty to mine a + /// block with this target (see `Self::difficulty`). + pub fn to_work(self) -> Work { Work(self.0.inverse()) } + + /// Computes the popular "difficulty" measure for mining. + /// + /// Difficulty represents how difficult the current target makes it to find a block, relative to + /// how difficult it would be at the highest possible target (highest target == lowest difficulty). + /// + /// For example, a difficulty of 6,695,826 means that at a given hash rate, it will, on average, + /// take ~6.6 million times as long to find a valid block as it would at a difficulty of 1, or + /// alternatively, it will take, again on average, ~6.6 million times as many hashes to find a + /// valid block + /// + /// # Note + /// + /// Difficulty is calculated using the following algorithm `max / current` where [max] is + /// defined for the Bitcoin network and `current` is the current [target] for this block. As + /// such, a low target implies a high difficulty. Since [`Target`] is represented as a 256 bit + /// integer but `difficulty()` returns only 128 bits this means for targets below approximately + /// `0xffff_ffff_ffff_ffff_ffff_ffff` `difficulty()` will saturate at `u128::MAX`. + /// + /// [max]: Target::max + /// [target]: crate::blockdata::block::BlockHeader::target + pub fn difficulty(&self) -> u128 { + let d = Target::MAX.0 / self.0; + d.saturating_to_u128() + } +} +do_impl!(Target); + +/// Encoding of 256-bit target as 32-bit float. +/// +/// This is used to encode a target into the block header. Satoshi made this part of consensus code +/// in the original version of Bitcoin, likely copying an idea from OpenSSL. +/// +/// OpenSSL's bignum (BN) type has an encoding, which is even called "compact" as in bitcoin, which +/// is exactly this format. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +pub struct CompactTarget(u32); + +impl CompactTarget { + /// Creates a [`CompactTarget`] from a consensus encoded `u32`. + pub fn from_consensus(bits: u32) -> Self { Self(bits) } + + /// Returns the consensus encoded `u32` representation of this [`CompactTarget`]. + pub fn to_consensus(self) -> u32 { self.0 } +} + +impl From for Target { + fn from(c: CompactTarget) -> Self { Target::from_compact(c) } +} + +impl Encodable for CompactTarget { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + self.0.consensus_encode(w) + } +} + +impl Decodable for CompactTarget { + #[inline] + fn consensus_decode(r: &mut R) -> Result { + u32::consensus_decode(r).map(CompactTarget) + } +} + +/// Big-endian 256 bit integer type. +// (high, low): u.0 contains the high bits, u.1 contains the low bits. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +struct U256(u128, u128); + +impl U256 { + const MAX: U256 = + U256(0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff, 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff); + + const ZERO: U256 = U256(0, 0); + + const ONE: U256 = U256(0, 1); + + /// Creates [`U256`] from a big-endian array of `u8`s. + fn from_be_bytes(a: [u8; 32]) -> U256 { + let (high, low) = split_in_half(a); + let big = u128::from_be_bytes(high); + let little = u128::from_be_bytes(low); + U256(big, little) + } + + /// Creates a [`U256`] from a little-endian array of `u8`s. + fn from_le_bytes(a: [u8; 32]) -> U256 { + let (high, low) = split_in_half(a); + let little = u128::from_le_bytes(high); + let big = u128::from_le_bytes(low); + U256(big, little) + } + + /// Converts `Self` to a big-endian array of `u8`s. + fn to_be_bytes(self) -> [u8; 32] { + let mut out = [0; 32]; + out[..16].copy_from_slice(&self.0.to_be_bytes()); + out[16..].copy_from_slice(&self.1.to_be_bytes()); + out + } + + /// Converts `Self` to a little-endian array of `u8`s. + fn to_le_bytes(self) -> [u8; 32] { + let mut out = [0; 32]; + out[..16].copy_from_slice(&self.1.to_le_bytes()); + out[16..].copy_from_slice(&self.0.to_le_bytes()); + out + } + + /// Calculates 2^256 / (x + 1) where x is a 256 bit unsigned integer. + /// + /// 2**256 / (x + 1) == ~x / (x + 1) + 1 + /// + /// (Equation shamelessly stolen from bitcoind) + fn inverse(&self) -> U256 { + // We should never have a target/work of zero so this doesn't matter + // that much but we define the inverse of 0 as max. + if self.is_zero() { + return U256::MAX; + } + // We define the inverse of 1 as max. + if self.is_one() { + return U256::MAX; + } + // We define the inverse of max as 1. + if self.is_max() { + return U256::ONE; + } + + let ret = !*self / self.wrapping_inc(); + ret.wrapping_inc() + } + + fn is_zero(&self) -> bool { self.0 == 0 && self.1 == 0 } + + fn is_one(&self) -> bool { self.0 == 0 && self.1 == 1 } + + fn is_max(&self) -> bool { self.0 == u128::max_value() && self.1 == u128::max_value() } + + /// Returns the low 32 bits. + fn low_u32(&self) -> u32 { self.low_u128() as u32 } + + /// Returns the low 64 bits. + fn low_u64(&self) -> u64 { self.low_u128() as u64 } + + /// Returns the low 128 bits. + fn low_u128(&self) -> u128 { self.1 } + + /// Returns `self` as a `u128` saturating to `u128::MAX` if `self` is too big. + fn saturating_to_u128(&self) -> u128 { + if *self > U256::from(u128::max_value()) { + u128::max_value() + } else { + self.low_u128() + } + } + + /// Returns the least number of bits needed to represent the number. + fn bits(&self) -> u32 { + if self.0 > 0 { + 256 - self.0.leading_zeros() + } else { + 128 - self.1.leading_zeros() + } + } + + /// Wrapping multiplication by `u64`. + /// + /// Returns a tuple of the addition along with a boolean indicating whether an arithmetic + /// overflow would occur. If an overflow would have occurred then the wrapped value is returned. + fn mul_u64(self, rhs: u64) -> (U256, bool) { + // Multiply 64 bit parts of `mul` by `rhs`. + fn mul_parts(mul: u128, rhs: u64) -> (u128, u128) { + let upper = (rhs as u128) * (mul >> 64); + let lower = (rhs as u128) * (mul & 0xFFFF_FFFF_FFFF_FFFF); + (upper, lower) + } + + if self.is_zero() || rhs == 0 { + return (U256::ZERO, false); + } + + let mut ret = U256::ZERO; + let mut ret_overflow = false; + + let (upper, lower) = mul_parts(self.0, rhs); + ret.0 = lower + (upper << 64); + ret_overflow |= upper >> 64 > 0; + + let (upper, lower) = mul_parts(self.1, rhs); + ret.1 = lower + (upper << 64); + ret.0 += upper >> 64; + + (ret, ret_overflow) + } + + /// Calculates quotient and remainder. + /// + /// # Returns + /// + /// (quotient, remainder) + /// + /// # Panics + /// + /// If `rhs` is zero. + fn div_rem(self, rhs: Self) -> (Self, Self) { + let mut sub_copy = self; + let mut shift_copy = rhs; + let mut ret = [0u128; 2]; + + let my_bits = self.bits(); + let your_bits = rhs.bits(); + + // Check for division by 0 + assert!(your_bits != 0, "attempted to divide {} by zero", self); + + // Early return in case we are dividing by a larger number than us + if my_bits < your_bits { + return (U256::ZERO, sub_copy); + } + + // Bitwise long division + let mut shift = my_bits - your_bits; + shift_copy = shift_copy << shift; + loop { + if sub_copy >= shift_copy { + ret[1 - (shift / 128) as usize] |= 1 << (shift % 128); + sub_copy = sub_copy.wrapping_sub(shift_copy); + } + shift_copy = shift_copy >> 1; + if shift == 0 { + break; + } + shift -= 1; + } + + (U256(ret[0], ret[1]), sub_copy) + } + + /// Calculates `self` + `rhs` + /// + /// Returns a tuple of the addition along with a boolean indicating whether an arithmetic + /// overflow would occur. If an overflow would have occurred then the wrapped value is returned. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn overflowing_add(self, rhs: Self) -> (Self, bool) { + let mut ret = U256::ZERO; + let mut ret_overflow = false; + + let (high, overflow) = self.0.overflowing_add(rhs.0); + ret.0 = high; + ret_overflow |= overflow; + + let (low, overflow) = self.1.overflowing_add(rhs.1); + ret.1 = low; + if overflow { + let (high, overflow) = ret.0.overflowing_add(1); + ret.0 = high; + ret_overflow |= overflow; + } + + (ret, ret_overflow) + } + + /// Calculates `self` - `rhs` + /// + /// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic + /// overflow would occur. If an overflow would have occurred then the wrapped value is returned. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + let ret = self.wrapping_add(!rhs).wrapping_add(Self::ONE); + let overflow = rhs > self; + (ret, overflow) + } + + /// Calculates the multiplication of `self` and `rhs`. + /// + /// Returns a tuple of the multiplication along with a boolean + /// indicating whether an arithmetic overflow would occur. If an + /// overflow would have occurred then the wrapped value is returned. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + let mut ret = U256::ZERO; + let mut ret_overflow = false; + + for i in 0..3 { + let to_mul = (rhs >> (64 * i)).low_u64(); + let (mul_res, _) = self.mul_u64(to_mul); + ret = ret.wrapping_add(mul_res << (64 * i)); + } + + let to_mul = (rhs >> (192)).low_u64(); + let (mul_res, overflow) = self.mul_u64(to_mul); + ret_overflow |= overflow; + let (sum, overflow) = ret.overflowing_add(mul_res); + ret = sum; + ret_overflow |= overflow; + + (ret, ret_overflow) + } + + /// Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the boundary of the + /// type. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn wrapping_add(self, rhs: Self) -> Self { + let (ret, _overflow) = self.overflowing_add(rhs); + ret + } + + /// Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the boundary of + /// the type. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn wrapping_sub(self, rhs: Self) -> Self { + let (ret, _overflow) = self.overflowing_sub(rhs); + ret + } + + /// Wrapping (modular) multiplication. Computes `self * rhs`, wrapping around at the boundary of + /// the type. + #[must_use = "this returns the result of the operation, without modifying the original"] + #[cfg(test)] + fn wrapping_mul(self, rhs: Self) -> Self { + let (ret, _overflow) = self.overflowing_mul(rhs); + ret + } + + /// Returns `self` incremented by 1 wrapping around at the boundary of the type. + #[must_use = "this returns the result of the increment, without modifying the original"] + fn wrapping_inc(&self) -> U256 { + let mut ret = U256::ZERO; + + ret.1 = self.1.wrapping_add(1); + if ret.1 == 0 { + ret.0 = self.0.wrapping_add(1); + } else { + ret.0 = self.0; + } + ret + } + + /// Panic-free bitwise shift-left; yields `self << mask(rhs)`, where `mask` removes any + /// high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type. + /// + /// Note that this is *not* the same as a rotate-left; the RHS of a wrapping shift-left is + /// restricted to the range of the type, rather than the bits shifted out of the LHS being + /// returned to the other end. We do not currently support `rotate_left`. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn wrapping_shl(self, rhs: u32) -> Self { + let shift = rhs & 0x000000ff; + + let mut ret = U256::ZERO; + let word_shift = shift >= 128; + let bit_shift = shift % 128; + + if word_shift { + ret.0 = self.1 << bit_shift + } else { + ret.0 = self.0 << bit_shift; + if bit_shift > 0 { + ret.0 += self.1.wrapping_shr(128 - bit_shift); + } + ret.1 = self.1 << bit_shift; + } + ret + } + + /// Panic-free bitwise shift-right; yields `self >> mask(rhs)`, where `mask` removes any + /// high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type. + /// + /// Note that this is *not* the same as a rotate-right; the RHS of a wrapping shift-right is + /// restricted to the range of the type, rather than the bits shifted out of the LHS being + /// returned to the other end. We do not currently support `rotate_right`. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn wrapping_shr(self, rhs: u32) -> Self { + let shift = rhs & 0x000000ff; + + let mut ret = U256::ZERO; + let word_shift = shift >= 128; + let bit_shift = shift % 128; + + if word_shift { + ret.1 = self.0 >> bit_shift + } else { + ret.0 = self.0 >> bit_shift; + ret.1 = self.1 >> bit_shift; + if bit_shift > 0 { + ret.1 += self.0.wrapping_shl(128 - bit_shift); + } + } + ret + } + + /// Format `self` to `f` as a decimal when value is known to be non-zero. + fn fmt_decimal(&self, f: &mut fmt::Formatter) -> fmt::Result { + const DIGITS: usize = 78; // U256::MAX has 78 base 10 digits. + const TEN: U256 = U256(0, 10); + + let mut buf = [0_u8; DIGITS]; + let mut i = DIGITS - 1; // We loop backwards. + let mut cur = *self; + + loop { + let digit = (cur % TEN).low_u128() as u8; // Cast after rem 10 is lossless. + buf[i] = digit + b'0'; + cur = cur / TEN; + if cur.is_zero() { + break; + } + i -= 1; + } + let s = core::str::from_utf8(&buf[i..]).expect("digits 0-9 are valid UTF8"); + f.pad_integral(true, "", s) + } +} + +impl> From for U256 { + fn from(x: T) -> Self { U256(0, x.into()) } +} + +/// Error from `TryFrom` implementations, occurs when input is negative. +#[derive(Debug)] +pub struct TryFromError(i128); + +impl fmt::Display for TryFromError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "attempt to create unsigned integer type from negative number: {}", self.0) + } +} + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl std::error::Error for TryFromError {} + +impl Add for U256 { + type Output = Self; + fn add(self, rhs: Self) -> Self { + let (res, overflow) = self.overflowing_add(rhs); + debug_assert!(!overflow, "Addition of U256 values overflowed"); + res + } +} + +impl Sub for U256 { + type Output = Self; + fn sub(self, rhs: Self) -> Self { + let (res, overflow) = self.overflowing_sub(rhs); + debug_assert!(!overflow, "Subtraction of U256 values overflowed"); + res + } +} + +impl Mul for U256 { + type Output = Self; + fn mul(self, rhs: Self) -> Self { + let (res, overflow) = self.overflowing_mul(rhs); + debug_assert!(!overflow, "Multiplication of U256 values overflowed"); + res + } +} + +impl> Mul for U256 { + type Output = Self; + fn mul(self, rhs: T) -> Self { + let (res, overflow) = self.mul_u64(rhs.into()); + debug_assert!(!overflow, "U256 multiplied by integer overflowed"); + res + } +} + +/// Implements mul by unsigned int in both directions. Requires `u64::from($int)`. +macro_rules! impl_int_mul_u256 { + ($($int:ident),+ $(,)?) => { + $( + impl Mul for $int { + type Output = U256; + fn mul(self, rhs: U256) -> U256 { + let (res, overflow) = rhs.mul_u64(u64::from(self)); + debug_assert!(!overflow, "Integer multiplied by U256 overflowed"); + res + } + } + )+ + }; +} +impl_int_mul_u256!(u8, u16, u32, u64); + +impl Div for U256 { + type Output = Self; + fn div(self, rhs: Self) -> Self { self.div_rem(rhs).0 } +} + +impl Rem for U256 { + type Output = Self; + fn rem(self, rhs: Self) -> Self { self.div_rem(rhs).1 } +} + +impl Not for U256 { + type Output = Self; + + fn not(self) -> Self { U256(!self.0, !self.1) } +} + +impl Shl for U256 { + type Output = Self; + fn shl(self, shift: u32) -> U256 { self.wrapping_shl(shift) } +} + +impl Shr for U256 { + type Output = Self; + fn shr(self, shift: u32) -> U256 { self.wrapping_shr(shift) } +} + +impl fmt::Display for U256 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.is_zero() { + f.pad_integral(true, "", "0") + } else { + self.fmt_decimal(f) + } + } +} + +impl fmt::Debug for U256 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:#x}", self) } +} + +macro_rules! impl_hex { + ($hex:ident, $fmt:literal) => { + impl $hex for U256 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if f.alternate() { + write!(f, "0x")?; + } + write!(f, $fmt, self.0)?; + write!(f, $fmt, self.1)?; + Ok(()) + } + } + }; +} +impl_hex!(LowerHex, "{:032x}"); +impl_hex!(UpperHex, "{:032X}"); + +#[cfg(feature = "serde")] +#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] +impl crate::serde::Serialize for U256 { + fn serialize(&self, serializer: S) -> Result + where + S: crate::serde::Serializer, + { + use crate::hashes::hex::ToHex; + let bytes = self.to_be_bytes(); + if serializer.is_human_readable() { + // TODO: fast hex encoding. + serializer.serialize_str(&bytes.to_hex()) + } else { + serializer.serialize_bytes(&bytes) + } + } +} + +#[cfg(feature = "serde")] +#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] +impl<'de> crate::serde::Deserialize<'de> for U256 { + fn deserialize>(d: D) -> Result { + use core::convert::TryInto; + + use crate::hashes::hex::FromHex; + use crate::serde::de; + + if d.is_human_readable() { + struct HexVisitor; + + impl<'de> de::Visitor<'de> for HexVisitor { + type Value = U256; + + fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("a 32 byte ASCII hex string") + } + + fn visit_str(self, s: &str) -> Result + where + E: de::Error, + { + if s.len() != 64 { + return Err(de::Error::invalid_length(s.len(), &self)); + } + + let b = <[u8; 32]>::from_hex(s) + .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(s), &self))?; + + Ok(U256::from_be_bytes(b)) + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: de::Error, + { + if let Ok(hex) = core::str::from_utf8(v) { + let b = <[u8; 32]>::from_hex(hex).map_err(|_| { + de::Error::invalid_value(de::Unexpected::Str(hex), &self) + })?; + + Ok(U256::from_be_bytes(b)) + } else { + Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self)) + } + } + } + d.deserialize_str(HexVisitor) + } else { + struct BytesVisitor; + + impl<'de> serde::de::Visitor<'de> for BytesVisitor { + type Value = U256; + + fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + f.write_str("a sequence of bytes") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: serde::de::Error, + { + let b = v.try_into().map_err(|_| de::Error::invalid_length(v.len(), &self))?; + Ok(U256::from_be_bytes(b)) + } + } + + d.deserialize_bytes(BytesVisitor) + } + } +} + +/// Splits a 32 byte array into two 16 byte arrays. +fn split_in_half(a: [u8; 32]) -> ([u8; 16], [u8; 16]) { + let mut high = [0_u8; 16]; + let mut low = [0_u8; 16]; + + high.copy_from_slice(&a[..16]); + low.copy_from_slice(&a[16..]); + + (high, low) +} + +#[cfg(test)] +mod tests { + use super::*; + + impl> From for Target { + fn from(x: T) -> Self { Self(U256::from(x)) } + } + + impl> From for Work { + fn from(x: T) -> Self { Self(U256::from(x)) } + } + + impl U256 { + fn bit_at(&self, index: usize) -> bool { + if index > 255 { + panic!("index out of bounds"); + } + + let word = if index < 128 { self.1 } else { self.0 }; + (word & (1 << (index % 128))) != 0 + } + } + + impl U256 { + /// Creates a U256 from a big-endian array of u64's + fn from_array(a: [u64; 4]) -> Self { + let mut ret = U256::ZERO; + ret.0 = (a[0] as u128) << 64 ^ (a[1] as u128); + ret.1 = (a[2] as u128) << 64 ^ (a[3] as u128); + ret + } + } + + #[test] + fn u256_num_bits() { + assert_eq!(U256::from(255_u64).bits(), 8); + assert_eq!(U256::from(256_u64).bits(), 9); + assert_eq!(U256::from(300_u64).bits(), 9); + assert_eq!(U256::from(60000_u64).bits(), 16); + assert_eq!(U256::from(70000_u64).bits(), 17); + + // Try to read the following lines out loud quickly + let mut shl = U256::from(70000_u64); + shl = shl << 100; + assert_eq!(shl.bits(), 117); + shl = shl << 100; + assert_eq!(shl.bits(), 217); + shl = shl << 100; + assert_eq!(shl.bits(), 0); + } + + #[test] + fn u256_bit_at() { + assert!(!U256::from(10_u64).bit_at(0)); + assert!(U256::from(10_u64).bit_at(1)); + assert!(!U256::from(10_u64).bit_at(2)); + assert!(U256::from(10_u64).bit_at(3)); + assert!(!U256::from(10_u64).bit_at(4)); + + let u = U256(0xa000_0000_0000_0000_0000_0000_0000_0000, 0); + assert!(u.bit_at(255)); + assert!(!u.bit_at(254)); + assert!(u.bit_at(253)); + assert!(!u.bit_at(252)); + } + + #[test] + fn u256_lower_hex() { + assert_eq!( + format!("{:x}", U256::from(0xDEADBEEF_u64)), + "00000000000000000000000000000000000000000000000000000000deadbeef", + ); + assert_eq!( + format!("{:#x}", U256::from(0xDEADBEEF_u64)), + "0x00000000000000000000000000000000000000000000000000000000deadbeef", + ); + assert_eq!( + format!("{:x}", U256::MAX), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + ); + assert_eq!( + format!("{:#x}", U256::MAX), + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + ); + } + + #[test] + fn u256_upper_hex() { + assert_eq!( + format!("{:X}", U256::from(0xDEADBEEF_u64)), + "00000000000000000000000000000000000000000000000000000000DEADBEEF", + ); + assert_eq!( + format!("{:#X}", U256::from(0xDEADBEEF_u64)), + "0x00000000000000000000000000000000000000000000000000000000DEADBEEF", + ); + assert_eq!( + format!("{:X}", U256::MAX), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + ); + assert_eq!( + format!("{:#X}", U256::MAX), + "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + ); + } + + #[test] + fn u256_display() { + assert_eq!(format!("{}", U256::from(100_u32)), "100",); + assert_eq!(format!("{}", U256::ZERO), "0",); + assert_eq!(format!("{}", U256::from(u64::max_value())), format!("{}", u64::max_value()),); + assert_eq!( + format!("{}", U256::MAX), + "115792089237316195423570985008687907853269984665640564039457584007913129639935", + ); + } + + macro_rules! check_format { + ($($test_name:ident, $val:literal, $format_string:literal, $expected:literal);* $(;)?) => { + $( + #[test] + fn $test_name() { + assert_eq!(format!($format_string, U256::from($val)), $expected); + } + )* + } + } + check_format! { + check_fmt_0, 0_u32, "{}", "0"; + check_fmt_1, 0_u32, "{:2}", " 0"; + check_fmt_2, 0_u32, "{:02}", "00"; + + check_fmt_3, 1_u32, "{}", "1"; + check_fmt_4, 1_u32, "{:2}", " 1"; + check_fmt_5, 1_u32, "{:02}", "01"; + + check_fmt_10, 10_u32, "{}", "10"; + check_fmt_11, 10_u32, "{:2}", "10"; + check_fmt_12, 10_u32, "{:02}", "10"; + check_fmt_13, 10_u32, "{:3}", " 10"; + check_fmt_14, 10_u32, "{:03}", "010"; + + check_fmt_20, 1_u32, "{:<2}", "1 "; + check_fmt_21, 1_u32, "{:<02}", "01"; + check_fmt_22, 1_u32, "{:>2}", " 1"; // This is default but check it anyways. + check_fmt_23, 1_u32, "{:>02}", "01"; + check_fmt_24, 1_u32, "{:^3}", " 1 "; + check_fmt_25, 1_u32, "{:^03}", "001"; + // Sanity check, for integral types precision is ignored. + check_fmt_30, 0_u32, "{:.1}", "0"; + check_fmt_31, 0_u32, "{:4.1}", " 0"; + check_fmt_32, 0_u32, "{:04.1}", "0000"; + } + + #[test] + fn u256_comp() { + let small = U256::from_array([0, 0, 0, 10]); + let big = U256::from_array([0, 0, 0x0209_E737_8231_E632, 0x8C8C_3EE7_0C64_4118]); + let bigger = U256::from_array([0, 0, 0x0209_E737_8231_E632, 0x9C8C_3EE7_0C64_4118]); + let biggest = U256::from_array([1, 0, 0x0209_E737_8231_E632, 0x5C8C_3EE7_0C64_4118]); + + assert!(small < big); + assert!(big < bigger); + assert!(bigger < biggest); + assert!(bigger <= biggest); + assert!(biggest <= biggest); + assert!(bigger >= big); + assert!(bigger >= small); + assert!(small <= small); + } + + const WANT: U256 = + U256(0x1bad_cafe_dead_beef_deaf_babe_2bed_feed, 0xbaad_f00d_defa_ceda_11fe_d2ba_d1c0_ffe0); + + #[rustfmt::skip] + const BE_BYTES: [u8; 32] = [ + 0x1b, 0xad, 0xca, 0xfe, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xaf, 0xba, 0xbe, 0x2b, 0xed, 0xfe, 0xed, + 0xba, 0xad, 0xf0, 0x0d, 0xde, 0xfa, 0xce, 0xda, 0x11, 0xfe, 0xd2, 0xba, 0xd1, 0xc0, 0xff, 0xe0, + ]; + + #[rustfmt::skip] + const LE_BYTES: [u8; 32] = [ + 0xe0, 0xff, 0xc0, 0xd1, 0xba, 0xd2, 0xfe, 0x11, 0xda, 0xce, 0xfa, 0xde, 0x0d, 0xf0, 0xad, 0xba, + 0xed, 0xfe, 0xed, 0x2b, 0xbe, 0xba, 0xaf, 0xde, 0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b, + ]; + + // Sanity check that we have the bytes in the correct big-endian order. + #[test] + fn sanity_be_bytes() { + let mut out = [0_u8; 32]; + out[..16].copy_from_slice(&WANT.0.to_be_bytes()); + out[16..].copy_from_slice(&WANT.1.to_be_bytes()); + assert_eq!(out, BE_BYTES); + } + + // Sanity check that we have the bytes in the correct little-endian order. + #[test] + fn sanity_le_bytes() { + let mut out = [0_u8; 32]; + out[..16].copy_from_slice(&WANT.1.to_le_bytes()); + out[16..].copy_from_slice(&WANT.0.to_le_bytes()); + assert_eq!(out, LE_BYTES); + } + + #[test] + fn u256_to_be_bytes() { + assert_eq!(WANT.to_be_bytes(), BE_BYTES); + } + + #[test] + fn u256_from_be_bytes() { + assert_eq!(U256::from_be_bytes(BE_BYTES), WANT); + } + + #[test] + fn u256_to_le_bytes() { + assert_eq!(WANT.to_le_bytes(), LE_BYTES); + } + + #[test] + fn u256_from_le_bytes() { + assert_eq!(U256::from_le_bytes(LE_BYTES), WANT); + } + + #[test] + fn u256_from_u8() { + let u = U256::from(0xbe_u8); + assert_eq!(u, U256(0, 0xbe)); + } + + #[test] + fn u256_from_u16() { + let u = U256::from(0xbeef_u16); + assert_eq!(u, U256(0, 0xbeef)); + } + + #[test] + fn u256_from_u32() { + let u = U256::from(0xdeadbeef_u32); + assert_eq!(u, U256(0, 0xdeadbeef)); + } + + #[test] + fn u256_from_u64() { + let u = U256::from(0xdead_beef_cafe_babe_u64); + assert_eq!(u, U256(0, 0xdead_beef_cafe_babe)); + } + + #[test] + fn u256_from_u128() { + let u = U256::from(0xdead_beef_cafe_babe_0123_4567_89ab_cdefu128); + assert_eq!(u, U256(0, 0xdead_beef_cafe_babe_0123_4567_89ab_cdef)); + } + + macro_rules! test_from_unsigned_integer_type { + ($($test_name:ident, $ty:ident);* $(;)?) => { + $( + #[test] + fn $test_name() { + // Internal representation is big-endian. + let want = U256(0, 0xAB); + + let x = 0xAB as $ty; + let got = U256::from(x); + + assert_eq!(got, want); + } + )* + } + } + test_from_unsigned_integer_type! { + from_unsigned_integer_type_u8, u8; + from_unsigned_integer_type_u16, u16; + from_unsigned_integer_type_u32, u32; + from_unsigned_integer_type_u64, u64; + from_unsigned_integer_type_u128, u128; + } + + #[test] + fn u256_from_be_array_u64() { + let array = [ + 0x1bad_cafe_dead_beef, + 0xdeaf_babe_2bed_feed, + 0xbaad_f00d_defa_ceda, + 0x11fe_d2ba_d1c0_ffe0, + ]; + + let uint = U256::from_array(array); + assert_eq!(uint, WANT); + } + + #[test] + fn u256_shift_left() { + let u = U256::from(1_u32); + assert_eq!(u << 0, u); + assert_eq!(u << 1, U256::from(2_u64)); + assert_eq!(u << 63, U256::from(0x8000_0000_0000_0000_u64)); + assert_eq!(u << 64, U256::from_array([0, 0, 0x0000_0000_0000_0001, 0])); + assert_eq!(u << 128, U256(1, 0)); + } + + #[test] + fn u256_shift_right() { + let u = U256(1, 0); + assert_eq!(u >> 0, u); + assert_eq!(u >> 1, U256(0, 0x8000_0000_0000_0000_0000_0000_0000_0000)); + assert_eq!(u >> 128, U256(0, 1)); + } + + #[test] + fn u256_arithmetic() { + let init = U256::from(0xDEAD_BEEF_DEAD_BEEF_u64); + let copy = init; + + let add = init.wrapping_add(copy); + assert_eq!(add, U256::from_array([0, 0, 1, 0xBD5B_7DDF_BD5B_7DDE])); + // Bitshifts + let shl = add << 88; + assert_eq!(shl, U256::from_array([0, 0x01BD_5B7D, 0xDFBD_5B7D_DE00_0000, 0])); + let shr = shl >> 40; + assert_eq!(shr, U256::from_array([0, 0, 0x0001_BD5B_7DDF_BD5B, 0x7DDE_0000_0000_0000])); + // Increment + let mut incr = shr; + incr = incr.wrapping_inc(); + assert_eq!(incr, U256::from_array([0, 0, 0x0001_BD5B_7DDF_BD5B, 0x7DDE_0000_0000_0001])); + // Subtraction + let sub = incr.wrapping_sub(init); + assert_eq!(sub, U256::from_array([0, 0, 0x0001_BD5B_7DDF_BD5A, 0x9F30_4110_2152_4112])); + // Multiplication + let (mult, _) = sub.mul_u64(300); + assert_eq!(mult, U256::from_array([0, 0, 0x0209_E737_8231_E632, 0x8C8C_3EE7_0C64_4118])); + // Division + assert_eq!(U256::from(105_u32) / U256::from(5_u32), U256::from(21_u32)); + let div = mult / U256::from(300_u32); + assert_eq!(div, U256::from_array([0, 0, 0x0001_BD5B_7DDF_BD5A, 0x9F30_4110_2152_4112])); + + assert_eq!(U256::from(105_u32) % U256::from(5_u32), U256::ZERO); + assert_eq!(U256::from(35498456_u32) % U256::from(3435_u32), U256::from(1166_u32)); + let rem_src = mult.wrapping_mul(U256::from(39842_u32)).wrapping_add(U256::from(9054_u32)); + assert_eq!(rem_src % U256::from(39842_u32), U256::from(9054_u32)); + } + + #[test] + fn u256_bit_inversion() { + let v = U256(1, 0); + let want = U256( + 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_fffe, + 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff, + ); + assert_eq!(!v, want); + + let v = U256(0x0c0c_0c0c_0c0c_0c0c_0c0c_0c0c_0c0c_0c0c, 0xeeee_eeee_eeee_eeee); + let want = U256( + 0xf3f3_f3f3_f3f3_f3f3_f3f3_f3f3_f3f3_f3f3, + 0xffff_ffff_ffff_ffff_1111_1111_1111_1111, + ); + assert_eq!(!v, want); + } + + #[test] + fn u256_mul_u64_by_one() { + let v = U256::from(0xDEAD_BEEF_DEAD_BEEF_u64); + assert_eq!(v, v.mul_u64(1_u64).0); + } + + #[test] + fn u256_mul_u64_by_zero() { + let v = U256::from(0xDEAD_BEEF_DEAD_BEEF_u64); + assert_eq!(U256::ZERO, v.mul_u64(0_u64).0); + } + + #[test] + fn u256_mul_u64() { + let u64_val = U256::from(0xDEAD_BEEF_DEAD_BEEF_u64); + + let u96_res = u64_val.mul_u64(0xFFFF_FFFF).0; + let u128_res = u96_res.mul_u64(0xFFFF_FFFF).0; + let u160_res = u128_res.mul_u64(0xFFFF_FFFF).0; + let u192_res = u160_res.mul_u64(0xFFFF_FFFF).0; + let u224_res = u192_res.mul_u64(0xFFFF_FFFF).0; + let u256_res = u224_res.mul_u64(0xFFFF_FFFF).0; + + assert_eq!(u96_res, U256::from_array([0, 0, 0xDEAD_BEEE, 0xFFFF_FFFF_2152_4111])); + assert_eq!( + u128_res, + U256::from_array([0, 0, 0xDEAD_BEEE_2152_4110, 0x2152_4111_DEAD_BEEF]) + ); + assert_eq!( + u160_res, + U256::from_array([0, 0xDEAD_BEED, 0x42A4_8222_0000_0001, 0xBD5B_7DDD_2152_4111]) + ); + assert_eq!( + u192_res, + U256::from_array([ + 0, + 0xDEAD_BEEC_63F6_C334, + 0xBD5B_7DDF_BD5B_7DDB, + 0x63F6_C333_DEAD_BEEF + ]) + ); + assert_eq!( + u224_res, + U256::from_array([ + 0xDEAD_BEEB, + 0x8549_0448_5964_BAAA, + 0xFFFF_FFFB_A69B_4558, + 0x7AB6_FBBB_2152_4111 + ]) + ); + assert_eq!( + u256_res, + U256( + 0xDEAD_BEEA_A69B_455C_D41B_B662_A69B_4550, + 0xA69B_455C_D41B_B662_A69B_4555_DEAD_BEEF, + ) + ); + } + + #[test] + fn u256_multiplication() { + let u64_val = U256::from(0xDEAD_BEEF_DEAD_BEEF_u64); + + let u128_res = u64_val.wrapping_mul(u64_val); + + assert_eq!(u128_res, U256(0, 0xC1B1_CD13_A4D1_3D46_048D_1354_216D_A321)); + + let u256_res = u128_res.wrapping_mul(u128_res); + + assert_eq!( + u256_res, + U256( + 0x928D_92B4_D7F5_DF33_4AFC_FF6F_0375_C608, + 0xF5CF_7F36_18C2_C886_F4E1_66AA_D40D_0A41, + ) + ); + } + + #[test] + fn u256_increment() { + let mut val = U256( + 0xEFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF, + 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFE, + ); + val = val.wrapping_inc(); + assert_eq!( + val, + U256( + 0xEFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF, + 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF, + ) + ); + val = val.wrapping_inc(); + assert_eq!( + val, + U256( + 0xF000_0000_0000_0000_0000_0000_0000_0000, + 0x0000_0000_0000_0000_0000_0000_0000_0000, + ) + ); + + assert_eq!(U256::MAX.wrapping_inc(), U256::ZERO); + } + + #[test] + fn u256_extreme_bitshift() { + // Shifting a u64 by 64 bits gives an undefined value, so make sure that + // we're doing the Right Thing here + let init = U256::from(0xDEAD_BEEF_DEAD_BEEF_u64); + + assert_eq!(init << 64, U256(0, 0xDEAD_BEEF_DEAD_BEEF_0000_0000_0000_0000)); + let add = (init << 64).wrapping_add(init); + assert_eq!(add, U256(0, 0xDEAD_BEEF_DEAD_BEEF_DEAD_BEEF_DEAD_BEEF)); + assert_eq!(add >> 0, U256(0, 0xDEAD_BEEF_DEAD_BEEF_DEAD_BEEF_DEAD_BEEF)); + assert_eq!(add << 0, U256(0, 0xDEAD_BEEF_DEAD_BEEF_DEAD_BEEF_DEAD_BEEF)); + assert_eq!(add >> 64, U256(0, 0x0000_0000_0000_0000_DEAD_BEEF_DEAD_BEEF)); + assert_eq!( + add << 64, + U256(0xDEAD_BEEF_DEAD_BEEF, 0xDEAD_BEEF_DEAD_BEEF_0000_0000_0000_0000) + ); + } + + #[cfg(feature = "serde")] + #[test] + fn u256_serde() { + let check = |uint, hex| { + let json = format!("\"{}\"", hex); + assert_eq!(::serde_json::to_string(&uint).unwrap(), json); + assert_eq!(::serde_json::from_str::(&json).unwrap(), uint); + + let bin_encoded = bincode::serialize(&uint).unwrap(); + let bin_decoded: U256 = bincode::deserialize(&bin_encoded).unwrap(); + assert_eq!(bin_decoded, uint); + }; + + check(U256::ZERO, "0000000000000000000000000000000000000000000000000000000000000000"); + check( + U256::from(0xDEADBEEF_u32), + "00000000000000000000000000000000000000000000000000000000deadbeef", + ); + check( + U256::from_array([0xdd44, 0xcc33, 0xbb22, 0xaa11]), + "000000000000dd44000000000000cc33000000000000bb22000000000000aa11", + ); + check(U256::MAX, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + check( + U256( + 0xDEAD_BEEA_A69B_455C_D41B_B662_A69B_4550, + 0xA69B_455C_D41B_B662_A69B_4555_DEAD_BEEF, + ), + "deadbeeaa69b455cd41bb662a69b4550a69b455cd41bb662a69b4555deadbeef", + ); + + assert!(::serde_json::from_str::( + "\"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg\"" + ) + .is_err()); // invalid char + assert!(::serde_json::from_str::( + "\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"" + ) + .is_err()); // invalid length + assert!(::serde_json::from_str::( + "\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"" + ) + .is_err()); // invalid length + } + + #[test] + fn target_from_compact() { + // (nBits, target) + let tests = vec![ + (0x0100_3456_u32, 0x00_u64), // High bit set. + (0x0112_3456_u32, 0x12_u64), + (0x0200_8000_u32, 0x80_u64), + (0x0500_9234_u32, 0x9234_0000_u64), + (0x0492_3456_u32, 0x00_u64), // High bit set (0x80 in 0x92). + (0x0412_3456_u32, 0x1234_5600_u64), // Inverse of above; no high bit. + ]; + + for (n_bits, target) in tests { + let want = Target::from(target); + let got = Target::from_compact(CompactTarget::from_consensus(n_bits)); + assert_eq!(got, want); + } + } + + #[test] + fn max_target_from_compact() { + // The highest possible target is defined as 0x1d00ffff + let bits = 0x1d00ffff_u32; + let want = Target::MAX; + let got = Target::from_compact(CompactTarget::from_consensus(bits)); + assert_eq!(got, want) + } + + #[test] + fn roundtrip_compact_target() { + let consensus = 0x1d00_ffff; + let compact = CompactTarget::from_consensus(consensus); + let t = Target::from_compact(CompactTarget::from_consensus(consensus)); + assert_eq!(t, Target::from(compact)); // From/Into sanity check. + + let back = t.to_compact_lossy(); + assert_eq!(back, compact); // From/Into sanity check. + + assert_eq!(back.to_consensus(), consensus); + } + + #[test] + fn roundtrip_target_work() { + let target = Target::from(0xdeadbeef_u32); + let work = target.to_work(); + let back = work.to_target(); + assert_eq!(back, target) + } + + #[test] + fn u256_zero_min_max_inverse() { + assert_eq!(U256::MAX.inverse(), U256::ONE); + assert_eq!(U256::ONE.inverse(), U256::MAX); + assert_eq!(U256::ZERO.inverse(), U256::MAX); + } + + #[test] + fn u256_max_min_inverse_roundtrip() { + let max = U256::MAX; + + for min in [U256::ZERO, U256::ONE].iter() { + // lower target means more work required. + assert_eq!(Target(max).to_work(), Work(U256::ONE)); + assert_eq!(Target(*min).to_work(), Work(max)); + + assert_eq!(Work(max).to_target(), Target(U256::ONE)); + assert_eq!(Work(*min).to_target(), Target(max)); + } + } + + #[test] + fn u256_wrapping_add_wraps_at_boundry() { + assert_eq!(U256::MAX.wrapping_add(U256::ONE), U256::ZERO); + assert_eq!(U256::MAX.wrapping_add(U256::from(2_u8)), U256::ONE); + } + + #[test] + fn u256_wrapping_sub_wraps_at_boundry() { + assert_eq!(U256::ZERO.wrapping_sub(U256::ONE), U256::MAX); + assert_eq!(U256::ONE.wrapping_sub(U256::from(2_u8)), U256::MAX); + } + + #[test] + fn mul_u64_overflows() { + let (_, overflow) = U256::MAX.mul_u64(2); + assert!(overflow, "max * 2 should overflow"); + } + + #[test] + #[should_panic] + fn u256_overflowing_addition_panics() { let _ = U256::MAX + U256::ONE; } + + #[test] + #[should_panic] + fn u256_overflowing_subtraction_panics() { let _ = U256::ZERO - U256::ONE; } + + // We only test with test case value on the right hand side of the multiplication but that + // should be enough coverage since we call the same underlying method to do multiplication the + // sides inverted. + macro_rules! test_u256_multiplication_panics { + ($($test_name:ident, $x:expr);* $(;)?) => { + $( + #[test] + #[should_panic] + fn $test_name() { + let _ = U256::MAX * $x; + } + )* + } + } + test_u256_multiplication_panics! { + u256_multiplication_by_max, U256::MAX; + u256_multiplication_by_u8, 2_u8; + u256_multiplication_by_u16, 2_u16; + u256_multiplication_by_u32, 2_u32; + u256_multiplication_by_u64, 2_u64; + } + + #[test] + #[should_panic] + fn work_overflowing_addition_panics() { let _ = Work(U256::MAX) + Work(U256::ONE); } + + #[test] + #[should_panic] + fn work_overflowing_subtraction_panics() { let _ = Work(U256::ZERO) - Work(U256::ONE); } + + // Just test Work since Target is implemented using the same macro. + macro_rules! test_u256_multiplication_panics { + ($($test_name:ident, $x:expr);* $(;)?) => { + $( + #[test] + #[should_panic] + fn $test_name() { + let _ = Work(U256::MAX) * $x; + } + )* + } + } + test_u256_multiplication_panics! { + work_multiplication_by_u8, 2_u8; + work_multiplication_by_u16, 2_u16; + work_multiplication_by_u32, 2_u32; + work_multiplication_by_u64, 2_u64; + } +} diff --git a/bitcoin/src/util/bip152.rs b/bitcoin/src/util/bip152.rs index 7ff07040..8072db59 100644 --- a/bitcoin/src/util/bip152.rs +++ b/bitcoin/src/util/bip152.rs @@ -376,8 +376,8 @@ mod test { use crate::consensus::encode::{deserialize, serialize}; use crate::hashes::hex::FromHex; use crate::{ - Block, BlockHash, BlockHeader, BlockVersion, OutPoint, Script, Sequence, Transaction, TxIn, TxMerkleNode, - TxOut, Txid, Witness, + Block, BlockHash, BlockHeader, BlockVersion, OutPoint, Script, Sequence, Transaction, TxIn, + TxMerkleNode, TxOut, Txid, Witness, CompactTarget, }; fn dummy_tx(nonce: &[u8]) -> Transaction { @@ -401,7 +401,7 @@ mod test { prev_blockhash: BlockHash::hash(&[0]), merkle_root: TxMerkleNode::hash(&[1]), time: 2, - bits: 3, + bits: CompactTarget::from_consensus(3), nonce: 4, }, txdata: vec![dummy_tx(&[2]), dummy_tx(&[3]), dummy_tx(&[4])], diff --git a/bitcoin/src/util/endian.rs b/bitcoin/src/util/endian.rs index 105ec032..2f31d187 100644 --- a/bitcoin/src/util/endian.rs +++ b/bitcoin/src/util/endian.rs @@ -54,9 +54,7 @@ macro_rules! define_le_to_array { } define_slice_to_be!(slice_to_u32_be, u32); -define_slice_to_be!(slice_to_u64_be, u64); define_be_to_array!(u32_to_array_be, u32, 4); -define_be_to_array!(u64_to_array_be, u64, 8); define_slice_to_le!(slice_to_u16_le, u16); define_slice_to_le!(slice_to_u32_le, u32); define_slice_to_le!(slice_to_u64_le, u64); @@ -89,19 +87,6 @@ pub fn i64_to_array_le(val: i64) -> [u8; 8] { u64_to_array_le(val as u64) } -macro_rules! define_chunk_slice_to_int { - ($name: ident, $type: ty, $converter: ident) => { - #[inline] - pub fn $name(inp: &[u8], outp: &mut [$type]) { - assert_eq!(inp.len(), outp.len() * core::mem::size_of::<$type>()); - for (outp_val, data_bytes) in outp.iter_mut().zip(inp.chunks(::core::mem::size_of::<$type>())) { - *outp_val = $converter(data_bytes); - } - } - } -} -define_chunk_slice_to_int!(bytes_to_u64_slice_le, u64, slice_to_u64_le); - #[cfg(test)] mod tests { use super::*; @@ -109,7 +94,6 @@ mod tests { #[test] fn endianness_test() { assert_eq!(slice_to_u32_be(&[0xde, 0xad, 0xbe, 0xef]), 0xdeadbeef); - assert_eq!(slice_to_u64_be(&[0xde, 0xad, 0xbe, 0xef, 0x1b, 0xad, 0xca, 0xfe]), 0xdeadbeef1badcafe); assert_eq!(u32_to_array_be(0xdeadbeef), [0xde, 0xad, 0xbe, 0xef]); assert_eq!(slice_to_u16_le(&[0xad, 0xde]), 0xdead); @@ -119,12 +103,4 @@ mod tests { assert_eq!(u32_to_array_le(0xdeadbeef), [0xef, 0xbe, 0xad, 0xde]); assert_eq!(u64_to_array_le(0x1badcafedeadbeef), [0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b]); } - - #[test] - fn endian_chunk_test() { - let inp = [0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b, 0xfe, 0xca, 0xad, 0x1b, 0xce, 0xfa, 0x01, 0x02]; - let mut out = [0; 2]; - bytes_to_u64_slice_le(&inp, &mut out); - assert_eq!(out, [0x1badcafedeadbeef, 0x0201face1badcafe]); - } } diff --git a/bitcoin/src/util/mod.rs b/bitcoin/src/util/mod.rs index c451326d..acd1668c 100644 --- a/bitcoin/src/util/mod.rs +++ b/bitcoin/src/util/mod.rs @@ -16,7 +16,6 @@ pub mod hash; pub mod merkleblock; pub mod psbt; pub mod taproot; -pub mod uint; pub mod sighash; pub(crate) mod endian; @@ -29,27 +28,6 @@ use bitcoin_internals::write_err; use crate::consensus::encode; -/// A trait which allows numbers to act as fixed-size bit arrays -pub trait BitArray { - /// Is bit set? - fn bit(&self, idx: usize) -> bool; - - /// Returns an array which is just the bits from start to end - fn bit_slice(&self, start: usize, end: usize) -> Self; - - /// Bitwise and with `n` ones - fn mask(&self, n: usize) -> Self; - - /// Trailing zeros - fn trailing_zeros(&self) -> usize; - - /// Create all-zeros value - fn zero() -> Self; - - /// Create value representing one - fn one() -> Self; -} - /// A general error code, other errors should implement conversions to/from this /// if appropriate. #[derive(Debug)] diff --git a/bitcoin/src/util/uint.rs b/bitcoin/src/util/uint.rs deleted file mode 100644 index 5614bd50..00000000 --- a/bitcoin/src/util/uint.rs +++ /dev/null @@ -1,817 +0,0 @@ -// Written in 2014 by Andrew Poelstra -// SPDX-License-Identifier: CC0-1.0 - -//! Big unsigned integer types. -//! -//! Implementation of various large-but-fixed sized unsigned integer types. -//! The functions here are designed to be fast. -//! - -macro_rules! construct_uint { - ($name:ident, $n_words:literal) => { - /// Little-endian large integer type - #[derive(Copy, Clone, PartialEq, Eq, Hash, Default)] - pub struct $name(pub [u64; $n_words]); - $crate::internal_macros::impl_array_newtype!($name, u64, $n_words); - - impl $name { - /// Conversion to u32 - #[inline] - pub fn low_u32(&self) -> u32 { - let &$name(ref arr) = self; - arr[0] as u32 - } - - /// Conversion to u64 - #[inline] - pub fn low_u64(&self) -> u64 { - let &$name(ref arr) = self; - arr[0] as u64 - } - - - /// Return the least number of bits needed to represent the number - #[inline] - pub fn bits(&self) -> usize { - let &$name(ref arr) = self; - for i in 1..$n_words { - if arr[$n_words - i] > 0 { return (0x40 * ($n_words - i + 1)) - arr[$n_words - i].leading_zeros() as usize; } - } - 0x40 - arr[0].leading_zeros() as usize - } - - /// Multiplication by u32 - pub fn mul_u32(self, other: u32) -> $name { - let $name(ref arr) = self; - let mut carry = [0u64; $n_words]; - let mut ret = [0u64; $n_words]; - for i in 0..$n_words { - let not_last_word = i < $n_words - 1; - let upper = other as u64 * (arr[i] >> 32); - let lower = other as u64 * (arr[i] & 0xFFFFFFFF); - if not_last_word { - carry[i + 1] += upper >> 32; - } - let (sum, overflow) = lower.overflowing_add(upper << 32); - ret[i] = sum; - if overflow && not_last_word { - carry[i + 1] += 1; - } - } - $name(ret) + $name(carry) - } - - /// Create an object from a given unsigned 64-bit integer - #[inline] - pub fn from_u64(init: u64) -> Option<$name> { - let mut ret = [0; $n_words]; - ret[0] = init; - Some($name(ret)) - } - - /// Create an object from a given signed 64-bit integer - #[inline] - pub fn from_i64(init: i64) -> Option<$name> { - if init >= 0 { - $name::from_u64(init as u64) - } else { - None - } - } - - /// Creates big integer value from a byte array using - /// big-endian encoding - pub fn from_be_bytes(bytes: [u8; $n_words * 8]) -> $name { - Self::_from_be_slice(&bytes) - } - - /// Creates big integer value from a byte slice using - /// big-endian encoding - pub fn from_be_slice(bytes: &[u8]) -> Result<$name, ParseLengthError> { - if bytes.len() != $n_words * 8 { - Err(ParseLengthError { actual: bytes.len(), expected: $n_words*8 }) - } else { - Ok(Self::_from_be_slice(bytes)) - } - } - - fn _from_be_slice(bytes: &[u8]) -> $name { - use super::endian::slice_to_u64_be; - let mut slice = [0u64; $n_words]; - slice.iter_mut() - .rev() - .zip(bytes.chunks(8)) - .for_each(|(word, bytes)| *word = slice_to_u64_be(bytes)); - $name(slice) - } - - /// Convert a big integer into a byte array using big-endian encoding - pub fn to_be_bytes(self) -> [u8; $n_words * 8] { - use super::endian::u64_to_array_be; - let mut res = [0; $n_words * 8]; - for i in 0..$n_words { - let start = i * 8; - res[start..start+8].copy_from_slice(&u64_to_array_be(self.0[$n_words - (i+1)])); - } - res - } - - // divmod like operation, returns (quotient, remainder) - #[inline] - fn div_rem(self, other: Self) -> (Self, Self) { - let mut sub_copy = self; - let mut shift_copy = other; - let mut ret = [0u64; $n_words]; - - let my_bits = self.bits(); - let your_bits = other.bits(); - - // Check for division by 0 - assert!(your_bits != 0, "attempted to divide {:#x} by zero", self); - - // Early return in case we are dividing by a larger number than us - if my_bits < your_bits { - return ($name(ret), sub_copy); - } - - // Bitwise long division - let mut shift = my_bits - your_bits; - shift_copy = shift_copy << shift; - loop { - if sub_copy >= shift_copy { - ret[shift / 64] |= 1 << (shift % 64); - sub_copy = sub_copy - shift_copy; - } - shift_copy = shift_copy >> 1; - if shift == 0 { - break; - } - shift -= 1; - } - - ($name(ret), sub_copy) - } - - /// Increment by 1 - #[inline] - pub fn increment(&mut self) { - let &mut $name(ref mut arr) = self; - for i in 0..$n_words { - arr[i] = arr[i].wrapping_add(1); - if arr[i] != 0 { - break; - } - } - } - } - - impl PartialOrd for $name { - #[inline] - fn partial_cmp(&self, other: &$name) -> Option { - Some(self.cmp(&other)) - } - } - - impl Ord for $name { - #[inline] - fn cmp(&self, other: &$name) -> core::cmp::Ordering { - // We need to manually implement ordering because we use little-endian - // and the auto derive is a lexicographic ordering(i.e. memcmp) - // which with numbers is equivalent to big-endian - for i in 0..$n_words { - if self[$n_words - 1 - i] < other[$n_words - 1 - i] { - return core::cmp::Ordering::Less; - } - if self[$n_words - 1 - i] > other[$n_words - 1 - i] { - return core::cmp::Ordering::Greater; - } - } - core::cmp::Ordering::Equal - } - } - - impl core::ops::Add<$name> for $name { - type Output = $name; - - fn add(self, other: $name) -> $name { - let $name(ref me) = self; - let $name(ref you) = other; - let mut ret = [0u64; $n_words]; - let mut carry = [0u64; $n_words]; - let mut b_carry = false; - for i in 0..$n_words { - ret[i] = me[i].wrapping_add(you[i]); - if i < $n_words - 1 && ret[i] < me[i] { - carry[i + 1] = 1; - b_carry = true; - } - } - if b_carry { $name(ret) + $name(carry) } else { $name(ret) } - } - } - - impl core::ops::Sub<$name> for $name { - type Output = $name; - - #[inline] - fn sub(self, other: $name) -> $name { - self + !other + $crate::util::BitArray::one() - } - } - - impl core::ops::Mul<$name> for $name { - type Output = $name; - - fn mul(self, other: $name) -> $name { - use $crate::util::BitArray; - let mut me = $name::zero(); - // TODO: be more efficient about this - for i in 0..(2 * $n_words) { - let to_mul = (other >> (32 * i)).low_u32(); - me = me + (self.mul_u32(to_mul) << (32 * i)); - } - me - } - } - - impl core::ops::Div<$name> for $name { - type Output = $name; - - fn div(self, other: $name) -> $name { - self.div_rem(other).0 - } - } - - impl core::ops::Rem<$name> for $name { - type Output = $name; - - fn rem(self, other: $name) -> $name { - self.div_rem(other).1 - } - } - - impl $crate::util::BitArray for $name { - #[inline] - fn bit(&self, index: usize) -> bool { - let &$name(ref arr) = self; - arr[index / 64] & (1 << (index % 64)) != 0 - } - - #[inline] - fn bit_slice(&self, start: usize, end: usize) -> $name { - (*self >> start).mask(end - start) - } - - #[inline] - fn mask(&self, n: usize) -> $name { - let &$name(ref arr) = self; - let mut ret = [0; $n_words]; - for i in 0..$n_words { - if n >= 0x40 * (i + 1) { - ret[i] = arr[i]; - } else { - ret[i] = arr[i] & ((1 << (n - 0x40 * i)) - 1); - break; - } - } - $name(ret) - } - - #[inline] - fn trailing_zeros(&self) -> usize { - let &$name(ref arr) = self; - for i in 0..($n_words - 1) { - if arr[i] > 0 { return (0x40 * i) + arr[i].trailing_zeros() as usize; } - } - (0x40 * ($n_words - 1)) + arr[$n_words - 1].trailing_zeros() as usize - } - - fn zero() -> $name { Default::default() } - fn one() -> $name { - $name({ let mut ret = [0; $n_words]; ret[0] = 1; ret }) - } - } - - impl core::ops::BitAnd<$name> for $name { - type Output = $name; - - #[inline] - fn bitand(self, other: $name) -> $name { - let $name(ref arr1) = self; - let $name(ref arr2) = other; - let mut ret = [0u64; $n_words]; - for i in 0..$n_words { - ret[i] = arr1[i] & arr2[i]; - } - $name(ret) - } - } - - impl core::ops::BitXor<$name> for $name { - type Output = $name; - - #[inline] - fn bitxor(self, other: $name) -> $name { - let $name(ref arr1) = self; - let $name(ref arr2) = other; - let mut ret = [0u64; $n_words]; - for i in 0..$n_words { - ret[i] = arr1[i] ^ arr2[i]; - } - $name(ret) - } - } - - impl core::ops::BitOr<$name> for $name { - type Output = $name; - - #[inline] - fn bitor(self, other: $name) -> $name { - let $name(ref arr1) = self; - let $name(ref arr2) = other; - let mut ret = [0u64; $n_words]; - for i in 0..$n_words { - ret[i] = arr1[i] | arr2[i]; - } - $name(ret) - } - } - - impl core::ops::Not for $name { - type Output = $name; - - #[inline] - fn not(self) -> $name { - let $name(ref arr) = self; - let mut ret = [0u64; $n_words]; - for i in 0..$n_words { - ret[i] = !arr[i]; - } - $name(ret) - } - } - - impl core::ops::Shl for $name { - type Output = $name; - - fn shl(self, shift: usize) -> $name { - let $name(ref original) = self; - let mut ret = [0u64; $n_words]; - let word_shift = shift / 64; - let bit_shift = shift % 64; - for i in 0..$n_words { - // Shift - if bit_shift < 64 && i + word_shift < $n_words { - ret[i + word_shift] += original[i] << bit_shift; - } - // Carry - if bit_shift > 0 && i + word_shift + 1 < $n_words { - ret[i + word_shift + 1] += original[i] >> (64 - bit_shift); - } - } - $name(ret) - } - } - - impl core::ops::Shr for $name { - type Output = $name; - - fn shr(self, shift: usize) -> $name { - let $name(ref original) = self; - let mut ret = [0u64; $n_words]; - let word_shift = shift / 64; - let bit_shift = shift % 64; - for i in word_shift..$n_words { - // Shift - ret[i - word_shift] += original[i] >> bit_shift; - // Carry - if bit_shift > 0 && i < $n_words - 1 { - ret[i - word_shift] += original[i + 1] << (64 - bit_shift); - } - } - $name(ret) - } - } - - impl core::fmt::LowerHex for $name { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - let &$name(ref data) = self; - if f.alternate() { - write!(f, "0x")?; - } - for ch in data.iter().rev() { - write!(f, "{:016x}", ch)?; - } - Ok(()) - } - } - - impl core::fmt::Debug for $name { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - write!(f,"{:#x}", self) - } - } - - impl $crate::consensus::Encodable for $name { - #[inline] - fn consensus_encode( - &self, - w: &mut W, - ) -> Result { - let &$name(ref data) = self; - let mut len = 0; - for word in data.iter() { - len += word.consensus_encode(w)?; - } - Ok(len) - } - } - - impl $crate::consensus::Decodable for $name { - fn consensus_decode( - r: &mut R, - ) -> Result<$name, $crate::consensus::encode::Error> { - use $crate::consensus::Decodable; - let mut ret: [u64; $n_words] = [0; $n_words]; - for i in 0..$n_words { - ret[i] = Decodable::consensus_decode(r)?; - } - Ok($name(ret)) - } - } - - #[cfg(feature = "serde")] - #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] - impl $crate::serde::Serialize for $name { - fn serialize(&self, serializer: S) -> Result - where - S: $crate::serde::Serializer, - { - use $crate::hashes::hex::ToHex; - let bytes = self.to_be_bytes(); - if serializer.is_human_readable() { - serializer.serialize_str(&bytes.to_hex()) - } else { - serializer.serialize_bytes(&bytes) - } - } - } - - #[cfg(feature = "serde")] - #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] - impl<'de> $crate::serde::Deserialize<'de> for $name { - fn deserialize>( - deserializer: D, - ) -> Result { - use core::fmt; - use $crate::hashes::hex::FromHex; - use $crate::serde::de; - struct Visitor; - impl<'de> de::Visitor<'de> for Visitor { - type Value = $name; - - fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} bytes or a hex string with {} characters", $n_words * 8, $n_words * 8 * 2) - } - - fn visit_str(self, s: &str) -> Result - where - E: de::Error, - { - let bytes = $crate::prelude::Vec::from_hex(s) - .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(s), &self))?; - $name::from_be_slice(&bytes) - .map_err(|_| de::Error::invalid_length(bytes.len() * 2, &self)) - } - - fn visit_bytes(self, bytes: &[u8]) -> Result - where - E: de::Error, - { - $name::from_be_slice(bytes) - .map_err(|_| de::Error::invalid_length(bytes.len(), &self)) - } - } - - if deserializer.is_human_readable() { - deserializer.deserialize_str(Visitor) - } else { - deserializer.deserialize_bytes(Visitor) - } - } - } - }; -} - -construct_uint!(Uint256, 4); -construct_uint!(Uint128, 2); - -/// Invalid slice length. -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] -pub struct ParseLengthError { - /// The length of the slice de-facto - pub actual: usize, - /// The required length of the slice - pub expected: usize, -} - -impl core::fmt::Display for ParseLengthError { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - write!(f, "Invalid length: got {}, expected {}", self.actual, self.expected) - } -} - -crate::error::impl_std_error!(ParseLengthError); - -impl Uint256 { - /// Decay to a uint128 - #[inline] - pub fn low_128(&self) -> Uint128 { - let &Uint256(data) = self; - Uint128([data[0], data[1]]) - } -} - -#[cfg(test)] -mod tests { - use crate::consensus::{deserialize, serialize}; - use crate::util::uint::{Uint256, Uint128}; - use crate::util::BitArray; - - #[test] - pub fn uint256_bits_test() { - assert_eq!(Uint256::from_u64(255).unwrap().bits(), 8); - assert_eq!(Uint256::from_u64(256).unwrap().bits(), 9); - assert_eq!(Uint256::from_u64(300).unwrap().bits(), 9); - assert_eq!(Uint256::from_u64(60000).unwrap().bits(), 16); - assert_eq!(Uint256::from_u64(70000).unwrap().bits(), 17); - - // Try to read the following lines out loud quickly - let mut shl = Uint256::from_u64(70000).unwrap(); - shl = shl << 100; - assert_eq!(shl.bits(), 117); - shl = shl << 100; - assert_eq!(shl.bits(), 217); - shl = shl << 100; - assert_eq!(shl.bits(), 0); - - // Bit set check - assert!(!Uint256::from_u64(10).unwrap().bit(0)); - assert!(Uint256::from_u64(10).unwrap().bit(1)); - assert!(!Uint256::from_u64(10).unwrap().bit(2)); - assert!(Uint256::from_u64(10).unwrap().bit(3)); - assert!(!Uint256::from_u64(10).unwrap().bit(4)); - } - - #[test] - pub fn uint256_display_test() { - assert_eq!(format!("{:#x}", Uint256::from_u64(0xDEADBEEF).unwrap()), - "0x00000000000000000000000000000000000000000000000000000000deadbeef"); - assert_eq!(format!("{:x}", Uint256::from_u64(0xDEADBEEF).unwrap()), - "00000000000000000000000000000000000000000000000000000000deadbeef"); - assert_eq!(format!("{:#x}", Uint256::from_u64(u64::max_value()).unwrap()), - "0x000000000000000000000000000000000000000000000000ffffffffffffffff"); - - let max_val = Uint256([0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, - 0xFFFFFFFFFFFFFFFF]); - assert_eq!(format!("{:#x}", max_val), - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - } - - #[test] - pub fn uint256_debug_test() { - assert_eq!(format!("{:?}", Uint256::from_u64(0xDEADBEEF).unwrap()), - "0x00000000000000000000000000000000000000000000000000000000deadbeef"); - } - - #[test] - pub fn uint256_comp_test() { - let small = Uint256([10u64, 0, 0, 0]); - let big = Uint256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0]); - let bigger = Uint256([0x9C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0]); - let biggest = Uint256([0x5C8C3EE70C644118u64, 0x0209E7378231E632, 0, 1]); - - assert!(small < big); - assert!(big < bigger); - assert!(bigger < biggest); - assert!(bigger <= biggest); - assert!(biggest <= biggest); - assert!(bigger >= big); - assert!(bigger >= small); - assert!(small <= small); - } - - #[test] - pub fn uint_from_be_bytes() { - assert_eq!(Uint128::from_be_bytes([0x1b, 0xad, 0xca, 0xfe, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xaf, 0xba, 0xbe, 0x2b, 0xed, 0xfe, 0xed]), - Uint128([0xdeafbabe2bedfeed, 0x1badcafedeadbeef])); - - assert_eq!(Uint256::from_be_bytes([0x1b, 0xad, 0xca, 0xfe, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xaf, 0xba, 0xbe, 0x2b, 0xed, 0xfe, 0xed, - 0xba, 0xad, 0xf0, 0x0d, 0xde, 0xfa, 0xce, 0xda, 0x11, 0xfe, 0xd2, 0xba, 0xd1, 0xc0, 0xff, 0xe0]), - Uint256([0x11fed2bad1c0ffe0, 0xbaadf00ddefaceda, 0xdeafbabe2bedfeed, 0x1badcafedeadbeef])); - } - - #[test] - pub fn uint_to_be_bytes() { - assert_eq!(Uint128([0xdeafbabe2bedfeed, 0x1badcafedeadbeef]).to_be_bytes(), - [0x1b, 0xad, 0xca, 0xfe, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xaf, 0xba, 0xbe, 0x2b, 0xed, 0xfe, 0xed]); - - assert_eq!(Uint256([0x11fed2bad1c0ffe0, 0xbaadf00ddefaceda, 0xdeafbabe2bedfeed, 0x1badcafedeadbeef]).to_be_bytes(), - [0x1b, 0xad, 0xca, 0xfe, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xaf, 0xba, 0xbe, 0x2b, 0xed, 0xfe, 0xed, - 0xba, 0xad, 0xf0, 0x0d, 0xde, 0xfa, 0xce, 0xda, 0x11, 0xfe, 0xd2, 0xba, 0xd1, 0xc0, 0xff, 0xe0]); - } - - #[test] - pub fn uint256_arithmetic_test() { - let init = Uint256::from_u64(0xDEADBEEFDEADBEEF).unwrap(); - let copy = init; - - let add = init + copy; - assert_eq!(add, Uint256([0xBD5B7DDFBD5B7DDEu64, 1, 0, 0])); - // Bitshifts - let shl = add << 88; - assert_eq!(shl, Uint256([0u64, 0xDFBD5B7DDE000000, 0x1BD5B7D, 0])); - let shr = shl >> 40; - assert_eq!(shr, Uint256([0x7DDE000000000000u64, 0x0001BD5B7DDFBD5B, 0, 0])); - // Increment - let mut incr = shr; - incr.increment(); - assert_eq!(incr, Uint256([0x7DDE000000000001u64, 0x0001BD5B7DDFBD5B, 0, 0])); - // Subtraction - let sub = incr - init; - assert_eq!(sub, Uint256([0x9F30411021524112u64, 0x0001BD5B7DDFBD5A, 0, 0])); - // Multiplication - let mult = sub.mul_u32(300); - assert_eq!(mult, Uint256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0])); - // Division - assert_eq!(Uint256::from_u64(105).unwrap() / - Uint256::from_u64(5).unwrap(), - Uint256::from_u64(21).unwrap()); - let div = mult / Uint256::from_u64(300).unwrap(); - assert_eq!(div, Uint256([0x9F30411021524112u64, 0x0001BD5B7DDFBD5A, 0, 0])); - - assert_eq!(Uint256::from_u64(105).unwrap() % Uint256::from_u64(5).unwrap(), - Uint256::from_u64(0).unwrap()); - assert_eq!(Uint256::from_u64(35498456).unwrap() % Uint256::from_u64(3435).unwrap(), - Uint256::from_u64(1166).unwrap()); - let rem_src = mult * Uint256::from_u64(39842).unwrap() + Uint256::from_u64(9054).unwrap(); - assert_eq!(rem_src % Uint256::from_u64(39842).unwrap(), - Uint256::from_u64(9054).unwrap()); - // TODO: bit inversion - } - - #[test] - pub fn mul_u32_test() { - let u64_val = Uint256::from_u64(0xDEADBEEFDEADBEEF).unwrap(); - - let u96_res = u64_val.mul_u32(0xFFFFFFFF); - let u128_res = u96_res.mul_u32(0xFFFFFFFF); - let u160_res = u128_res.mul_u32(0xFFFFFFFF); - let u192_res = u160_res.mul_u32(0xFFFFFFFF); - let u224_res = u192_res.mul_u32(0xFFFFFFFF); - let u256_res = u224_res.mul_u32(0xFFFFFFFF); - - assert_eq!(u96_res, Uint256([0xffffffff21524111u64, 0xDEADBEEE, 0, 0])); - assert_eq!(u128_res, Uint256([0x21524111DEADBEEFu64, 0xDEADBEEE21524110, 0, 0])); - assert_eq!(u160_res, Uint256([0xBD5B7DDD21524111u64, 0x42A4822200000001, 0xDEADBEED, 0])); - assert_eq!(u192_res, Uint256([0x63F6C333DEADBEEFu64, 0xBD5B7DDFBD5B7DDB, 0xDEADBEEC63F6C334, 0])); - assert_eq!(u224_res, Uint256([0x7AB6FBBB21524111u64, 0xFFFFFFFBA69B4558, 0x854904485964BAAA, 0xDEADBEEB])); - assert_eq!(u256_res, Uint256([0xA69B4555DEADBEEFu64, 0xA69B455CD41BB662, 0xD41BB662A69B4550, 0xDEADBEEAA69B455C])); - } - - #[test] - pub fn multiplication_test() { - let u64_val = Uint256::from_u64(0xDEADBEEFDEADBEEF).unwrap(); - - let u128_res = u64_val * u64_val; - - assert_eq!(u128_res, Uint256([0x048D1354216DA321u64, 0xC1B1CD13A4D13D46, 0, 0])); - - let u256_res = u128_res * u128_res; - - assert_eq!(u256_res, Uint256([0xF4E166AAD40D0A41u64, 0xF5CF7F3618C2C886u64, - 0x4AFCFF6F0375C608u64, 0x928D92B4D7F5DF33u64])); - } - - #[test] - pub fn increment_test() { - let mut val = Uint256([ - 0xFFFFFFFFFFFFFFFEu64, - 0xFFFFFFFFFFFFFFFFu64, - 0xFFFFFFFFFFFFFFFFu64, - 0xEFFFFFFFFFFFFFFFu64, - ]); - val.increment(); - assert_eq!( - val, - Uint256([ - 0xFFFFFFFFFFFFFFFFu64, - 0xFFFFFFFFFFFFFFFFu64, - 0xFFFFFFFFFFFFFFFFu64, - 0xEFFFFFFFFFFFFFFFu64, - ]) - ); - val.increment(); - assert_eq!( - val, - Uint256([ - 0x0000000000000000u64, - 0x0000000000000000u64, - 0x0000000000000000u64, - 0xF000000000000000u64, - ]) - ); - - let mut val = Uint256([ - 0xFFFFFFFFFFFFFFFFu64, - 0xFFFFFFFFFFFFFFFFu64, - 0xFFFFFFFFFFFFFFFFu64, - 0xFFFFFFFFFFFFFFFFu64, - ]); - val.increment(); - assert_eq!( - val, - Uint256([ - 0x0000000000000000u64, - 0x0000000000000000u64, - 0x0000000000000000u64, - 0x0000000000000000u64, - ]) - ); - } - - #[test] - pub fn uint256_bitslice_test() { - let init = Uint256::from_u64(0xDEADBEEFDEADBEEF).unwrap(); - let add = init + (init << 64); - assert_eq!(add.bit_slice(64, 128), init); - assert_eq!(add.mask(64), init); - } - - #[test] - pub fn uint256_extreme_bitshift_test() { - // Shifting a u64 by 64 bits gives an undefined value, so make sure that - // we're doing the Right Thing here - let init = Uint256::from_u64(0xDEADBEEFDEADBEEF).unwrap(); - - assert_eq!(init << 64, Uint256([0, 0xDEADBEEFDEADBEEF, 0, 0])); - let add = (init << 64) + init; - assert_eq!(add, Uint256([0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0, 0])); - assert_eq!(add >> 0, Uint256([0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0, 0])); - assert_eq!(add << 0, Uint256([0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0, 0])); - assert_eq!(add >> 64, Uint256([0xDEADBEEFDEADBEEF, 0, 0, 0])); - assert_eq!(add << 64, Uint256([0, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0])); - } - - #[test] - pub fn uint256_serialize_test() { - let start1 = Uint256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0]); - let start2 = Uint256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0xABCD, 0xFFFF]); - let serial1 = serialize(&start1); - let serial2 = serialize(&start2); - let end1: Result = deserialize(&serial1); - let end2: Result = deserialize(&serial2); - - assert_eq!(end1.ok(), Some(start1)); - assert_eq!(end2.ok(), Some(start2)); - } - - #[cfg(feature = "serde")] - #[test] - pub fn uint256_serde_test() { - let check = |uint, hex| { - let json = format!("\"{}\"", hex); - assert_eq!(::serde_json::to_string(&uint).unwrap(), json); - assert_eq!(::serde_json::from_str::(&json).unwrap(), uint); - - let bin_encoded = bincode::serialize(&uint).unwrap(); - let bin_decoded: Uint256 = bincode::deserialize(&bin_encoded).unwrap(); - assert_eq!(bin_decoded, uint); - }; - - check( - Uint256::from_u64(0).unwrap(), - "0000000000000000000000000000000000000000000000000000000000000000", - ); - check( - Uint256::from_u64(0xDEADBEEF).unwrap(), - "00000000000000000000000000000000000000000000000000000000deadbeef", - ); - check( - Uint256([0xaa11, 0xbb22, 0xcc33, 0xdd44]), - "000000000000dd44000000000000cc33000000000000bb22000000000000aa11", - ); - check( - Uint256([u64::max_value(), u64::max_value(), u64::max_value(), u64::max_value()]), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - ); - check( - Uint256([ 0xA69B4555DEADBEEF, 0xA69B455CD41BB662, 0xD41BB662A69B4550, 0xDEADBEEAA69B455C ]), - "deadbeeaa69b455cd41bb662a69b4550a69b455cd41bb662a69b4555deadbeef", - ); - - assert!(::serde_json::from_str::("\"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg\"").is_err()); // invalid char - assert!(::serde_json::from_str::("\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"").is_err()); // invalid length - assert!(::serde_json::from_str::("\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"").is_err()); // invalid length - } -} diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index ae61cee3..153b708e 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -56,10 +56,6 @@ path = "fuzz_targets/deserialize_psbt.rs" name = "deser_net_msg" path = "fuzz_targets/deser_net_msg.rs" -[[bin]] -name = "uint128_fuzz" -path = "fuzz_targets/uint128_fuzz.rs" - [[bin]] name = "script_bytes_to_asm_fmt" path = "fuzz_targets/script_bytes_to_asm_fmt.rs" diff --git a/fuzz/fuzz_targets/uint128_fuzz.rs b/fuzz/fuzz_targets/uint128_fuzz.rs deleted file mode 100644 index 6a34e2ab..00000000 --- a/fuzz/fuzz_targets/uint128_fuzz.rs +++ /dev/null @@ -1,113 +0,0 @@ -extern crate bitcoin; -use std::str::FromStr; -use std::convert::Into; - -fn do_test(data: &[u8]) { - macro_rules! read_ints { - ($start: expr) => { { - let mut native = 0; - for c in data[$start..$start + 16].iter() { - native <<= 8; - native |= (*c) as u128; - } - // Note BE: - let uint128 = bitcoin::util::uint::Uint128::from(&[native as u64, (native >> 8*8) as u64][..]); - - // Checking two conversion methods against each other - let mut slice = [0u8; 16]; - slice.copy_from_slice(&data[$start..$start + 16]); - assert_eq!(uint128, bitcoin::util::uint::Uint128::from_be_bytes(slice)); - - (native, uint128) - } } - } - macro_rules! check_eq { - ($native: expr, $uint: expr) => { { - assert_eq!(&[$native as u64, ($native >> 8*8) as u64], $uint.as_bytes()); - } } - } - - if data.len() != 16*2 { return; } - let (a_native, a) = read_ints!(0); - - // Checks using only a: - for i in 0..128 { - check_eq!(a_native << i, a << i); - check_eq!(a_native >> i, a >> i); - } - assert_eq!(a_native as u64, a.low_u64()); - assert_eq!(a_native as u32, a.low_u32()); - assert_eq!(128 - a_native.leading_zeros() as usize, a.bits()); - assert_eq!(a_native as u64, bitcoin::util::uint::Uint128::from_u64(a_native as u64).unwrap().low_u64()); - - let mut a_inc = a.clone(); - a_inc.increment(); - check_eq!(a_native.wrapping_add(1), a_inc); - - // Checks with two numbers: - let (b_native, b) = read_ints!(16); - - check_eq!(a_native.wrapping_add(b_native), a + b); - check_eq!(a_native.wrapping_sub(b_native), a - b); - if b_native != 0 { - check_eq!(a_native.wrapping_div(b_native), a / b); - check_eq!(a_native.wrapping_rem(b_native), a % b); - } - check_eq!(a_native.wrapping_mul(b_native), a * b); - check_eq!(a_native & b_native, a & b); - check_eq!(a_native | b_native, a | b); - check_eq!(a_native ^ b_native, a ^ b); - check_eq!(a_native.wrapping_mul((b_native as u32) as u128), a.mul_u32(b.low_u32())); - - assert_eq!(a_native > b_native, a > b); - assert_eq!(a_native >= b_native, a >= b); - assert_eq!(a_native < b_native, a < b); - assert_eq!(a_native <= b_native, a <= b); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(&data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -#[cfg(test)] -mod tests { - fn extend_vec_from_hex(hex: &str, out: &mut Vec) { - let mut b = 0; - for (idx, c) in hex.as_bytes().iter().enumerate() { - b <<= 4; - match *c { - b'A'..=b'F' => b |= c - b'A' + 10, - b'a'..=b'f' => b |= c - b'a' + 10, - b'0'..=b'9' => b |= c - b'0', - _ => panic!("Bad hex"), - } - if (idx & 1) == 1 { - out.push(b); - b = 0; - } - } - } - - #[test] - fn duplicate_crash() { - let mut a = Vec::new(); - extend_vec_from_hex("100000a70000000000000000000000000000000000000000000000000000000054", &mut a); - super::do_test(&a); - } -} From 02a2b43b2b0729aa7b18afbdc90be8654a959790 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 30 Sep 2022 09:16:56 +1000 Subject: [PATCH 2/2] Remove Default impl for Target and Work A zero default value for `Target` and `Work` has no significance and/or usecase, remove the derived `Default` implementation. Includes making `Target::ZERO` public. --- bitcoin/src/blockdata/block.rs | 2 +- bitcoin/src/pow.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs index 1dd8a290..1fa7bc1b 100644 --- a/bitcoin/src/blockdata/block.rs +++ b/bitcoin/src/blockdata/block.rs @@ -513,7 +513,7 @@ mod tests { assert_eq!(some_header.validate_pow(some_header.target()).unwrap(), some_header.block_hash()); // test with zero target - match some_header.validate_pow(Target::default()) { + match some_header.validate_pow(Target::ZERO) { Err(BlockBadTarget) => (), _ => panic!("unexpected result from validate_pow"), } diff --git a/bitcoin/src/pow.rs b/bitcoin/src/pow.rs index c1bd127c..f267d349 100644 --- a/bitcoin/src/pow.rs +++ b/bitcoin/src/pow.rs @@ -90,7 +90,7 @@ macro_rules! do_impl { /// Work is a measure of how difficult it is to find a hash below a given [`Target`]. /// /// ref: -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] pub struct Work(U256); @@ -130,14 +130,14 @@ impl Sub for Work { /// a block. (See also [`Work`].) /// /// ref: -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] pub struct Target(U256); impl Target { - // When parsing nBits, Bitcoin Core converts a negative target threshold into a target of zero. - const ZERO: Target = Target(U256::ZERO); + /// When parsing nBits, Bitcoin Core converts a negative target threshold into a target of zero. + pub const ZERO: Target = Target(U256::ZERO); /// The maximum possible target. /// /// This value is used to calculate difficulty, which is defined as how difficult the current