updated with latest spec changes

This commit is contained in:
mjkeating
2018-12-12 13:48:54 -08:00
parent 1e4e92bf2e
commit be2c82a732
5 changed files with 34 additions and 130 deletions

View File

@@ -6,4 +6,4 @@ authors = ["Paul Hauner <paul@paulhauner.com>"]
[dependencies]
bytes = "0.4.9"
ethereum-types = "0.4.0"
blake2-rfc = "0.2.18"
hashing = { path = "../hashing" }

View File

@@ -1,6 +1,6 @@
extern crate blake2_rfc;
extern crate hashing;
use self::blake2_rfc::blake2b::blake2b;
use self::hashing::canonical_hash;
use super::ethereum_types::{Address, H256};
use super::{merkle_hash, ssz_encode, TreeHash};
use std::cmp::Ord;
@@ -84,11 +84,8 @@ where
}
}
/// From the Spec:
/// We define hash(x) as BLAKE2b-512(x)[0:32]
fn hash(data: &[u8]) -> Vec<u8> {
let result = blake2b(32, &[], &data);
result.as_bytes().to_vec()
canonical_hash(data)
}
#[cfg(test)]
@@ -113,13 +110,12 @@ mod tests {
map.insert("f", 5);
let result = map.tree_hash();
// TODO: resolve inconsistencies between the python sample code and
// the spec; and create tests that tie-out to an offical result
// TODO: create tests that tie-out to an offical result
assert_eq!(
result,
[
59, 110, 242, 24, 177, 184, 73, 109, 190, 19, 172, 39, 74, 94, 224, 198, 0, 170,
225, 152, 249, 59, 10, 76, 137, 124, 52, 159, 37, 42, 26, 157
232, 63, 235, 91, 115, 69, 159, 54, 95, 239, 147, 30, 179, 96, 232, 210, 225, 31,
12, 95, 149, 104, 134, 158, 45, 51, 20, 101, 202, 164, 200, 163
]
);
}

View File

@@ -1,4 +1,4 @@
const CHUNKSIZE: usize = 128;
const SSZ_CHUNK_SIZE: usize = 128;
const HASHSIZE: usize = 32;
pub trait TreeHash {
@@ -9,15 +9,15 @@ pub trait TreeHash {
/// Note that this will consume 'list'.
pub fn merkle_hash(list: &mut Vec<Vec<u8>>) -> Vec<u8> {
// flatten list
let data = &mut list_to_blob(list);
let (chunk_size, mut data) = list_to_blob(list);
// get data_len as bytes. It will hashed will the merkle root
let dlen = data.len() as u64;
let dlen = list.len() as u64;
let data_len_bytes = &mut dlen.tree_hash();
data_len_bytes.resize(32, 0);
// merklize
let mut mhash = hash_level(data, CHUNKSIZE);
let mut mhash = hash_level(&mut data, chunk_size);
while mhash.len() > HASHSIZE {
mhash = hash_level(&mut mhash, HASHSIZE);
}
@@ -33,9 +33,9 @@ fn hash_level(data: &mut Vec<u8>, chunk_size: usize) -> Vec<u8> {
for two_chunks in data.chunks(chunk_size * 2) {
if two_chunks.len() == chunk_size && data.len() > chunk_size {
// if there is only one chunk here, hash it with a zero-byte
// CHUNKSIZE vector
// SSZ_CHUNK_SIZE vector
let mut c = two_chunks.to_vec();
c.append(&mut vec![0; CHUNKSIZE]);
c.append(&mut vec![0; SSZ_CHUNK_SIZE]);
result.append(&mut c.as_slice().tree_hash());
} else {
result.append(&mut two_chunks.tree_hash());
@@ -45,46 +45,30 @@ fn hash_level(data: &mut Vec<u8>, chunk_size: usize) -> Vec<u8> {
result
}
fn list_to_blob(list: &mut Vec<Vec<u8>>) -> Vec<u8> {
if list[0].len().is_power_of_two() == false {
for x in list.iter_mut() {
extend_to_power_of_2(x);
fn list_to_blob(list: &mut Vec<Vec<u8>>) -> (usize, Vec<u8>) {
let chunk_size = if list.is_empty() {
SSZ_CHUNK_SIZE
} else if list[0].len() < SSZ_CHUNK_SIZE {
let items_per_chunk = SSZ_CHUNK_SIZE / list[0].len();
items_per_chunk * list[0].len()
} else {
list[0].len()
};
let mut data = Vec::new();
if list.is_empty() {
// handle and empty list
data.append(&mut vec![0; SSZ_CHUNK_SIZE]);
} else {
// just create a blob here; we'll divide into
// chunked slices when we merklize
data.reserve(list[0].len() * list.len());
for item in list.iter_mut() {
data.append(item);
}
}
let mut data_len = list[0].len() * list.len();
// do we need padding?
let extend_by = if data_len % CHUNKSIZE > 0 {
CHUNKSIZE - (data_len % CHUNKSIZE)
} else {
0
};
// allocate buffer and append each list element (flatten the vec of vecs)
data_len += extend_by;
let mut data: Vec<u8> = Vec::with_capacity(data_len);
for x in list.iter_mut() {
data.append(x);
}
// add padding
let mut i = 0;
while i < extend_by {
data.push(0);
i += 1;
}
data
}
/// Extends data length to a power of 2 by minimally right-zero-padding
fn extend_to_power_of_2(data: &mut Vec<u8>) {
let len = data.len();
let new_len = len.next_power_of_two();
if new_len > len {
data.resize(new_len, 0);
}
(chunk_size, data)
}
#[cfg(test)]
@@ -103,5 +87,4 @@ mod tests {
assert_eq!(HASHSIZE, result.len());
println!("merkle_hash: {:?}", result);
}
}