Merge rust-bitcoin/rust-bitcoin#3401: Move the `block` hash types over to `primitives`

2d8c613340 Move the block hash types to primitives (Tobin C. Harding)
6b9429ac7b Remove BlockHash::all_zeros (Tobin C. Harding)
20d8dbd586 Add missing line of whitespace (Tobin C. Harding)

Pull request description:

  As an initial step in moving the `block` module, just move over the hash types `BlockHash` and `WitnessCommitment`.

  Patch 2 introduces an associated const `BlockHash::GENESIS_PREV_BLOCKHASH` and removes `all_zeros`.

ACKs for top commit:
  apoelstra:
    ACK 2d8c613340 successfully ran local tests

Tree-SHA512: 64aa0ae81e1c8ab1b5d4cd8cd28e6ef04ed01bf79175dc5b1fd607a6f0967e06b0aaf4c10ad368e2b327edcad3705187b6643d5ca8647716319424f19a838ba1
This commit is contained in:
merge-script 2024-09-30 19:40:15 +00:00
commit 0b5e0bac31
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
7 changed files with 44 additions and 29 deletions

View File

@ -497,7 +497,7 @@ mod test {
{ {
// test serialization // test serialization
let raw: Vec<u8> = serialize(&BlockTransactionsRequest { let raw: Vec<u8> = serialize(&BlockTransactionsRequest {
block_hash: BlockHash::all_zeros(), block_hash: BlockHash::from_byte_array([0; 32]),
indexes: testcase.1, indexes: testcase.1,
}); });
let mut expected_raw: Vec<u8> = [0u8; 32].to_vec(); let mut expected_raw: Vec<u8> = [0u8; 32].to_vec();
@ -520,7 +520,7 @@ mod test {
#[should_panic] // 'attempt to add with overflow' in consensus_encode() #[should_panic] // 'attempt to add with overflow' in consensus_encode()
fn test_getblocktx_panic_when_encoding_u64_max() { fn test_getblocktx_panic_when_encoding_u64_max() {
serialize(&BlockTransactionsRequest { serialize(&BlockTransactionsRequest {
block_hash: BlockHash::all_zeros(), block_hash: BlockHash::from_byte_array([0; 32]),
indexes: vec![u64::MAX], indexes: vec![u64::MAX],
}); });
} }

View File

@ -23,20 +23,11 @@ use crate::prelude::Vec;
use crate::script::{self, ScriptExt as _}; use crate::script::{self, ScriptExt as _};
use crate::transaction::{Transaction, Wtxid}; use crate::transaction::{Transaction, Wtxid};
hashes::hash_newtype! { #[rustfmt::skip] // Keep public re-exports separate.
/// A bitcoin block hash. #[doc(inline)]
pub struct BlockHash(sha256d::Hash); pub use primitives::block::*;
/// A hash corresponding to the witness structure commitment in the coinbase transaction.
pub struct WitnessCommitment(sha256d::Hash);
}
impl_hashencode!(BlockHash); 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. /// Bitcoin block header.
/// ///
@ -76,7 +67,7 @@ impl Header {
pub fn block_hash(&self) -> BlockHash { pub fn block_hash(&self) -> BlockHash {
let mut engine = sha256d::Hash::engine(); let mut engine = sha256d::Hash::engine();
self.consensus_encode(&mut engine).expect("engines don't error"); 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. /// 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(); let mut encoder = sha256d::Hash::engine();
witness_root.consensus_encode(&mut encoder).expect("engines don't error"); witness_root.consensus_encode(&mut encoder).expect("engines don't error");
encoder.input(witness_reserved_value); 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. /// Computes the Merkle root of transactions hashed for witness.

View File

@ -113,7 +113,7 @@ pub fn genesis_block(params: impl AsRef<Params>) -> Block {
Network::Bitcoin => Block { Network::Bitcoin => Block {
header: block::Header { header: block::Header {
version: block::Version::ONE, version: block::Version::ONE,
prev_blockhash: BlockHash::all_zeros(), prev_blockhash: BlockHash::GENESIS_PREVIOUS_BLOCK_HASH,
merkle_root, merkle_root,
time: 1231006505, time: 1231006505,
bits: CompactTarget::from_consensus(0x1d00ffff), bits: CompactTarget::from_consensus(0x1d00ffff),
@ -124,7 +124,7 @@ pub fn genesis_block(params: impl AsRef<Params>) -> Block {
Network::Testnet => Block { Network::Testnet => Block {
header: block::Header { header: block::Header {
version: block::Version::ONE, version: block::Version::ONE,
prev_blockhash: BlockHash::all_zeros(), prev_blockhash: BlockHash::GENESIS_PREVIOUS_BLOCK_HASH,
merkle_root, merkle_root,
time: 1296688602, time: 1296688602,
bits: CompactTarget::from_consensus(0x1d00ffff), bits: CompactTarget::from_consensus(0x1d00ffff),
@ -135,7 +135,7 @@ pub fn genesis_block(params: impl AsRef<Params>) -> Block {
Network::Signet => Block { Network::Signet => Block {
header: block::Header { header: block::Header {
version: block::Version::ONE, version: block::Version::ONE,
prev_blockhash: BlockHash::all_zeros(), prev_blockhash: BlockHash::GENESIS_PREVIOUS_BLOCK_HASH,
merkle_root, merkle_root,
time: 1598918400, time: 1598918400,
bits: CompactTarget::from_consensus(0x1e0377ae), bits: CompactTarget::from_consensus(0x1e0377ae),
@ -146,7 +146,7 @@ pub fn genesis_block(params: impl AsRef<Params>) -> Block {
Network::Regtest => Block { Network::Regtest => Block {
header: block::Header { header: block::Header {
version: block::Version::ONE, version: block::Version::ONE,
prev_blockhash: BlockHash::all_zeros(), prev_blockhash: BlockHash::GENESIS_PREVIOUS_BLOCK_HASH,
merkle_root, merkle_root,
time: 1296688602, time: 1296688602,
bits: CompactTarget::from_consensus(0x207fffff), bits: CompactTarget::from_consensus(0x207fffff),
@ -261,7 +261,7 @@ mod test {
let gen = genesis_block(&params::MAINNET); let gen = genesis_block(&params::MAINNET);
assert_eq!(gen.header.version, block::Version::ONE); 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!( assert_eq!(
gen.header.merkle_root.to_string(), gen.header.merkle_root.to_string(),
"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
@ -280,7 +280,7 @@ mod test {
fn testnet_genesis_full_block() { fn testnet_genesis_full_block() {
let gen = genesis_block(&params::TESTNET); let gen = genesis_block(&params::TESTNET);
assert_eq!(gen.header.version, block::Version::ONE); 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!( assert_eq!(
gen.header.merkle_root.to_string(), gen.header.merkle_root.to_string(),
"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
@ -298,7 +298,7 @@ mod test {
fn signet_genesis_full_block() { fn signet_genesis_full_block() {
let gen = genesis_block(&params::SIGNET); let gen = genesis_block(&params::SIGNET);
assert_eq!(gen.header.version, block::Version::ONE); 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!( assert_eq!(
gen.header.merkle_root.to_string(), gen.header.merkle_root.to_string(),
"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"

View File

@ -159,7 +159,7 @@ mod tests {
assert_eq!(real_decode.version, 70002); assert_eq!(real_decode.version, 70002);
assert_eq!(real_decode.locator_hashes.len(), 1); assert_eq!(real_decode.locator_hashes.len(), 1);
assert_eq!(serialize(&real_decode.locator_hashes[0]), genhash); 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); assert_eq!(serialize(&real_decode), from_sat);
} }
@ -175,7 +175,7 @@ mod tests {
assert_eq!(real_decode.version, 70002); assert_eq!(real_decode.version, 70002);
assert_eq!(real_decode.locator_hashes.len(), 1); assert_eq!(real_decode.locator_hashes.len(), 1);
assert_eq!(serialize(&real_decode.locator_hashes[0]), genhash); 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); assert_eq!(serialize(&real_decode), from_sat);
} }

View File

@ -1771,7 +1771,7 @@ mod tests {
// Block 2015, the only information used are `bits` and `time` // Block 2015, the only information used are `bits` and `time`
let current = Header { let current = Header {
version: Version::ONE, version: Version::ONE,
prev_blockhash: BlockHash::all_zeros(), prev_blockhash: BlockHash::from_byte_array([0; 32]),
merkle_root: TxMerkleNode::from_byte_array([0; 32]), merkle_root: TxMerkleNode::from_byte_array([0; 32]),
time: 1599332177, time: 1599332177,
bits: epoch_start.bits, bits: epoch_start.bits,
@ -1793,7 +1793,7 @@ mod tests {
// Block 2016, the only information used is `time` // Block 2016, the only information used is `time`
let epoch_start = Header { let epoch_start = Header {
version: Version::ONE, version: Version::ONE,
prev_blockhash: BlockHash::all_zeros(), prev_blockhash: BlockHash::from_byte_array([0; 32]),
merkle_root: TxMerkleNode::from_byte_array([0; 32]), merkle_root: TxMerkleNode::from_byte_array([0; 32]),
time: 1599332844, time: 1599332844,
bits: starting_bits, bits: starting_bits,
@ -1803,7 +1803,7 @@ mod tests {
// Block 4031, the only information used are `bits` and `time` // Block 4031, the only information used are `bits` and `time`
let current = Header { let current = Header {
version: Version::ONE, version: Version::ONE,
prev_blockhash: BlockHash::all_zeros(), prev_blockhash: BlockHash::from_byte_array([0; 32]),
merkle_root: TxMerkleNode::from_byte_array([0; 32]), merkle_root: TxMerkleNode::from_byte_array([0; 32]),
time: 1600591200, time: 1600591200,
bits: starting_bits, bits: starting_bits,

22
primitives/src/block.rs Normal file
View File

@ -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]);
}

View File

@ -29,6 +29,7 @@ extern crate std;
#[macro_use] #[macro_use]
extern crate serde; extern crate serde;
pub mod block;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
pub mod locktime; pub mod locktime;
pub mod opcodes; pub mod opcodes;
@ -45,6 +46,7 @@ pub use units::*;
pub use self::locktime::{absolute, relative}; pub use self::locktime::{absolute, relative};
#[doc(inline)] #[doc(inline)]
pub use self::{ pub use self::{
block::{BlockHash, WitnessCommitment},
pow::CompactTarget, pow::CompactTarget,
sequence::Sequence, sequence::Sequence,
transaction::{Txid, Wtxid}, transaction::{Txid, Wtxid},