diff --git a/networks/monero/src/block.rs b/networks/monero/src/block.rs index 15a8d1fc..9b787c61 100644 --- a/networks/monero/src/block.rs +++ b/networks/monero/src/block.rs @@ -121,8 +121,13 @@ impl Block { /// use the [`Block::hash`] function. pub fn serialize_pow_hash(&self) -> Vec { let mut blob = self.header.serialize(); - blob.extend_from_slice(&merkle_root(self.miner_transaction.hash(), &self.transactions)); - write_varint(&(1 + u64::try_from(self.transactions.len()).unwrap()), &mut blob).unwrap(); + + let mut transactions = Vec::with_capacity(self.transactions.len() + 1); + transactions.push(self.miner_transaction.hash()); + transactions.extend_from_slice(&self.transactions); + + blob.extend_from_slice(&merkle_root(&transactions)); + write_varint(&(1 + self.transactions.len()), &mut blob).unwrap(); blob } @@ -132,7 +137,7 @@ impl Block { // Monero pre-appends a VarInt of the block-to-hash'ss length before getting the block hash, // but doesn't do this when getting the proof of work hash :) let mut hashing_blob = Vec::with_capacity(9 + hashable.len()); - write_varint(&u64::try_from(hashable.len()).unwrap(), &mut hashing_blob).unwrap(); + write_varint(&hashable.len(), &mut hashing_blob).unwrap(); hashing_blob.append(&mut hashable); let hash = keccak256(hashing_blob); diff --git a/networks/monero/src/lib.rs b/networks/monero/src/lib.rs index 2eaa63e1..1af98e68 100644 --- a/networks/monero/src/lib.rs +++ b/networks/monero/src/lib.rs @@ -7,7 +7,8 @@ pub use monero_io as io; pub use monero_generators as generators; pub use monero_primitives as primitives; -mod merkle; +/// Merkel tree functionality. +pub mod merkle; /// Ring Signature structs and functionality. pub mod ring_signatures; diff --git a/networks/monero/src/merkle.rs b/networks/monero/src/merkle.rs index 6c689618..e052f6c9 100644 --- a/networks/monero/src/merkle.rs +++ b/networks/monero/src/merkle.rs @@ -2,14 +2,13 @@ use std_shims::vec::Vec; use crate::primitives::keccak256; -pub(crate) fn merkle_root(root: [u8; 32], leafs: &[[u8; 32]]) -> [u8; 32] { +/// Calculates the merkel root of the given tree. Equivalent to `tree_hash` in monero-core. +pub fn merkle_root(leafs: &[[u8; 32]]) -> [u8; 32] { match leafs.len() { - 0 => root, - 1 => keccak256([root, leafs[0]].concat()), + 1 => leafs[0], + 2 => keccak256([leafs[0], leafs[1]].concat()), _ => { - let mut hashes = Vec::with_capacity(1 + leafs.len()); - hashes.push(root); - hashes.extend(leafs); + let mut hashes = leafs.to_vec(); // Monero preprocess this so the length is a power of 2 let mut high_pow_2 = 4; // 4 is the lowest value this can be