diff --git a/bitcoin/src/bip152.rs b/bitcoin/src/bip152.rs index b19ed3109..7fad7fdeb 100644 --- a/bitcoin/src/bip152.rs +++ b/bitcoin/src/bip152.rs @@ -497,7 +497,7 @@ mod test { { // test serialization let raw: Vec = serialize(&BlockTransactionsRequest { - block_hash: BlockHash::all_zeros(), + block_hash: BlockHash::from_byte_array([0; 32]), indexes: testcase.1, }); let mut expected_raw: Vec = [0u8; 32].to_vec(); @@ -520,7 +520,7 @@ mod test { #[should_panic] // 'attempt to add with overflow' in consensus_encode() fn test_getblocktx_panic_when_encoding_u64_max() { serialize(&BlockTransactionsRequest { - block_hash: BlockHash::all_zeros(), + block_hash: BlockHash::from_byte_array([0; 32]), indexes: vec![u64::MAX], }); } diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs index 9661b7612..c5ddf11fa 100644 --- a/bitcoin/src/blockdata/block.rs +++ b/bitcoin/src/blockdata/block.rs @@ -23,20 +23,11 @@ use crate::prelude::Vec; use crate::script::{self, ScriptExt as _}; use crate::transaction::{Transaction, Wtxid}; -hashes::hash_newtype! { - /// A bitcoin block hash. - pub struct BlockHash(sha256d::Hash); - /// A hash corresponding to the witness structure commitment in the coinbase transaction. - pub struct WitnessCommitment(sha256d::Hash); -} +#[rustfmt::skip] // Keep public re-exports separate. +#[doc(inline)] +pub use primitives::block::*; + impl_hashencode!(BlockHash); -impl BlockHash { - /// The "all zeros" blockhash. - /// - /// This is not the hash of a real block. It is used as the previous blockhash - /// of the genesis block and in other placeholder contexts. - pub fn all_zeros() -> Self { Self::from_byte_array([0; 32]) } -} /// Bitcoin block header. /// @@ -76,7 +67,7 @@ impl Header { pub fn block_hash(&self) -> BlockHash { let mut engine = sha256d::Hash::engine(); self.consensus_encode(&mut engine).expect("engines don't error"); - BlockHash(sha256d::Hash::from_engine(engine)) + BlockHash::from_byte_array(sha256d::Hash::from_engine(engine).to_byte_array()) } /// Computes the target (range [0, T] inclusive) that a blockhash must land in to be valid. @@ -298,7 +289,7 @@ impl Block { let mut encoder = sha256d::Hash::engine(); witness_root.consensus_encode(&mut encoder).expect("engines don't error"); encoder.input(witness_reserved_value); - WitnessCommitment(sha256d::Hash::from_engine(encoder)) + WitnessCommitment::from_byte_array(sha256d::Hash::from_engine(encoder).to_byte_array()) } /// Computes the Merkle root of transactions hashed for witness. diff --git a/bitcoin/src/blockdata/constants.rs b/bitcoin/src/blockdata/constants.rs index 5312a32f2..8e828304b 100644 --- a/bitcoin/src/blockdata/constants.rs +++ b/bitcoin/src/blockdata/constants.rs @@ -113,7 +113,7 @@ pub fn genesis_block(params: impl AsRef) -> Block { Network::Bitcoin => Block { header: block::Header { version: block::Version::ONE, - prev_blockhash: BlockHash::all_zeros(), + prev_blockhash: BlockHash::GENESIS_PREVIOUS_BLOCK_HASH, merkle_root, time: 1231006505, bits: CompactTarget::from_consensus(0x1d00ffff), @@ -124,7 +124,7 @@ pub fn genesis_block(params: impl AsRef) -> Block { Network::Testnet => Block { header: block::Header { version: block::Version::ONE, - prev_blockhash: BlockHash::all_zeros(), + prev_blockhash: BlockHash::GENESIS_PREVIOUS_BLOCK_HASH, merkle_root, time: 1296688602, bits: CompactTarget::from_consensus(0x1d00ffff), @@ -135,7 +135,7 @@ pub fn genesis_block(params: impl AsRef) -> Block { Network::Signet => Block { header: block::Header { version: block::Version::ONE, - prev_blockhash: BlockHash::all_zeros(), + prev_blockhash: BlockHash::GENESIS_PREVIOUS_BLOCK_HASH, merkle_root, time: 1598918400, bits: CompactTarget::from_consensus(0x1e0377ae), @@ -146,7 +146,7 @@ pub fn genesis_block(params: impl AsRef) -> Block { Network::Regtest => Block { header: block::Header { version: block::Version::ONE, - prev_blockhash: BlockHash::all_zeros(), + prev_blockhash: BlockHash::GENESIS_PREVIOUS_BLOCK_HASH, merkle_root, time: 1296688602, bits: CompactTarget::from_consensus(0x207fffff), @@ -261,7 +261,7 @@ mod test { let gen = genesis_block(¶ms::MAINNET); assert_eq!(gen.header.version, block::Version::ONE); - assert_eq!(gen.header.prev_blockhash, BlockHash::all_zeros()); + assert_eq!(gen.header.prev_blockhash, BlockHash::GENESIS_PREVIOUS_BLOCK_HASH); assert_eq!( gen.header.merkle_root.to_string(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" @@ -280,7 +280,7 @@ mod test { fn testnet_genesis_full_block() { let gen = genesis_block(¶ms::TESTNET); assert_eq!(gen.header.version, block::Version::ONE); - assert_eq!(gen.header.prev_blockhash, BlockHash::all_zeros()); + assert_eq!(gen.header.prev_blockhash, BlockHash::GENESIS_PREVIOUS_BLOCK_HASH); assert_eq!( gen.header.merkle_root.to_string(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" @@ -298,7 +298,7 @@ mod test { fn signet_genesis_full_block() { let gen = genesis_block(¶ms::SIGNET); assert_eq!(gen.header.version, block::Version::ONE); - assert_eq!(gen.header.prev_blockhash, BlockHash::all_zeros()); + assert_eq!(gen.header.prev_blockhash, BlockHash::GENESIS_PREVIOUS_BLOCK_HASH); assert_eq!( gen.header.merkle_root.to_string(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" diff --git a/bitcoin/src/p2p/message_blockdata.rs b/bitcoin/src/p2p/message_blockdata.rs index 9c9d3b001..78c34f059 100644 --- a/bitcoin/src/p2p/message_blockdata.rs +++ b/bitcoin/src/p2p/message_blockdata.rs @@ -159,7 +159,7 @@ mod tests { assert_eq!(real_decode.version, 70002); assert_eq!(real_decode.locator_hashes.len(), 1); assert_eq!(serialize(&real_decode.locator_hashes[0]), genhash); - assert_eq!(real_decode.stop_hash, BlockHash::all_zeros()); + assert_eq!(real_decode.stop_hash, BlockHash::GENESIS_PREVIOUS_BLOCK_HASH); assert_eq!(serialize(&real_decode), from_sat); } @@ -175,7 +175,7 @@ mod tests { assert_eq!(real_decode.version, 70002); assert_eq!(real_decode.locator_hashes.len(), 1); assert_eq!(serialize(&real_decode.locator_hashes[0]), genhash); - assert_eq!(real_decode.stop_hash, BlockHash::all_zeros()); + assert_eq!(real_decode.stop_hash, BlockHash::GENESIS_PREVIOUS_BLOCK_HASH); assert_eq!(serialize(&real_decode), from_sat); } diff --git a/bitcoin/src/pow.rs b/bitcoin/src/pow.rs index 6d1afe18c..0e505b4bd 100644 --- a/bitcoin/src/pow.rs +++ b/bitcoin/src/pow.rs @@ -1771,7 +1771,7 @@ mod tests { // Block 2015, the only information used are `bits` and `time` let current = Header { version: Version::ONE, - prev_blockhash: BlockHash::all_zeros(), + prev_blockhash: BlockHash::from_byte_array([0; 32]), merkle_root: TxMerkleNode::from_byte_array([0; 32]), time: 1599332177, bits: epoch_start.bits, @@ -1793,7 +1793,7 @@ mod tests { // Block 2016, the only information used is `time` let epoch_start = Header { version: Version::ONE, - prev_blockhash: BlockHash::all_zeros(), + prev_blockhash: BlockHash::from_byte_array([0; 32]), merkle_root: TxMerkleNode::from_byte_array([0; 32]), time: 1599332844, bits: starting_bits, @@ -1803,7 +1803,7 @@ mod tests { // Block 4031, the only information used are `bits` and `time` let current = Header { version: Version::ONE, - prev_blockhash: BlockHash::all_zeros(), + prev_blockhash: BlockHash::from_byte_array([0; 32]), merkle_root: TxMerkleNode::from_byte_array([0; 32]), time: 1600591200, bits: starting_bits, diff --git a/primitives/src/block.rs b/primitives/src/block.rs new file mode 100644 index 000000000..3ddf01034 --- /dev/null +++ b/primitives/src/block.rs @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin blocks. +//! +//! A block is a bundle of transactions with a proof-of-work attached, +//! which commits to an earlier block to form the blockchain. This +//! module describes structures and functions needed to describe +//! these blocks and the blockchain. + +use hashes::sha256d; + +hashes::hash_newtype! { + /// A bitcoin block hash. + pub struct BlockHash(sha256d::Hash); + /// A hash corresponding to the witness structure commitment in the coinbase transaction. + pub struct WitnessCommitment(sha256d::Hash); +} + +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]); +} diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 59498095f..e649bdf4e 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -29,6 +29,7 @@ extern crate std; #[macro_use] extern crate serde; +pub mod block; #[cfg(feature = "alloc")] pub mod locktime; pub mod opcodes; @@ -45,6 +46,7 @@ pub use units::*; pub use self::locktime::{absolute, relative}; #[doc(inline)] pub use self::{ + block::{BlockHash, WitnessCommitment}, pow::CompactTarget, sequence::Sequence, transaction::{Txid, Wtxid},