use hashing::hash; use tree_hash::{BYTES_PER_CHUNK, HASHSIZE, MERKLE_HASH_CHUNK}; /// Split `values` into a power-of-two, identical-length chunks (padding with `0`) and merkleize /// them, returning the entire merkle tree. /// /// The root hash is `merkleize(values)[0..BYTES_PER_CHUNK]`. pub fn merkleize(values: Vec) -> Vec { let values = sanitise_bytes(values); let leaves = values.len() / HASHSIZE; if leaves == 0 { panic!("No full leaves"); } if !leaves.is_power_of_two() { panic!("leaves is not power of two"); } let mut o: Vec = vec![0; (num_nodes(leaves) - leaves) * HASHSIZE]; o.append(&mut values.to_vec()); let mut i = o.len(); let mut j = o.len() - values.len(); while i >= MERKLE_HASH_CHUNK { i -= MERKLE_HASH_CHUNK; let hash = hash(&o[i..i + MERKLE_HASH_CHUNK]); j -= HASHSIZE; o[j..j + HASHSIZE].copy_from_slice(&hash); } o } pub fn sanitise_bytes(mut bytes: Vec) -> Vec { let present_leaves = num_unsanitized_leaves(bytes.len()); let required_leaves = present_leaves.next_power_of_two(); if (present_leaves != required_leaves) | last_leaf_needs_padding(bytes.len()) { bytes.resize(num_bytes(required_leaves), 0); } bytes } pub fn pad_for_leaf_count(num_leaves: usize, bytes: &mut Vec) { let required_leaves = num_leaves.next_power_of_two(); bytes.resize( bytes.len() + (required_leaves - num_leaves) * BYTES_PER_CHUNK, 0, ); } fn last_leaf_needs_padding(num_bytes: usize) -> bool { num_bytes % HASHSIZE != 0 } /// Rounds up pub fn num_unsanitized_leaves(num_bytes: usize) -> usize { (num_bytes + HASHSIZE - 1) / HASHSIZE } fn num_bytes(num_leaves: usize) -> usize { num_leaves * HASHSIZE } fn num_nodes(num_leaves: usize) -> usize { 2 * num_leaves - 1 } pub fn num_sanitized_leaves(num_bytes: usize) -> usize { let leaves = (num_bytes + HASHSIZE - 1) / HASHSIZE; leaves.next_power_of_two() }