Merge rust-bitcoin/rust-bitcoin#3059: Move `CompactTarget` to `primitives`
2ec901fd63
Move the CompactTarget type to primitives (Tobin C. Harding)a00bd7cc4d
Introduce CompactTargetExt trait (Tobin C. Harding)100ce03643
Run cargo +nightly fmt (Tobin C. Harding)9c4a629659
Wrap CompactTarget impl block in temporary module (Tobin C. Harding)578143c09e
Separate CompactTarget impl blocks (Tobin C. Harding)22d5646f7b
Stop using CompactTarget inner field (Tobin C. Harding)244d7dbe6c
Remove generic test impl (Tobin C. Harding)3d85ee3a02
primitives: Fix alloc feature (Tobin C. Harding) Pull request description: Done in preparation for moving `BlockHash` and `block::Header` to `primitives`. - Patch 1 introduces an extension trait using `define_extension_trait!` - Patch 2 is the trivial copy and past to move the type to `primitives` This one shouldn't be to arduous to review, thanks. ACKs for top commit: Kixunil: ACK2ec901fd63
apoelstra: ACK2ec901fd63
successfully ran local tests Tree-SHA512: b0e4f1af0b268e249a056cae71d7cafd1b025c4a079e5393ce80cd0b9c9bb6d2c6306531dc6786d986ff8a094b61866a86285b20d54037ef1395d127876bfd9c
This commit is contained in:
commit
49e420a6e0
|
@ -15,8 +15,13 @@ use units::parse::{self, ParseIntError, PrefixedHexError, UnprefixedHexError};
|
||||||
|
|
||||||
use crate::block::{BlockHash, Header};
|
use crate::block::{BlockHash, Header};
|
||||||
use crate::consensus::encode::{self, Decodable, Encodable};
|
use crate::consensus::encode::{self, Decodable, Encodable};
|
||||||
|
use crate::internal_macros::define_extension_trait;
|
||||||
use crate::network::Params;
|
use crate::network::Params;
|
||||||
|
|
||||||
|
#[rustfmt::skip] // Keep public re-exports separate.
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use primitives::CompactTarget;
|
||||||
|
|
||||||
/// Implement traits and methods shared by `Target` and `Work`.
|
/// Implement traits and methods shared by `Target` and `Work`.
|
||||||
macro_rules! do_impl {
|
macro_rules! do_impl {
|
||||||
($ty:ident) => {
|
($ty:ident) => {
|
||||||
|
@ -164,7 +169,7 @@ impl Target {
|
||||||
///
|
///
|
||||||
/// ref: <https://developer.bitcoin.org/reference/block_chain.html#target-nbits>
|
/// ref: <https://developer.bitcoin.org/reference/block_chain.html#target-nbits>
|
||||||
pub fn from_compact(c: CompactTarget) -> Target {
|
pub fn from_compact(c: CompactTarget) -> Target {
|
||||||
let bits = c.0;
|
let bits = c.to_consensus();
|
||||||
// This is a floating-point "compact" encoding originally used by
|
// This is a floating-point "compact" encoding originally used by
|
||||||
// OpenSSL, which satoshi put into consensus code, so we're stuck
|
// OpenSSL, which satoshi put into consensus code, so we're stuck
|
||||||
// with it. The exponent needs to have 3 subtracted from it, hence
|
// with it. The exponent needs to have 3 subtracted from it, hence
|
||||||
|
@ -204,7 +209,7 @@ impl Target {
|
||||||
size += 1;
|
size += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
CompactTarget(compact | (size << 24))
|
CompactTarget::from_consensus(compact | (size << 24))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if block hash is less than or equal to this [`Target`].
|
/// Returns true if block hash is less than or equal to this [`Target`].
|
||||||
|
@ -329,33 +334,17 @@ impl Target {
|
||||||
}
|
}
|
||||||
do_impl!(Target);
|
do_impl!(Target);
|
||||||
|
|
||||||
/// Encoding of 256-bit target as 32-bit float.
|
define_extension_trait! {
|
||||||
///
|
/// Extension functionality for the [`CompactTarget`] type.
|
||||||
/// This is used to encode a target into the block header. Satoshi made this part of consensus code
|
pub trait CompactTargetExt impl for CompactTarget {
|
||||||
/// 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.
|
|
||||||
///
|
|
||||||
/// # Note on order/equality
|
|
||||||
///
|
|
||||||
/// Usage of the ordering and equality traits for this type may be surprising. Converting between
|
|
||||||
/// `CompactTarget` and `Target` is lossy *in both directions* (there are multiple `CompactTarget`
|
|
||||||
/// values that map to the same `Target` value). Ordering and equality for this type are defined in
|
|
||||||
/// terms of the underlying `u32`.
|
|
||||||
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
|
||||||
pub struct CompactTarget(u32);
|
|
||||||
|
|
||||||
impl CompactTarget {
|
|
||||||
/// Creates a `CompactTarget` from a prefixed hex string.
|
/// Creates a `CompactTarget` from a prefixed hex string.
|
||||||
pub fn from_hex(s: &str) -> Result<Self, PrefixedHexError> {
|
fn from_hex(s: &str) -> Result<CompactTarget, PrefixedHexError> {
|
||||||
let target = parse::hex_u32_prefixed(s)?;
|
let target = parse::hex_u32_prefixed(s)?;
|
||||||
Ok(Self::from_consensus(target))
|
Ok(Self::from_consensus(target))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `CompactTarget` from an unprefixed hex string.
|
/// Creates a `CompactTarget` from an unprefixed hex string.
|
||||||
pub fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError> {
|
fn from_unprefixed_hex(s: &str) -> Result<CompactTarget, UnprefixedHexError> {
|
||||||
let target = parse::hex_u32_unprefixed(s)?;
|
let target = parse::hex_u32_unprefixed(s)?;
|
||||||
Ok(Self::from_consensus(target))
|
Ok(Self::from_consensus(target))
|
||||||
}
|
}
|
||||||
|
@ -382,7 +371,7 @@ impl CompactTarget {
|
||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
/// The expected [`CompactTarget`] recalculation.
|
/// The expected [`CompactTarget`] recalculation.
|
||||||
pub fn from_next_work_required(
|
fn from_next_work_required(
|
||||||
last: CompactTarget,
|
last: CompactTarget,
|
||||||
timespan: u64,
|
timespan: u64,
|
||||||
params: impl AsRef<Params>,
|
params: impl AsRef<Params>,
|
||||||
|
@ -426,7 +415,7 @@ impl CompactTarget {
|
||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
/// The expected [`CompactTarget`] recalculation.
|
/// The expected [`CompactTarget`] recalculation.
|
||||||
pub fn from_header_difficulty_adjustment(
|
fn from_header_difficulty_adjustment(
|
||||||
last_epoch_boundary: Header,
|
last_epoch_boundary: Header,
|
||||||
current: Header,
|
current: Header,
|
||||||
params: impl AsRef<Params>,
|
params: impl AsRef<Params>,
|
||||||
|
@ -435,12 +424,7 @@ impl CompactTarget {
|
||||||
let bits = current.bits;
|
let bits = current.bits;
|
||||||
CompactTarget::from_next_work_required(bits, timespan.into(), params)
|
CompactTarget::from_next_work_required(bits, timespan.into(), params)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/// 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<CompactTarget> for Target {
|
impl From<CompactTarget> for Target {
|
||||||
|
@ -450,27 +434,17 @@ impl From<CompactTarget> for Target {
|
||||||
impl Encodable for CompactTarget {
|
impl Encodable for CompactTarget {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
|
fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
self.0.consensus_encode(w)
|
self.to_consensus().consensus_encode(w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for CompactTarget {
|
impl Decodable for CompactTarget {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<R: BufRead + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: BufRead + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
u32::consensus_decode(r).map(CompactTarget)
|
u32::consensus_decode(r).map(CompactTarget::from_consensus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::LowerHex for CompactTarget {
|
|
||||||
#[inline]
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::UpperHex for CompactTarget {
|
|
||||||
#[inline]
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Big-endian 256 bit integer type.
|
/// Big-endian 256 bit integer type.
|
||||||
// (high, low): u.0 contains the high bits, u.1 contains the low bits.
|
// (high, low): u.0 contains the high bits, u.1 contains the low bits.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
|
@ -1099,8 +1073,12 @@ impl kani::Arbitrary for U256 {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
impl<T: Into<u128>> From<T> for Target {
|
impl From<u64> for Target {
|
||||||
fn from(x: T) -> Self { Self(U256::from(x)) }
|
fn from(x: u64) -> Self { Self(U256::from(x)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u32> for Target {
|
||||||
|
fn from(x: u32) -> Self { Self(U256::from(x)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Into<u128>> From<T> for Work {
|
impl<T: Into<u128>> From<T> for Work {
|
||||||
|
@ -1721,25 +1699,25 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn compact_target_from_hex_lower() {
|
fn compact_target_from_hex_lower() {
|
||||||
let target = CompactTarget::from_hex("0x010034ab").unwrap();
|
let target = CompactTarget::from_hex("0x010034ab").unwrap();
|
||||||
assert_eq!(target, CompactTarget(0x010034ab));
|
assert_eq!(target, CompactTarget::from_consensus(0x010034ab));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn compact_target_from_hex_upper() {
|
fn compact_target_from_hex_upper() {
|
||||||
let target = CompactTarget::from_hex("0X010034AB").unwrap();
|
let target = CompactTarget::from_hex("0X010034AB").unwrap();
|
||||||
assert_eq!(target, CompactTarget(0x010034ab));
|
assert_eq!(target, CompactTarget::from_consensus(0x010034ab));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn compact_target_from_unprefixed_hex_lower() {
|
fn compact_target_from_unprefixed_hex_lower() {
|
||||||
let target = CompactTarget::from_unprefixed_hex("010034ab").unwrap();
|
let target = CompactTarget::from_unprefixed_hex("010034ab").unwrap();
|
||||||
assert_eq!(target, CompactTarget(0x010034ab));
|
assert_eq!(target, CompactTarget::from_consensus(0x010034ab));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn compact_target_from_unprefixed_hex_upper() {
|
fn compact_target_from_unprefixed_hex_upper() {
|
||||||
let target = CompactTarget::from_unprefixed_hex("010034AB").unwrap();
|
let target = CompactTarget::from_unprefixed_hex("010034AB").unwrap();
|
||||||
assert_eq!(target, CompactTarget(0x010034ab));
|
assert_eq!(target, CompactTarget::from_consensus(0x010034ab));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1751,8 +1729,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn compact_target_lower_hex_and_upper_hex() {
|
fn compact_target_lower_hex_and_upper_hex() {
|
||||||
assert_eq!(format!("{:08x}", CompactTarget(0x01D0F456)), "01d0f456");
|
assert_eq!(format!("{:08x}", CompactTarget::from_consensus(0x01D0F456)), "01d0f456");
|
||||||
assert_eq!(format!("{:08X}", CompactTarget(0x01d0f456)), "01D0F456");
|
assert_eq!(format!("{:08X}", CompactTarget::from_consensus(0x01d0f456)), "01D0F456");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -31,6 +31,7 @@ extern crate serde;
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub mod locktime;
|
pub mod locktime;
|
||||||
pub mod opcodes;
|
pub mod opcodes;
|
||||||
|
pub mod pow;
|
||||||
pub mod sequence;
|
pub mod sequence;
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
|
@ -40,7 +41,10 @@ pub use units::*;
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub use self::locktime::{absolute, relative};
|
pub use self::locktime::{absolute, relative};
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use self::sequence::Sequence;
|
pub use self::{
|
||||||
|
pow::CompactTarget,
|
||||||
|
sequence::Sequence,
|
||||||
|
};
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
//! Proof-of-work related integer types.
|
||||||
|
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
|
/// 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.
|
||||||
|
///
|
||||||
|
/// # Note on order/equality
|
||||||
|
///
|
||||||
|
/// Usage of the ordering and equality traits for this type may be surprising. Converting between
|
||||||
|
/// `CompactTarget` and `Target` is lossy *in both directions* (there are multiple `CompactTarget`
|
||||||
|
/// values that map to the same `Target` value). Ordering and equality for this type are defined in
|
||||||
|
/// terms of the underlying `u32`.
|
||||||
|
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
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 fmt::LowerHex for CompactTarget {
|
||||||
|
#[inline]
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::UpperHex for CompactTarget {
|
||||||
|
#[inline]
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) }
|
||||||
|
}
|
Loading…
Reference in New Issue