1use 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] #[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
26macro_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#[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 pub const ZERO: Self = Self(U256::ZERO);
109
110 #[inline]
116 pub fn to_target(self) -> Result<Target, ZeroConversionError> {
117 if self.0 == U256::ZERO {
119 return Err(ZeroConversionError);
120 }
121 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#[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 pub const ZERO: Self = Self(U256::ZERO);
168
169 pub const MAX: Self = Self(U256::new(0xFFFF_u128 << (208 - 128), 0));
179
180 pub const MAX_ATTAINABLE_MAINNET: Self = Self(U256::new(0xFFFF_u128 << (208 - 128), 0));
187
188 pub const MAX_ATTAINABLE_TESTNET: Self = Self(U256::new(0xFFFF_u128 << (208 - 128), 0));
192
193 pub const MAX_ATTAINABLE_REGTEST: Self = Self(U256::new(0x7FFF_FF00u128 << 96, 0));
197
198 pub const MAX_ATTAINABLE_SIGNET: Self = Self(U256::new(0x0377_ae00 << 80, 0));
202
203 pub fn from_compact(c: CompactTarget) -> Result<Self, InvalidCompactTargetError> {
214 let (target, negative, overflow) = Self::decode_compact(c);
215 if negative || overflow {
217 Err(InvalidCompactTargetError(c))
218 } else {
219 Ok(target)
220 }
221 }
222
223 pub(super) fn decode_compact(c: CompactTarget) -> (Self, bool, bool) {
228 let bits = c.to_consensus_u32();
229 let unshifted_expt = bits >> 24;
234 let (mant, expt) = {
235 if unshifted_expt <= 3 {
236 ((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 let target = if expt < 256 { Self(U256::from(mant) << expt) } else { Self::ZERO };
251 (target, negative, overflow)
252 }
253
254 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 #[inline]
288 pub fn to_work(self) -> Result<Work, ZeroConversionError> {
289 if self.0 == U256::ZERO {
290 return Err(ZeroConversionError);
291 }
292 if self.0 == U256::MAX {
294 return Ok(Work(U256::ONE));
295 }
296
297 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#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
321#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
322pub struct CompactTarget(u32);
323
324impl CompactTarget {
325 #[inline]
327 pub fn from_consensus(bits: u32) -> Self { Self(bits) }
328
329 #[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 #[inline]
336 pub const fn to_consensus_u32(self) -> u32 { self.0 }
337
338 #[inline]
346 pub fn to_target(self) -> Result<Target, InvalidCompactTargetError> {
347 Target::from_compact(self)
348 }
349
350 #[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 #[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 #[derive(Debug, Clone)]
417 pub struct CompactTargetEncoder<'e>(encoding::ArrayEncoder<4>);
418}
419
420#[cfg(feature = "encoding")]
421crate::decoder_newtype! {
422 #[derive(Debug, Clone)]
424 pub struct CompactTargetDecoder(encoding::ArrayDecoder<4>);
425
426 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
436pub 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 fn is_target_negative(c: CompactTarget) -> bool { Target::decode_compact(c).1 }
450
451 #[derive(Debug, Clone, PartialEq, Eq)]
453 pub struct InvalidCompactTargetError(pub(super) CompactTarget);
454
455 impl InvalidCompactTargetError {
456 #[inline]
458 pub fn invalid_compact(&self) -> CompactTarget { self.0 }
459
460 #[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 #[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 #[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 #[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 #[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
627trait U256Ext: Sized {
630 fn from_hex(s: &str) -> Result<Self, PrefixedHexError>;
632
633 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 #[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 assert!(Target::from_unprefixed_hex("1+0000000000000000000000000000000").is_err());
688 assert!(Target::from_unprefixed_hex("++0000000000000000000000000000000").is_err());
689 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 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 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 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 let tests = [
759 (0x0100_3456_u32, 0x00_u64), (0x0112_3456_u32, 0x12_u64),
761 (0x0200_8000_u32, 0x80_u64),
762 (0x0500_9234_u32, 0x9234_0000_u64),
763 (0x0492_3456_u32, 0x00_u64), (0x0412_3456_u32, 0x1234_5600_u64), (0x2101_0000_u32, 0x00_u64), (0x2200_0100_u32, 0x00_u64), (0x2200_0101_u32, 0x00_u64), (0x2300_0001_u32, 0x00_u64), ];
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 let str_tgt = "340282366920938463463374607431768211456";
814 let got = str_tgt.parse::<$ty>().unwrap();
815 assert_eq!(got, $ty(U256::new(1, 0)));
816
817 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 let got = "00000000000042".parse::<$ty>().unwrap();
827 assert_eq!(got, $ty(U256::new(0, 42)));
828
829 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 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 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()); let back = t.to_compact_lossy();
902 assert_eq!(back, compact); assert_eq!(back.to_consensus_u32(), consensus);
905 }
906
907 #[test]
908 fn from_compact_rejects_negative_nbits() {
909 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 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 let max_mainnet: Target = Target(U256::new(u128::MAX >> 32, u128::MAX));
940 let max_testnet: Target = Target(U256::new(u128::MAX >> 32, u128::MAX));
942 let max_regtest: Target = Target(U256::new(u128::MAX >> 1, u128::MAX));
944 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 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 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}