Further tidy tree_hash crate.

This commit is contained in:
Paul Hauner 2019-04-26 10:37:50 +10:00
parent 461f3d2382
commit f1d8224d89
No known key found for this signature in database
GPG Key ID: D362883A9218FCC6
5 changed files with 79 additions and 76 deletions

View File

@ -1,5 +1,7 @@
use super::*;
use crate::merkleize::merkle_root;
use ethereum_types::H256;
use hashing::hash;
use int_to_bytes::int_to_bytes32;
macro_rules! impl_for_bitsize {

View File

@ -1,6 +1,5 @@
use hashing::hash;
pub mod impls;
pub mod merkleize;
pub const BYTES_PER_CHUNK: usize = 32;
pub const HASHSIZE: usize = 32;
@ -28,73 +27,6 @@ pub trait SignedRoot: TreeHash {
fn signed_root(&self) -> Vec<u8>;
}
pub fn merkle_root(bytes: &[u8]) -> Vec<u8> {
// TODO: replace this with a more memory efficient method.
efficient_merkleize(&bytes)[0..32].to_vec()
}
pub fn efficient_merkleize(bytes: &[u8]) -> Vec<u8> {
// If the bytes are just one chunk (or less than one chunk) just return them.
if bytes.len() <= HASHSIZE {
let mut o = bytes.to_vec();
o.resize(HASHSIZE, 0);
return o;
}
let leaves = num_sanitized_leaves(bytes.len());
let nodes = num_nodes(leaves);
let internal_nodes = nodes - leaves;
let num_bytes = std::cmp::max(internal_nodes, 1) * HASHSIZE + bytes.len();
let mut o: Vec<u8> = vec![0; internal_nodes * HASHSIZE];
o.append(&mut bytes.to_vec());
assert_eq!(o.len(), num_bytes);
let empty_chunk_hash = hash(&[0; MERKLE_HASH_CHUNK]);
let mut i = nodes * HASHSIZE;
let mut j = internal_nodes * HASHSIZE;
while i >= MERKLE_HASH_CHUNK {
i -= MERKLE_HASH_CHUNK;
j -= HASHSIZE;
let hash = match o.get(i..i + MERKLE_HASH_CHUNK) {
// All bytes are available, hash as ususal.
Some(slice) => hash(slice),
// Unable to get all the bytes.
None => {
match o.get(i..) {
// Able to get some of the bytes, pad them out.
Some(slice) => {
let mut bytes = slice.to_vec();
bytes.resize(MERKLE_HASH_CHUNK, 0);
hash(&bytes)
}
// Unable to get any bytes, use the empty-chunk hash.
None => empty_chunk_hash.clone(),
}
}
};
o[j..j + HASHSIZE].copy_from_slice(&hash);
}
o
}
fn num_sanitized_leaves(num_bytes: usize) -> usize {
let leaves = (num_bytes + HASHSIZE - 1) / HASHSIZE;
leaves.next_power_of_two()
}
fn num_nodes(num_leaves: usize) -> usize {
2 * num_leaves - 1
}
#[macro_export]
macro_rules! tree_hash_ssz_encoding_as_vector {
($type: ident) => {
@ -112,7 +44,7 @@ macro_rules! tree_hash_ssz_encoding_as_vector {
}
fn tree_hash_root(&self) -> Vec<u8> {
tree_hash::merkle_root(&ssz::ssz_encode(self))
tree_hash::merkleize::merkle_root(&ssz::ssz_encode(self))
}
}
};

View File

@ -0,0 +1,69 @@
use super::*;
use hashing::hash;
pub fn merkle_root(bytes: &[u8]) -> Vec<u8> {
// TODO: replace this with a more memory efficient method.
efficient_merkleize(&bytes)[0..32].to_vec()
}
pub fn efficient_merkleize(bytes: &[u8]) -> Vec<u8> {
// If the bytes are just one chunk (or less than one chunk) just return them.
if bytes.len() <= HASHSIZE {
let mut o = bytes.to_vec();
o.resize(HASHSIZE, 0);
return o;
}
let leaves = num_sanitized_leaves(bytes.len());
let nodes = num_nodes(leaves);
let internal_nodes = nodes - leaves;
let num_bytes = std::cmp::max(internal_nodes, 1) * HASHSIZE + bytes.len();
let mut o: Vec<u8> = vec![0; internal_nodes * HASHSIZE];
o.append(&mut bytes.to_vec());
assert_eq!(o.len(), num_bytes);
let empty_chunk_hash = hash(&[0; MERKLE_HASH_CHUNK]);
let mut i = nodes * HASHSIZE;
let mut j = internal_nodes * HASHSIZE;
while i >= MERKLE_HASH_CHUNK {
i -= MERKLE_HASH_CHUNK;
j -= HASHSIZE;
let hash = match o.get(i..i + MERKLE_HASH_CHUNK) {
// All bytes are available, hash as ususal.
Some(slice) => hash(slice),
// Unable to get all the bytes.
None => {
match o.get(i..) {
// Able to get some of the bytes, pad them out.
Some(slice) => {
let mut bytes = slice.to_vec();
bytes.resize(MERKLE_HASH_CHUNK, 0);
hash(&bytes)
}
// Unable to get any bytes, use the empty-chunk hash.
None => empty_chunk_hash.clone(),
}
}
};
o[j..j + HASHSIZE].copy_from_slice(&hash);
}
o
}
fn num_sanitized_leaves(num_bytes: usize) -> usize {
let leaves = (num_bytes + HASHSIZE - 1) / HASHSIZE;
leaves.next_power_of_two()
}
fn num_nodes(num_leaves: usize) -> usize {
2 * num_leaves - 1
}

View File

@ -149,7 +149,7 @@ pub fn tree_hash_derive(input: TokenStream) -> TokenStream {
leaves.append(&mut self.#idents.tree_hash_root());
)*
tree_hash::merkle_root(&leaves)
tree_hash::merkleize::merkle_root(&leaves)
}
}
};
@ -179,7 +179,7 @@ pub fn tree_hash_signed_root_derive(input: TokenStream) -> TokenStream {
leaves.append(&mut self.#idents.tree_hash_root());
)*
tree_hash::merkle_root(&leaves)
tree_hash::merkleize::merkle_root(&leaves)
}
}
};

View File

@ -1,5 +1,5 @@
use cached_tree_hash::{CachedTreeHash, CachedTreeHasher};
use tree_hash::{SignedRoot, TreeHash};
use tree_hash::{merkleize::merkle_root, SignedRoot, TreeHash};
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
#[derive(Clone, Debug, TreeHash, CachedTreeHash)]
@ -120,7 +120,7 @@ impl CryptoKitties {
leaves.append(&mut self.best_kitty.tree_hash_root());
leaves.append(&mut self.worst_kitty.tree_hash_root());
leaves.append(&mut self.kitties.tree_hash_root());
tree_hash::merkle_root(&leaves)
merkle_root(&leaves)
}
}
@ -158,14 +158,14 @@ impl Casper {
let mut list = Vec::new();
list.append(&mut self.friendly.tree_hash_root());
list.append(&mut self.friends.tree_hash_root());
tree_hash::merkle_root(&list)
merkle_root(&list)
}
fn expected_tree_hash(&self) -> Vec<u8> {
let mut list = Vec::new();
list.append(&mut self.friendly.tree_hash_root());
list.append(&mut self.dead.tree_hash_root());
tree_hash::merkle_root(&list)
merkle_root(&list)
}
}