Skip to main content

bitcoin_units/
pow.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Proof-of-work related integer types.
4
5use core::fmt;
6use core::ops::{Add, Sub};
7
8#[cfg(feature = "arbitrary")]
9use arbitrary::{Arbitrary, Unstructured};
10use internals::u256::U256;
11#[cfg(feature = "serde")]
12use serde::{Deserialize, Serialize};
13
14use crate::internal_macros::impl_fmt_traits_for_u32_wrapper;
15use crate::parse_int::{self, PrefixedHexError, UnprefixedHexError};
16
17#[rustfmt::skip]                // Keep public re-exports separate.
18#[cfg(feature = "encoding")]
19#[doc(no_inline)]
20pub use self::error::CompactTargetDecoderError;
21#[doc(no_inline)]
22pub use self::error::{
23    InvalidCompactTargetError, ParseTargetError, ParseWorkError, ZeroConversionError,
24};
25
26/// Implement traits and methods shared by [`Target`] and [`Work`].
27macro_rules! do_impl {
28    ($ty:ident, $err_ty:ident) => {
29        impl $ty {
30            #[doc = "Constructs a new [`"]
31            #[doc = stringify!($ty)]
32            #[doc = "`] from a prefixed hex string.\n"]
33            #[doc = "\n# Errors\n"]
34            #[doc = "\n - If the input string does not contain a `0x` (or `0X`) prefix."]
35            #[doc = "\n - If the input string is not a valid hex encoding of a [`"]
36            #[doc = stringify!($ty)]
37            #[doc = "`]."]
38            #[inline]
39            pub fn from_hex(s: &str) -> Result<Self, PrefixedHexError> {
40                Ok($ty(U256::from_hex(s)?))
41            }
42
43            #[doc = "Constructs a new [`"]
44            #[doc = stringify!($ty)]
45            #[doc = "`] from an unprefixed hex string.\n"]
46            #[doc = "\n# Errors\n"]
47            #[doc = "\n - If the input string contains a `0x` (or `0X`) prefix."]
48            #[doc = "\n - If the input string is not a valid hex encoding of a [`"]
49            #[doc = stringify!($ty)]
50            #[doc = "`]."]
51            #[inline]
52            pub fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError> {
53                Ok($ty(U256::from_unprefixed_hex(s)?))
54            }
55
56            #[doc = "Constructs [`"]
57            #[doc = stringify!($ty)]
58            #[doc = "`] from a big-endian byte array."]
59            #[inline]
60            pub fn from_be_bytes(bytes: [u8; 32]) -> $ty { $ty(U256::from_be_bytes(bytes)) }
61
62            #[doc = "Constructs [`"]
63            #[doc = stringify!($ty)]
64            #[doc = "`] from a little-endian byte array."]
65            #[inline]
66            pub fn from_le_bytes(bytes: [u8; 32]) -> $ty { $ty(U256::from_le_bytes(bytes)) }
67
68            #[doc = "Converts [`"]
69            #[doc = stringify!($ty)]
70            #[doc = "`] to a big-endian byte array."]
71            #[inline]
72            pub fn to_be_bytes(self) -> [u8; 32] { self.0.to_be_bytes() }
73
74            #[doc = "Converts [`"]
75            #[doc = stringify!($ty)]
76            #[doc = "`] to a little-endian byte array."]
77            #[inline]
78            pub fn to_le_bytes(self) -> [u8; 32] { self.0.to_le_bytes() }
79        }
80
81        impl fmt::Display for $ty {
82            #[inline]
83            fn fmt(&self, f: &mut fmt::Formatter) -> core::fmt::Result {
84                fmt::Display::fmt(&self.0, f)
85            }
86        }
87
88        impl core::str::FromStr for $ty {
89            type Err = $err_ty;
90
91            #[inline]
92            fn from_str(s: &str) -> Result<Self, Self::Err> {
93                U256::from_str(s).map($ty).map_err($err_ty)
94            }
95        }
96    };
97}
98
99/// A 256 bit integer representing work.
100///
101/// Work is a measure of how difficult it is to find a hash below a given [`Target`].
102#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
103#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
104pub struct Work(U256);
105
106impl Work {
107    /// Zero work.
108    pub const ZERO: Self = Self(U256::ZERO);
109
110    /// Converts this [`Work`] to [`Target`], `target = 2^256 / work - 1`.
111    ///
112    /// # Errors
113    ///
114    /// If the work is zero.
115    #[inline]
116    pub fn to_target(self) -> Result<Target, ZeroConversionError> {
117        // prevents division by zero.
118        if self.0 == U256::ZERO {
119            return Err(ZeroConversionError);
120        }
121        // From consensus formula, we know that:
122        //  work   = 2^256 / (target + 1) =>
123        //  target = 2^256 / work - 1
124        //         = (2^256 - work) / work
125        //         = (!work + 1) / work.
126        // where 2^256 - work = -work (mod 2^256)
127        // and   work + !work = 2^256 - 1 => (a bitmask with all 1 bits)
128        //       -work = !work + 1 (mod 2^256).
129        Ok(Target((!self.0).wrapping_inc() / self.0))
130    }
131}
132
133do_impl!(Work, ParseWorkError);
134impl_fmt_traits_for_u32_wrapper!(Work);
135
136impl Add for Work {
137    type Output = Self;
138    #[inline]
139    #[track_caller]
140    fn add(self, rhs: Self) -> Self { Self(self.0 + rhs.0) }
141}
142
143impl Sub for Work {
144    type Output = Self;
145    #[inline]
146    #[track_caller]
147    fn sub(self, rhs: Self) -> Self { Self(self.0 - rhs.0) }
148}
149
150/// A 256 bit integer representing target.
151///
152/// The SHA-256 hash of a block's header must be lower than or equal to the current target for the
153/// block to be accepted by the network. The lower the target, the more difficult it is to generate
154/// a block. (See also [`Work`].)
155///
156/// [`Target`] does not limit its value to the maximum attainable value for any network when it
157/// is constructed. If you need to enforce that invariant, you should compare the constructed value
158/// against the required network's `MAX_ATTAINABLE_*` target constant.
159///
160/// ref: <https://en.bitcoin.it/wiki/Target>
161#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
162#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
163pub struct Target(U256);
164
165impl Target {
166    /// When parsing nBits, Bitcoin Core converts a negative target threshold into a target of zero.
167    pub const ZERO: Self = Self(U256::ZERO);
168
169    /// The maximum possible target.
170    ///
171    /// This value is used to calculate difficulty, which is defined as how difficult the current
172    /// target makes it to find a block relative to how difficult it would be at the highest
173    /// possible target. Remember highest target == lowest difficulty.
174    ///
175    /// ref: <https://en.bitcoin.it/wiki/Target>
176    // In Bitcoind this is ~(u256)0 >> 32 stored as a floating-point type so it gets truncated, hence
177    // the low 208 bits are all zero.
178    pub const MAX: Self = Self(U256::new(0xFFFF_u128 << (208 - 128), 0));
179
180    /// The maximum **attainable** target value on mainnet.
181    ///
182    /// Not all target values are attainable because consensus code uses the compact format to
183    /// represent targets (see [`CompactTarget`]).
184    // Taken from Bitcoin Core but had lossy conversion to/from compact form.
185    // https://github.com/bitcoin/bitcoin/blob/8105bce5b384c72cf08b25b7c5343622754e7337/src/kernel/chainparams.cpp#L88
186    pub const MAX_ATTAINABLE_MAINNET: Self = Self(U256::new(0xFFFF_u128 << (208 - 128), 0));
187
188    /// The maximum **attainable** target value on testnet.
189    // Taken from Bitcoin Core but had lossy conversion to/from compact form.
190    // https://github.com/bitcoin/bitcoin/blob/8105bce5b384c72cf08b25b7c5343622754e7337/src/kernel/chainparams.cpp#L208
191    pub const MAX_ATTAINABLE_TESTNET: Self = Self(U256::new(0xFFFF_u128 << (208 - 128), 0));
192
193    /// The maximum **attainable** target value on regtest.
194    // Taken from Bitcoin Core but had lossy conversion to/from compact form.
195    // https://github.com/bitcoin/bitcoin/blob/8105bce5b384c72cf08b25b7c5343622754e7337/src/kernel/chainparams.cpp#L411
196    pub const MAX_ATTAINABLE_REGTEST: Self = Self(U256::new(0x7FFF_FF00u128 << 96, 0));
197
198    /// The maximum **attainable** target value on signet.
199    // Taken from Bitcoin Core but had lossy conversion to/from compact form.
200    // https://github.com/bitcoin/bitcoin/blob/8105bce5b384c72cf08b25b7c5343622754e7337/src/kernel/chainparams.cpp#L348
201    pub const MAX_ATTAINABLE_SIGNET: Self = Self(U256::new(0x0377_ae00 << 80, 0));
202
203    /// Computes the [`Target`] value from a compact representation.
204    ///
205    /// Bitcoin Core parses a negative or overflowing compact value as a zero target. Use
206    /// `.unwrap_or(Target::ZERO)` to match that behavior.
207    ///
208    /// ref: <https://developer.bitcoin.org/reference/block_chain.html#target-nbits>
209    ///
210    /// # Errors
211    ///
212    /// - If the compact value is negative or overflows 256 bits.
213    pub fn from_compact(c: CompactTarget) -> Result<Self, InvalidCompactTargetError> {
214        let (target, negative, overflow) = Self::decode_compact(c);
215        // The mantissa is signed but may not be negative or overflow.
216        if negative || overflow {
217            Err(InvalidCompactTargetError(c))
218        } else {
219            Ok(target)
220        }
221    }
222
223    /// Decodes a compact value the way Bitcoin Core's `SetCompact` does, returning the target
224    /// along with the negative and overflow flags.
225    ///
226    /// ref: <https://github.com/bitcoin/bitcoin/blob/f13ae519de94394314cd63a27924b0998ac65d45/src/arith_uint256.cpp#L176>
227    pub(super) fn decode_compact(c: CompactTarget) -> (Self, bool, bool) {
228        let bits = c.to_consensus_u32();
229        // This is a floating-point "compact" encoding originally used by
230        // OpenSSL, which satoshi put into consensus code, so we're stuck
231        // with it. The exponent needs to have 3 subtracted from it, hence
232        // this goofy decoding code. 3 is due to 3 bytes in the mantissa.
233        let unshifted_expt = bits >> 24;
234        let (mant, expt) = {
235            if unshifted_expt <= 3 {
236                // Bit 23 is the sign bit. The shift below moves it out of place for an
237                // exponent of 1 or 2. For correctness, it must be masked out before.
238                ((bits & 0x7F_FFFF) >> (8 * (3 - unshifted_expt as usize)), 0)
239            } else {
240                (bits & 0x7F_FFFF, 8 * ((bits >> 24) - 3))
241            }
242        };
243        let negative = mant != 0 && (bits & 0x80_0000) != 0;
244        let overflow = mant != 0
245            && (unshifted_expt > 34
246                || (mant > 0xFF && unshifted_expt > 33)
247                || (mant > 0xFFFF && unshifted_expt > 32));
248
249        // A shift of 256 or more bits leaves zero in Core.
250        let target = if expt < 256 { Self(U256::from(mant) << expt) } else { Self::ZERO };
251        (target, negative, overflow)
252    }
253
254    /// Computes the compact value from a [`Target`] representation.
255    ///
256    /// The compact form is by definition lossy, this means that
257    /// `t == Target::from_compact(t.to_compact_lossy())` does not always hold.
258    pub fn to_compact_lossy(self) -> CompactTarget {
259        let mut size = self.0.bits().div_ceil(8);
260        let mut compact = if size <= 3 {
261            (self.0.low_u64() << (8 * (3 - size))) as u32
262        } else {
263            let bn = self.0 >> (8 * (size - 3));
264            bn.low_u32()
265        };
266
267        if (compact & 0x0080_0000) != 0 {
268            compact >>= 8;
269            size += 1;
270        }
271
272        CompactTarget::from_consensus(compact | (size << 24))
273    }
274
275    /// Converts this [`Target`] to [`Work`], `work = 2^256 / (target + 1)`.
276    ///
277    /// "Work" is defined as the work done to mine a block with this target value (recorded in the
278    /// block header in compact form as nBits). This is not the same as the difficulty to mine a
279    /// block with this target (see `Self::difficulty`).
280    ///
281    /// When validating a chain, Bitcoin Core counts a zero target as zero work. Use
282    /// `.unwrap_or(Work::ZERO)` to match that behavior.
283    ///
284    /// # Errors
285    ///
286    /// If the target is zero.
287    #[inline]
288    pub fn to_work(self) -> Result<Work, ZeroConversionError> {
289        if self.0 == U256::ZERO {
290            return Err(ZeroConversionError);
291        }
292        // target + 1 wraps to zero for the max target.
293        if self.0 == U256::MAX {
294            return Ok(Work(U256::ONE));
295        }
296
297        // Calculates 2^256 / (x + 1) where x is a 256 bit unsigned integer.
298        // But 2^256 does not fit in `U256`, so we compute as Core does:
299        // 2**256 / (x + 1) == ~x / (x + 1) + 1
300        //
301        // ref: <https://github.com/bitcoin/bitcoin/blob/5fe753b56f450b054c42227c5df8346c72447490/src/chain.cpp#L133>
302        Ok(Work((!self.0 / self.0.wrapping_inc()).wrapping_inc()))
303    }
304}
305do_impl!(Target, ParseTargetError);
306impl_fmt_traits_for_u32_wrapper!(Target);
307
308/// Encoding of 256-bit target as 32-bit float.
309///
310/// This is used to encode a target into the block header. Satoshi made this part of consensus code
311/// in the original version of Bitcoin, likely copying an idea from OpenSSL.
312///
313/// OpenSSL's bignum (BN) type has an encoding, which is even called "compact" as in Bitcoin, which
314/// is exactly this format.
315///
316/// # Note on equality
317///
318/// Equality is on the consensus encoded `u32`. Conversion to [`Target`] is lossy, so this type is
319/// not ordered. To compare two targets convert them first.
320#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
321#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
322pub struct CompactTarget(u32);
323
324impl CompactTarget {
325    /// Constructs a new [`CompactTarget`] from a consensus encoded `u32`.
326    #[inline]
327    pub fn from_consensus(bits: u32) -> Self { Self(bits) }
328
329    /// Returns the consensus encoded `u32` representation of this [`CompactTarget`].
330    #[deprecated(since = "0.6.0", note = "use 'to_consensus_u32()' instead")]
331    #[inline]
332    pub const fn to_consensus(self) -> u32 { self.0 }
333
334    /// Returns the consensus encoded `u32` representation of this [`CompactTarget`].
335    #[inline]
336    pub const fn to_consensus_u32(self) -> u32 { self.0 }
337
338    /// Computes the [`Target`] value from this compact representation.
339    ///
340    /// ref: <https://developer.bitcoin.org/reference/block_chain.html#target-nbits>
341    ///
342    /// # Errors
343    ///
344    /// - If the compact value is negative or overflows 256 bits.
345    #[inline]
346    pub fn to_target(self) -> Result<Target, InvalidCompactTargetError> {
347        Target::from_compact(self)
348    }
349
350    /// Constructs a new [`CompactTarget`] from a prefixed hex string.
351    ///
352    /// # Errors
353    ///
354    /// - If the input string does not contain a `0x` (or `0X`) prefix.
355    /// - If the input string is not a valid hex encoding of a `u32`.
356    #[inline]
357    pub fn from_hex(s: &str) -> Result<Self, PrefixedHexError>
358    where
359        Self: Sized,
360    {
361        let target = parse_int::hex_u32_prefixed(s)?;
362        Ok(Self::from_consensus(target))
363    }
364
365    /// Constructs a new [`CompactTarget`] from an unprefixed hex string.
366    ///
367    /// # Errors
368    ///
369    /// - If the input string contains a `0x` (or `0X`) prefix.
370    /// - If the input string is not a valid hex encoding of a `u32`.
371    #[inline]
372    pub fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError>
373    where
374        Self: Sized,
375    {
376        let target = parse_int::hex_u32_unprefixed(s)?;
377        Ok(Self::from_consensus(target))
378    }
379}
380
381crate::internal_macros::impl_fmt_traits_for_u32_wrapper!(CompactTarget);
382
383impl fmt::Display for CompactTarget {
384    #[inline]
385    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
386}
387
388parse_int::impl_parse_str_from_int_infallible!(CompactTarget, u32, from_consensus);
389
390impl TryFrom<CompactTarget> for Target {
391    type Error = InvalidCompactTargetError;
392
393    #[inline]
394    fn try_from(c: CompactTarget) -> Result<Self, Self::Error> { Self::from_compact(c) }
395}
396
397#[cfg(feature = "encoding")]
398impl encoding::Encode for CompactTarget {
399    type Encoder<'e> = CompactTargetEncoder<'e>;
400    #[inline]
401    fn encoder(&self) -> Self::Encoder<'_> {
402        CompactTargetEncoder::new(encoding::ArrayEncoder::without_length_prefix(
403            self.to_consensus_u32().to_le_bytes(),
404        ))
405    }
406}
407
408#[cfg(feature = "encoding")]
409impl encoding::Decode for CompactTarget {
410    type Decoder = CompactTargetDecoder;
411}
412
413#[cfg(feature = "encoding")]
414encoding::encoder_newtype_exact! {
415    /// The encoder for the [`CompactTarget`] type.
416    #[derive(Debug, Clone)]
417    pub struct CompactTargetEncoder<'e>(encoding::ArrayEncoder<4>);
418}
419
420#[cfg(feature = "encoding")]
421crate::decoder_newtype! {
422    /// The decoder for the [`CompactTarget`] type.
423    #[derive(Debug, Clone)]
424    pub struct CompactTargetDecoder(encoding::ArrayDecoder<4>);
425
426    /// Constructs a new [`CompactTarget`] decoder.
427    pub const fn new() -> Self { Self(encoding::ArrayDecoder::new()) }
428
429    fn end(result: Result<[u8; 4], encoding::UnexpectedEofError>) -> Result<CompactTarget, CompactTargetDecoderError> {
430        let value = result.map_err(CompactTargetDecoderError)?;
431        let n = u32::from_le_bytes(value);
432        Ok(CompactTarget::from_consensus(n))
433    }
434}
435
436/// Error types for proof-of-work related integer types.
437pub mod error {
438    use core::convert::Infallible;
439    use core::fmt;
440
441    use internals::u256::ParseU256Error;
442    use internals::write_err;
443
444    use super::{CompactTarget, Target};
445
446    /// Returns true if the sign bit is set and the mantissa is non-zero.
447    ///
448    /// ref: <https://github.com/bitcoin/bitcoin/blob/f13ae519de94394314cd63a27924b0998ac65d45/src/arith_uint256.cpp#L176>
449    fn is_target_negative(c: CompactTarget) -> bool { Target::decode_compact(c).1 }
450
451    /// Error returned when a compact target is negative or overflows 256 bits.
452    #[derive(Debug, Clone, PartialEq, Eq)]
453    pub struct InvalidCompactTargetError(pub(super) CompactTarget);
454
455    impl InvalidCompactTargetError {
456        /// Returns the compact value that failed to convert.
457        #[inline]
458        pub fn invalid_compact(&self) -> CompactTarget { self.0 }
459
460        /// Returns the target as Bitcoin Core decodes it, ignoring the error.
461        ///
462        /// ref: <https://github.com/bitcoin/bitcoin/blob/830583eb9d07e054c54a177907a98153ab3e29ae/src/pow.cpp#L64>
463        #[inline]
464        pub fn invalid_target(&self) -> Target { Target::decode_compact(self.0).0 }
465    }
466
467    impl From<Infallible> for InvalidCompactTargetError {
468        #[inline]
469        fn from(never: Infallible) -> Self { match never {} }
470    }
471
472    impl fmt::Display for InvalidCompactTargetError {
473        #[inline]
474        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
475            let bits = self.0.to_consensus_u32();
476            if is_target_negative(self.0) {
477                write!(f, "compact target {:#010x} is negative", bits)
478            } else {
479                write!(f, "compact target {:#010x} overflows 256 bits", bits)
480            }
481        }
482    }
483
484    #[cfg(feature = "std")]
485    impl std::error::Error for InvalidCompactTargetError {
486        #[inline]
487        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
488            let Self(_) = self;
489            None
490        }
491    }
492
493    /// Error returned when converting zero [`Work`] or zero [`Target`].
494    ///
495    /// Zero work conversion divides by zero, and the work of a zero target does not fit in U256
496    /// bits. Bitcoin Core maps both to zero. Use `.unwrap_or(Work::ZERO)` or
497    /// `.unwrap_or(Target::ZERO)` to match that behavior.
498    ///
499    /// [`Work`]: super::Work
500    /// [`Target`]: super::Target
501    #[derive(Debug, Clone, PartialEq, Eq)]
502    #[non_exhaustive]
503    pub struct ZeroConversionError;
504
505    impl From<Infallible> for ZeroConversionError {
506        #[inline]
507        fn from(never: Infallible) -> Self { match never {} }
508    }
509
510    impl fmt::Display for ZeroConversionError {
511        #[inline]
512        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
513            f.write_str("zero work or target cannot be converted")
514        }
515    }
516
517    #[cfg(feature = "std")]
518    impl std::error::Error for ZeroConversionError {
519        #[inline]
520        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
521            let Self = self;
522            None
523        }
524    }
525
526    /// An error consensus decoding a [`CompactTarget`].
527    ///
528    /// [`CompactTarget`]: super::CompactTarget
529    #[derive(Debug, Clone, PartialEq, Eq)]
530    #[cfg(feature = "encoding")]
531    pub struct CompactTargetDecoderError(pub(super) encoding::UnexpectedEofError);
532
533    #[cfg(feature = "encoding")]
534    impl From<Infallible> for CompactTargetDecoderError {
535        #[inline]
536        fn from(never: Infallible) -> Self { match never {} }
537    }
538
539    #[cfg(feature = "encoding")]
540    impl fmt::Display for CompactTargetDecoderError {
541        #[inline]
542        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
543            write_err!(f, "compact target decoder error"; self.0)
544        }
545    }
546
547    #[cfg(feature = "std")]
548    #[cfg(feature = "encoding")]
549    impl std::error::Error for CompactTargetDecoderError {
550        #[inline]
551        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
552    }
553
554    /// Error returned when parsing a [`Work`] from a string.
555    ///
556    /// [`Work`]: super::Work
557    #[derive(Debug, Clone, PartialEq, Eq)]
558    pub struct ParseWorkError(pub(super) ParseU256Error);
559
560    impl From<Infallible> for ParseWorkError {
561        #[inline]
562        fn from(never: Infallible) -> Self { match never {} }
563    }
564
565    impl fmt::Display for ParseWorkError {
566        #[inline]
567        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
568            write_err!(f, "work parse error"; self.0)
569        }
570    }
571
572    #[cfg(feature = "std")]
573    impl std::error::Error for ParseWorkError {
574        #[inline]
575        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
576    }
577
578    /// Error returned when parsing a [`Target`] from a string.
579    ///
580    /// [`Target`]: super::Target
581    #[derive(Debug, Clone, PartialEq, Eq)]
582    pub struct ParseTargetError(pub(super) ParseU256Error);
583
584    impl From<Infallible> for ParseTargetError {
585        #[inline]
586        fn from(never: Infallible) -> Self { match never {} }
587    }
588
589    impl fmt::Display for ParseTargetError {
590        #[inline]
591        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
592            write_err!(f, "target parse error"; self.0)
593        }
594    }
595
596    #[cfg(feature = "std")]
597    impl std::error::Error for ParseTargetError {
598        #[inline]
599        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
600    }
601}
602
603#[cfg(feature = "arbitrary")]
604impl<'a> Arbitrary<'a> for CompactTarget {
605    #[inline]
606    fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
607        Ok(Self::from_consensus(u.arbitrary()?))
608    }
609}
610
611#[cfg(feature = "arbitrary")]
612impl<'a> Arbitrary<'a> for Target {
613    #[inline]
614    fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
615        Ok(Self::from_be_bytes(<[u8; 32]>::arbitrary(u)?))
616    }
617}
618
619#[cfg(feature = "arbitrary")]
620impl<'a> Arbitrary<'a> for Work {
621    #[inline]
622    fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
623        Ok(Self::from_be_bytes(<[u8; 32]>::arbitrary(u)?))
624    }
625}
626
627/// Extension functionality for [`U256`] that is specific to `units` (hex parsing that goes
628/// through `units::parse_int`).
629trait U256Ext: Sized {
630    /// Constructs a new `U256` from a prefixed hex string.
631    fn from_hex(s: &str) -> Result<Self, PrefixedHexError>;
632
633    /// Constructs a new `U256` from an unprefixed hex string.
634    fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError>;
635}
636
637impl U256Ext for U256 {
638    fn from_hex(s: &str) -> Result<Self, PrefixedHexError> { parse_int::hex_u256_prefixed(s) }
639
640    /// Constructs a new [`U256`] from an unprefixed hex string.
641    #[inline]
642    fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError> {
643        parse_int::hex_u256_unprefixed(s)
644    }
645}
646
647#[cfg(test)]
648mod tests {
649    #[cfg(feature = "alloc")]
650    use alloc::format;
651    #[cfg(feature = "alloc")]
652    #[cfg(feature = "encoding")]
653    use alloc::string::ToString;
654
655    #[cfg(feature = "encoding")]
656    use encoding::Decoder as _;
657
658    use super::*;
659
660    #[test]
661    #[cfg(feature = "alloc")]
662    fn u256_to_from_hex_roundtrips() {
663        let val = U256::new(
664            0xDEAD_BEEA_A69B_455C_D41B_B662_A69B_4550,
665            0xA69B_455C_D41B_B662_A69B_4555_DEAD_BEEF,
666        );
667        let hex = format!("0x{:x}", val);
668        let got = U256::from_hex(&hex).expect("failed to parse hex");
669        assert_eq!(got, val);
670    }
671
672    #[test]
673    #[cfg(feature = "alloc")]
674    fn u256_to_from_unprefixed_hex_roundtrips() {
675        let val = U256::new(
676            0xDEAD_BEEA_A69B_455C_D41B_B662_A69B_4550,
677            0xA69B_455C_D41B_B662_A69B_4555_DEAD_BEEF,
678        );
679        let hex = format!("{:x}", val);
680        let got = U256::from_unprefixed_hex(&hex).expect("failed to parse hex");
681        assert_eq!(got, val);
682    }
683
684    #[test]
685    fn u256_from_hex_rejects_sign_at_split() {
686        // 33 hex digits, so the low 32 digit half starts with the sign.
687        assert!(Target::from_unprefixed_hex("1+0000000000000000000000000000000").is_err());
688        assert!(Target::from_unprefixed_hex("++0000000000000000000000000000000").is_err());
689        // A single leading sign is allowed.
690        assert!(Target::from_unprefixed_hex("+10000000000000000000000000000000").is_ok());
691    }
692
693    #[test]
694    fn u256_from_hex_32_characters_long() {
695        let hex = "a69b455cd41bb662a69b4555deadbeef";
696        let want = U256::new(0x00, 0xA69B_455C_D41B_B662_A69B_4555_DEAD_BEEF);
697        let got = U256::from_unprefixed_hex(hex).expect("failed to parse hex");
698        assert_eq!(got, want);
699    }
700
701    #[test]
702    fn work_target_edge_values() {
703        let max = U256::MAX;
704
705        let half = U256::new(1 << 127, 0);
706
707        // lower target means more work required.
708        assert_eq!(Target(max).to_work(), Ok(Work(U256::ONE)));
709        assert_eq!(Target(U256::ONE).to_work(), Ok(Work(half)));
710        assert_eq!(Target(U256::ZERO).to_work(), Err(ZeroConversionError));
711
712        assert_eq!(Work(max).to_target(), Ok(Target(U256::ZERO)));
713        assert_eq!(Work(U256::ONE).to_target(), Ok(Target(max)));
714        assert_eq!(Work(U256::ZERO).to_target(), Err(ZeroConversionError));
715    }
716
717    #[test]
718    #[cfg(debug_assertions)]
719    #[should_panic(expected = "overflowed")]
720    fn work_overflowing_addition_panics() { let _ = Work(U256::MAX) + Work(U256::ONE); }
721
722    #[test]
723    #[cfg(debug_assertions)]
724    #[should_panic(expected = "overflowed")]
725    fn work_overflowing_subtraction_panics() { let _ = Work(U256::ZERO) - Work(U256::ONE); }
726
727    #[test]
728    fn target_one_carries_half_max_work() {
729        // nBits 0x0101_0000 is the compact encoding of target = 1.
730        let target = Target::from_compact(CompactTarget::from_consensus(0x0101_0000)).unwrap();
731        assert_eq!(target, Target(U256::ONE));
732        assert_eq!(target.to_work(), Ok(Work(U256::new(1 << 127, 0))));
733    }
734
735    #[test]
736    fn work_and_target_convert_both_ways() {
737        let half = U256::new(1 << 127, 0);
738
739        assert_eq!(
740            Work(U256::new(0, 2)).to_target(),
741            Ok(Target(U256::new(u128::MAX >> 1, u128::MAX)))
742        );
743        assert_eq!(Work(half).to_target(), Ok(Target(U256::ONE)));
744
745        // Up to u128::MAX the target is smaller than its work, so to_work drops a
746        // remainder too small to change the target on the way back.
747        for target in
748            [Target(U256::ONE), Target(U256::new(0, 0xdead_beef)), Target(U256::new(0, u128::MAX))]
749        {
750            assert_eq!(target.to_work().unwrap().to_target(), Ok(target));
751        }
752        assert_eq!(Target(U256::MAX).to_work().unwrap().to_target(), Ok(Target(U256::MAX)));
753    }
754
755    #[test]
756    fn compact_to_target() {
757        // (nBits, target)
758        let tests = [
759            (0x0100_3456_u32, 0x00_u64), // High bit set.
760            (0x0112_3456_u32, 0x12_u64),
761            (0x0200_8000_u32, 0x80_u64),
762            (0x0500_9234_u32, 0x9234_0000_u64),
763            (0x0492_3456_u32, 0x00_u64), // High bit set (0x80 in 0x92).
764            (0x0412_3456_u32, 0x1234_5600_u64), // Inverse of above; no high bit.
765            (0x2101_0000_u32, 0x00_u64), // Overflows 256 bits.
766            (0x2200_0100_u32, 0x00_u64), // Overflows 256 bits.
767            (0x2200_0101_u32, 0x00_u64), // Overflows 256 bits.
768            (0x2300_0001_u32, 0x00_u64), // Overflows 256 bits.
769        ];
770
771        for (n_bits, target) in tests {
772            let want = Target(U256::from(target));
773            let got = CompactTarget::from_consensus(n_bits).to_target().unwrap_or(Target::ZERO);
774            assert_eq!(got, want);
775        }
776    }
777
778    #[test]
779    fn compact_to_target_overflow_boundaries() {
780        let tests = [
781            (0x2100_FFFF_u32, Target(U256::from(0xFFFF_u32) << 240)),
782            (0x2200_00FF_u32, Target(U256::from(0xFF_u32) << 248)),
783        ];
784
785        for (n_bits, want) in tests {
786            let got = CompactTarget::from_consensus(n_bits).to_target().unwrap();
787            assert_eq!(got, want);
788        }
789    }
790
791    macro_rules! check_from_str {
792        ($ty:ident, $err_ty:ident, $mod_name:ident) => {
793            #[cfg(feature = "alloc")]
794            mod $mod_name {
795                use alloc::string::ToString;
796                use core::str::FromStr;
797
798                use internals::u256::ParseU256Error;
799
800                use super::{$err_ty, $ty, U256};
801
802                #[test]
803                fn target_from_str_decimal() {
804                    assert_eq!($ty::from_str("0").unwrap(), $ty(U256::ZERO));
805                    assert_eq!("1".parse::<$ty>().unwrap(), $ty(U256::new(0, 1)));
806                    assert_eq!("123456789".parse::<$ty>().unwrap(), $ty(U256::new(0, 123_456_789)));
807
808                    let str_tgt = "340282366920938463463374607431768211455";
809                    let got = str_tgt.parse::<$ty>().unwrap();
810                    assert_eq!(got, $ty(u128::MAX.into()));
811
812                    // 2^128
813                    let str_tgt = "340282366920938463463374607431768211456";
814                    let got = str_tgt.parse::<$ty>().unwrap();
815                    assert_eq!(got, $ty(U256::new(1, 0)));
816
817                    // 2^256 - 1
818                    let str_tgt = concat!(
819                        "115792089237316195423570985008687907853",
820                        "269984665640564039457584007913129639935"
821                    );
822                    let got = str_tgt.parse::<$ty>().unwrap();
823                    assert_eq!(got, $ty(U256::MAX));
824
825                    // Padding
826                    let got = "00000000000042".parse::<$ty>().unwrap();
827                    assert_eq!(got, $ty(U256::new(0, 42)));
828
829                    // roundtrip
830                    let want = $ty(u128::MAX.into());
831                    let got = want.to_string().parse::<$ty>().unwrap();
832                    assert_eq!(got, want);
833                }
834
835                #[test]
836                fn target_from_str_error() {
837                    assert!(matches!(
838                        "".parse::<$ty>().unwrap_err(),
839                        $err_ty(ParseU256Error::Empty),
840                    ));
841                    assert!(matches!(
842                        "12a34".parse::<$ty>().unwrap_err(),
843                        $err_ty(ParseU256Error::InvalidDigit(_)),
844                    ));
845                    assert!(matches!(
846                        " 42".parse::<$ty>().unwrap_err(),
847                        $err_ty(ParseU256Error::InvalidDigit(_)),
848                    ));
849                    assert!(matches!(
850                        "-1".parse::<$ty>().unwrap_err(),
851                        $err_ty(ParseU256Error::InvalidDigit(_)),
852                    ));
853
854                    assert!(matches!(
855                        "1157ééééé92089237316195423570985008687907853".parse::<$ty>().unwrap_err(),
856                        $err_ty(ParseU256Error::InvalidEncoding(_)),
857                    ));
858
859                    // 2^256
860                    let tgt_str = concat!(
861                        "115792089237316195423570985008687907853",
862                        "269984665640564039457584007913129639936"
863                    );
864                    assert!(matches!(
865                        tgt_str.parse::<$ty>().unwrap_err(),
866                        $err_ty(ParseU256Error::Overflow),
867                    ));
868                }
869            }
870        };
871    }
872
873    check_from_str!(Target, ParseTargetError, target_from_str);
874    check_from_str!(Work, ParseWorkError, work_from_str);
875
876    #[test]
877    fn target_to_compact_lossy() {
878        // (nBits, target)
879        let tests = [
880            (0x0_u32, 0x00_u64),
881            (0x0112_0000_u32, 0x12_u64),
882            (0x0200_8000_u32, 0x80_u64),
883            (0x0500_9234_u32, 0x9234_0000_u64),
884            (0x0412_3456_u32, 0x1234_5600_u64),
885        ];
886
887        for (n_bits, target) in tests {
888            let want = CompactTarget::from_consensus(n_bits);
889            let got = Target(U256::from(target)).to_compact_lossy();
890            assert_eq!(got, want);
891        }
892    }
893
894    #[test]
895    fn roundtrip_compact_target() {
896        let consensus = 0x1d00_ffff;
897        let compact = CompactTarget::from_consensus(consensus);
898        let t = Target::from_compact(CompactTarget::from_consensus(consensus)).unwrap();
899        assert_eq!(t, Target::try_from(compact).unwrap()); // From/Into sanity check.
900
901        let back = t.to_compact_lossy();
902        assert_eq!(back, compact); // From/Into sanity check.
903
904        assert_eq!(back.to_consensus_u32(), consensus);
905    }
906
907    #[test]
908    fn from_compact_rejects_negative_nbits() {
909        // Exponents of 1 and 2 shift the mantissa right by 16 and 8, which is where
910        // a sign bit left in the mantissa may hide from the sign test.
911        for bits in [0x0180_0000_u32, 0x0280_0000] {
912            assert_eq!(
913                Target::from_compact(CompactTarget::from_consensus(bits)).unwrap_or(Target::ZERO),
914                Target::ZERO
915            );
916        }
917    }
918
919    #[test]
920    fn from_compact_errors_on_negative_and_overflow() {
921        for bits in [0x0492_3456, 0x2101_0000, 0x2300_0001] {
922            assert!(Target::try_from(CompactTarget::from_consensus(bits)).is_err());
923        }
924    }
925
926    #[test]
927    fn max_target_from_compact() {
928        // The highest possible target is defined as 0x1d00ffff
929        let bits = 0x1d00_ffff_u32;
930        let want = Target::MAX;
931        let got = Target::from_compact(CompactTarget::from_consensus(bits)).unwrap();
932        assert_eq!(got, want);
933    }
934
935    #[test]
936    fn target_attainable_constants_from_original() {
937        // The plain target values for the various nets from Bitcoin Core with no conversions.
938        // https://github.com/bitcoin/bitcoin/blob/8105bce5b384c72cf08b25b7c5343622754e7337/src/kernel/chainparams.cpp#L88
939        let max_mainnet: Target = Target(U256::new(u128::MAX >> 32, u128::MAX));
940        // https://github.com/bitcoin/bitcoin/blob/8105bce5b384c72cf08b25b7c5343622754e7337/src/kernel/chainparams.cpp#L208
941        let max_testnet: Target = Target(U256::new(u128::MAX >> 32, u128::MAX));
942        // https://github.com/bitcoin/bitcoin/blob/8105bce5b384c72cf08b25b7c5343622754e7337/src/kernel/chainparams.cpp#L411
943        let max_regtest: Target = Target(U256::new(u128::MAX >> 1, u128::MAX));
944        // https://github.com/bitcoin/bitcoin/blob/8105bce5b384c72cf08b25b7c5343622754e7337/src/kernel/chainparams.cpp#L348
945        let max_signet: Target = Target(U256::new(0x3_77aeu128 << 88, 0));
946
947        assert_eq!(
948            Target::MAX_ATTAINABLE_MAINNET,
949            Target::from_compact(max_mainnet.to_compact_lossy()).unwrap()
950        );
951        assert_eq!(
952            Target::MAX_ATTAINABLE_TESTNET,
953            Target::from_compact(max_testnet.to_compact_lossy()).unwrap()
954        );
955        assert_eq!(
956            Target::MAX_ATTAINABLE_REGTEST,
957            Target::from_compact(max_regtest.to_compact_lossy()).unwrap()
958        );
959        assert_eq!(
960            Target::MAX_ATTAINABLE_SIGNET,
961            Target::from_compact(max_signet.to_compact_lossy()).unwrap()
962        );
963    }
964
965    #[test]
966    #[cfg(feature = "alloc")]
967    fn target_max_attainable_hex() {
968        // Also check explicit hex representations for regression testing.
969        assert_eq!(
970            format!("{:x}", Target::MAX_ATTAINABLE_MAINNET),
971            "00000000ffff0000000000000000000000000000000000000000000000000000"
972        );
973        assert_eq!(
974            format!("{:x}", Target::MAX_ATTAINABLE_TESTNET),
975            "00000000ffff0000000000000000000000000000000000000000000000000000"
976        );
977        assert_eq!(
978            format!("{:x}", Target::MAX_ATTAINABLE_REGTEST),
979            "7fffff0000000000000000000000000000000000000000000000000000000000"
980        );
981        assert_eq!(
982            format!("{:x}", Target::MAX_ATTAINABLE_SIGNET),
983            "00000377ae000000000000000000000000000000000000000000000000000000"
984        );
985    }
986
987    #[test]
988    #[cfg(feature = "encoding")]
989    fn compact_target_decoder_read_limit() {
990        // read_limit is one u32 = 4 bytes for empty decoder
991        assert_eq!(CompactTargetDecoder::default().read_limit(), 4);
992        assert_eq!(<CompactTarget as encoding::Decode>::decoder().read_limit(), 4);
993    }
994
995    #[test]
996    #[cfg(feature = "encoding")]
997    fn compact_target_decoder_round_trip() {
998        let bits: u32 = 0x1d00_ffff;
999        let compact_target =
1000            encoding::decode_from_slice::<CompactTarget>(&bits.to_le_bytes()).unwrap();
1001        assert_eq!(compact_target.to_consensus_u32(), bits);
1002    }
1003
1004    #[test]
1005    #[cfg(feature = "alloc")]
1006    fn compact_target_to_hex() {
1007        let compact_target = CompactTarget::from_consensus(0x1d00_ffff);
1008        let got = alloc::format!("{:x}", compact_target);
1009        assert_eq!(got, "1d00ffff");
1010    }
1011
1012    #[test]
1013    #[cfg(feature = "encoding")]
1014    #[cfg(feature = "alloc")]
1015    fn compact_target_decoder_error_display_and_source() {
1016        #[cfg(feature = "std")]
1017        use std::error::Error as _;
1018
1019        let mut slice = [0u8; 3].as_slice();
1020        let mut decoder = CompactTargetDecoder::new();
1021
1022        assert!(decoder.push_bytes(&mut slice).unwrap().needs_more());
1023
1024        let err = decoder.end().unwrap_err();
1025        assert!(!err.to_string().is_empty());
1026        #[cfg(feature = "std")]
1027        assert!(err.source().is_some());
1028    }
1029
1030    #[test]
1031    fn compact_target_equality() {
1032        let lower = CompactTarget::from_consensus(0x1d00_fffe);
1033        let lower_copy = CompactTarget::from_consensus(0x1d00_fffe);
1034        let higher = CompactTarget::from_consensus(0x1d00_ffff);
1035
1036        assert!(lower == lower_copy);
1037        assert!(lower != higher);
1038    }
1039
1040    #[test]
1041    #[cfg(feature = "alloc")]
1042    fn compact_target_formatting() {
1043        let compact_target = CompactTarget::from_consensus(0x1d00_ffff);
1044        assert_eq!(format!("{}", compact_target), "486604799");
1045        assert_eq!(format!("{:x}", compact_target), "1d00ffff");
1046        assert_eq!(format!("{:#x}", compact_target), "0x1d00ffff");
1047        assert_eq!(format!("{:X}", compact_target), "1D00FFFF");
1048        assert_eq!(format!("{:#X}", compact_target), "0x1D00FFFF");
1049        assert_eq!(format!("{:o}", compact_target), "3500177777");
1050        assert_eq!(format!("{:#o}", compact_target), "0o3500177777");
1051        assert_eq!(format!("{:b}", compact_target), "11101000000001111111111111111");
1052        assert_eq!(format!("{:#b}", compact_target), "0b11101000000001111111111111111");
1053        assert_eq!(compact_target.to_consensus_u32(), 0x1d00_ffff);
1054    }
1055
1056    #[test]
1057    fn compact_target_from_hex_lower() {
1058        let target = CompactTarget::from_hex("0x010034ab").unwrap();
1059        assert_eq!(target, CompactTarget::from_consensus(0x0100_34ab));
1060    }
1061
1062    #[test]
1063    fn compact_target_from_hex_upper() {
1064        let target = CompactTarget::from_hex("0X010034AB").unwrap();
1065        assert_eq!(target, CompactTarget::from_consensus(0x0100_34ab));
1066    }
1067
1068    #[test]
1069    fn compact_target_from_unprefixed_hex_lower() {
1070        let target = CompactTarget::from_unprefixed_hex("010034ab").unwrap();
1071        assert_eq!(target, CompactTarget::from_consensus(0x0100_34ab));
1072    }
1073
1074    #[test]
1075    fn compact_target_from_unprefixed_hex_upper() {
1076        let target = CompactTarget::from_unprefixed_hex("010034AB").unwrap();
1077        assert_eq!(target, CompactTarget::from_consensus(0x0100_34ab));
1078    }
1079
1080    #[test]
1081    fn compact_target_from_hex_invalid_hex_should_err() {
1082        let hex = "0xzbf9";
1083        let result = CompactTarget::from_hex(hex);
1084        assert!(result.is_err());
1085    }
1086
1087    #[test]
1088    #[cfg(feature = "alloc")]
1089    fn compact_target_lower_hex_and_upper_hex() {
1090        assert_eq!(format!("{:08x}", CompactTarget::from_consensus(0x01D0_F456)), "01d0f456");
1091        assert_eq!(format!("{:08X}", CompactTarget::from_consensus(0x01d0_f456)), "01D0F456");
1092    }
1093}