Skip to content

Commit 429b785

Browse files
committed
Merge rust-bitcoin#5463: Remove rand from MerkleBlock unit tests
44ad0ec Add PRNG to `MerkleBlock` tests (rustaceanrob) Pull request description: In an effort to move `MerkleBlock` to `p2p`, I think adding `rand` as a development dependency to `p2p` would be a net loss in developer UX. This replaces `rand` with deterministic PRNG. ACKs for top commit: apoelstra: ACK 44ad0ec; successfully ran local tests; lol, we got there tcharding: ACK 44ad0ec Tree-SHA512: 882bead98c9a33f13a2060f09e93e0f6f0f3ee9490b29a6e33912f7466ea103fdbe53816a202a4f115a3b67f07689d604ae4669ae7cacb8ea280f93f99f73338
2 parents f7457ab + 44ad0ec commit 429b785

File tree

1 file changed

+50
-12
lines changed

1 file changed

+50
-12
lines changed

bitcoin/src/merkle_tree/block.rs

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -532,15 +532,53 @@ impl<'a> Arbitrary<'a> for MerkleBlock {
532532
mod tests {
533533
use hex::{DisplayHex, FromHex};
534534
use hex_lit::hex;
535-
#[cfg(all(feature = "rand", feature = "std"))]
536-
use {core::cmp, secp256k1::rand::prelude::*};
535+
#[cfg(feature = "std")]
536+
use core::cmp;
537537

538538
use super::*;
539539
use crate::block::Unchecked;
540540
use crate::consensus::encode;
541541
use crate::Txid;
542542

543-
#[cfg(all(feature = "rand", feature = "std"))]
543+
// `bloc` in hex.
544+
#[cfg(feature = "std")]
545+
const PRNG_SEED: usize = 0x626C6F63;
546+
547+
// Simple and deterministic PRNG, not suitable for cryptographic use cases.
548+
#[cfg(feature = "std")]
549+
struct LcgPrng {
550+
state: usize,
551+
}
552+
553+
#[cfg(feature = "std")]
554+
impl LcgPrng {
555+
const P: usize = 1039;
556+
const Q: usize = 677;
557+
558+
const fn new(seed: usize) -> Self {
559+
Self {
560+
state: seed
561+
}
562+
}
563+
564+
#[inline]
565+
fn next_usize(&mut self) -> usize {
566+
self.state = self.state.wrapping_mul(Self::P).wrapping_add(Self::Q);
567+
self.state
568+
}
569+
570+
#[inline]
571+
fn next_in_range(&mut self, max: usize) -> usize {
572+
self.next_usize() % max
573+
}
574+
575+
#[inline]
576+
fn next_u8(&mut self) -> u8 {
577+
self.next_usize().to_le_bytes()[0]
578+
}
579+
}
580+
581+
#[cfg(feature = "std")]
544582
macro_rules! pmt_tests {
545583
($($name:ident),* $(,)?) => {
546584
$(
@@ -552,7 +590,7 @@ mod tests {
552590
}
553591
}
554592

555-
#[cfg(all(feature = "rand", feature = "std"))]
593+
#[cfg(feature = "std")]
556594
pmt_tests!(
557595
pmt_test_1,
558596
pmt_test_4,
@@ -569,12 +607,12 @@ mod tests {
569607
);
570608

571609
/// Parses the transaction count out of `name` with form: `pmt_test_$num`.
572-
#[cfg(all(feature = "rand", feature = "std"))]
610+
#[cfg(feature = "std")]
573611
fn pmt_test_from_name(name: &str) { pmt_test(name[9..].parse().unwrap()) }
574612

575-
#[cfg(all(feature = "rand", feature = "std"))]
613+
#[cfg(feature = "std")]
576614
fn pmt_test(tx_count: usize) {
577-
let mut rng = secp256k1::rand::rng();
615+
let mut rng = LcgPrng::new(PRNG_SEED ^ tx_count);
578616
// Create some fake tx ids
579617
let tx_ids = (1..=tx_count)
580618
.map(|i| format!("{:064x}", i).parse::<Txid>().unwrap())
@@ -598,7 +636,7 @@ mod tests {
598636
// Generate `att / 2` random bits
599637
let rand_bits = match att / 2 {
600638
0 => 0,
601-
bits => rng.random::<u64>() >> (64 - bits),
639+
bits => rng.next_usize().rotate_right(64 - bits),
602640
};
603641
let include = rand_bits == 0;
604642
matches[j] = include;
@@ -742,12 +780,12 @@ mod tests {
742780
assert_eq!(index.len(), 0);
743781
}
744782

745-
#[cfg(all(feature = "rand", feature = "std"))]
783+
#[cfg(feature = "std")]
746784
impl PartialMerkleTree {
747785
/// Flip one bit in one of the hashes - this should break the authentication
748-
fn damage(&mut self, rng: &mut ThreadRng) {
749-
let n = rng.random_range(0..self.hashes.len());
750-
let bit = rng.random::<u8>();
786+
fn damage(&mut self, rng: &mut LcgPrng) {
787+
let n = rng.next_in_range(self.hashes.len());
788+
let bit = rng.next_u8();
751789
let hashes = &mut self.hashes;
752790
let mut hash = hashes[n].to_byte_array();
753791
hash[(bit >> 3) as usize] ^= 1 << (bit & 7);

0 commit comments

Comments
 (0)