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: ACKf55c4099d5
apoelstra: ACKf55c4099d5
Tree-SHA512: 2f47fc426988b4755408fea5f8c4c47ebe23b53850737a1640fa9477cfd83f0ada046aec734986a92a9effbaaee0f34764ef87d82deff1a594f7b73bf2e93e93
This commit is contained in:
commit
7d6aa83389
|
@ -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);
|
||||||
|
|
|
@ -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`.
|
||||||
///
|
///
|
||||||
|
@ -41,7 +39,7 @@ pub use block::{MerkleBlock, PartialMerkleTree, MerkleBlockError};
|
||||||
pub fn calculate_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,
|
||||||
{
|
{
|
||||||
match hashes.len() {
|
match hashes.len() {
|
||||||
0 => None,
|
0 => None,
|
||||||
|
@ -60,7 +58,7 @@ 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,
|
||||||
I: Iterator<Item=T>,
|
I: Iterator<Item = T>,
|
||||||
{
|
{
|
||||||
let first = hashes.next()?;
|
let first = hashes.next()?;
|
||||||
let second = match hashes.next() {
|
let second = match hashes.next() {
|
||||||
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue