Merge rust-bitcoin/rust-bitcoin#1394: Format the `merkle_tree` module

f55c4099d5 Format the merkle_tree module (Tobin C. Harding)

Pull request description:

  Run `cargo +nightly fmt` and commit the changes to the `merkle_tree` module. No manual changes, only those introduced by `rustfmt`.

ACKs for top commit:
  tcharding:
    ACK f55c4099d5
  apoelstra:
    ACK f55c4099d5

Tree-SHA512: 2f47fc426988b4755408fea5f8c4c47ebe23b53850737a1640fa9477cfd83f0ada046aec734986a92a9effbaaee0f34764ef87d82deff1a594f7b73bf2e93e93
This commit is contained in:
Andrew Poelstra 2022-11-17 14:40:47 +00:00
commit 7d6aa83389
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
2 changed files with 51 additions and 74 deletions

View File

@ -42,18 +42,15 @@
use core::fmt; use core::fmt;
use crate::prelude::*;
use crate::io;
use crate::hashes::Hash;
use crate::hash_types::{Txid, TxMerkleNode};
use crate::blockdata::block::{self, Block}; use crate::blockdata::block::{self, Block};
use crate::blockdata::transaction::Transaction;
use crate::blockdata::constants::{MAX_BLOCK_WEIGHT, MIN_TRANSACTION_WEIGHT}; use crate::blockdata::constants::{MAX_BLOCK_WEIGHT, MIN_TRANSACTION_WEIGHT};
use crate::blockdata::transaction::Transaction;
use crate::consensus::encode::{self, Decodable, Encodable}; use crate::consensus::encode::{self, Decodable, Encodable};
use crate::hash_types::{TxMerkleNode, Txid};
use crate::hashes::Hash;
use crate::io;
use crate::merkle_tree::MerkleBlockError::*; use crate::merkle_tree::MerkleBlockError::*;
use crate::prelude::*;
/// An error when verifying the merkle block. /// An error when verifying the merkle block.
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
@ -139,19 +136,13 @@ pub struct PartialMerkleTree {
impl PartialMerkleTree { impl PartialMerkleTree {
/// Returns the total number of transactions in the block. /// Returns the total number of transactions in the block.
pub fn num_transactions(&self) -> u32 { pub fn num_transactions(&self) -> u32 { self.num_transactions }
self.num_transactions
}
/// Returns the node-is-parent-of-matched-txid bits of the partial merkle tree. /// Returns the node-is-parent-of-matched-txid bits of the partial merkle tree.
pub fn bits(&self) -> &Vec<bool> { pub fn bits(&self) -> &Vec<bool> { &self.bits }
&self.bits
}
/// Returns the transaction ids and internal hashes of the partial merkle tree. /// Returns the transaction ids and internal hashes of the partial merkle tree.
pub fn hashes(&self) -> &Vec<TxMerkleNode> { pub fn hashes(&self) -> &Vec<TxMerkleNode> { &self.hashes }
&self.hashes
}
/// Construct a partial merkle tree /// Construct a partial merkle tree
/// The `txids` are the transaction hashes of the block and the `matches` is the contains flags /// The `txids` are the transaction hashes of the block and the `matches` is the contains flags
@ -372,8 +363,7 @@ impl PartialMerkleTree {
impl Encodable for PartialMerkleTree { impl Encodable for PartialMerkleTree {
fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> { fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
let ret = self.num_transactions.consensus_encode(w)? let ret = self.num_transactions.consensus_encode(w)? + self.hashes.consensus_encode(w)?;
+ self.hashes.consensus_encode(w)?;
let mut bytes: Vec<u8> = vec![0; (self.bits.len() + 7) / 8]; let mut bytes: Vec<u8> = vec![0; (self.bits.len() + 7) / 8];
for p in 0..self.bits.len() { for p in 0..self.bits.len() {
bytes[p / 8] |= (self.bits[p] as u8) << (p % 8) as u8; bytes[p / 8] |= (self.bits[p] as u8) << (p % 8) as u8;
@ -393,11 +383,7 @@ impl Decodable for PartialMerkleTree {
for (p, bit) in bits.iter_mut().enumerate() { for (p, bit) in bits.iter_mut().enumerate() {
*bit = (bytes[p / 8] & (1 << (p % 8) as u8)) != 0; *bit = (bytes[p / 8] & (1 << (p % 8) as u8)) != 0;
} }
Ok(PartialMerkleTree { Ok(PartialMerkleTree { num_transactions, hashes, bits })
num_transactions,
hashes,
bits,
})
} }
} }
@ -453,7 +439,7 @@ impl MerkleBlock {
/// ``` /// ```
pub fn from_block_with_predicate<F>(block: &Block, match_txids: F) -> Self pub fn from_block_with_predicate<F>(block: &Block, match_txids: F) -> Self
where where
F: Fn(&Txid) -> bool F: Fn(&Txid) -> bool,
{ {
let block_txids: Vec<_> = block.txdata.iter().map(Transaction::txid).collect(); let block_txids: Vec<_> = block.txdata.iter().map(Transaction::txid).collect();
Self::from_header_txids_with_predicate(&block.header, &block_txids, match_txids) Self::from_header_txids_with_predicate(&block.header, &block_txids, match_txids)
@ -469,18 +455,12 @@ impl MerkleBlock {
match_txids: F, match_txids: F,
) -> Self ) -> Self
where where
F: Fn(&Txid) -> bool F: Fn(&Txid) -> bool,
{ {
let matches: Vec<bool> = block_txids let matches: Vec<bool> = block_txids.iter().map(match_txids).collect();
.iter()
.map(match_txids)
.collect();
let pmt = PartialMerkleTree::from_txids(block_txids, &matches); let pmt = PartialMerkleTree::from_txids(block_txids, &matches);
MerkleBlock { MerkleBlock { header: *header, txn: pmt }
header: *header,
txn: pmt,
}
} }
/// Extract the matching txid's represented by this partial merkle tree /// Extract the matching txid's represented by this partial merkle tree
@ -503,8 +483,7 @@ impl MerkleBlock {
impl Encodable for MerkleBlock { impl Encodable for MerkleBlock {
fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> { fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
let len = self.header.consensus_encode(w)? let len = self.header.consensus_encode(w)? + self.txn.consensus_encode(w)?;
+ self.txn.consensus_encode(w)?;
Ok(len) Ok(len)
} }
} }
@ -520,22 +499,19 @@ impl Decodable for MerkleBlock {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
use core::cmp::min; use core::cmp::min;
use crate::hashes::Hash;
use crate::hashes::hex::{FromHex, ToHex};
use crate::hash_types::{Txid, TxMerkleNode};
use secp256k1::rand::prelude::*; use secp256k1::rand::prelude::*;
use super::*;
use crate::consensus::encode::{deserialize, serialize}; use crate::consensus::encode::{deserialize, serialize};
use crate::hash_types::{TxMerkleNode, Txid};
use crate::hashes::hex::{FromHex, ToHex};
use crate::hashes::Hash;
use crate::{merkle_tree, 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) { pmt_test(name[9..].parse().unwrap()) }
pmt_test(name[9..].parse().unwrap())
}
macro_rules! pmt_tests { macro_rules! pmt_tests {
($($name:ident),* $(,)?) => { ($($name:ident),* $(,)?) => {
@ -547,8 +523,20 @@ mod tests {
)* )*
} }
} }
pmt_tests!(pmt_test_1, pmt_test_4, pmt_test_7, pmt_test_17, pmt_test_56, pmt_test_100, pmt_tests!(
pmt_test_127, pmt_test_256, pmt_test_312, pmt_test_513, pmt_test_1000, pmt_test_4095); pmt_test_1,
pmt_test_4,
pmt_test_7,
pmt_test_17,
pmt_test_56,
pmt_test_100,
pmt_test_127,
pmt_test_256,
pmt_test_312,
pmt_test_513,
pmt_test_1000,
pmt_test_4095
);
fn pmt_test(tx_count: usize) { fn pmt_test(tx_count: usize) {
let mut rng = thread_rng(); let mut rng = thread_rng();
@ -559,7 +547,8 @@ 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 = merkle_tree::calculate_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 {
@ -616,9 +605,7 @@ mod tests {
let mut pmt3: PartialMerkleTree = deserialize(&serialized).unwrap(); let mut pmt3: PartialMerkleTree = deserialize(&serialized).unwrap();
pmt3.damage(&mut rng); pmt3.damage(&mut rng);
let mut match_txid3 = vec![]; let mut match_txid3 = vec![];
let merkle_root_3 = pmt3 let merkle_root_3 = pmt3.extract_matches(&mut match_txid3, &mut indexes).unwrap();
.extract_matches(&mut match_txid3, &mut indexes)
.unwrap();
assert_ne!(merkle_root_3, merkle_root_1); assert_ne!(merkle_root_3, merkle_root_1);
} }
} }
@ -632,9 +619,8 @@ mod tests {
.map(|i| Txid::from_hex(&format!("{:064x}", i)).unwrap()) .map(|i| Txid::from_hex(&format!("{:064x}", i)).unwrap())
.collect(); .collect();
let matches = vec![ let matches =
false, false, false, false, false, false, false, false, false, true, true, false, vec![false, false, false, false, false, false, false, false, false, true, true, false];
];
let tree = PartialMerkleTree::from_txids(&txids, &matches); let tree = PartialMerkleTree::from_txids(&txids, &matches);
// Should fail due to duplicate txs found // Should fail due to duplicate txs found
@ -690,10 +676,7 @@ mod tests {
let mut index: Vec<u32> = vec![]; let mut index: Vec<u32> = vec![];
assert_eq!( assert_eq!(
merkle_block merkle_block.txn.extract_matches(&mut matches, &mut index).unwrap(),
.txn
.extract_matches(&mut matches, &mut index)
.unwrap(),
block.header.merkle_root block.header.merkle_root
); );
assert_eq!(matches.len(), 2); assert_eq!(matches.len(), 2);
@ -723,10 +706,7 @@ mod tests {
let mut index: Vec<u32> = vec![]; let mut index: Vec<u32> = vec![];
assert_eq!( assert_eq!(
merkle_block merkle_block.txn.extract_matches(&mut matches, &mut index).unwrap(),
.txn
.extract_matches(&mut matches, &mut index)
.unwrap(),
block.header.merkle_root block.header.merkle_root
); );
assert_eq!(matches.len(), 0); assert_eq!(matches.len(), 0);

View File

@ -16,17 +16,15 @@
mod block; mod block;
use core::cmp::min;
use core::iter; use core::iter;
use crate::prelude::*; pub use block::{MerkleBlock, MerkleBlockError, PartialMerkleTree};
use crate::io;
use core::cmp::min;
use crate::hashes::Hash;
use crate::consensus::encode::Encodable; use crate::consensus::encode::Encodable;
use crate::hashes::Hash;
pub use block::{MerkleBlock, PartialMerkleTree, MerkleBlockError}; use crate::io;
use crate::prelude::*;
/// 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`.
/// ///
@ -94,7 +92,7 @@ where
<T as Hash>::Engine: io::Write, <T as Hash>::Engine: io::Write,
{ {
if hashes.len() == 1 { if hashes.len() == 1 {
return hashes[0] return hashes[0];
} }
for idx in 0..((hashes.len() + 1) / 2) { for idx in 0..((hashes.len() + 1) / 2) {
@ -112,12 +110,11 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
use crate::blockdata::block::Block;
use crate::consensus::encode::deserialize; use crate::consensus::encode::deserialize;
use crate::hashes::sha256d; use crate::hashes::sha256d;
use crate::blockdata::block::Block;
use super::*;
#[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