From 05cda9762fed504cce9bc6b30d0a4c7286590df3 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Fri, 15 Nov 2024 19:36:51 +0000 Subject: [PATCH] review fixes --- networks/monero/src/block.rs | 2 +- networks/monero/src/lib.rs | 2 +- networks/monero/src/merkle.rs | 36 +++++++++++++++++++---------------- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/networks/monero/src/block.rs b/networks/monero/src/block.rs index 9b787c613..a0bbe506b 100644 --- a/networks/monero/src/block.rs +++ b/networks/monero/src/block.rs @@ -126,7 +126,7 @@ impl Block { transactions.push(self.miner_transaction.hash()); transactions.extend_from_slice(&self.transactions); - blob.extend_from_slice(&merkle_root(&transactions)); + blob.extend_from_slice(&merkle_root(transactions)); write_varint(&(1 + self.transactions.len()), &mut blob).unwrap(); blob } diff --git a/networks/monero/src/lib.rs b/networks/monero/src/lib.rs index 1af98e68c..e058f6206 100644 --- a/networks/monero/src/lib.rs +++ b/networks/monero/src/lib.rs @@ -7,7 +7,7 @@ pub use monero_io as io; pub use monero_generators as generators; pub use monero_primitives as primitives; -/// Merkel tree functionality. +/// Merkle tree functionality. pub mod merkle; /// Ring Signature structs and functionality. diff --git a/networks/monero/src/merkle.rs b/networks/monero/src/merkle.rs index e052f6c98..8a0f8134b 100644 --- a/networks/monero/src/merkle.rs +++ b/networks/monero/src/merkle.rs @@ -2,25 +2,29 @@ use std_shims::vec::Vec; use crate::primitives::keccak256; -/// Calculates the merkel root of the given tree. Equivalent to `tree_hash` in monero-core. -pub fn merkle_root(leafs: &[[u8; 32]]) -> [u8; 32] { +/// Calculates the Merkle root of the given tree. Equivalent to `tree_hash` in monero-core: +/// https://github.com/monero-project/monero/blob/893916ad091a92e765ce3241b94e706ad012b62a +/// /src/crypto/tree-hash.c#L62 +/// +/// # Panics +/// This function will panic if the tree is empty. +pub fn merkle_root(mut leafs: Vec<[u8; 32]>) -> [u8; 32] { match leafs.len() { + 0 => panic!("Can't compute Merkle root for empty tree"), 1 => leafs[0], 2 => keccak256([leafs[0], leafs[1]].concat()), _ => { - 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 - while high_pow_2 < hashes.len() { + while high_pow_2 < leafs.len() { high_pow_2 *= 2; } let low_pow_2 = high_pow_2 / 2; // Merge right-most hashes until we're at the low_pow_2 { - let overage = hashes.len() - low_pow_2; - let mut rightmost = hashes.drain((low_pow_2 - overage) ..); + let overage = leafs.len() - low_pow_2; + let mut rightmost = leafs.drain((low_pow_2 - overage) ..); // This is true since we took overage from beneath and above low_pow_2, taking twice as // many elements as overage debug_assert_eq!(rightmost.len() % 2, 0); @@ -32,23 +36,23 @@ pub fn merkle_root(leafs: &[[u8; 32]]) -> [u8; 32] { } drop(rightmost); - hashes.extend(paired_hashes); - assert_eq!(hashes.len(), low_pow_2); + leafs.extend(paired_hashes); + assert_eq!(leafs.len(), low_pow_2); } // Do a traditional pairing off - let mut new_hashes = Vec::with_capacity(hashes.len() / 2); - while hashes.len() > 1 { + let mut new_hashes = Vec::with_capacity(leafs.len() / 2); + while leafs.len() > 1 { let mut i = 0; - while i < hashes.len() { - new_hashes.push(keccak256([hashes[i], hashes[i + 1]].concat())); + while i < leafs.len() { + new_hashes.push(keccak256([leafs[i], leafs[i + 1]].concat())); i += 2; } - hashes = new_hashes; - new_hashes = Vec::with_capacity(hashes.len() / 2); + leafs = new_hashes; + new_hashes = Vec::with_capacity(leafs.len() / 2); } - hashes[0] + leafs[0] } } }