Begin implementing cached hashing in types

This commit is contained in:
Paul Hauner 2019-04-26 15:24:18 +10:00
parent ecff8f0007
commit f65e981f6f
No known key found for this signature in database
GPG Key ID: D362883A9218FCC6
41 changed files with 590 additions and 47 deletions

View File

@ -5,7 +5,7 @@ use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash::TreeHash; use tree_hash::TreeHash;
use tree_hash_derive::{SignedRoot, TreeHash}; use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// Details an attestation that can be slashable. /// Details an attestation that can be slashable.
/// ///
@ -19,6 +19,7 @@ use tree_hash_derive::{SignedRoot, TreeHash};
Encode, Encode,
Decode, Decode,
TreeHash, TreeHash,
CachedTreeHash,
TestRandom, TestRandom,
SignedRoot, SignedRoot,
)] )]
@ -58,4 +59,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(Attestation); ssz_tests!(Attestation);
cached_tree_hash_tests!(Attestation);
} }

View File

@ -5,7 +5,7 @@ use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash::TreeHash; use tree_hash::TreeHash;
use tree_hash_derive::{SignedRoot, TreeHash}; use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// The data upon which an attestation is based. /// The data upon which an attestation is based.
/// ///
@ -21,6 +21,7 @@ use tree_hash_derive::{SignedRoot, TreeHash};
Encode, Encode,
Decode, Decode,
TreeHash, TreeHash,
CachedTreeHash,
TestRandom, TestRandom,
SignedRoot, SignedRoot,
)] )]
@ -47,4 +48,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(AttestationData); ssz_tests!(AttestationData);
cached_tree_hash_tests!(AttestationData);
} }

View File

@ -3,12 +3,12 @@ use crate::test_utils::TestRandom;
use rand::RngCore; use rand::RngCore;
use serde_derive::Serialize; use serde_derive::Serialize;
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use tree_hash_derive::TreeHash; use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Used for pairing an attestation with a proof-of-custody. /// Used for pairing an attestation with a proof-of-custody.
/// ///
/// Spec v0.5.1 /// Spec v0.5.1
#[derive(Debug, Clone, PartialEq, Default, Serialize, Encode, Decode, TreeHash)] #[derive(Debug, Clone, PartialEq, Default, Serialize, Encode, Decode, TreeHash, CachedTreeHash)]
pub struct AttestationDataAndCustodyBit { pub struct AttestationDataAndCustodyBit {
pub data: AttestationData, pub data: AttestationData,
pub custody_bit: bool, pub custody_bit: bool,
@ -28,4 +28,5 @@ mod test {
use super::*; use super::*;
ssz_tests!(AttestationDataAndCustodyBit); ssz_tests!(AttestationDataAndCustodyBit);
cached_tree_hash_tests!(AttestationDataAndCustodyBit);
} }

View File

@ -3,12 +3,23 @@ use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash; use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Two conflicting attestations. /// Two conflicting attestations.
/// ///
/// Spec v0.5.1 /// Spec v0.5.1
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] #[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct AttesterSlashing { pub struct AttesterSlashing {
pub slashable_attestation_1: SlashableAttestation, pub slashable_attestation_1: SlashableAttestation,
pub slashable_attestation_2: SlashableAttestation, pub slashable_attestation_2: SlashableAttestation,
@ -19,4 +30,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(AttesterSlashing); ssz_tests!(AttesterSlashing);
cached_tree_hash_tests!(AttesterSlashing);
} }

View File

@ -6,7 +6,7 @@ use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash::TreeHash; use tree_hash::TreeHash;
use tree_hash_derive::{SignedRoot, TreeHash}; use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// A block of the `BeaconChain`. /// A block of the `BeaconChain`.
/// ///
@ -20,6 +20,7 @@ use tree_hash_derive::{SignedRoot, TreeHash};
Encode, Encode,
Decode, Decode,
TreeHash, TreeHash,
CachedTreeHash,
TestRandom, TestRandom,
SignedRoot, SignedRoot,
)] )]
@ -100,4 +101,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(BeaconBlock); ssz_tests!(BeaconBlock);
cached_tree_hash_tests!(BeaconBlock);
} }

View File

@ -4,12 +4,23 @@ use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash; use tree_hash_derive::{CachedTreeHash, TreeHash};
/// The body of a `BeaconChain` block, containing operations. /// The body of a `BeaconChain` block, containing operations.
/// ///
/// Spec v0.5.1 /// Spec v0.5.1
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] #[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct BeaconBlockBody { pub struct BeaconBlockBody {
pub randao_reveal: Signature, pub randao_reveal: Signature,
pub eth1_data: Eth1Data, pub eth1_data: Eth1Data,
@ -26,4 +37,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(BeaconBlockBody); ssz_tests!(BeaconBlockBody);
cached_tree_hash_tests!(BeaconBlockBody);
} }

View File

@ -6,7 +6,7 @@ use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash::{SignedRoot, TreeHash}; use tree_hash::{SignedRoot, TreeHash};
use tree_hash_derive::{SignedRoot, TreeHash}; use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// A header of a `BeaconBlock`. /// A header of a `BeaconBlock`.
/// ///
@ -20,6 +20,7 @@ use tree_hash_derive::{SignedRoot, TreeHash};
Encode, Encode,
Decode, Decode,
TreeHash, TreeHash,
CachedTreeHash,
TestRandom, TestRandom,
SignedRoot, SignedRoot,
)] )]
@ -59,4 +60,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(BeaconBlockHeader); ssz_tests!(BeaconBlockHeader);
cached_tree_hash_tests!(BeaconBlockHeader);
} }

View File

@ -9,7 +9,7 @@ use ssz::{hash, ssz_encode};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash::TreeHash; use tree_hash::TreeHash;
use tree_hash_derive::TreeHash; use tree_hash_derive::{CachedTreeHash, TreeHash};
mod epoch_cache; mod epoch_cache;
mod pubkey_cache; mod pubkey_cache;
@ -47,7 +47,18 @@ pub enum Error {
/// The state of the `BeaconChain` at some slot. /// The state of the `BeaconChain` at some slot.
/// ///
/// Spec v0.5.1 /// Spec v0.5.1
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, TestRandom, Encode, Decode, TreeHash)] #[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
TestRandom,
Encode,
Decode,
TreeHash,
CachedTreeHash,
)]
pub struct BeaconState { pub struct BeaconState {
// Misc // Misc
pub slot: Slot, pub slot: Slot,

View File

@ -3,6 +3,7 @@ use super::*;
use crate::test_utils::*; use crate::test_utils::*;
ssz_tests!(BeaconState); ssz_tests!(BeaconState);
cached_tree_hash_tests!(BeaconState);
/// Test that /// Test that
/// ///

View File

@ -4,7 +4,7 @@ use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash; use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Specifies the block hash for a shard at an epoch. /// Specifies the block hash for a shard at an epoch.
/// ///
@ -20,6 +20,7 @@ use tree_hash_derive::TreeHash;
Encode, Encode,
Decode, Decode,
TreeHash, TreeHash,
CachedTreeHash,
TestRandom, TestRandom,
)] )]
pub struct Crosslink { pub struct Crosslink {
@ -32,4 +33,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(Crosslink); ssz_tests!(Crosslink);
cached_tree_hash_tests!(Crosslink);
} }

View File

@ -1,9 +1,20 @@
use crate::*; use crate::*;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use tree_hash_derive::TreeHash; use tree_hash_derive::{CachedTreeHash, TreeHash};
#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize, Decode, Encode, TreeHash)] #[derive(
Default,
Clone,
Debug,
PartialEq,
Serialize,
Deserialize,
Decode,
Encode,
TreeHash,
CachedTreeHash,
)]
pub struct CrosslinkCommittee { pub struct CrosslinkCommittee {
pub slot: Slot, pub slot: Slot,
pub shard: Shard, pub shard: Shard,

View File

@ -4,12 +4,23 @@ use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash; use tree_hash_derive::{CachedTreeHash, TreeHash};
/// A deposit to potentially become a beacon chain validator. /// A deposit to potentially become a beacon chain validator.
/// ///
/// Spec v0.5.1 /// Spec v0.5.1
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] #[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct Deposit { pub struct Deposit {
pub proof: TreeHashVector<Hash256>, pub proof: TreeHashVector<Hash256>,
pub index: u64, pub index: u64,
@ -21,4 +32,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(Deposit); ssz_tests!(Deposit);
cached_tree_hash_tests!(Deposit);
} }

View File

@ -4,12 +4,23 @@ use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash; use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Data generated by the deposit contract. /// Data generated by the deposit contract.
/// ///
/// Spec v0.5.1 /// Spec v0.5.1
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] #[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct DepositData { pub struct DepositData {
pub amount: u64, pub amount: u64,
pub timestamp: u64, pub timestamp: u64,
@ -21,4 +32,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(DepositData); ssz_tests!(DepositData);
cached_tree_hash_tests!(DepositData);
} }

View File

@ -6,7 +6,7 @@ use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash::{SignedRoot, TreeHash}; use tree_hash::{SignedRoot, TreeHash};
use tree_hash_derive::{SignedRoot, TreeHash}; use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// The data supplied by the user to the deposit contract. /// The data supplied by the user to the deposit contract.
/// ///
@ -21,6 +21,7 @@ use tree_hash_derive::{SignedRoot, TreeHash};
Decode, Decode,
SignedRoot, SignedRoot,
TreeHash, TreeHash,
CachedTreeHash,
TestRandom, TestRandom,
)] )]
pub struct DepositInput { pub struct DepositInput {
@ -68,6 +69,7 @@ mod tests {
use super::*; use super::*;
ssz_tests!(DepositInput); ssz_tests!(DepositInput);
cached_tree_hash_tests!(DepositInput);
#[test] #[test]
fn can_create_and_validate() { fn can_create_and_validate() {

View File

@ -4,13 +4,23 @@ use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash; use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Contains data obtained from the Eth1 chain. /// Contains data obtained from the Eth1 chain.
/// ///
/// Spec v0.5.1 /// Spec v0.5.1
#[derive( #[derive(
Debug, PartialEq, Clone, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom, Debug,
PartialEq,
Clone,
Default,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)] )]
pub struct Eth1Data { pub struct Eth1Data {
pub deposit_root: Hash256, pub deposit_root: Hash256,
@ -22,4 +32,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(Eth1Data); ssz_tests!(Eth1Data);
cached_tree_hash_tests!(Eth1Data);
} }

View File

@ -4,13 +4,23 @@ use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash; use tree_hash_derive::{CachedTreeHash, TreeHash};
/// A summation of votes for some `Eth1Data`. /// A summation of votes for some `Eth1Data`.
/// ///
/// Spec v0.5.1 /// Spec v0.5.1
#[derive( #[derive(
Debug, PartialEq, Clone, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom, Debug,
PartialEq,
Clone,
Default,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)] )]
pub struct Eth1DataVote { pub struct Eth1DataVote {
pub eth1_data: Eth1Data, pub eth1_data: Eth1Data,
@ -22,4 +32,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(Eth1DataVote); ssz_tests!(Eth1DataVote);
cached_tree_hash_tests!(Eth1DataVote);
} }

View File

@ -7,13 +7,23 @@ use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash; use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Specifies a fork of the `BeaconChain`, to prevent replay attacks. /// Specifies a fork of the `BeaconChain`, to prevent replay attacks.
/// ///
/// Spec v0.5.1 /// Spec v0.5.1
#[derive( #[derive(
Debug, Clone, PartialEq, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom, Debug,
Clone,
PartialEq,
Default,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)] )]
pub struct Fork { pub struct Fork {
#[serde(deserialize_with = "fork_from_hex_str")] #[serde(deserialize_with = "fork_from_hex_str")]
@ -54,6 +64,7 @@ mod tests {
use super::*; use super::*;
ssz_tests!(Fork); ssz_tests!(Fork);
cached_tree_hash_tests!(Fork);
fn test_genesis(version: u32, epoch: Epoch) { fn test_genesis(version: u32, epoch: Epoch) {
let mut spec = ChainSpec::foundation(); let mut spec = ChainSpec::foundation();

View File

@ -4,12 +4,23 @@ use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash; use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Historical block and state roots. /// Historical block and state roots.
/// ///
/// Spec v0.5.1 /// Spec v0.5.1
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] #[derive(
Debug,
Clone,
PartialEq,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct HistoricalBatch { pub struct HistoricalBatch {
pub block_roots: TreeHashVector<Hash256>, pub block_roots: TreeHashVector<Hash256>,
pub state_roots: TreeHashVector<Hash256>, pub state_roots: TreeHashVector<Hash256>,
@ -20,4 +31,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(HistoricalBatch); ssz_tests!(HistoricalBatch);
cached_tree_hash_tests!(HistoricalBatch);
} }

View File

@ -4,12 +4,23 @@ use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash; use tree_hash_derive::{CachedTreeHash, TreeHash};
/// An attestation that has been included in the state but not yet fully processed. /// An attestation that has been included in the state but not yet fully processed.
/// ///
/// Spec v0.5.1 /// Spec v0.5.1
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] #[derive(
Debug,
Clone,
PartialEq,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct PendingAttestation { pub struct PendingAttestation {
pub aggregation_bitfield: Bitfield, pub aggregation_bitfield: Bitfield,
pub data: AttestationData, pub data: AttestationData,
@ -34,4 +45,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(PendingAttestation); ssz_tests!(PendingAttestation);
cached_tree_hash_tests!(PendingAttestation);
} }

View File

@ -4,12 +4,23 @@ use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash; use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Two conflicting proposals from the same proposer (validator). /// Two conflicting proposals from the same proposer (validator).
/// ///
/// Spec v0.5.1 /// Spec v0.5.1
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] #[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct ProposerSlashing { pub struct ProposerSlashing {
pub proposer_index: u64, pub proposer_index: u64,
pub header_1: BeaconBlockHeader, pub header_1: BeaconBlockHeader,
@ -21,4 +32,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(ProposerSlashing); ssz_tests!(ProposerSlashing);
cached_tree_hash_tests!(ProposerSlashing);
} }

View File

@ -4,7 +4,7 @@ use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash::TreeHash; use tree_hash::TreeHash;
use tree_hash_derive::{SignedRoot, TreeHash}; use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// Details an attestation that can be slashable. /// Details an attestation that can be slashable.
/// ///
@ -20,6 +20,7 @@ use tree_hash_derive::{SignedRoot, TreeHash};
Encode, Encode,
Decode, Decode,
TreeHash, TreeHash,
CachedTreeHash,
TestRandom, TestRandom,
SignedRoot, SignedRoot,
)] )]
@ -133,6 +134,7 @@ mod tests {
} }
ssz_tests!(SlashableAttestation); ssz_tests!(SlashableAttestation);
cached_tree_hash_tests!(SlashableAttestation);
fn create_slashable_attestation( fn create_slashable_attestation(
slot_factor: u64, slot_factor: u64,

View File

@ -224,6 +224,26 @@ macro_rules! impl_ssz {
} }
} }
impl cached_tree_hash::CachedTreeHash<$type> for $type {
fn new_tree_hash_cache(
&self,
depth: usize,
) -> Result<cached_tree_hash::TreeHashCache, cached_tree_hash::Error> {
self.0.new_tree_hash_cache(depth)
}
fn tree_hash_cache_schema(&self, depth: usize) -> cached_tree_hash::BTreeSchema {
self.0.tree_hash_cache_schema(depth)
}
fn update_tree_hash_cache(
&self,
cache: &mut cached_tree_hash::TreeHashCache,
) -> Result<(), cached_tree_hash::Error> {
self.0.update_tree_hash_cache(cache)
}
}
impl<T: RngCore> TestRandom<T> for $type { impl<T: RngCore> TestRandom<T> for $type {
fn random_for_test(rng: &mut T) -> Self { fn random_for_test(rng: &mut T) -> Self {
$type::from(u64::random_for_test(rng)) $type::from(u64::random_for_test(rng))
@ -545,6 +565,7 @@ macro_rules! all_tests {
math_between_tests!($type, $type); math_between_tests!($type, $type);
math_tests!($type); math_tests!($type);
ssz_tests!($type); ssz_tests!($type);
cached_tree_hash_tests!($type);
mod u64_tests { mod u64_tests {
use super::*; use super::*;

View File

@ -32,3 +32,29 @@ macro_rules! ssz_tests {
} }
}; };
} }
#[cfg(test)]
#[macro_export]
macro_rules! cached_tree_hash_tests {
($type: ident) => {
#[test]
pub fn test_cached_tree_hash() {
use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng};
use tree_hash::TreeHash;
let mut rng = XorShiftRng::from_seed([42; 16]);
let original = $type::random_for_test(&mut rng);
let mut hasher = cached_tree_hash::CachedTreeHasher::new(&original).unwrap();
assert_eq!(hasher.tree_hash_root().unwrap(), original.tree_hash_root());
let modified = $type::random_for_test(&mut rng);
hasher.update(&modified).unwrap();
assert_eq!(hasher.tree_hash_root().unwrap(), modified.tree_hash_root());
}
};
}

View File

@ -7,7 +7,7 @@ use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash::TreeHash; use tree_hash::TreeHash;
use tree_hash_derive::{SignedRoot, TreeHash}; use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// The data submitted to the deposit contract. /// The data submitted to the deposit contract.
/// ///
@ -20,6 +20,7 @@ use tree_hash_derive::{SignedRoot, TreeHash};
Encode, Encode,
Decode, Decode,
TreeHash, TreeHash,
CachedTreeHash,
TestRandom, TestRandom,
SignedRoot, SignedRoot,
Derivative, Derivative,
@ -42,4 +43,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(Transfer); ssz_tests!(Transfer);
cached_tree_hash_tests!(Transfer);
} }

View File

@ -108,3 +108,25 @@ where
Vec::random_for_test(rng).into() Vec::random_for_test(rng).into()
} }
} }
#[cfg(test)]
mod test {
use super::*;
use tree_hash::TreeHash;
#[test]
pub fn test_cached_tree_hash() {
let original = TreeHashVector::from(vec![1_u64, 2, 3, 4]);
let mut hasher = cached_tree_hash::CachedTreeHasher::new(&original).unwrap();
assert_eq!(hasher.tree_hash_root().unwrap(), original.tree_hash_root());
let modified = TreeHashVector::from(vec![1_u64, 1, 1, 1]);
hasher.update(&modified).unwrap();
assert_eq!(hasher.tree_hash_root().unwrap(), modified.tree_hash_root());
}
}

View File

@ -3,12 +3,23 @@ use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash; use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Information about a `BeaconChain` validator. /// Information about a `BeaconChain` validator.
/// ///
/// Spec v0.5.1 /// Spec v0.5.1
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TestRandom, TreeHash)] #[derive(
Debug,
Clone,
PartialEq,
Serialize,
Deserialize,
Encode,
Decode,
TestRandom,
TreeHash,
CachedTreeHash,
)]
pub struct Validator { pub struct Validator {
pub pubkey: PublicKey, pub pubkey: PublicKey,
pub withdrawal_credentials: Hash256, pub withdrawal_credentials: Hash256,
@ -111,4 +122,5 @@ mod tests {
} }
ssz_tests!(Validator); ssz_tests!(Validator);
cached_tree_hash_tests!(Validator);
} }

View File

@ -5,7 +5,7 @@ use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash::TreeHash; use tree_hash::TreeHash;
use tree_hash_derive::{SignedRoot, TreeHash}; use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// An exit voluntarily submitted a validator who wishes to withdraw. /// An exit voluntarily submitted a validator who wishes to withdraw.
/// ///
@ -19,6 +19,7 @@ use tree_hash_derive::{SignedRoot, TreeHash};
Encode, Encode,
Decode, Decode,
TreeHash, TreeHash,
CachedTreeHash,
TestRandom, TestRandom,
SignedRoot, SignedRoot,
)] )]
@ -34,4 +35,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(VoluntaryExit); ssz_tests!(VoluntaryExit);
cached_tree_hash_tests!(VoluntaryExit);
} }

View File

@ -6,6 +6,7 @@ edition = "2018"
[dependencies] [dependencies]
bls-aggregates = { git = "https://github.com/sigp/signature-schemes", tag = "0.6.1" } bls-aggregates = { git = "https://github.com/sigp/signature-schemes", tag = "0.6.1" }
cached_tree_hash = { path = "../cached_tree_hash" }
hashing = { path = "../hashing" } hashing = { path = "../hashing" }
hex = "0.3" hex = "0.3"
serde = "1.0" serde = "1.0"

View File

@ -2,6 +2,7 @@ use super::{AggregatePublicKey, Signature, BLS_AGG_SIG_BYTE_SIZE};
use bls_aggregates::{ use bls_aggregates::{
AggregatePublicKey as RawAggregatePublicKey, AggregateSignature as RawAggregateSignature, AggregatePublicKey as RawAggregatePublicKey, AggregateSignature as RawAggregateSignature,
}; };
use cached_tree_hash::cached_tree_hash_ssz_encoding_as_vector;
use serde::de::{Deserialize, Deserializer}; use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer}; use serde::ser::{Serialize, Serializer};
use serde_hex::{encode as hex_encode, HexVisitor}; use serde_hex::{encode as hex_encode, HexVisitor};
@ -167,6 +168,7 @@ impl<'de> Deserialize<'de> for AggregateSignature {
} }
tree_hash_ssz_encoding_as_vector!(AggregateSignature); tree_hash_ssz_encoding_as_vector!(AggregateSignature);
cached_tree_hash_ssz_encoding_as_vector!(AggregateSignature, 96);
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View File

@ -1,4 +1,5 @@
use super::{fake_signature::FakeSignature, AggregatePublicKey, BLS_AGG_SIG_BYTE_SIZE}; use super::{fake_signature::FakeSignature, AggregatePublicKey, BLS_AGG_SIG_BYTE_SIZE};
use cached_tree_hash::cached_tree_hash_ssz_encoding_as_vector;
use serde::de::{Deserialize, Deserializer}; use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer}; use serde::ser::{Serialize, Serializer};
use serde_hex::{encode as hex_encode, PrefixedHexVisitor}; use serde_hex::{encode as hex_encode, PrefixedHexVisitor};
@ -100,6 +101,7 @@ impl<'de> Deserialize<'de> for FakeAggregateSignature {
} }
tree_hash_ssz_encoding_as_vector!(FakeAggregateSignature); tree_hash_ssz_encoding_as_vector!(FakeAggregateSignature);
cached_tree_hash_ssz_encoding_as_vector!(FakeAggregateSignature, 96);
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View File

@ -1,4 +1,5 @@
use super::{PublicKey, SecretKey, BLS_SIG_BYTE_SIZE}; use super::{PublicKey, SecretKey, BLS_SIG_BYTE_SIZE};
use cached_tree_hash::cached_tree_hash_ssz_encoding_as_vector;
use hex::encode as hex_encode; use hex::encode as hex_encode;
use serde::de::{Deserialize, Deserializer}; use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer}; use serde::ser::{Serialize, Serializer};
@ -75,6 +76,7 @@ impl Decodable for FakeSignature {
} }
tree_hash_ssz_encoding_as_vector!(FakeSignature); tree_hash_ssz_encoding_as_vector!(FakeSignature);
cached_tree_hash_ssz_encoding_as_vector!(FakeSignature, 96);
impl Serialize for FakeSignature { impl Serialize for FakeSignature {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>

View File

@ -1,5 +1,6 @@
use super::{SecretKey, BLS_PUBLIC_KEY_BYTE_SIZE}; use super::{SecretKey, BLS_PUBLIC_KEY_BYTE_SIZE};
use bls_aggregates::PublicKey as RawPublicKey; use bls_aggregates::PublicKey as RawPublicKey;
use cached_tree_hash::cached_tree_hash_ssz_encoding_as_vector;
use serde::de::{Deserialize, Deserializer}; use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer}; use serde::ser::{Serialize, Serializer};
use serde_hex::{encode as hex_encode, HexVisitor}; use serde_hex::{encode as hex_encode, HexVisitor};
@ -106,6 +107,7 @@ impl<'de> Deserialize<'de> for PublicKey {
} }
tree_hash_ssz_encoding_as_vector!(PublicKey); tree_hash_ssz_encoding_as_vector!(PublicKey);
cached_tree_hash_ssz_encoding_as_vector!(PublicKey, 48);
impl PartialEq for PublicKey { impl PartialEq for PublicKey {
fn eq(&self, other: &PublicKey) -> bool { fn eq(&self, other: &PublicKey) -> bool {
@ -129,6 +131,7 @@ impl Hash for PublicKey {
mod tests { mod tests {
use super::*; use super::*;
use ssz::ssz_encode; use ssz::ssz_encode;
use tree_hash::TreeHash;
#[test] #[test]
pub fn test_ssz_round_trip() { pub fn test_ssz_round_trip() {
@ -140,4 +143,21 @@ mod tests {
assert_eq!(original, decoded); assert_eq!(original, decoded);
} }
#[test]
pub fn test_cached_tree_hash() {
let sk = SecretKey::random();
let original = PublicKey::from_secret_key(&sk);
let mut hasher = cached_tree_hash::CachedTreeHasher::new(&original).unwrap();
assert_eq!(hasher.tree_hash_root().unwrap(), original.tree_hash_root());
let sk = SecretKey::random();
let modified = PublicKey::from_secret_key(&sk);
hasher.update(&modified).unwrap();
assert_eq!(hasher.tree_hash_root().unwrap(), modified.tree_hash_root());
}
} }

View File

@ -1,5 +1,6 @@
use super::{PublicKey, SecretKey, BLS_SIG_BYTE_SIZE}; use super::{PublicKey, SecretKey, BLS_SIG_BYTE_SIZE};
use bls_aggregates::Signature as RawSignature; use bls_aggregates::Signature as RawSignature;
use cached_tree_hash::cached_tree_hash_ssz_encoding_as_vector;
use hex::encode as hex_encode; use hex::encode as hex_encode;
use serde::de::{Deserialize, Deserializer}; use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer}; use serde::ser::{Serialize, Serializer};
@ -116,6 +117,7 @@ impl Decodable for Signature {
} }
tree_hash_ssz_encoding_as_vector!(Signature); tree_hash_ssz_encoding_as_vector!(Signature);
cached_tree_hash_ssz_encoding_as_vector!(Signature, 96);
impl Serialize for Signature { impl Serialize for Signature {
/// Serde serialization is compliant the Ethereum YAML test format. /// Serde serialization is compliant the Ethereum YAML test format.
@ -145,6 +147,7 @@ mod tests {
use super::super::Keypair; use super::super::Keypair;
use super::*; use super::*;
use ssz::ssz_encode; use ssz::ssz_encode;
use tree_hash::TreeHash;
#[test] #[test]
pub fn test_ssz_round_trip() { pub fn test_ssz_round_trip() {
@ -158,6 +161,22 @@ mod tests {
assert_eq!(original, decoded); assert_eq!(original, decoded);
} }
#[test]
pub fn test_cached_tree_hash() {
let keypair = Keypair::random();
let original = Signature::new(&[42, 42], 0, &keypair.sk);
let mut hasher = cached_tree_hash::CachedTreeHasher::new(&original).unwrap();
assert_eq!(hasher.tree_hash_root().unwrap(), original.tree_hash_root());
let modified = Signature::new(&[99, 99], 0, &keypair.sk);
hasher.update(&modified).unwrap();
assert_eq!(hasher.tree_hash_root().unwrap(), modified.tree_hash_root());
}
#[test] #[test]
pub fn test_empty_signature() { pub fn test_empty_signature() {
let sig = Signature::empty_signature(); let sig = Signature::empty_signature();

View File

@ -5,6 +5,7 @@ authors = ["Paul Hauner <paul@paulhauner.com>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
cached_tree_hash = { path = "../cached_tree_hash" }
serde_hex = { path = "../serde_hex" } serde_hex = { path = "../serde_hex" }
ssz = { path = "../ssz" } ssz = { path = "../ssz" }
bit-vec = "0.5.0" bit-vec = "0.5.0"

View File

@ -3,6 +3,7 @@ extern crate ssz;
use bit_reverse::LookupReverse; use bit_reverse::LookupReverse;
use bit_vec::BitVec; use bit_vec::BitVec;
use cached_tree_hash::cached_tree_hash_bytes_as_list;
use serde::de::{Deserialize, Deserializer}; use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer}; use serde::ser::{Serialize, Serializer};
use serde_hex::{encode, PrefixedHexVisitor}; use serde_hex::{encode, PrefixedHexVisitor};
@ -270,11 +271,31 @@ impl tree_hash::TreeHash for BooleanBitfield {
} }
} }
cached_tree_hash_bytes_as_list!(BooleanBitfield);
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use serde_yaml; use serde_yaml;
use ssz::{decode, ssz_encode, SszStream}; use ssz::{decode, ssz_encode, SszStream};
use tree_hash::TreeHash;
#[test]
pub fn test_cached_tree_hash() {
let original = BooleanBitfield::from_bytes(&vec![18; 12][..]);
let mut hasher = cached_tree_hash::CachedTreeHasher::new(&original).unwrap();
assert_eq!(hasher.tree_hash_root().unwrap(), original.tree_hash_root());
/*
let modified = BooleanBitfield::from_bytes(&vec![2; 1][..]);
hasher.update(&modified).unwrap();
assert_eq!(hasher.tree_hash_root().unwrap(), modified.tree_hash_root());
*/
}
#[test] #[test]
fn test_new_bitfield() { fn test_new_bitfield() {

View File

@ -1,12 +1,46 @@
use super::*; use super::*;
use crate::merkleize::merkleize; use crate::merkleize::merkleize;
use ethereum_types::H256;
pub mod vec; pub mod vec;
impl CachedTreeHash<u64> for u64 { macro_rules! impl_for_single_leaf_int {
($type: ident) => {
impl CachedTreeHash<$type> for $type {
fn new_tree_hash_cache(&self, _depth: usize) -> Result<TreeHashCache, Error> {
Ok(TreeHashCache::from_bytes(
merkleize(self.to_le_bytes().to_vec()),
false,
None,
)?)
}
fn tree_hash_cache_schema(&self, depth: usize) -> BTreeSchema {
BTreeSchema::from_lengths(depth, vec![1])
}
fn update_tree_hash_cache(&self, cache: &mut TreeHashCache) -> Result<(), Error> {
let leaf = merkleize(self.to_le_bytes().to_vec());
cache.maybe_update_chunk(cache.chunk_index, &leaf)?;
cache.chunk_index += 1;
Ok(())
}
}
};
}
impl_for_single_leaf_int!(u8);
impl_for_single_leaf_int!(u16);
impl_for_single_leaf_int!(u32);
impl_for_single_leaf_int!(u64);
impl_for_single_leaf_int!(usize);
impl CachedTreeHash<bool> for bool {
fn new_tree_hash_cache(&self, _depth: usize) -> Result<TreeHashCache, Error> { fn new_tree_hash_cache(&self, _depth: usize) -> Result<TreeHashCache, Error> {
Ok(TreeHashCache::from_bytes( Ok(TreeHashCache::from_bytes(
merkleize(self.to_le_bytes().to_vec()), merkleize((*self as u8).to_le_bytes().to_vec()),
false, false,
None, None,
)?) )?)
@ -17,20 +51,19 @@ impl CachedTreeHash<u64> for u64 {
} }
fn update_tree_hash_cache(&self, cache: &mut TreeHashCache) -> Result<(), Error> { fn update_tree_hash_cache(&self, cache: &mut TreeHashCache) -> Result<(), Error> {
let leaf = merkleize(self.to_le_bytes().to_vec()); let leaf = merkleize((*self as u8).to_le_bytes().to_vec());
cache.maybe_update_chunk(cache.chunk_index, &leaf)?; cache.maybe_update_chunk(cache.chunk_index, &leaf)?;
cache.chunk_index += 1; cache.chunk_index += 1;
// cache.overlay_index += 1;
Ok(()) Ok(())
} }
} }
impl CachedTreeHash<usize> for usize { impl CachedTreeHash<[u8; 4]> for [u8; 4] {
fn new_tree_hash_cache(&self, _depth: usize) -> Result<TreeHashCache, Error> { fn new_tree_hash_cache(&self, _depth: usize) -> Result<TreeHashCache, Error> {
Ok(TreeHashCache::from_bytes( Ok(TreeHashCache::from_bytes(
merkleize(self.to_le_bytes().to_vec()), merkleize(self.to_vec()),
false, false,
None, None,
)?) )?)
@ -41,11 +74,33 @@ impl CachedTreeHash<usize> for usize {
} }
fn update_tree_hash_cache(&self, cache: &mut TreeHashCache) -> Result<(), Error> { fn update_tree_hash_cache(&self, cache: &mut TreeHashCache) -> Result<(), Error> {
let leaf = merkleize(self.to_le_bytes().to_vec()); let leaf = merkleize(self.to_vec());
cache.maybe_update_chunk(cache.chunk_index, &leaf)?;
cache.chunk_index += 1;
Ok(())
}
}
impl CachedTreeHash<H256> for H256 {
fn new_tree_hash_cache(&self, _depth: usize) -> Result<TreeHashCache, Error> {
Ok(TreeHashCache::from_bytes(
merkleize(self.as_bytes().to_vec()),
false,
None,
)?)
}
fn tree_hash_cache_schema(&self, depth: usize) -> BTreeSchema {
BTreeSchema::from_lengths(depth, vec![1])
}
fn update_tree_hash_cache(&self, cache: &mut TreeHashCache) -> Result<(), Error> {
let leaf = merkleize(self.as_bytes().to_vec());
cache.maybe_update_chunk(cache.chunk_index, &leaf)?; cache.maybe_update_chunk(cache.chunk_index, &leaf)?;
cache.chunk_index += 1; cache.chunk_index += 1;
// cache.overlay_index += 1;
Ok(()) Ok(())
} }

View File

@ -95,6 +95,11 @@ pub fn update_tree_hash_cache<T: CachedTreeHash<T>>(
let old_overlay = cache.get_overlay(cache.schema_index, cache.chunk_index)?; let old_overlay = cache.get_overlay(cache.schema_index, cache.chunk_index)?;
let new_overlay = BTreeOverlay::new(vec, cache.chunk_index, old_overlay.depth); let new_overlay = BTreeOverlay::new(vec, cache.chunk_index, old_overlay.depth);
dbg!(cache.schema_index);
dbg!(cache.schemas.len());
dbg!(&old_overlay);
dbg!(&new_overlay);
cache.replace_overlay(cache.schema_index, cache.chunk_index, new_overlay.clone())?; cache.replace_overlay(cache.schema_index, cache.chunk_index, new_overlay.clone())?;
cache.schema_index += 1; cache.schema_index += 1;

View File

@ -1,4 +1,5 @@
use hashing::hash; use hashing::hash;
use merkleize::num_unsanitized_leaves;
use std::ops::Range; use std::ops::Range;
use tree_hash::{TreeHash, TreeHashType, BYTES_PER_CHUNK, HASHSIZE}; use tree_hash::{TreeHash, TreeHashType, BYTES_PER_CHUNK, HASHSIZE};
@ -62,3 +63,92 @@ impl CachedTreeHasher {
Ok(self.cache.root()?.to_vec()) Ok(self.cache.root()?.to_vec())
} }
} }
#[macro_export]
macro_rules! cached_tree_hash_ssz_encoding_as_vector {
($type: ident, $num_bytes: expr) => {
impl cached_tree_hash::CachedTreeHash<$type> for $type {
fn new_tree_hash_cache(
&self,
depth: usize,
) -> Result<cached_tree_hash::TreeHashCache, cached_tree_hash::Error> {
let (cache, _schema) = cached_tree_hash::impls::vec::new_tree_hash_cache(
&ssz::ssz_encode(self),
depth,
)?;
Ok(cache)
}
fn tree_hash_cache_schema(&self, depth: usize) -> cached_tree_hash::BTreeSchema {
let lengths =
vec![1; cached_tree_hash::merkleize::num_unsanitized_leaves($num_bytes)];
cached_tree_hash::BTreeSchema::from_lengths(depth, lengths)
}
fn update_tree_hash_cache(
&self,
cache: &mut cached_tree_hash::TreeHashCache,
) -> Result<(), cached_tree_hash::Error> {
cached_tree_hash::impls::vec::update_tree_hash_cache(
&ssz::ssz_encode(self),
cache,
)?;
Ok(())
}
}
};
}
#[macro_export]
macro_rules! cached_tree_hash_bytes_as_list {
($type: ident) => {
impl cached_tree_hash::CachedTreeHash<$type> for $type {
fn new_tree_hash_cache(
&self,
depth: usize,
) -> Result<cached_tree_hash::TreeHashCache, cached_tree_hash::Error> {
let bytes = self.to_bytes();
let (mut cache, schema) =
cached_tree_hash::impls::vec::new_tree_hash_cache(&bytes, depth)?;
cache.add_length_nodes(schema.into_overlay(0).chunk_range(), bytes.len())?;
Ok(cache)
}
fn num_tree_hash_cache_chunks(&self) -> usize {
// Add two extra nodes to cater for the node before and after to allow mixing-in length.
cached_tree_hash::BTreeOverlay::new(self, 0, 0).num_chunks() + 2
}
fn tree_hash_cache_schema(&self, depth: usize) -> cached_tree_hash::BTreeSchema {
cached_tree_hash::impls::vec::produce_schema(&ssz::ssz_encode(self), depth)
}
fn update_tree_hash_cache(
&self,
cache: &mut cached_tree_hash::TreeHashCache,
) -> Result<(), cached_tree_hash::Error> {
let bytes = self.to_bytes();
// Skip the length-mixed-in root node.
cache.chunk_index += 1;
// Update the cache, returning the new overlay.
let new_overlay =
cached_tree_hash::impls::vec::update_tree_hash_cache(&bytes, cache)?;
// Mix in length
cache.mix_in_length(new_overlay.chunk_range(), bytes.len())?;
// Skip an extra node to clear the length node.
cache.chunk_index = new_overlay.next_node() + 1;
Ok(())
}
}
};
}

View File

@ -60,7 +60,7 @@ fn last_leaf_needs_padding(num_bytes: usize) -> bool {
} }
/// Rounds up /// Rounds up
fn num_unsanitized_leaves(num_bytes: usize) -> usize { pub fn num_unsanitized_leaves(num_bytes: usize) -> usize {
(num_bytes + HASHSIZE - 1) / HASHSIZE (num_bytes + HASHSIZE - 1) / HASHSIZE
} }

View File

@ -231,6 +231,41 @@ pub struct StructWithVecOfStructs {
pub c: Vec<Inner>, pub c: Vec<Inner>,
} }
fn get_inners() -> Vec<Inner> {
vec![
Inner {
a: 12,
b: 13,
c: 14,
d: 15,
},
Inner {
a: 99,
b: 100,
c: 101,
d: 102,
},
Inner {
a: 255,
b: 256,
c: 257,
d: 0,
},
Inner {
a: 1000,
b: 2000,
c: 3000,
d: 0,
},
Inner {
a: 0,
b: 0,
c: 0,
d: 0,
},
]
}
fn get_struct_with_vec_of_structs() -> Vec<StructWithVecOfStructs> { fn get_struct_with_vec_of_structs() -> Vec<StructWithVecOfStructs> {
let inner_a = Inner { let inner_a = Inner {
a: 12, a: 12,
@ -342,6 +377,56 @@ fn test_struct_with_vec_of_struct_with_vec_of_structs() {
} }
} }
#[derive(Clone, Debug, TreeHash, CachedTreeHash)]
pub struct StructWithTwoVecs {
pub a: Vec<Inner>,
pub b: Vec<Inner>,
}
#[test]
fn test_struct_with_two_vecs() {
let inners = get_inners();
let variants = vec![
StructWithTwoVecs {
a: inners[..].to_vec(),
b: inners[..].to_vec(),
},
StructWithTwoVecs {
a: inners[0..1].to_vec(),
b: inners[..].to_vec(),
},
StructWithTwoVecs {
a: inners[0..1].to_vec(),
b: inners[0..2].to_vec(),
},
StructWithTwoVecs {
a: inners[0..4].to_vec(),
b: inners[0..2].to_vec(),
},
StructWithTwoVecs {
a: vec![],
b: inners[..].to_vec(),
},
StructWithTwoVecs {
a: inners[..].to_vec(),
b: vec![],
},
StructWithTwoVecs {
a: inners[0..3].to_vec(),
b: inners[0..1].to_vec(),
},
];
test_routine(variants[0].clone(), variants[6..7].to_vec());
/*
for v in &variants {
test_routine(v.clone(), variants.clone());
}
*/
}
#[derive(Clone, Debug, TreeHash, CachedTreeHash)] #[derive(Clone, Debug, TreeHash, CachedTreeHash)]
pub struct Inner { pub struct Inner {
pub a: u64, pub a: u64,

View File

@ -52,7 +52,7 @@ impl TreeHash for bool {
impl TreeHash for [u8; 4] { impl TreeHash for [u8; 4] {
fn tree_hash_type() -> TreeHashType { fn tree_hash_type() -> TreeHashType {
TreeHashType::List TreeHashType::Vector
} }
fn tree_hash_packed_encoding(&self) -> Vec<u8> { fn tree_hash_packed_encoding(&self) -> Vec<u8> {