Merge rust-bitcoin/rust-bitcoin#1334: Rename `hash` module to `merkle_root`

29df410ea3 Document state after call to calculate_root_inline (Tobin C. Harding)
2dbc7fdf21 Rename merkle_root functions (Tobin C. Harding)
22dd904735 Rename util::hash module (Tobin C. Harding)

Pull request description:

  Done as part of flattening `util`.

  The `util::hash` module only provides two functions, both to calculate the merkle root of a list of hashes.

  1. Rename `util::hash` -> `crate::merkle_root`
  2. Change function names to `calculate[_inline]` so usage becomes `merkle_root::calculate`

  Done as two separate patches so we can bikeshed the names, can squash if needed.

ACKs for top commit:
  Kixunil:
    ACK 29df410ea3
  apoelstra:
    ACK 29df410ea3

Tree-SHA512: 17ace90c7700b5d7adf8b95731c9a348b5c92863806cc88bc40730547f457e44160efb19985e025970b59fea86d68f0bf4be0af17717a65ae44f11c8d10ec4c6
This commit is contained in:
Andrew Poelstra 2022-11-04 14:32:43 +00:00
commit b27169979b
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
5 changed files with 52 additions and 17 deletions

View File

@ -13,9 +13,8 @@ use crate::prelude::*;
use core::fmt; use core::fmt;
use crate::util; use crate::{merkle_tree, util};
use crate::util::Error::{BlockBadTarget, BlockBadProofOfWork}; use crate::util::Error::{BlockBadTarget, BlockBadProofOfWork};
use crate::util::hash::bitcoin_merkle_root;
use crate::hashes::{Hash, HashEngine}; use crate::hashes::{Hash, HashEngine};
use crate::hash_types::{Wtxid, BlockHash, TxMerkleNode, WitnessMerkleNode, WitnessCommitment}; use crate::hash_types::{Wtxid, BlockHash, TxMerkleNode, WitnessMerkleNode, WitnessCommitment};
use crate::consensus::{encode, Encodable, Decodable}; use crate::consensus::{encode, Encodable, Decodable};
@ -235,7 +234,7 @@ impl Block {
/// Computes the transaction merkle root. /// Computes the transaction merkle root.
pub fn compute_merkle_root(&self) -> Option<TxMerkleNode> { pub fn compute_merkle_root(&self) -> Option<TxMerkleNode> {
let hashes = self.txdata.iter().map(|obj| obj.txid().as_hash()); let hashes = self.txdata.iter().map(|obj| obj.txid().as_hash());
bitcoin_merkle_root(hashes).map(|h| h.into()) merkle_tree::calculate_root(hashes).map(|h| h.into())
} }
/// Computes the witness commitment for the block's transaction list. /// Computes the witness commitment for the block's transaction list.
@ -256,7 +255,7 @@ impl Block {
t.wtxid().as_hash() t.wtxid().as_hash()
} }
}); });
bitcoin_merkle_root(hashes).map(|h| h.into()) merkle_tree::calculate_root(hashes).map(|h| h.into())
} }
/// base_size == size of header + size of encoded transaction count. /// base_size == size of header + size of encoded transaction count.

View File

@ -92,6 +92,7 @@ pub mod blockdata;
pub mod consensus; pub mod consensus;
pub mod error; pub mod error;
pub mod hash_types; pub mod hash_types;
pub mod merkle_tree;
pub mod policy; pub mod policy;
pub mod pow; pub mod pow;
pub mod sighash; pub mod sighash;

View File

@ -1,11 +1,18 @@
// Written in 2014 by Andrew Poelstra <apoelstra@wpsoftware.net> // Written in 2014 by Andrew Poelstra <apoelstra@wpsoftware.net>
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
//! Bitcoin hash functions. //! Bitcoin merkle tree functions.
//! //!
//! This module provides utility functions related to hashing data, including //! # Examples
//! merkleization.
//! //!
//! ```
//! # use bitcoin::{merkle_tree, Txid};
//! # use bitcoin::hashes::Hash;
//! # let tx1 = Txid::all_zeros(); // Dummy hash values.
//! # let tx2 = Txid::all_zeros();
//! let tx_hashes = vec![tx1, tx2]; // All the hashes we wish to merkelize.
//! let root = merkle_tree::calculate_root(tx_hashes.into_iter());
//! ```
use core::iter; use core::iter;
@ -19,13 +26,15 @@ use crate::consensus::encode::Encodable;
/// Calculates the merkle root of a list of *hashes*, inline (in place) in `hashes`. /// Calculates the merkle root of a list of *hashes*, inline (in place) in `hashes`.
/// ///
/// In most cases, you'll want to use [bitcoin_merkle_root] instead. /// In most cases, you'll want to use [`calculate_root`] instead. Please note, calling this function
/// trashes the data in `hashes` (i.e. the `hashes` is left in an undefined state at conclusion of
/// this method and should not be used again afterwards).
/// ///
/// # Returns /// # Returns
/// - `None` if `hashes` is empty. The merkle root of an empty tree of hashes is undefined. /// - `None` if `hashes` is empty. The merkle root of an empty tree of hashes is undefined.
/// - `Some(hash)` if `hashes` contains one element. A single hash is by definition the merkle root. /// - `Some(hash)` if `hashes` contains one element. A single hash is by definition the merkle root.
/// - `Some(merkle_root)` if length of `hashes` is greater than one. /// - `Some(merkle_root)` if length of `hashes` is greater than one.
pub fn bitcoin_merkle_root_inline<T>(hashes: &mut [T]) -> Option<T> pub fn calculate_root_inline<T>(hashes: &mut [T]) -> Option<T>
where where
T: Hash + Encodable, T: Hash + Encodable,
<T as Hash>::Engine: io::Write, <T as Hash>::Engine: io::Write,
@ -43,7 +52,7 @@ where
/// - `None` if `hashes` is empty. The merkle root of an empty tree of hashes is undefined. /// - `None` if `hashes` is empty. The merkle root of an empty tree of hashes is undefined.
/// - `Some(hash)` if `hashes` contains one element. A single hash is by definition the merkle root. /// - `Some(hash)` if `hashes` contains one element. A single hash is by definition the merkle root.
/// - `Some(merkle_root)` if length of `hashes` is greater than one. /// - `Some(merkle_root)` if length of `hashes` is greater than one.
pub fn bitcoin_merkle_root<T, I>(mut hashes: I) -> Option<T> pub fn calculate_root<T, I>(mut hashes: I) -> Option<T>
where where
T: Hash + Encodable, T: Hash + Encodable,
<T as Hash>::Engine: io::Write, <T as Hash>::Engine: io::Write,
@ -108,7 +117,7 @@ mod tests {
#[test] #[test]
fn both_merkle_root_functions_return_the_same_result() { fn both_merkle_root_functions_return_the_same_result() {
// testnet block 000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b // testnet block 000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b
let segwit_block = include_bytes!("../../tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw"); let segwit_block = include_bytes!("../tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw");
let block: Block = deserialize(&segwit_block[..]).expect("Failed to deserialize block"); let block: Block = deserialize(&segwit_block[..]).expect("Failed to deserialize block");
assert!(block.check_merkle_root()); // Sanity check. assert!(block.check_merkle_root()); // Sanity check.
@ -119,8 +128,8 @@ mod tests {
hashes_array[i] = hash; hashes_array[i] = hash;
} }
let from_iter = bitcoin_merkle_root(hashes_iter); let from_iter = calculate_root(hashes_iter);
let from_array = bitcoin_merkle_root_inline(&mut hashes_array); let from_array = calculate_root_inline(&mut hashes_array);
assert_eq!(from_iter, from_array); assert_eq!(from_iter, from_array);
} }
} }

View File

@ -528,9 +528,8 @@ mod tests {
use secp256k1::rand::prelude::*; use secp256k1::rand::prelude::*;
use crate::consensus::encode::{deserialize, serialize}; use crate::consensus::encode::{deserialize, serialize};
use crate::util::hash::bitcoin_merkle_root;
use crate::util::merkleblock::{MerkleBlock, PartialMerkleTree}; use crate::util::merkleblock::{MerkleBlock, PartialMerkleTree};
use crate::Block; use crate::{merkle_tree, Block};
/// accepts `pmt_test_$num` /// accepts `pmt_test_$num`
fn pmt_test_from_name(name: &str) { fn pmt_test_from_name(name: &str) {
@ -559,7 +558,7 @@ mod tests {
// Calculate the merkle root and height // Calculate the merkle root and height
let hashes = tx_ids.iter().map(|t| t.as_hash()); let hashes = tx_ids.iter().map(|t| t.as_hash());
let merkle_root_1: TxMerkleNode = bitcoin_merkle_root(hashes).expect("hashes is not empty").into(); let merkle_root_1: TxMerkleNode = merkle_tree::calculate_root(hashes).expect("hashes is not empty").into();
let mut height = 1; let mut height = 1;
let mut ntx = tx_count; let mut ntx = tx_count;
while ntx > 1 { while ntx > 1 {

View File

@ -11,7 +11,6 @@ pub mod ecdsa;
pub mod schnorr; pub mod schnorr;
pub mod amount; pub mod amount;
pub mod base58; pub mod base58;
pub mod hash;
pub mod merkleblock; pub mod merkleblock;
pub mod psbt; pub mod psbt;
pub mod taproot; pub mod taproot;
@ -95,6 +94,34 @@ pub use crate::bip32;
#[deprecated(since = "0.30.0", note = "Please use crate::bip158")] #[deprecated(since = "0.30.0", note = "Please use crate::bip158")]
pub use crate::bip158; pub use crate::bip158;
/// Functions from the `hash` module were renamed and moved to `../merkle_tree`.
pub mod hash {
use crate::consensus::encode::Encodable;
use crate::hashes::Hash;
use crate::{io, merkle_tree};
/// Calculates the merkle root of a list of *hashes*, inline (in place) in `hashes`.
#[deprecated(since = "0.30.0", note = "Please use crate::merkle_tree::calculate_root_inline")]
pub fn bitcoin_merkle_root_inline<T>(hashes: &mut [T]) -> Option<T>
where
T: Hash + Encodable,
<T as Hash>::Engine: io::Write,
{
crate::merkle_tree::calculate_root_inline(hashes)
}
/// Calculates the merkle root of an iterator of *hashes*.
#[deprecated(since = "0.30.0", note = "Please use crate::merkle_tree::calculate_root")]
pub fn bitcoin_merkle_root<T, I>(hashes: I) -> Option<T>
where
T: Hash + Encodable,
<T as Hash>::Engine: io::Write,
I: Iterator<Item=T>,
{
merkle_tree::calculate_root(hashes)
}
}
/// The `misc` module was moved and re-named to `sign_message`. /// The `misc` module was moved and re-named to `sign_message`.
pub mod misc { pub mod misc {
use crate::prelude::*; use crate::prelude::*;