diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs index 9ab112a8..143bc208 100644 --- a/bitcoin/src/blockdata/block.rs +++ b/bitcoin/src/blockdata/block.rs @@ -13,9 +13,8 @@ use crate::prelude::*; use core::fmt; -use crate::util; +use crate::{merkle_tree, util}; use crate::util::Error::{BlockBadTarget, BlockBadProofOfWork}; -use crate::util::hash::bitcoin_merkle_root; use crate::hashes::{Hash, HashEngine}; use crate::hash_types::{Wtxid, BlockHash, TxMerkleNode, WitnessMerkleNode, WitnessCommitment}; use crate::consensus::{encode, Encodable, Decodable}; @@ -235,7 +234,7 @@ impl Block { /// Computes the transaction merkle root. pub fn compute_merkle_root(&self) -> Option { 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. @@ -256,7 +255,7 @@ impl Block { 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. diff --git a/bitcoin/src/lib.rs b/bitcoin/src/lib.rs index a7dfc845..1f42d543 100644 --- a/bitcoin/src/lib.rs +++ b/bitcoin/src/lib.rs @@ -92,6 +92,7 @@ pub mod blockdata; pub mod consensus; pub mod error; pub mod hash_types; +pub mod merkle_tree; pub mod policy; pub mod pow; pub mod sighash; diff --git a/bitcoin/src/util/hash.rs b/bitcoin/src/merkle_tree.rs similarity index 78% rename from bitcoin/src/util/hash.rs rename to bitcoin/src/merkle_tree.rs index 79f75c77..a9cfb385 100644 --- a/bitcoin/src/util/hash.rs +++ b/bitcoin/src/merkle_tree.rs @@ -1,11 +1,18 @@ // Written in 2014 by Andrew Poelstra // SPDX-License-Identifier: CC0-1.0 -//! Bitcoin hash functions. +//! Bitcoin merkle tree functions. //! -//! This module provides utility functions related to hashing data, including -//! merkleization. +//! # Examples //! +//! ``` +//! # 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; @@ -19,13 +26,15 @@ use crate::consensus::encode::Encodable; /// 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 /// - `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(merkle_root)` if length of `hashes` is greater than one. -pub fn bitcoin_merkle_root_inline(hashes: &mut [T]) -> Option +pub fn calculate_root_inline(hashes: &mut [T]) -> Option where T: Hash + Encodable, ::Engine: io::Write, @@ -43,7 +52,7 @@ where /// - `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(merkle_root)` if length of `hashes` is greater than one. -pub fn bitcoin_merkle_root(mut hashes: I) -> Option +pub fn calculate_root(mut hashes: I) -> Option where T: Hash + Encodable, ::Engine: io::Write, @@ -108,7 +117,7 @@ mod tests { #[test] fn both_merkle_root_functions_return_the_same_result() { // 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"); assert!(block.check_merkle_root()); // Sanity check. @@ -119,8 +128,8 @@ mod tests { hashes_array[i] = hash; } - let from_iter = bitcoin_merkle_root(hashes_iter); - let from_array = bitcoin_merkle_root_inline(&mut hashes_array); + let from_iter = calculate_root(hashes_iter); + let from_array = calculate_root_inline(&mut hashes_array); assert_eq!(from_iter, from_array); } } diff --git a/bitcoin/src/util/merkleblock.rs b/bitcoin/src/util/merkleblock.rs index b1f9fd36..057cb0ba 100644 --- a/bitcoin/src/util/merkleblock.rs +++ b/bitcoin/src/util/merkleblock.rs @@ -528,9 +528,8 @@ mod tests { use secp256k1::rand::prelude::*; use crate::consensus::encode::{deserialize, serialize}; - use crate::util::hash::bitcoin_merkle_root; use crate::util::merkleblock::{MerkleBlock, PartialMerkleTree}; - use crate::Block; + use crate::{merkle_tree, Block}; /// accepts `pmt_test_$num` fn pmt_test_from_name(name: &str) { @@ -559,7 +558,7 @@ mod tests { // Calculate the merkle root and height 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 ntx = tx_count; while ntx > 1 { diff --git a/bitcoin/src/util/mod.rs b/bitcoin/src/util/mod.rs index 3f96ab3e..06ea34ba 100644 --- a/bitcoin/src/util/mod.rs +++ b/bitcoin/src/util/mod.rs @@ -11,7 +11,6 @@ pub mod ecdsa; pub mod schnorr; pub mod amount; pub mod base58; -pub mod hash; pub mod merkleblock; pub mod psbt; pub mod taproot; @@ -95,6 +94,34 @@ pub use crate::bip32; #[deprecated(since = "0.30.0", note = "Please 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(hashes: &mut [T]) -> Option + where + T: Hash + Encodable, + ::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(hashes: I) -> Option + where + T: Hash + Encodable, + ::Engine: io::Write, + I: Iterator, + { + merkle_tree::calculate_root(hashes) + } +} + /// The `misc` module was moved and re-named to `sign_message`. pub mod misc { use crate::prelude::*;