1use crate::constants::*;
4use crate::error::{ConsensusError, Result};
5use crate::types::*;
6#[cfg(feature = "spec-lock")]
7use blvm_spec_lock::spec_locked;
8use sha2::{Digest, Sha256};
9
10#[cfg_attr(feature = "spec-lock", spec_locked("7.1", "GetNextWorkRequired"))]
35pub fn get_next_work_required(
36 _current_header: &BlockHeader,
37 prev_headers: &[BlockHeader],
38) -> Result<Natural> {
39 get_next_work_required_internal(_current_header, prev_headers, false)
40}
41
42pub fn get_next_work_required_corrected(
54 _current_header: &BlockHeader,
55 prev_headers: &[BlockHeader],
56) -> Result<Natural> {
57 get_next_work_required_internal(_current_header, prev_headers, true)
58}
59
60fn get_next_work_required_internal(
65 _current_header: &BlockHeader,
66 prev_headers: &[BlockHeader],
67 use_corrected: bool,
68) -> Result<Natural> {
69 if prev_headers.len() < 2 {
71 return Err(ConsensusError::InvalidProofOfWork(
72 "Insufficient headers for difficulty adjustment".into(),
73 ));
74 }
75
76 let last_header = &prev_headers[prev_headers.len() - 1];
78 let previous_bits = last_header.bits;
79
80 let first_timestamp = prev_headers[0].timestamp;
83 let last_timestamp = last_header.timestamp;
84
85 if last_timestamp < first_timestamp {
87 return Err(ConsensusError::InvalidProofOfWork(
88 "Invalid timestamp order in difficulty adjustment".into(),
89 ));
90 }
91
92 let time_span = last_timestamp - first_timestamp;
93
94 let expected_time = if use_corrected {
99 let num_intervals = prev_headers.len() as u64;
103 if num_intervals == DIFFICULTY_ADJUSTMENT_INTERVAL {
104 (DIFFICULTY_ADJUSTMENT_INTERVAL - 1) * TARGET_TIME_PER_BLOCK
105 } else {
106 (num_intervals - 1) * TARGET_TIME_PER_BLOCK
108 }
109 } else {
110 DIFFICULTY_ADJUSTMENT_INTERVAL * TARGET_TIME_PER_BLOCK
112 };
113
114 let clamped_timespan = time_span.max(expected_time / 4).min(expected_time * 4);
117
118 debug_assert!(
120 clamped_timespan >= expected_time / 4,
121 "Clamped timespan ({}) must be >= expected_time/4 ({})",
122 clamped_timespan,
123 expected_time / 4
124 );
125 debug_assert!(
126 clamped_timespan <= expected_time * 4,
127 "Clamped timespan ({}) must be <= expected_time*4 ({})",
128 clamped_timespan,
129 expected_time * 4
130 );
131
132 let old_target = expand_target(previous_bits)?;
134
135 if old_target.is_zero() {
136 return Err(ConsensusError::InvalidProofOfWork(
137 "Previous block target is zero (invalid compact bits)".into(),
138 ));
139 }
140
141 let multiplied_target = match old_target.checked_mul_u64(clamped_timespan) {
146 Some(t) => t,
147 None => {
148 return Ok(previous_bits);
149 }
150 };
151
152 debug_assert!(
154 multiplied_target >= old_target || clamped_timespan < expected_time,
155 "Multiplied target should be >= old target when timespan >= expected_time"
156 );
157
158 let new_target = multiplied_target.div_u64(expected_time);
160
161 if new_target.is_zero() {
162 return Err(ConsensusError::InvalidProofOfWork(
163 "Difficulty adjustment produced zero expanded target".into(),
164 ));
165 }
166
167 let new_bits = compress_target(&new_target)?;
169
170 let clamped_bits = new_bits.min(MAX_TARGET as Natural);
172
173 debug_assert!(
175 clamped_bits > 0,
176 "Clamped bits ({clamped_bits}) must be positive"
177 );
178 debug_assert!(
179 clamped_bits <= MAX_TARGET as Natural,
180 "Clamped bits ({clamped_bits}) must be <= MAX_TARGET ({MAX_TARGET})"
181 );
182
183 if clamped_bits == 0 {
185 return Err(ConsensusError::InvalidProofOfWork(
186 "Difficulty adjustment resulted in zero target".into(),
187 ));
188 }
189
190 Ok(clamped_bits)
191}
192
193struct PowParams {
199 limit_bits: u64,
200 interval: u64,
201 timespan: u64,
202 spacing: u64,
203 allow_min_difficulty: bool,
204 no_retargeting: bool,
205 enforce_bip94: bool,
207}
208
209fn pow_params(network: Network) -> PowParams {
210 let mainnet_timespan = DIFFICULTY_ADJUSTMENT_INTERVAL * TARGET_TIME_PER_BLOCK;
211 match network {
212 Network::Mainnet => PowParams {
213 limit_bits: MAX_TARGET as u64,
214 interval: DIFFICULTY_ADJUSTMENT_INTERVAL,
215 timespan: mainnet_timespan,
216 spacing: TARGET_TIME_PER_BLOCK,
217 allow_min_difficulty: false,
218 no_retargeting: false,
219 enforce_bip94: false,
220 },
221 Network::Testnet => PowParams {
222 limit_bits: MAX_TARGET as u64,
223 interval: DIFFICULTY_ADJUSTMENT_INTERVAL,
224 timespan: mainnet_timespan,
225 spacing: TARGET_TIME_PER_BLOCK,
226 allow_min_difficulty: true,
227 no_retargeting: false,
228 enforce_bip94: false,
229 },
230 Network::Testnet4 => PowParams {
231 limit_bits: MAX_TARGET as u64,
232 interval: DIFFICULTY_ADJUSTMENT_INTERVAL,
233 timespan: mainnet_timespan,
234 spacing: TARGET_TIME_PER_BLOCK,
235 allow_min_difficulty: true,
236 no_retargeting: false,
237 enforce_bip94: true,
238 },
239 Network::Signet => PowParams {
240 limit_bits: 0x1e0377ae,
241 interval: DIFFICULTY_ADJUSTMENT_INTERVAL,
242 timespan: mainnet_timespan,
243 spacing: TARGET_TIME_PER_BLOCK,
244 allow_min_difficulty: false,
245 no_retargeting: false,
246 enforce_bip94: false,
247 },
248 Network::Regtest => PowParams {
249 limit_bits: 0x207fffff,
250 interval: 144,
251 timespan: 24 * 60 * 60,
252 spacing: TARGET_TIME_PER_BLOCK,
253 allow_min_difficulty: true,
254 no_retargeting: true,
255 enforce_bip94: false,
256 },
257 }
258}
259
260pub fn next_required_bits(
274 network: Network,
275 height: u64,
276 block_timestamp: u64,
277 ancestor: &dyn Fn(u64) -> Option<(u64, u64)>,
278) -> Result<Option<u64>> {
279 if height == 0 {
280 return Ok(None);
281 }
282 let params = pow_params(network);
283 let parent_height = height - 1;
284 let (parent_bits, parent_time) = ancestor(parent_height).ok_or_else(|| {
285 ConsensusError::InvalidProofOfWork(
286 format!("missing ancestor header at height {parent_height} for difficulty").into(),
287 )
288 })?;
289
290 if params.interval == 0 || height % params.interval != 0 {
291 if params.allow_min_difficulty {
292 let limit_time = parent_time.saturating_add(params.spacing.saturating_mul(2));
293 if block_timestamp > limit_time {
294 return Ok(Some(params.limit_bits));
295 }
296 let mut walk_height = parent_height;
297 let mut bits = parent_bits;
298 while walk_height > 0 && walk_height % params.interval != 0 && bits == params.limit_bits
299 {
300 walk_height -= 1;
301 let (prev_bits, _) = ancestor(walk_height).ok_or_else(|| {
302 ConsensusError::InvalidProofOfWork(
303 format!("missing ancestor header at height {walk_height} for difficulty")
304 .into(),
305 )
306 })?;
307 bits = prev_bits;
308 }
309 return Ok(Some(bits));
310 }
311 return Ok(Some(parent_bits));
312 }
313
314 if params.no_retargeting {
315 return Ok(Some(parent_bits));
316 }
317
318 let first_height = parent_height - (params.interval - 1);
322 let (first_bits, first_time) = ancestor(first_height).ok_or_else(|| {
323 ConsensusError::InvalidProofOfWork(
324 format!("missing ancestor header at height {first_height} for difficulty").into(),
325 )
326 })?;
327 let base_bits = if params.enforce_bip94 {
328 first_bits
329 } else {
330 parent_bits
331 };
332 Ok(Some(retarget_bits(
333 base_bits,
334 first_time,
335 parent_time,
336 params.timespan,
337 params.limit_bits,
338 )?))
339}
340
341fn retarget_bits(
342 prev_bits: u64,
343 first_time: u64,
344 last_time: u64,
345 timespan: u64,
346 limit_bits: u64,
347) -> Result<u64> {
348 let actual = (last_time as i64).saturating_sub(first_time as i64);
349 let min_span = (timespan / 4) as i64;
350 let max_span = timespan.saturating_mul(4) as i64;
351 let span = if actual < min_span {
352 min_span
353 } else if actual > max_span {
354 max_span
355 } else {
356 actual
357 } as u64;
358
359 let old = expand_target(prev_bits)?;
360 if old.is_zero() {
361 return Ok(0);
362 }
363 let limit = expand_target(limit_bits)?;
364 let product = old.checked_mul_u64(span).ok_or_else(|| {
365 ConsensusError::InvalidProofOfWork("difficulty adjustment overflow".into())
366 })?;
367 let new_target = product.div_u64(timespan);
368 if new_target.is_zero() {
369 return Ok(0);
370 }
371 if new_target > limit {
372 return Ok(limit_bits);
373 }
374 compress_target(&new_target)
375}
376
377#[cfg_attr(feature = "spec-lock", spec_locked("7.2", "CheckProofOfWork"))]
382#[cfg_attr(feature = "production", inline(always))]
383#[cfg_attr(not(feature = "production"), inline)]
384pub fn check_proof_of_work(header: &BlockHeader) -> Result<bool> {
385 let header_bytes = serialize_header(header);
386 let hash1 = Sha256::digest(header_bytes);
387 let hash2 = Sha256::digest(hash1);
388 let mut hash_bytes = [0u8; 32];
389 hash_bytes.copy_from_slice(&hash2);
390 proof_hash_meets_target(header.bits, &U256::from_bytes(&hash_bytes))
391}
392
393#[inline]
394fn proof_hash_meets_target(bits: Natural, hash_value: &U256) -> Result<bool> {
395 if bits & 0x0080_0000 != 0 {
397 return Ok(false);
398 }
399 let target = expand_target(bits)?;
400 if target.is_zero() {
401 return Ok(false);
402 }
403 Ok(*hash_value <= target)
404}
405
406pub fn meet_regtest_proof_of_work(header: &mut BlockHeader) {
411 header.bits = 0x207f_ffff;
412 header.nonce = 0;
413 while !check_proof_of_work(header).unwrap_or(false) {
414 header.nonce = header.nonce.wrapping_add(1);
415 }
416}
417
418#[cfg_attr(feature = "spec-lock", spec_locked("7.2", "CheckProofOfWork"))]
431#[cfg(feature = "production")]
432pub fn batch_check_proof_of_work(headers: &[BlockHeader]) -> Result<Vec<(bool, Option<Hash>)>> {
433 use crate::optimizations::simd_vectorization;
434
435 if headers.is_empty() {
436 return Ok(Vec::new());
437 }
438
439 let header_bytes_vec: Vec<[u8; 80]> = {
441 #[cfg(feature = "rayon")]
442 {
443 use rayon::prelude::*;
444 headers.par_iter().map(serialize_header).collect()
445 }
446 #[cfg(not(feature = "rayon"))]
447 {
448 headers.iter().map(serialize_header).collect()
449 }
450 };
451
452 let header_refs: Vec<&[u8]> = header_bytes_vec.iter().map(|v| v.as_slice()).collect();
454 let aligned_hashes = simd_vectorization::batch_double_sha256_aligned(&header_refs);
455 let hashes: Vec<[u8; 32]> = aligned_hashes.iter().map(|h| *h.as_bytes()).collect();
457
458 let mut results = Vec::with_capacity(headers.len());
460 for (i, header) in headers.iter().enumerate() {
461 let hash = hashes[i];
462
463 let hash_value = U256::from_bytes(&hash);
465
466 match proof_hash_meets_target(header.bits, &hash_value) {
468 Ok(true) => results.push((true, Some(hash))),
469 Ok(false) => results.push((false, None)),
470 Err(_) => results.push((false, None)),
471 }
472 }
473
474 Ok(results)
475}
476
477#[derive(Debug, Clone, Copy, PartialEq, Eq)]
479pub struct U256([u64; 4]); impl U256 {
482 pub fn zero() -> Self {
483 U256([0; 4])
484 }
485
486 fn from_u32(value: u32) -> Self {
487 U256([value as u64, 0, 0, 0])
488 }
489
490 #[cfg(test)]
491 fn from_u64(value: u64) -> Self {
492 U256([value, 0, 0, 0])
493 }
494
495 fn get_low_64(&self) -> u64 {
498 self.0[0]
499 }
500
501 pub fn to_le_bytes(&self) -> [u8; 32] {
503 let mut bytes = [0u8; 32];
504 for (i, &word) in self.0.iter().enumerate() {
505 let word_bytes = word.to_le_bytes();
506 bytes[i * 8..(i + 1) * 8].copy_from_slice(&word_bytes);
507 }
508 bytes
509 }
510
511 pub fn from_le_bytes(bytes: [u8; 32]) -> Self {
513 let mut words = [0u64; 4];
514 for (i, word) in words.iter_mut().enumerate() {
515 let mut buf = [0u8; 8];
516 buf.copy_from_slice(&bytes[i * 8..(i + 1) * 8]);
517 *word = u64::from_le_bytes(buf);
518 }
519 U256(words)
520 }
521
522 pub fn gbt_target_hex(&self) -> String {
524 let mut bytes = self.to_le_bytes();
525 bytes.reverse();
526 hex::encode(bytes)
527 }
528
529 pub fn low_u128(&self) -> u128 {
531 self.0[0] as u128 | ((self.0[1] as u128) << 64)
532 }
533
534 pub fn from_u128(value: u128) -> Self {
536 U256([value as u64, (value >> 64) as u64, 0, 0])
537 }
538
539 pub fn one() -> Self {
540 U256([1, 0, 0, 0])
541 }
542
543 pub fn is_zero(&self) -> bool {
544 self.0.iter().all(|&w| w == 0)
545 }
546
547 #[allow(clippy::should_implement_trait)]
548 pub fn not(self) -> Self {
549 U256([!self.0[0], !self.0[1], !self.0[2], !self.0[3]])
550 }
551
552 pub fn checked_add(self, other: Self) -> Option<Self> {
553 let mut result = [0u64; 4];
554 let mut carry = 0u128;
555 for (i, word) in result.iter_mut().enumerate() {
556 let sum = self.0[i] as u128 + other.0[i] as u128 + carry;
557 *word = sum as u64;
558 carry = sum >> 64;
559 }
560 if carry != 0 { None } else { Some(U256(result)) }
561 }
562
563 pub fn saturating_add(self, other: Self) -> Self {
564 self.checked_add(other).unwrap_or(U256([u64::MAX; 4]))
565 }
566
567 fn sub(self, other: Self) -> Self {
568 let mut result = [0u64; 4];
569 let mut borrow = 0u8;
570 for (i, word) in result.iter_mut().enumerate() {
571 let mut minuend = self.0[i] as u128;
572 if borrow != 0 {
573 minuend += 1u128 << 64;
574 borrow = 0;
575 }
576 if minuend >= other.0[i] as u128 {
577 *word = (minuend - other.0[i] as u128) as u64;
578 } else {
579 *word = (minuend + (1u128 << 64) - other.0[i] as u128) as u64;
580 borrow = 1;
581 }
582 }
583 U256(result)
584 }
585
586 fn bit(self, bit: u32) -> bool {
587 (self.0[(bit / 64) as usize] >> (bit % 64)) & 1 == 1
588 }
589
590 fn with_bit_set(self, bit: u32) -> Self {
591 let mut result = self;
592 result.0[(bit / 64) as usize] |= 1u64 << (bit % 64);
593 result
594 }
595
596 #[allow(clippy::should_implement_trait)]
598 pub fn div(self, divisor: Self) -> Self {
599 if divisor.is_zero() {
600 return U256::zero();
601 }
602 if self < divisor {
603 return U256::zero();
604 }
605 let mut quotient = U256::zero();
606 let mut remainder = U256::zero();
607 for bit in (0..256).rev() {
608 remainder = remainder.shl(1);
609 if self.bit(bit) {
610 remainder = remainder
611 .checked_add(U256::one())
612 .unwrap_or(U256([u64::MAX; 4]));
613 }
614 if remainder >= divisor {
615 remainder = remainder.sub(divisor);
616 quotient = quotient.with_bit_set(bit);
617 }
618 }
619 quotient
620 }
621
622 pub fn to_be_bytes(self) -> [u8; 32] {
624 let mut bytes = self.to_le_bytes();
625 bytes.reverse();
626 bytes
627 }
628
629 pub fn from_be_bytes(bytes: &[u8; 32]) -> Self {
631 let mut le = *bytes;
632 le.reverse();
633 Self::from_bytes(&le)
634 }
635
636 #[cfg(test)]
637 fn to_bytes(&self) -> [u8; 32] {
638 self.to_le_bytes()
639 }
640
641 fn shl(&self, shift: u32) -> Self {
642 if shift >= 256 {
643 return U256::zero();
644 }
645
646 let mut result = U256::zero();
647 let word_shift = (shift / 64) as usize;
648 let bit_shift = shift % 64;
649
650 for i in 0..4 {
651 if i + word_shift < 4 {
652 result.0[i + word_shift] |= self.0[i] << bit_shift;
653 if bit_shift > 0 && i + word_shift + 1 < 4 {
654 result.0[i + word_shift + 1] |= self.0[i] >> (64 - bit_shift);
655 }
656 }
657 }
658
659 result
660 }
661
662 fn shr(&self, shift: u32) -> Self {
663 if shift >= 256 {
664 return U256::zero();
665 }
666
667 let mut result = U256::zero();
668 let word_shift = (shift / 64) as usize;
669 let bit_shift = shift % 64;
670
671 debug_assert!(
673 word_shift < 4,
674 "Word shift ({word_shift}) must be < 4 (shift: {shift})"
675 );
676
677 debug_assert!(
679 bit_shift < 64,
680 "Bit shift ({bit_shift}) must be < 64 (shift: {shift})"
681 );
682
683 if bit_shift == 0 {
684 for i in word_shift..4 {
685 result.0[i - word_shift] = self.0[i];
686 }
687 } else {
688 for i in word_shift..4 {
691 let mut word = self.0[i] >> bit_shift;
692 if i + 1 < 4 {
693 word |= self.0[i + 1] << (64 - bit_shift);
694 }
695 result.0[i - word_shift] = word;
696 }
697 }
698
699 result
700 }
701
702 fn from_bytes(bytes: &[u8; 32]) -> Self {
703 let mut words = [0u64; 4];
704 for (i, word) in words.iter_mut().enumerate() {
705 let start = i * 8;
706 let _end = start + 8;
707 *word = u64::from_le_bytes([
708 bytes[start],
709 bytes[start + 1],
710 bytes[start + 2],
711 bytes[start + 3],
712 bytes[start + 4],
713 bytes[start + 5],
714 bytes[start + 6],
715 bytes[start + 7],
716 ]);
717 }
718 U256(words)
719 }
720
721 fn checked_mul_u64(&self, rhs: u64) -> Option<Self> {
724 let mut carry = 0u128;
726 let mut result = U256::zero();
727
728 #[cfg(feature = "production")]
731 {
732 let product = (self.0[0] as u128) * (rhs as u128) + carry;
735 result.0[0] = product as u64;
736 carry = product >> 64;
737
738 let product = (self.0[1] as u128) * (rhs as u128) + carry;
740 result.0[1] = product as u64;
741 carry = product >> 64;
742
743 let product = (self.0[2] as u128) * (rhs as u128) + carry;
745 result.0[2] = product as u64;
746 carry = product >> 64;
747
748 let product = (self.0[3] as u128) * (rhs as u128) + carry;
750 result.0[3] = product as u64;
751 carry = product >> 64;
752
753 if carry > 0 {
755 return None; }
757 }
758
759 #[cfg(not(feature = "production"))]
760 {
761 for i in 0..4 {
762 let product = (self.0[i] as u128) * (rhs as u128) + carry;
763 result.0[i] = product as u64;
764 carry = product >> 64;
765
766 if i == 3 && carry > 0 {
768 return None; }
770 }
771 }
772
773 Some(result)
774 }
775
776 fn div_u64(&self, rhs: u64) -> Self {
783 if rhs == 0 {
784 return U256([u64::MAX; 4]);
787 }
788
789 let mut remainder = 0u128;
790 let mut result = U256::zero();
791
792 #[cfg(feature = "production")]
796 {
797 let dividend = (remainder << 64) | (self.0[3] as u128);
800 let quotient = dividend / (rhs as u128);
801 remainder = dividend % (rhs as u128);
802 debug_assert!(quotient <= u64::MAX as u128, "Quotient must fit in u64");
803 result.0[3] = quotient as u64;
804
805 let dividend = (remainder << 64) | (self.0[2] as u128);
807 let quotient = dividend / (rhs as u128);
808 remainder = dividend % (rhs as u128);
809 debug_assert!(quotient <= u64::MAX as u128, "Quotient must fit in u64");
810 result.0[2] = quotient as u64;
811
812 let dividend = (remainder << 64) | (self.0[1] as u128);
814 let quotient = dividend / (rhs as u128);
815 remainder = dividend % (rhs as u128);
816 debug_assert!(quotient <= u64::MAX as u128, "Quotient must fit in u64");
817 result.0[1] = quotient as u64;
818
819 let dividend = (remainder << 64) | (self.0[0] as u128);
821 let quotient = dividend / (rhs as u128);
822 remainder = dividend % (rhs as u128);
823 debug_assert!(quotient <= u64::MAX as u128, "Quotient must fit in u64");
824 result.0[0] = quotient as u64;
825 }
826
827 #[cfg(not(feature = "production"))]
828 {
829 for i in (0..4).rev() {
831 let dividend = (remainder << 64) | (self.0[i] as u128);
832 let quotient = dividend / (rhs as u128);
833 remainder = dividend % (rhs as u128);
834 debug_assert!(
835 quotient <= u64::MAX as u128,
836 "Quotient ({quotient}) must fit in u64"
837 );
838 result.0[i] = quotient as u64;
839 }
840 }
841
842 debug_assert!(
844 result <= *self,
845 "Division result ({result:?}) must be <= dividend ({self:?})"
846 );
847
848 debug_assert!(
850 remainder < rhs as u128,
851 "Remainder ({remainder}) must be < divisor ({rhs})"
852 );
853
854 result
855 }
856
857 fn highest_set_bit(&self) -> Option<u32> {
860 for (i, &word) in self.0.iter().rev().enumerate() {
861 if word != 0 {
862 let word_index = (3 - i) as u32;
863 let bit_pos = word_index * 64 + (63 - word.leading_zeros());
864 return Some(bit_pos);
865 }
866 }
867 None
868 }
869
870 fn to_f64(self) -> f64 {
873 if self.is_zero() {
874 return 0.0;
875 }
876 let mut result = 0.0_f64;
877 result += self.0[0] as f64;
878 result += (self.0[1] as f64) * 2.0_f64.powi(64);
879 result += (self.0[2] as f64) * 2.0_f64.powi(128);
880 result += (self.0[3] as f64) * 2.0_f64.powi(192);
881 result
882 }
883}
884
885impl serde::Serialize for U256 {
886 fn serialize<S: serde::Serializer>(
887 &self,
888 serializer: S,
889 ) -> std::result::Result<S::Ok, S::Error> {
890 serializer.serialize_str(&self.gbt_target_hex())
891 }
892}
893
894impl<'de> serde::Deserialize<'de> for U256 {
895 fn deserialize<D: serde::Deserializer<'de>>(
896 deserializer: D,
897 ) -> std::result::Result<Self, D::Error> {
898 let hex_str = <String as serde::Deserialize>::deserialize(deserializer)?;
899 if hex_str.len() != 64 {
900 return Err(serde::de::Error::custom("target hex must be 64 characters"));
901 }
902 let mut bytes = [0u8; 32];
903 for i in 0..32 {
904 bytes[i] = u8::from_str_radix(&hex_str[i * 2..i * 2 + 2], 16)
905 .map_err(serde::de::Error::custom)?;
906 }
907 bytes.reverse();
908 Ok(U256::from_le_bytes(bytes))
909 }
910}
911
912impl PartialOrd for U256 {
913 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
914 Some(self.cmp(other))
915 }
916}
917
918impl Ord for U256 {
919 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
920 for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) {
921 match a.cmp(b) {
922 std::cmp::Ordering::Equal => continue,
923 other => return other,
924 }
925 }
926 std::cmp::Ordering::Equal
927 }
928}
929
930pub fn difficulty_from_bits(bits: Natural) -> Result<f64> {
935 let target = expand_target(bits)?;
936 if target.is_zero() {
937 return Ok(1.0);
938 }
939 let max_target = U256::from_bytes(&[
941 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, 0xFF,
942 0xFF, 0x00, 0x00, 0x00, 0x00,
943 ]);
944 let max_f64 = max_target.to_f64();
945 let target_f64 = target.to_f64();
946 if target_f64 == 0.0 {
947 return Ok(1.0);
948 }
949 Ok((max_f64 / target_f64).max(1.0))
950}
951
952#[cfg_attr(feature = "spec-lock", spec_locked("7.1", "ExpandTarget"))]
982pub fn expand_target(bits: Natural) -> Result<U256> {
983 let exponent = (bits >> 24) as u8;
995 let mantissa = bits & 0x007fffff;
997
998 if !(3..=32).contains(&exponent) {
1001 return Err(ConsensusError::InvalidProofOfWork(
1002 "Invalid target exponent".into(),
1003 ));
1004 }
1005
1006 if mantissa == 0 {
1007 return Ok(U256::zero());
1008 }
1009
1010 if exponent <= 3 {
1012 let shift = 8 * (3 - exponent);
1017 let mantissa_u256 = U256::from_u32(mantissa as u32);
1018 Ok(mantissa_u256.shr(shift as u32))
1019 } else {
1020 let shift = 8u32 * (exponent as u32 - 3);
1024 if shift >= 256 {
1025 return Err(crate::error::ConsensusError::InvalidProofOfWork(
1026 "Target too large".into(),
1027 ));
1028 }
1029 let mantissa_u256 = U256::from_u32(mantissa as u32);
1030 Ok(mantissa_u256.shl(shift))
1031 }
1032}
1033
1034#[cfg_attr(feature = "spec-lock", spec_locked("11.3", "GetBlockProof"))]
1039pub fn get_block_proof(bits: Natural) -> Result<U256> {
1040 let target = expand_target(bits)?;
1041 if target.is_zero() {
1042 return Ok(U256::zero());
1043 }
1044 let target_plus_one = target
1045 .checked_add(U256::one())
1046 .ok_or_else(|| ConsensusError::InvalidProofOfWork("Target overflow".into()))?;
1047 let quotient = target.not().div(target_plus_one);
1048 Ok(quotient
1049 .checked_add(U256::one())
1050 .unwrap_or(U256([u64::MAX; 4])))
1051}
1052
1053#[cfg_attr(feature = "spec-lock", spec_locked("7.1", "CompressTarget"))]
1082pub(crate) fn compress_target(target: &U256) -> Result<Natural> {
1083 if target.is_zero() {
1085 return Ok(0x1d000000); }
1087
1088 let highest_bit = target
1090 .highest_set_bit()
1091 .ok_or_else(|| ConsensusError::InvalidProofOfWork("Cannot compress zero target".into()))?;
1092
1093 let n_size = (highest_bit + 1).div_ceil(8);
1096
1097 let mut n_compact: u64;
1100
1101 if n_size <= 3 {
1102 let low_64 = target.get_low_64();
1105 let shift_bytes = 3 - n_size;
1106 n_compact = low_64 << (8 * shift_bytes);
1107 } else {
1108 let shift_bytes = n_size - 3;
1111 let shifted = target.shr(shift_bytes * 8);
1112 n_compact = shifted.get_low_64();
1113 }
1114
1115 let mut n_size_final = n_size;
1119 while (n_compact & 0x00800000) != 0 {
1120 n_compact >>= 8;
1121 n_size_final += 1;
1122 }
1123
1124 let mantissa = (n_compact & 0x007fffff) as u32;
1127
1128 if n_size_final > 32 {
1131 return Err(ConsensusError::InvalidProofOfWork(
1132 format!("Target too large: exponent {n_size_final} exceeds maximum 32").into(),
1133 ));
1134 }
1135
1136 let bits = (n_size_final << 24) | mantissa;
1138
1139 Ok(bits as Natural)
1140}
1141
1142fn serialize_header(header: &BlockHeader) -> [u8; 80] {
1144 let mut bytes = [0u8; 80];
1146
1147 bytes[0..4].copy_from_slice(&(header.version as u32).to_le_bytes());
1148 bytes[4..36].copy_from_slice(&header.prev_block_hash);
1149 bytes[36..68].copy_from_slice(&header.merkle_root);
1150 bytes[68..72].copy_from_slice(&(header.timestamp as u32).to_le_bytes());
1151 bytes[72..76].copy_from_slice(&(header.bits as u32).to_le_bytes());
1152 bytes[76..80].copy_from_slice(&(header.nonce as u32).to_le_bytes());
1153
1154 bytes
1155}
1156
1157#[cfg(test)]
1158fn u256_from_bytes(bytes: &[u8]) -> u128 {
1160 let mut value = 0u128;
1161 for (i, &byte) in bytes.iter().enumerate() {
1162 if i < 16 {
1163 value |= (byte as u128) << (8 * (15 - i));
1165 }
1166 }
1167 value
1168}
1169
1170#[cfg(test)]
1184mod property_tests {
1185 use super::*;
1186 use proptest::prelude::*;
1187
1188 fn compact_target_bytes(exponent: u8, mantissa: u32) -> [u8; 32] {
1189 let mut out = [0u8; 32];
1190 if mantissa == 0 || !(3..=32).contains(&exponent) {
1191 return out;
1192 }
1193 let shift = (exponent as usize).saturating_sub(3);
1194 for (i, byte) in mantissa.to_le_bytes().iter().enumerate() {
1195 let pos = shift + i;
1196 if pos < 32 {
1197 out[pos] = *byte;
1198 }
1199 }
1200 out
1201 }
1202
1203 fn arb_block_header() -> impl Strategy<Value = BlockHeader> {
1204 (
1205 any::<i64>(),
1206 any::<[u8; 32]>(),
1207 any::<[u8; 32]>(),
1208 any::<u64>(),
1209 0x03000000u32..0x1d00ffffu32,
1210 any::<u64>(),
1211 )
1212 .prop_map(
1213 |(version, prev_block_hash, merkle_root, timestamp, bits, nonce)| BlockHeader {
1214 version,
1215 prev_block_hash,
1216 merkle_root,
1217 timestamp,
1218 bits: bits as u64,
1219 nonce,
1220 },
1221 )
1222 }
1223
1224 proptest! {
1226 #[test]
1227 fn prop_expand_target_valid_range(
1228 exponent in 0u8..=40,
1229 mantissa in 0u32..=0x007f_ffff
1230 ) {
1231 let bits = ((exponent as u64) << 24) | (mantissa as u64);
1232 let result = expand_target(bits);
1233 if !(3..=32).contains(&exponent) {
1234 prop_assert!(result.is_err());
1235 } else {
1236 let expected = compact_target_bytes(exponent, mantissa);
1237 prop_assert_eq!(result.unwrap().to_le_bytes(), expected);
1238 let signed = bits | 0x0080_0000;
1239 prop_assert_eq!(expand_target(signed).unwrap().to_le_bytes(), expected);
1240 }
1241 }
1242 }
1243
1244 proptest! {
1246 #[test]
1247 fn prop_check_proof_of_work_deterministic(
1248 header in arb_block_header()
1249 ) {
1250 let result1 = check_proof_of_work(&header);
1251 let result2 = check_proof_of_work(&header);
1252 prop_assert_eq!(result1, result2);
1253 }
1254 }
1255
1256 proptest! {
1258 #[test]
1259 fn prop_get_next_work_required_bounds(
1260 n in 0usize..6,
1261 span in 0u64..5_000_000,
1262 ordered in any::<bool>()
1263 ) {
1264 let start = 1_700_000_000u64;
1265 let mut headers: Vec<BlockHeader> = (0..n)
1266 .map(|i| BlockHeader {
1267 version: 1,
1268 prev_block_hash: [0; 32],
1269 merkle_root: [1; 32],
1270 timestamp: start + (i as u64) * span,
1271 bits: 0x1d00ffff,
1272 nonce: 0,
1273 })
1274 .collect();
1275 if n >= 2 && !ordered {
1276 headers[n - 1].timestamp = start.saturating_sub(1);
1277 }
1278 let current = headers.first().cloned().unwrap_or(BlockHeader {
1279 version: 1,
1280 prev_block_hash: [0; 32],
1281 merkle_root: [1; 32],
1282 timestamp: start,
1283 bits: 0x1d00ffff,
1284 nonce: 0,
1285 });
1286 let result = get_next_work_required(¤t, &headers);
1287 if n < 2 || !ordered {
1288 prop_assert!(result.is_err());
1289 } else {
1290 let bits = result.unwrap();
1291 prop_assert!(bits > 0);
1292 prop_assert!(bits <= MAX_TARGET as Natural);
1293 let next = expand_target(bits).unwrap();
1294 let previous = expand_target(0x1d00ffff).unwrap();
1295 prop_assert!(next <= previous);
1296 }
1297 }
1298 }
1299}
1300
1301#[cfg(test)]
1302mod tests {
1303 use super::*;
1304 use crate::constants::MAX_TARGET;
1305
1306 fn header_hash_meets(header: &BlockHeader) -> bool {
1307 if header.bits & 0x0080_0000 != 0 {
1308 return false;
1309 }
1310 let Ok(target) = expand_target(header.bits) else {
1311 return false;
1312 };
1313 if target.is_zero() {
1314 return false;
1315 }
1316 let bytes = serialize_header(header);
1317 let hash1 = Sha256::digest(bytes);
1318 let hash2 = Sha256::digest(hash1);
1319 let mut hash_bytes = [0u8; 32];
1320 hash_bytes.copy_from_slice(&hash2);
1321 let target_bytes = target.to_le_bytes();
1322 for i in (0..32).rev() {
1323 if hash_bytes[i] != target_bytes[i] {
1324 return hash_bytes[i] < target_bytes[i];
1325 }
1326 }
1327 true
1328 }
1329
1330 #[test]
1331 fn negative_or_zero_target_fails_and_equal_hash_passes() {
1332 let header = BlockHeader {
1333 version: 1,
1334 prev_block_hash: [0; 32],
1335 merkle_root: [0; 32],
1336 timestamp: 1,
1337 bits: 0x1d80_0001,
1338 nonce: 0,
1339 };
1340 assert!(!check_proof_of_work(&header).unwrap());
1341
1342 let mut zero = header;
1343 zero.bits = 0x0300_0000;
1344 assert!(!check_proof_of_work(&zero).unwrap());
1345
1346 let bits = 0x1d00ffff;
1347 let target = expand_target(bits).unwrap();
1348 assert!(proof_hash_meets_target(bits, &target).unwrap());
1349 let above = target.checked_add(U256::one()).unwrap();
1350 assert!(!proof_hash_meets_target(bits, &above).unwrap());
1351 }
1352
1353 #[test]
1354 fn test_get_next_work_required_insufficient_headers() {
1355 let header = BlockHeader {
1356 version: 1,
1357 prev_block_hash: [0; 32],
1358 merkle_root: [0; 32],
1359 timestamp: 1231006505,
1360 bits: 0x1d00ffff,
1361 nonce: 0,
1362 };
1363
1364 let prev_headers = vec![header.clone()];
1365 let result = get_next_work_required(&header, &prev_headers);
1366
1367 assert!(result.is_err());
1369 }
1370
1371 #[test]
1372 fn test_get_next_work_required_normal_adjustment() {
1373 let header1 = BlockHeader {
1374 version: 1,
1375 prev_block_hash: [0; 32],
1376 merkle_root: [0; 32],
1377 timestamp: 1000000,
1378 bits: 0x1d00ffff,
1379 nonce: 0,
1380 };
1381
1382 let header2 = BlockHeader {
1383 version: 1,
1384 prev_block_hash: [0; 32],
1385 merkle_root: [0; 32],
1386 timestamp: 1000000 + (DIFFICULTY_ADJUSTMENT_INTERVAL * TARGET_TIME_PER_BLOCK), bits: 0x1d00ffff,
1388 nonce: 0,
1389 };
1390
1391 let prev_headers = vec![header1, header2.clone()];
1392 let result = get_next_work_required(&header2, &prev_headers).unwrap();
1393
1394 assert_eq!(result, 0x1d00ffff);
1396 }
1397
1398 #[test]
1399 fn test_difficulty_from_bits() {
1400 let d = difficulty_from_bits(0x1d00ffff).unwrap();
1402 assert!(
1403 (d - 1.0).abs() < 0.01,
1404 "Genesis difficulty should be ~1.0, got {d}"
1405 );
1406 let d_harder = difficulty_from_bits(0x1d000800).unwrap();
1408 assert!(d_harder > d, "Harder target should have higher difficulty");
1409 }
1410
1411 #[test]
1412 fn test_expand_target() {
1413 let target = expand_target(0x0300ffff).unwrap(); assert!(!target.is_zero());
1417 }
1418
1419 #[test]
1420 fn test_check_proof_of_work_genesis() {
1421 let header = BlockHeader {
1423 version: 1,
1424 prev_block_hash: [0; 32],
1425 merkle_root: [0; 32],
1426 timestamp: 1231006505,
1427 bits: 0x0300ffff, nonce: 0,
1429 };
1430
1431 assert_eq!(
1432 check_proof_of_work(&header).unwrap(),
1433 header_hash_meets(&header)
1434 );
1435 }
1436
1437 #[test]
1442 fn test_get_next_work_required_fast_blocks() {
1443 let header1 = BlockHeader {
1444 version: 1,
1445 prev_block_hash: [0; 32],
1446 merkle_root: [0; 32],
1447 timestamp: 1000000,
1448 bits: 0x1d00ffff,
1449 nonce: 0,
1450 };
1451
1452 let header2 = BlockHeader {
1454 version: 1,
1455 prev_block_hash: [0; 32],
1456 merkle_root: [0; 32],
1457 timestamp: 1000000 + (DIFFICULTY_ADJUSTMENT_INTERVAL * TARGET_TIME_PER_BLOCK / 2),
1458 bits: 0x1d00ffff,
1459 nonce: 0,
1460 };
1461
1462 let prev_headers = vec![header1, header2.clone()];
1463 let result = get_next_work_required(&header2, &prev_headers).unwrap();
1464
1465 assert!(result <= 0x1d00ffff);
1468 }
1469
1470 #[test]
1471 fn test_get_next_work_required_slow_blocks() {
1472 let header1 = BlockHeader {
1473 version: 1,
1474 prev_block_hash: [0; 32],
1475 merkle_root: [0; 32],
1476 timestamp: 1000000,
1477 bits: 0x1d00ffff,
1478 nonce: 0,
1479 };
1480
1481 let header2 = BlockHeader {
1483 version: 1,
1484 prev_block_hash: [0; 32],
1485 merkle_root: [0; 32],
1486 timestamp: 1000000 + (DIFFICULTY_ADJUSTMENT_INTERVAL * TARGET_TIME_PER_BLOCK * 2),
1487 bits: 0x1d00ffff,
1488 nonce: 0,
1489 };
1490
1491 let prev_headers = vec![header1, header2.clone()];
1492 let result = get_next_work_required(&header2, &prev_headers).unwrap();
1493
1494 assert!(result <= 0x1d00ffff);
1497 }
1498
1499 #[test]
1500 fn test_get_next_work_required_extreme_fast_blocks() {
1501 let header1 = BlockHeader {
1502 version: 1,
1503 prev_block_hash: [0; 32],
1504 merkle_root: [0; 32],
1505 timestamp: 1000000,
1506 bits: 0x1d00ffff,
1507 nonce: 0,
1508 };
1509
1510 let header2 = BlockHeader {
1512 version: 1,
1513 prev_block_hash: [0; 32],
1514 merkle_root: [0; 32],
1515 timestamp: 1000000 + (DIFFICULTY_ADJUSTMENT_INTERVAL * TARGET_TIME_PER_BLOCK / 14),
1516 bits: 0x1d00ffff,
1517 nonce: 0,
1518 };
1519
1520 let prev_headers = vec![header1, header2.clone()];
1521 let result = get_next_work_required(&header2, &prev_headers).unwrap();
1522
1523 assert!(result <= 0x1d00ffff);
1526 }
1527
1528 #[test]
1529 fn test_get_next_work_required_extreme_slow_blocks() {
1530 let header1 = BlockHeader {
1531 version: 1,
1532 prev_block_hash: [0; 32],
1533 merkle_root: [0; 32],
1534 timestamp: 1000000,
1535 bits: 0x1d00ffff,
1536 nonce: 0,
1537 };
1538
1539 let header2 = BlockHeader {
1541 version: 1,
1542 prev_block_hash: [0; 32],
1543 merkle_root: [0; 32],
1544 timestamp: 1000000 + (DIFFICULTY_ADJUSTMENT_INTERVAL * TARGET_TIME_PER_BLOCK * 4),
1545 bits: 0x1d00ffff,
1546 nonce: 0,
1547 };
1548
1549 let prev_headers = vec![header1, header2.clone()];
1550 let result = get_next_work_required(&header2, &prev_headers).unwrap();
1551
1552 assert!(result <= 0x1d00ffff);
1555 }
1556
1557 #[test]
1558 fn test_expand_target_zero_mantissa() {
1559 let result = expand_target(0x1d000000).unwrap();
1560 assert!(result.is_zero());
1561 }
1562
1563 #[test]
1564 fn test_expand_target_invalid_exponent_too_small() {
1565 let result = expand_target(0x0200ffff);
1566 assert!(result.is_err());
1567 }
1568
1569 #[test]
1570 fn test_expand_target_invalid_exponent_too_large() {
1571 let result = expand_target(0x2100ffff);
1572 assert!(result.is_err());
1573 }
1574
1575 #[test]
1576 fn test_expand_target_exponent_31() {
1577 let result = expand_target(0x1f00ffff).unwrap(); assert!(!result.is_zero());
1579 }
1580
1581 #[test]
1582 fn test_expand_target_exponent_32_regtest_bits() {
1583 let result = expand_target(0x2000ffff).unwrap();
1585 assert!(!result.is_zero());
1586 }
1587
1588 #[test]
1589 fn test_gbt_target_hex_regtest_minimum_difficulty() {
1590 let target = expand_target(0x207fffff).expect("regtest nBits");
1591 let hex = target.gbt_target_hex();
1592 assert_eq!(hex.len(), 64);
1593 assert_ne!(hex, "0".repeat(64));
1594 assert!(hex.starts_with("7fffff"));
1596 }
1597
1598 #[test]
1599 fn test_expand_target_exponent_3() {
1600 let result = expand_target(0x0300ffff).unwrap();
1601 assert!(!result.is_zero());
1602 }
1603
1604 #[test]
1605 fn test_expand_target_exponent_4() {
1606 let result = expand_target(0x0400ffff).unwrap();
1607 assert!(!result.is_zero());
1608 }
1609
1610 #[test]
1611 fn test_expand_target_exponent_29() {
1612 let result = expand_target(0x1d00ffff).unwrap();
1613 assert!(!result.is_zero());
1614 }
1615
1616 #[test]
1617 fn test_check_proof_of_work_invalid_target() {
1618 let header = BlockHeader {
1621 version: 1,
1622 prev_block_hash: [0; 32],
1623 merkle_root: [0; 32],
1624 timestamp: 1231006505,
1625 bits: 0x0200ffff, nonce: 0,
1627 };
1628
1629 let result = check_proof_of_work(&header);
1630 assert!(result.is_err());
1631 }
1632
1633 #[test]
1634 fn test_check_proof_of_work_valid_target() {
1635 let header = BlockHeader {
1636 version: 1,
1637 prev_block_hash: [0; 32],
1638 merkle_root: [0; 32],
1639 timestamp: 1231006505,
1640 bits: 0x1d00ffff, nonce: 0,
1642 };
1643
1644 assert_eq!(
1645 check_proof_of_work(&header).unwrap(),
1646 header_hash_meets(&header)
1647 );
1648 let mut negative = header;
1649 negative.bits |= 0x0080_0000;
1650 assert!(!check_proof_of_work(&negative).unwrap());
1651 }
1652
1653 #[test]
1654 fn test_get_block_proof_genesis_mainnet() {
1655 let work = get_block_proof(0x1d00ffff).unwrap();
1656 assert_eq!(
1657 work.gbt_target_hex(),
1658 "0000000000000000000000000000000000000000000000000000000100010001"
1659 );
1660 assert!(work > U256::zero());
1661 }
1662
1663 #[test]
1664 fn test_get_block_proof_regtest_minimum_difficulty() {
1665 let work = get_block_proof(0x207fffff).unwrap();
1666 assert!(work > U256::zero());
1667 assert!(work < U256::from_u128(10));
1668 }
1669
1670 #[test]
1671 fn test_u256_zero() {
1672 let zero = U256::zero();
1673 assert!(zero.is_zero());
1674 }
1675
1676 #[test]
1677 fn test_u256_from_u32() {
1678 let value = U256::from_u32(0x12345678);
1679 assert!(!value.is_zero());
1680 }
1681
1682 #[test]
1683 fn test_u256_from_u64() {
1684 let value = U256::from_u64(0x123456789abcdef0);
1685 assert!(!value.is_zero());
1686 }
1687
1688 #[test]
1689 fn test_u256_shl_zero_shift() {
1690 let value = U256::from_u32(0x12345678);
1691 let result = value.shl(0);
1692 assert_eq!(result, value);
1693 }
1694
1695 #[test]
1696 fn test_u256_shl_large_shift() {
1697 let value = U256::from_u32(0x12345678);
1698 let result = value.shl(300); assert!(result.is_zero());
1700 }
1701
1702 #[test]
1703 fn test_u256_shr_zero_shift() {
1704 let value = U256::from_u32(0x12345678);
1705 let result = value.shr(0);
1706 assert_eq!(result, value);
1707 }
1708
1709 #[test]
1710 fn test_u256_shr_large_shift() {
1711 let value = U256::from_u32(0x12345678);
1712 let result = value.shr(300); assert!(result.is_zero());
1714 }
1715
1716 #[test]
1717 fn test_u256_shl_small_shift() {
1718 let value = U256::from_u32(0x12345678);
1719 let result = value.shl(8);
1720 assert!(!result.is_zero());
1721 assert_ne!(result, value);
1722 }
1723
1724 #[test]
1725 fn test_u256_shr_small_shift() {
1726 let value = U256::from_u32(0x12345678);
1727 let result = value.shr(8);
1728 assert!(!result.is_zero());
1729 assert_ne!(result, value);
1730 }
1731
1732 #[test]
1733 fn test_u256_to_bytes() {
1734 let value = U256::from_u32(0x12345678);
1735 let bytes = value.to_bytes();
1736 assert_eq!(bytes.len(), 32);
1737 }
1738
1739 #[test]
1740 fn test_u256_from_bytes() {
1741 let mut bytes = [0u8; 32];
1742 bytes[0] = 0x78;
1743 bytes[1] = 0x56;
1744 bytes[2] = 0x34;
1745 bytes[3] = 0x12;
1746 let value = U256::from_bytes(&bytes);
1747 assert!(!value.is_zero());
1748 }
1749
1750 #[test]
1751 fn test_u256_ordering() {
1752 let small = U256::from_u32(0x12345678);
1753 let large = U256::from_u32(0x87654321);
1754
1755 assert!(small < large);
1756 assert!(large > small);
1757 assert_eq!(small.cmp(&small), std::cmp::Ordering::Equal);
1758 }
1759
1760 #[test]
1761 fn test_expand_compress_round_trip() {
1762 let test_bits = vec![
1764 0x1d00ffff, 0x1b0404cb, 0x0300ffff, ];
1771
1772 for &bits in &test_bits {
1773 let expanded = match expand_target(bits) {
1775 Ok(t) => t,
1776 Err(_) => continue, };
1778
1779 let compressed = match compress_target(&expanded) {
1781 Ok(b) => b,
1782 Err(_) => {
1783 continue;
1786 }
1787 };
1788
1789 let re_expanded = match expand_target(compressed) {
1791 Ok(t) => t,
1792 Err(_) => continue,
1793 };
1794
1795 if re_expanded > expanded {
1799 panic!(
1800 "Round-trip failed for bits 0x{bits:08x}: re-expanded > original (compression should truncate, not add)"
1801 );
1802 }
1803 #[allow(clippy::eq_op)]
1810 let significant_words_match =
1811 expanded.0[2] == re_expanded.0[2] && expanded.0[3] == re_expanded.0[3];
1812 if !significant_words_match {
1813 panic!(
1814 "Round-trip failed for bits 0x{:08x}: significant bits differ (expanded: {:?}, re-expanded: {:?})",
1815 bits, expanded.0, re_expanded.0
1816 );
1817 }
1818 }
1820 }
1821
1822 #[test]
1823 fn test_compress_target_genesis() {
1824 let genesis_bits = 0x1d00ffff;
1826 let expanded = expand_target(genesis_bits).unwrap();
1827 let compressed = compress_target(&expanded).unwrap();
1828
1829 assert!(compressed <= MAX_TARGET as u64);
1831 assert!(compressed > 0);
1832
1833 let re_expanded = expand_target(compressed).unwrap();
1835 assert_eq!(expanded, re_expanded);
1836 }
1837
1838 #[test]
1839 fn test_serialize_header() {
1840 let header = BlockHeader {
1841 version: 1,
1842 prev_block_hash: [1; 32],
1843 merkle_root: [2; 32],
1844 timestamp: 1234567890,
1845 bits: 0x1d00ffff,
1846 nonce: 0x12345678,
1847 };
1848
1849 let bytes = serialize_header(&header);
1850 assert_eq!(bytes.len(), 80); }
1852
1853 #[test]
1858 fn test_serialize_header_returns_fixed_80_bytes() {
1859 let header = BlockHeader {
1861 version: 1,
1862 prev_block_hash: [0; 32],
1863 merkle_root: [0; 32],
1864 timestamp: 0,
1865 bits: 0,
1866 nonce: 0,
1867 };
1868 let bytes: [u8; 80] = serialize_header(&header);
1869 assert_eq!(bytes.len(), 80);
1870 }
1871
1872 #[test]
1873 fn test_serialize_header_field_layout() {
1874 let header = BlockHeader {
1876 version: 0x01020304,
1877 prev_block_hash: {
1878 let mut h = [0u8; 32];
1879 h[0] = 0xAA;
1880 h[31] = 0xBB;
1881 h
1882 },
1883 merkle_root: {
1884 let mut h = [0u8; 32];
1885 h[0] = 0xCC;
1886 h[31] = 0xDD;
1887 h
1888 },
1889 timestamp: 0x05060708,
1890 bits: 0x090A0B0C,
1891 nonce: 0x0D0E0F10,
1892 };
1893
1894 let bytes = serialize_header(&header);
1895
1896 assert_eq!(bytes[0], 0x04); assert_eq!(bytes[1], 0x03);
1899 assert_eq!(bytes[2], 0x02);
1900 assert_eq!(bytes[3], 0x01);
1901
1902 assert_eq!(bytes[4], 0xAA);
1904 assert_eq!(bytes[35], 0xBB);
1905
1906 assert_eq!(bytes[36], 0xCC);
1908 assert_eq!(bytes[67], 0xDD);
1909
1910 assert_eq!(bytes[68], 0x08);
1912 assert_eq!(bytes[69], 0x07);
1913 assert_eq!(bytes[70], 0x06);
1914 assert_eq!(bytes[71], 0x05);
1915
1916 assert_eq!(bytes[72], 0x0C);
1918 assert_eq!(bytes[73], 0x0B);
1919 assert_eq!(bytes[74], 0x0A);
1920 assert_eq!(bytes[75], 0x09);
1921
1922 assert_eq!(bytes[76], 0x10);
1924 assert_eq!(bytes[77], 0x0F);
1925 assert_eq!(bytes[78], 0x0E);
1926 assert_eq!(bytes[79], 0x0D);
1927 }
1928
1929 #[test]
1930 fn test_serialize_header_deterministic() {
1931 let header = BlockHeader {
1932 version: 1,
1933 prev_block_hash: [0xFF; 32],
1934 merkle_root: [0xAA; 32],
1935 timestamp: 1231006505,
1936 bits: 0x1d00ffff,
1937 nonce: 2083236893,
1938 };
1939
1940 let bytes1 = serialize_header(&header);
1941 let bytes2 = serialize_header(&header);
1942 assert_eq!(bytes1, bytes2, "Header serialization must be deterministic");
1943 }
1944
1945 #[test]
1946 fn test_serialize_header_different_headers_different_bytes() {
1947 let header1 = BlockHeader {
1948 version: 1,
1949 prev_block_hash: [0; 32],
1950 merkle_root: [0; 32],
1951 timestamp: 1231006505,
1952 bits: 0x1d00ffff,
1953 nonce: 0,
1954 };
1955
1956 let mut header2 = header1.clone();
1957 header2.nonce = 1;
1958
1959 let bytes1 = serialize_header(&header1);
1960 let bytes2 = serialize_header(&header2);
1961 assert_ne!(
1962 bytes1, bytes2,
1963 "Different nonces must produce different serializations"
1964 );
1965
1966 assert_eq!(
1968 bytes1[..76],
1969 bytes2[..76],
1970 "Non-nonce bytes should be identical"
1971 );
1972 assert_ne!(bytes1[76..], bytes2[76..], "Nonce bytes should differ");
1973 }
1974
1975 #[test]
1976 fn test_u256_from_bytes_simple() {
1977 let bytes = [0u8; 32];
1978 let value = u256_from_bytes(&bytes);
1979 assert_eq!(value, 0);
1980 }
1981
1982 #[test]
1983 fn test_u256_from_bytes_with_data() {
1984 let mut bytes = [0u8; 32];
1985 bytes[0] = 0x78;
1986 bytes[1] = 0x56;
1987 bytes[2] = 0x34;
1988 bytes[3] = 0x12;
1989 let value = u256_from_bytes(&bytes);
1990 assert_eq!(value, 0x78563412000000000000000000000000);
1993 }
1994
1995 fn ancestor_from(headers: &[(u64, u64, u64)]) -> impl Fn(u64) -> Option<(u64, u64)> + '_ {
1996 move |height| {
1997 headers
1998 .iter()
1999 .find(|(h, _, _)| *h == height)
2000 .map(|(_, bits, ts)| (*bits, *ts))
2001 }
2002 }
2003
2004 #[test]
2005 fn off_boundary_copies_parent_bits() {
2006 let headers = [(99u64, 0x1b012dcd, 1_000u64)];
2007 let bits = next_required_bits(Network::Mainnet, 100, 2_000, &ancestor_from(&headers))
2008 .unwrap()
2009 .unwrap();
2010 assert_eq!(bits, 0x1b012dcd);
2011 }
2012
2013 #[test]
2014 fn testnet4_retarget_uses_the_first_block_of_the_period() {
2015 let timespan = 2016 * 600;
2016 let headers = [
2017 (0u64, 0x1b012dcd, 1_700_000_000u64),
2018 (2015, 0x1d00ffff, 1_700_000_000 + timespan),
2019 ];
2020 let lookup = ancestor_from(&headers);
2021 let testnet3 = next_required_bits(Network::Testnet, 2016, 0, &lookup)
2022 .unwrap()
2023 .unwrap();
2024 let testnet4 = next_required_bits(Network::Testnet4, 2016, 0, &lookup)
2025 .unwrap()
2026 .unwrap();
2027 assert_eq!(testnet3, 0x1d00ffff);
2028 assert_eq!(testnet4, 0x1b012dcd);
2029 }
2030
2031 #[test]
2032 fn testnet_late_block_uses_pow_limit() {
2033 let headers = [(99u64, 0x1b012dcd, 1_000u64)];
2034 let late = next_required_bits(
2035 Network::Testnet,
2036 100,
2037 1_000 + 1_201,
2038 &ancestor_from(&headers),
2039 )
2040 .unwrap()
2041 .unwrap();
2042 assert_eq!(late, 0x1d00ffff);
2043 let on_time = next_required_bits(
2044 Network::Testnet,
2045 100,
2046 1_000 + 1_200,
2047 &ancestor_from(&headers),
2048 )
2049 .unwrap()
2050 .unwrap();
2051 assert_eq!(on_time, 0x1b012dcd);
2052 }
2053
2054 #[test]
2055 fn testnet_walks_back_past_minimum_difficulty_blocks() {
2056 let headers = [
2057 (8u64, 0x1b012dcd, 1_000u64),
2058 (9, 0x1d00ffff, 1_600),
2059 (10, 0x1d00ffff, 2_200),
2060 ];
2061 let bits = next_required_bits(Network::Testnet, 11, 2_800, &ancestor_from(&headers))
2062 .unwrap()
2063 .unwrap();
2064 assert_eq!(bits, 0x1b012dcd);
2065 }
2066
2067 #[test]
2068 fn regtest_does_not_retarget_and_uses_its_own_limit() {
2069 let headers = [(143u64, 0x181bc330, 10_000u64)];
2070 let bits = next_required_bits(Network::Regtest, 144, 20_000, &ancestor_from(&headers))
2071 .unwrap()
2072 .unwrap();
2073 assert_eq!(bits, 0x181bc330);
2074
2075 let min = [(0u64, 0x207fffff, 1_000u64), (1, 0x207fffff, 1_600)];
2076 let late = next_required_bits(Network::Regtest, 2, 1_600 + 1_201, &ancestor_from(&min))
2077 .unwrap()
2078 .unwrap();
2079 assert_eq!(late, 0x207fffff);
2080 let walked = next_required_bits(Network::Regtest, 2, 1_600 + 600, &ancestor_from(&min))
2081 .unwrap()
2082 .unwrap();
2083 assert_eq!(walked, 0x207fffff);
2084 }
2085
2086 #[test]
2087 fn mainnet_retarget_height_112896_matches_chain_bits() {
2088 let first_ts = 1_298_800_760u64;
2089 let last_ts = 1_299_683_275u64;
2090 let period_bits = 453_062_093u64;
2091 let headers = [
2092 (110_880u64, period_bits, first_ts),
2093 (112_895, period_bits, last_ts),
2094 ];
2095 let bits = next_required_bits(
2096 Network::Mainnet,
2097 112_896,
2098 1_299_684_355,
2099 &ancestor_from(&headers),
2100 )
2101 .unwrap()
2102 .unwrap();
2103 assert_eq!(bits, 453_041_201);
2104 }
2105
2106 #[test]
2107 fn genesis_has_no_required_bits() {
2108 assert!(
2109 next_required_bits(Network::Mainnet, 0, 1, &|_| None)
2110 .unwrap()
2111 .is_none()
2112 );
2113 }
2114}