updated with latest spec changes
This commit is contained in:
parent
1e4e92bf2e
commit
be2c82a732
@ -1,5 +1,3 @@
|
||||
use super::ssz::{merkle_hash, TreeHash};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct ShardAndCommittee {
|
||||
pub shard: u16,
|
||||
@ -17,22 +15,6 @@ impl ShardAndCommittee {
|
||||
}
|
||||
}
|
||||
|
||||
impl TreeHash for ShardAndCommittee {
|
||||
fn tree_hash(&self) -> Vec<u8> {
|
||||
let mut committee_ssz_items = Vec::new();
|
||||
for c in &self.committee {
|
||||
let mut h = (*c as u32).tree_hash();
|
||||
h.resize(3, 0);
|
||||
committee_ssz_items.push(h);
|
||||
}
|
||||
let mut result = Vec::new();
|
||||
result.append(&mut self.shard.tree_hash());
|
||||
result.append(&mut merkle_hash(&mut committee_ssz_items));
|
||||
|
||||
result.as_slice().tree_hash()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -43,15 +25,4 @@ mod tests {
|
||||
assert_eq!(s.shard, 0);
|
||||
assert_eq!(s.committee.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shard_and_committee_tree_hash() {
|
||||
let s = ShardAndCommittee {
|
||||
shard: 1,
|
||||
committee: vec![1, 2, 3],
|
||||
};
|
||||
|
||||
// should test a known hash value
|
||||
assert_eq!(s.tree_hash().len(), 32);
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,6 @@
|
||||
use super::bls::{Keypair, PublicKey};
|
||||
use super::ssz::TreeHash;
|
||||
use super::{Address, Hash256};
|
||||
|
||||
pub const HASH_SSZ_VALIDATOR_RECORD_LENGTH: usize = {
|
||||
32 + // pubkey.to_bytes(32, 'big')
|
||||
2 + // withdrawal_shard.to_bytes(2, 'big')
|
||||
20 + // withdrawal_address
|
||||
32 + // randao_commitment
|
||||
16 + // balance.to_bytes(16, 'big')
|
||||
16 + // start_dynasty.to_bytes(8, 'big')
|
||||
8 // end_dynasty.to_bytes(8, 'big')
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
pub enum ValidatorStatus {
|
||||
PendingActivation = 0,
|
||||
@ -55,32 +44,6 @@ impl ValidatorRecord {
|
||||
}
|
||||
}
|
||||
|
||||
impl TreeHash for ValidatorRecord {
|
||||
fn tree_hash(&self) -> Vec<u8> {
|
||||
let mut ssz = Vec::with_capacity(HASH_SSZ_VALIDATOR_RECORD_LENGTH);
|
||||
|
||||
// From python sample: "val.pubkey.to_bytes(32, 'big')"
|
||||
// TODO:
|
||||
// Need to actually convert (szz) pubkey into a big-endian 32 byte
|
||||
// array.
|
||||
// Also, our ValidatorRecord seems to be missing the start_dynasty
|
||||
// and end_dynasty fields
|
||||
let pub_key_bytes = &mut self.pubkey.as_bytes();
|
||||
pub_key_bytes.resize(32, 0);
|
||||
ssz.append(pub_key_bytes);
|
||||
|
||||
ssz.append(&mut self.withdrawal_shard.tree_hash());
|
||||
ssz.append(&mut self.withdrawal_address.tree_hash());
|
||||
ssz.append(&mut self.randao_commitment.tree_hash());
|
||||
|
||||
let mut balance = self.balance.tree_hash();
|
||||
balance.resize(16, 0);
|
||||
ssz.append(&mut balance);
|
||||
|
||||
ssz.as_slice().tree_hash()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -96,13 +59,4 @@ mod tests {
|
||||
assert_eq!(v.status, 0);
|
||||
assert_eq!(v.exit_slot, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_validator_record_ree_hash() {
|
||||
let (v, _kp) = ValidatorRecord::zero_with_thread_rand_keypair();
|
||||
let h = v.tree_hash();
|
||||
|
||||
// TODO: should check a known hash result value
|
||||
assert_eq!(h.len(), 32);
|
||||
}
|
||||
}
|
||||
|
@ -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" }
|
@ -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
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user