diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs index b70d17617..255409113 100644 --- a/bitcoin/src/blockdata/block.rs +++ b/bitcoin/src/blockdata/block.rs @@ -12,6 +12,8 @@ use core::fmt; use hashes::{sha256d, HashEngine}; use internals::compact_size; use io::{BufRead, Write}; +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; use super::Weight; use crate::consensus::{encode, Decodable, Encodable}; @@ -400,6 +402,30 @@ impl std::error::Error for ValidationError { } } +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for Header { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Header { + version: Version::arbitrary(u)?, + prev_blockhash: BlockHash::from_byte_array(u.arbitrary()?), + merkle_root: TxMerkleNode::from_byte_array(u.arbitrary()?), + time: u.arbitrary()?, + bits: CompactTarget::from_consensus(u.arbitrary()?), + nonce: u.arbitrary()? + }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for Block { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Block { + header: Header::arbitrary(u)?, + txdata: Vec::::arbitrary(u)?, + }) + } +} + #[cfg(test)] mod tests { use hex::{test_hex_unwrap as hex, FromHex}; diff --git a/primitives/src/block.rs b/primitives/src/block.rs index ca992a730..8b7120771 100644 --- a/primitives/src/block.rs +++ b/primitives/src/block.rs @@ -8,6 +8,8 @@ //! these blocks and the blockchain. use hashes::sha256d; +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; /// Bitcoin block version number. /// @@ -90,3 +92,17 @@ impl BlockHash { /// Dummy hash used as the previous blockhash of the genesis block. pub const GENESIS_PREVIOUS_BLOCK_HASH: Self = Self::from_byte_array([0; 32]); } + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for Version { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + // Equally weight known versions and arbitrary versions + let choice = u.int_in_range(0..=3)?; + match choice { + 0 => Ok(Version::ONE), + 1 => Ok(Version::TWO), + 2 => Ok(Version::NO_SOFT_FORK_SIGNALLING), + _ => Ok(Version::from_consensus(u.arbitrary()?)) + } + } +}