Skip to content

Commit

Permalink
review fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Boog900 committed Nov 15, 2024
1 parent 980c5f0 commit 05cda97
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 18 deletions.
2 changes: 1 addition & 1 deletion networks/monero/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion networks/monero/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
36 changes: 20 additions & 16 deletions networks/monero/src/merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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]
}
}
}

0 comments on commit 05cda97

Please sign in to comment.