Implement new BeaconStateTypes
trait in types
This commit is contained in:
parent
009d05cafd
commit
5ba069c774
@ -10,6 +10,7 @@ members = [
|
|||||||
"eth2/utils/bls",
|
"eth2/utils/bls",
|
||||||
"eth2/utils/boolean-bitfield",
|
"eth2/utils/boolean-bitfield",
|
||||||
"eth2/utils/cached_tree_hash",
|
"eth2/utils/cached_tree_hash",
|
||||||
|
"eth2/utils/fixed_len_vec",
|
||||||
"eth2/utils/hashing",
|
"eth2/utils/hashing",
|
||||||
"eth2/utils/honey-badger-split",
|
"eth2/utils/honey-badger-split",
|
||||||
"eth2/utils/merkle_proof",
|
"eth2/utils/merkle_proof",
|
||||||
|
@ -11,6 +11,7 @@ cached_tree_hash = { path = "../utils/cached_tree_hash" }
|
|||||||
dirs = "1.0"
|
dirs = "1.0"
|
||||||
derivative = "1.0"
|
derivative = "1.0"
|
||||||
ethereum-types = "0.5"
|
ethereum-types = "0.5"
|
||||||
|
fixed_len_vec = { path = "../utils/fixed_len_vec" }
|
||||||
hashing = { path = "../utils/hashing" }
|
hashing = { path = "../utils/hashing" }
|
||||||
hex = "0.3"
|
hex = "0.3"
|
||||||
honey-badger-split = { path = "../utils/honey-badger-split" }
|
honey-badger-split = { path = "../utils/honey-badger-split" }
|
||||||
@ -29,7 +30,6 @@ swap_or_not_shuffle = { path = "../utils/swap_or_not_shuffle" }
|
|||||||
test_random_derive = { path = "../utils/test_random_derive" }
|
test_random_derive = { path = "../utils/test_random_derive" }
|
||||||
tree_hash = { path = "../utils/tree_hash" }
|
tree_hash = { path = "../utils/tree_hash" }
|
||||||
tree_hash_derive = { path = "../utils/tree_hash_derive" }
|
tree_hash_derive = { path = "../utils/tree_hash_derive" }
|
||||||
typenum = "1.10"
|
|
||||||
libp2p = { git = "https://github.com/SigP/rust-libp2p", rev = "b3c32d9a821ae6cc89079499cc6e8a6bab0bffc3" }
|
libp2p = { git = "https://github.com/SigP/rust-libp2p", rev = "b3c32d9a821ae6cc89079499cc6e8a6bab0bffc3" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::{AggregateSignature, AttestationData, Bitfield};
|
use super::{AggregateSignature, AttestationData, Bitfield};
|
||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
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;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
use crate::{Crosslink, Epoch, Hash256, Slot};
|
use crate::{Crosslink, Epoch, Hash256, Slot};
|
||||||
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;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use super::AttestationData;
|
use super::AttestationData;
|
||||||
use crate::test_utils::TestRandom;
|
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};
|
||||||
@ -14,8 +15,8 @@ pub struct AttestationDataAndCustodyBit {
|
|||||||
pub custody_bit: bool,
|
pub custody_bit: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RngCore> TestRandom<T> for AttestationDataAndCustodyBit {
|
impl TestRandom for AttestationDataAndCustodyBit {
|
||||||
fn random_for_test(rng: &mut T) -> Self {
|
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||||
Self {
|
Self {
|
||||||
data: <_>::random_for_test(rng),
|
data: <_>::random_for_test(rng),
|
||||||
custody_bit: <_>::random_for_test(rng),
|
custody_bit: <_>::random_for_test(rng),
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{test_utils::TestRandom, SlashableAttestation};
|
use crate::{test_utils::TestRandom, SlashableAttestation};
|
||||||
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;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use bls::Signature;
|
use bls::Signature;
|
||||||
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;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
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;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use bls::Signature;
|
use bls::Signature;
|
||||||
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;
|
||||||
|
@ -4,7 +4,8 @@ use crate::*;
|
|||||||
use cached_tree_hash::{Error as TreeHashCacheError, TreeHashCache};
|
use cached_tree_hash::{Error as TreeHashCacheError, TreeHashCache};
|
||||||
use int_to_bytes::int_to_bytes32;
|
use int_to_bytes::int_to_bytes32;
|
||||||
use pubkey_cache::PubkeyCache;
|
use pubkey_cache::PubkeyCache;
|
||||||
use rand::RngCore;
|
|
||||||
|
use fixed_len_vec::FixedLenVec;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use ssz::{hash, ssz_encode};
|
use ssz::{hash, ssz_encode};
|
||||||
use ssz_derive::{Decode, Encode};
|
use ssz_derive::{Decode, Encode};
|
||||||
@ -12,8 +13,10 @@ use test_random_derive::TestRandom;
|
|||||||
use tree_hash::TreeHash;
|
use tree_hash::TreeHash;
|
||||||
use tree_hash_derive::{CachedTreeHash, TreeHash};
|
use tree_hash_derive::{CachedTreeHash, TreeHash};
|
||||||
|
|
||||||
|
pub use beacon_state_types::{BeaconStateTypes, FoundationBeaconState};
|
||||||
|
|
||||||
|
mod beacon_state_types;
|
||||||
mod epoch_cache;
|
mod epoch_cache;
|
||||||
mod fixed_params;
|
|
||||||
mod pubkey_cache;
|
mod pubkey_cache;
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
@ -62,7 +65,10 @@ pub enum Error {
|
|||||||
TreeHash,
|
TreeHash,
|
||||||
CachedTreeHash,
|
CachedTreeHash,
|
||||||
)]
|
)]
|
||||||
pub struct BeaconState {
|
pub struct BeaconState<T>
|
||||||
|
where
|
||||||
|
T: BeaconStateTypes,
|
||||||
|
{
|
||||||
// Misc
|
// Misc
|
||||||
pub slot: Slot,
|
pub slot: Slot,
|
||||||
pub genesis_time: u64,
|
pub genesis_time: u64,
|
||||||
@ -74,7 +80,7 @@ pub struct BeaconState {
|
|||||||
pub validator_registry_update_epoch: Epoch,
|
pub validator_registry_update_epoch: Epoch,
|
||||||
|
|
||||||
// Randomness and committees
|
// Randomness and committees
|
||||||
pub latest_randao_mixes: TreeHashVector<Hash256>,
|
pub latest_randao_mixes: FixedLenVec<Hash256, T::NumLatestRandaoMixes>,
|
||||||
pub previous_shuffling_start_shard: u64,
|
pub previous_shuffling_start_shard: u64,
|
||||||
pub current_shuffling_start_shard: u64,
|
pub current_shuffling_start_shard: u64,
|
||||||
pub previous_shuffling_epoch: Epoch,
|
pub previous_shuffling_epoch: Epoch,
|
||||||
@ -134,14 +140,18 @@ pub struct BeaconState {
|
|||||||
pub tree_hash_cache: TreeHashCache,
|
pub tree_hash_cache: TreeHashCache,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BeaconState {
|
impl<T: BeaconStateTypes> BeaconState<T> {
|
||||||
/// Produce the first state of the Beacon Chain.
|
/// Produce the first state of the Beacon Chain.
|
||||||
///
|
///
|
||||||
/// This does not fully build a genesis beacon state, it omits processing of initial validator
|
/// This does not fully build a genesis beacon state, it omits processing of initial validator
|
||||||
/// deposits. To obtain a full genesis beacon state, use the `BeaconStateBuilder`.
|
/// deposits. To obtain a full genesis beacon state, use the `BeaconStateBuilder`.
|
||||||
///
|
///
|
||||||
/// Spec v0.5.1
|
/// Spec v0.5.1
|
||||||
pub fn genesis(genesis_time: u64, latest_eth1_data: Eth1Data, spec: &ChainSpec) -> BeaconState {
|
pub fn genesis(
|
||||||
|
genesis_time: u64,
|
||||||
|
latest_eth1_data: Eth1Data,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> BeaconState<T> {
|
||||||
let initial_crosslink = Crosslink {
|
let initial_crosslink = Crosslink {
|
||||||
epoch: spec.genesis_epoch,
|
epoch: spec.genesis_epoch,
|
||||||
crosslink_data_root: spec.zero_hash,
|
crosslink_data_root: spec.zero_hash,
|
||||||
@ -425,7 +435,8 @@ impl BeaconState {
|
|||||||
& (epoch <= current_epoch)
|
& (epoch <= current_epoch)
|
||||||
{
|
{
|
||||||
let i = epoch.as_usize() % spec.latest_randao_mixes_length;
|
let i = epoch.as_usize() % spec.latest_randao_mixes_length;
|
||||||
if i < self.latest_randao_mixes.len() {
|
|
||||||
|
if i < (&self.latest_randao_mixes[..]).len() {
|
||||||
Ok(i)
|
Ok(i)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::InsufficientRandaoMixes)
|
Err(Error::InsufficientRandaoMixes)
|
||||||
|
15
eth2/types/src/beacon_state/beacon_state_types.rs
Normal file
15
eth2/types/src/beacon_state/beacon_state_types.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
use crate::*;
|
||||||
|
use fixed_len_vec::typenum::{Unsigned, U8192};
|
||||||
|
|
||||||
|
pub trait BeaconStateTypes {
|
||||||
|
type NumLatestRandaoMixes: Unsigned + Clone + Sync + Send;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
pub struct FoundationStateParams;
|
||||||
|
|
||||||
|
impl BeaconStateTypes for FoundationStateParams {
|
||||||
|
type NumLatestRandaoMixes = U8192;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type FoundationBeaconState = BeaconState<FoundationStateParams>;
|
@ -28,8 +28,8 @@ pub struct EpochCache {
|
|||||||
|
|
||||||
impl EpochCache {
|
impl EpochCache {
|
||||||
/// Return a new, fully initialized cache.
|
/// Return a new, fully initialized cache.
|
||||||
pub fn initialized(
|
pub fn initialized<T: BeaconStateTypes>(
|
||||||
state: &BeaconState,
|
state: &BeaconState<T>,
|
||||||
relative_epoch: RelativeEpoch,
|
relative_epoch: RelativeEpoch,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<EpochCache, Error> {
|
) -> Result<EpochCache, Error> {
|
||||||
@ -200,8 +200,8 @@ pub struct EpochCrosslinkCommitteesBuilder {
|
|||||||
|
|
||||||
impl EpochCrosslinkCommitteesBuilder {
|
impl EpochCrosslinkCommitteesBuilder {
|
||||||
/// Instantiates a builder that will build for the `state`'s previous epoch.
|
/// Instantiates a builder that will build for the `state`'s previous epoch.
|
||||||
pub fn for_previous_epoch(
|
pub fn for_previous_epoch<T: BeaconStateTypes>(
|
||||||
state: &BeaconState,
|
state: &BeaconState<T>,
|
||||||
active_validator_indices: Vec<usize>,
|
active_validator_indices: Vec<usize>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -215,8 +215,8 @@ impl EpochCrosslinkCommitteesBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Instantiates a builder that will build for the `state`'s next epoch.
|
/// Instantiates a builder that will build for the `state`'s next epoch.
|
||||||
pub fn for_current_epoch(
|
pub fn for_current_epoch<T: BeaconStateTypes>(
|
||||||
state: &BeaconState,
|
state: &BeaconState<T>,
|
||||||
active_validator_indices: Vec<usize>,
|
active_validator_indices: Vec<usize>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -233,8 +233,8 @@ impl EpochCrosslinkCommitteesBuilder {
|
|||||||
///
|
///
|
||||||
/// Note: there are two possible epoch builds for the next epoch, one where there is a registry
|
/// Note: there are two possible epoch builds for the next epoch, one where there is a registry
|
||||||
/// change and one where there is not.
|
/// change and one where there is not.
|
||||||
pub fn for_next_epoch(
|
pub fn for_next_epoch<T: BeaconStateTypes>(
|
||||||
state: &BeaconState,
|
state: &BeaconState<T>,
|
||||||
active_validator_indices: Vec<usize>,
|
active_validator_indices: Vec<usize>,
|
||||||
registry_change: bool,
|
registry_change: bool,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
|
@ -4,8 +4,8 @@ use super::*;
|
|||||||
use crate::test_utils::*;
|
use crate::test_utils::*;
|
||||||
use swap_or_not_shuffle::shuffle_list;
|
use swap_or_not_shuffle::shuffle_list;
|
||||||
|
|
||||||
fn do_sane_cache_test(
|
fn do_sane_cache_test<T: BeaconStateTypes>(
|
||||||
state: BeaconState,
|
state: BeaconState<T>,
|
||||||
epoch: Epoch,
|
epoch: Epoch,
|
||||||
relative_epoch: RelativeEpoch,
|
relative_epoch: RelativeEpoch,
|
||||||
validator_count: usize,
|
validator_count: usize,
|
||||||
@ -64,7 +64,10 @@ fn do_sane_cache_test(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_sane_cache_test(validator_count: usize, spec: &ChainSpec) -> BeaconState {
|
fn setup_sane_cache_test<T: BeaconStateTypes>(
|
||||||
|
validator_count: usize,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> BeaconState<T> {
|
||||||
let mut builder =
|
let mut builder =
|
||||||
TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(validator_count, spec);
|
TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(validator_count, spec);
|
||||||
|
|
||||||
@ -101,7 +104,7 @@ fn builds_sane_current_epoch_cache() {
|
|||||||
let mut spec = ChainSpec::few_validators();
|
let mut spec = ChainSpec::few_validators();
|
||||||
spec.shard_count = 4;
|
spec.shard_count = 4;
|
||||||
let validator_count = (spec.shard_count * spec.target_committee_size) + 1;
|
let validator_count = (spec.shard_count * spec.target_committee_size) + 1;
|
||||||
let state = setup_sane_cache_test(validator_count as usize, &spec);
|
let state: FoundationBeaconState = setup_sane_cache_test(validator_count as usize, &spec);
|
||||||
do_sane_cache_test(
|
do_sane_cache_test(
|
||||||
state.clone(),
|
state.clone(),
|
||||||
state.current_epoch(&spec),
|
state.current_epoch(&spec),
|
||||||
@ -118,7 +121,7 @@ fn builds_sane_previous_epoch_cache() {
|
|||||||
let mut spec = ChainSpec::few_validators();
|
let mut spec = ChainSpec::few_validators();
|
||||||
spec.shard_count = 2;
|
spec.shard_count = 2;
|
||||||
let validator_count = (spec.shard_count * spec.target_committee_size) + 1;
|
let validator_count = (spec.shard_count * spec.target_committee_size) + 1;
|
||||||
let state = setup_sane_cache_test(validator_count as usize, &spec);
|
let state: FoundationBeaconState = setup_sane_cache_test(validator_count as usize, &spec);
|
||||||
do_sane_cache_test(
|
do_sane_cache_test(
|
||||||
state.clone(),
|
state.clone(),
|
||||||
state.previous_epoch(&spec),
|
state.previous_epoch(&spec),
|
||||||
@ -135,7 +138,7 @@ fn builds_sane_next_without_update_epoch_cache() {
|
|||||||
let mut spec = ChainSpec::few_validators();
|
let mut spec = ChainSpec::few_validators();
|
||||||
spec.shard_count = 2;
|
spec.shard_count = 2;
|
||||||
let validator_count = (spec.shard_count * spec.target_committee_size) + 1;
|
let validator_count = (spec.shard_count * spec.target_committee_size) + 1;
|
||||||
let mut state = setup_sane_cache_test(validator_count as usize, &spec);
|
let mut state: FoundationBeaconState = setup_sane_cache_test(validator_count as usize, &spec);
|
||||||
state.validator_registry_update_epoch = state.slot.epoch(spec.slots_per_epoch);
|
state.validator_registry_update_epoch = state.slot.epoch(spec.slots_per_epoch);
|
||||||
do_sane_cache_test(
|
do_sane_cache_test(
|
||||||
state.clone(),
|
state.clone(),
|
||||||
|
@ -2,16 +2,16 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::test_utils::*;
|
use crate::test_utils::*;
|
||||||
|
|
||||||
ssz_tests!(BeaconState);
|
ssz_tests!(FoundationBeaconState);
|
||||||
cached_tree_hash_tests!(BeaconState);
|
cached_tree_hash_tests!(FoundationBeaconState);
|
||||||
|
|
||||||
/// Test that
|
/// Test that
|
||||||
///
|
///
|
||||||
/// 1. Using the cache before it's built fails.
|
/// 1. Using the cache before it's built fails.
|
||||||
/// 2. Using the cache after it's build passes.
|
/// 2. Using the cache after it's build passes.
|
||||||
/// 3. Using the cache after it's dropped fails.
|
/// 3. Using the cache after it's dropped fails.
|
||||||
fn test_cache_initialization<'a>(
|
fn test_cache_initialization<'a, T: BeaconStateTypes>(
|
||||||
state: &'a mut BeaconState,
|
state: &'a mut BeaconState<T>,
|
||||||
relative_epoch: RelativeEpoch,
|
relative_epoch: RelativeEpoch,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) {
|
) {
|
||||||
@ -46,7 +46,7 @@ fn test_cache_initialization<'a>(
|
|||||||
#[test]
|
#[test]
|
||||||
fn cache_initialization() {
|
fn cache_initialization() {
|
||||||
let spec = ChainSpec::few_validators();
|
let spec = ChainSpec::few_validators();
|
||||||
let (mut state, _keypairs) =
|
let (mut state, _keypairs): (FoundationBeaconState, Vec<Keypair>) =
|
||||||
TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(16, &spec).build();
|
TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(16, &spec).build();
|
||||||
|
|
||||||
state.slot = (spec.genesis_epoch + 1).start_slot(spec.slots_per_epoch);
|
state.slot = (spec.genesis_epoch + 1).start_slot(spec.slots_per_epoch);
|
||||||
@ -64,7 +64,7 @@ fn tree_hash_cache() {
|
|||||||
|
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
|
|
||||||
let mut state = BeaconState::random_for_test(&mut rng);
|
let mut state: FoundationBeaconState = BeaconState::random_for_test(&mut rng);
|
||||||
|
|
||||||
let root = state.update_tree_hash_cache().unwrap();
|
let root = state.update_tree_hash_cache().unwrap();
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
use crate::{Epoch, Hash256};
|
use crate::{Epoch, Hash256};
|
||||||
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;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::{DepositData, Hash256, TreeHashVector};
|
use super::{DepositData, Hash256, TreeHashVector};
|
||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
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;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::DepositInput;
|
use super::DepositInput;
|
||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
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;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use bls::{PublicKey, Signature};
|
use bls::{PublicKey, Signature};
|
||||||
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;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::Hash256;
|
use super::Hash256;
|
||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
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;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::Eth1Data;
|
use super::Eth1Data;
|
||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
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;
|
||||||
|
@ -3,7 +3,7 @@ use crate::{
|
|||||||
ChainSpec, Epoch,
|
ChainSpec, Epoch,
|
||||||
};
|
};
|
||||||
use int_to_bytes::int_to_bytes4;
|
use int_to_bytes::int_to_bytes4;
|
||||||
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;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
use crate::{Hash256, TreeHashVector};
|
use crate::{Hash256, TreeHashVector};
|
||||||
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;
|
||||||
|
@ -36,6 +36,7 @@ pub mod slot_epoch;
|
|||||||
pub mod slot_height;
|
pub mod slot_height;
|
||||||
pub mod validator;
|
pub mod validator;
|
||||||
|
|
||||||
|
use beacon_state::FoundationBeaconState;
|
||||||
use ethereum_types::{H160, H256, U256};
|
use ethereum_types::{H160, H256, U256};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
@ -47,7 +48,7 @@ pub use crate::attester_slashing::AttesterSlashing;
|
|||||||
pub use crate::beacon_block::BeaconBlock;
|
pub use crate::beacon_block::BeaconBlock;
|
||||||
pub use crate::beacon_block_body::BeaconBlockBody;
|
pub use crate::beacon_block_body::BeaconBlockBody;
|
||||||
pub use crate::beacon_block_header::BeaconBlockHeader;
|
pub use crate::beacon_block_header::BeaconBlockHeader;
|
||||||
pub use crate::beacon_state::{BeaconState, Error as BeaconStateError};
|
pub use crate::beacon_state::{BeaconState, BeaconStateTypes, Error as BeaconStateError};
|
||||||
pub use crate::chain_spec::{ChainSpec, Domain};
|
pub use crate::chain_spec::{ChainSpec, Domain};
|
||||||
pub use crate::crosslink::Crosslink;
|
pub use crate::crosslink::Crosslink;
|
||||||
pub use crate::crosslink_committee::CrosslinkCommittee;
|
pub use crate::crosslink_committee::CrosslinkCommittee;
|
||||||
@ -87,6 +88,7 @@ pub type AttesterMap = HashMap<(u64, u64), Vec<usize>>;
|
|||||||
pub type ProposerMap = HashMap<u64, usize>;
|
pub type ProposerMap = HashMap<u64, usize>;
|
||||||
|
|
||||||
pub use bls::{AggregatePublicKey, AggregateSignature, Keypair, PublicKey, SecretKey, Signature};
|
pub use bls::{AggregatePublicKey, AggregateSignature, Keypair, PublicKey, SecretKey, Signature};
|
||||||
|
pub use fixed_len_vec::FixedLenVec;
|
||||||
pub use libp2p::floodsub::{Topic, TopicBuilder, TopicHash};
|
pub use libp2p::floodsub::{Topic, TopicBuilder, TopicHash};
|
||||||
pub use libp2p::multiaddr;
|
pub use libp2p::multiaddr;
|
||||||
pub use libp2p::Multiaddr;
|
pub use libp2p::Multiaddr;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
use crate::{Attestation, AttestationData, Bitfield, Slot};
|
use crate::{Attestation, AttestationData, Bitfield, Slot};
|
||||||
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;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::BeaconBlockHeader;
|
use super::BeaconBlockHeader;
|
||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
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;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{test_utils::TestRandom, AggregateSignature, AttestationData, Bitfield, ChainSpec};
|
use crate::{test_utils::TestRandom, AggregateSignature, AttestationData, Bitfield, ChainSpec};
|
||||||
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;
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
|
//! The `Slot` and `Epoch` types are defined as newtypes over u64 to enforce type-safety between
|
||||||
|
//! the two types.
|
||||||
|
//!
|
||||||
|
//! `Slot` and `Epoch` have implementations which permit conversion, comparison and math operations
|
||||||
|
//! between each and `u64`, however specifically not between each other.
|
||||||
|
//!
|
||||||
|
//! All math operations on `Slot` and `Epoch` are saturating, they never wrap.
|
||||||
|
//!
|
||||||
|
//! It would be easy to define `PartialOrd` and other traits generically across all types which
|
||||||
|
//! implement `Into<u64>`, however this would allow operations between `Slots` and `Epochs` which
|
||||||
|
//! may lead to programming errors which are not detected by the compiler.
|
||||||
|
|
||||||
use crate::slot_height::SlotHeight;
|
use crate::slot_height::SlotHeight;
|
||||||
/// The `Slot` and `Epoch` types are defined as newtypes over u64 to enforce type-safety between
|
|
||||||
/// the two types.
|
|
||||||
///
|
|
||||||
/// `Slot` and `Epoch` have implementations which permit conversion, comparison and math operations
|
|
||||||
/// between each and `u64`, however specifically not between each other.
|
|
||||||
///
|
|
||||||
/// All math operations on `Slot` and `Epoch` are saturating, they never wrap.
|
|
||||||
///
|
|
||||||
/// It would be easy to define `PartialOrd` and other traits generically across all types which
|
|
||||||
/// implement `Into<u64>`, however this would allow operations between `Slots` and `Epochs` which
|
|
||||||
/// may lead to programming errors which are not detected by the compiler.
|
|
||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
@ -244,8 +244,8 @@ macro_rules! impl_ssz {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RngCore> TestRandom<T> for $type {
|
impl TestRandom for $type {
|
||||||
fn random_for_test(rng: &mut T) -> Self {
|
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||||
$type::from(u64::random_for_test(rng))
|
$type::from(u64::random_for_test(rng))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::slot_epoch::{Epoch, Slot};
|
use crate::slot_epoch::{Epoch, Slot};
|
||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
|
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use serde_derive::Serialize;
|
use serde_derive::Serialize;
|
||||||
use ssz::{ssz_encode, Decodable, DecodeError, Encodable, SszStream};
|
use ssz::{ssz_encode, Decodable, DecodeError, Encodable, SszStream};
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use crate::*;
|
||||||
|
use fixed_len_vec::typenum::Unsigned;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
|
|
||||||
mod address;
|
mod address;
|
||||||
@ -8,42 +10,39 @@ mod public_key;
|
|||||||
mod secret_key;
|
mod secret_key;
|
||||||
mod signature;
|
mod signature;
|
||||||
|
|
||||||
pub trait TestRandom<T>
|
pub trait TestRandom {
|
||||||
where
|
fn random_for_test(rng: &mut impl RngCore) -> Self;
|
||||||
T: RngCore,
|
|
||||||
{
|
|
||||||
fn random_for_test(rng: &mut T) -> Self;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RngCore> TestRandom<T> for bool {
|
impl TestRandom for bool {
|
||||||
fn random_for_test(rng: &mut T) -> Self {
|
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||||
(rng.next_u32() % 2) == 1
|
(rng.next_u32() % 2) == 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RngCore> TestRandom<T> for u64 {
|
impl TestRandom for u64 {
|
||||||
fn random_for_test(rng: &mut T) -> Self {
|
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||||
rng.next_u64()
|
rng.next_u64()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RngCore> TestRandom<T> for u32 {
|
impl TestRandom for u32 {
|
||||||
fn random_for_test(rng: &mut T) -> Self {
|
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||||
rng.next_u32()
|
rng.next_u32()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RngCore> TestRandom<T> for usize {
|
impl TestRandom for usize {
|
||||||
fn random_for_test(rng: &mut T) -> Self {
|
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||||
rng.next_u32() as usize
|
rng.next_u32() as usize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RngCore, U> TestRandom<T> for Vec<U>
|
impl<U> TestRandom for Vec<U>
|
||||||
where
|
where
|
||||||
U: TestRandom<T>,
|
U: TestRandom,
|
||||||
{
|
{
|
||||||
fn random_for_test(rng: &mut T) -> Self {
|
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
|
|
||||||
for _ in 0..(usize::random_for_test(rng) % 4) {
|
for _ in 0..(usize::random_for_test(rng) % 4) {
|
||||||
@ -54,10 +53,25 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T, N: Unsigned> TestRandom for FixedLenVec<T, N>
|
||||||
|
where
|
||||||
|
T: TestRandom + Default,
|
||||||
|
{
|
||||||
|
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||||
|
let mut output = vec![];
|
||||||
|
|
||||||
|
for _ in 0..(usize::random_for_test(rng) % std::cmp::min(4, N::to_usize())) {
|
||||||
|
output.push(<T>::random_for_test(rng));
|
||||||
|
}
|
||||||
|
|
||||||
|
output.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! impl_test_random_for_u8_array {
|
macro_rules! impl_test_random_for_u8_array {
|
||||||
($len: expr) => {
|
($len: expr) => {
|
||||||
impl<T: RngCore> TestRandom<T> for [u8; $len] {
|
impl TestRandom for [u8; $len] {
|
||||||
fn random_for_test(rng: &mut T) -> Self {
|
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||||
let mut bytes = [0; $len];
|
let mut bytes = [0; $len];
|
||||||
rng.fill_bytes(&mut bytes);
|
rng.fill_bytes(&mut bytes);
|
||||||
bytes
|
bytes
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use super::TestRandom;
|
use super::*;
|
||||||
use crate::Address;
|
use crate::Address;
|
||||||
use rand::RngCore;
|
|
||||||
|
|
||||||
impl<T: RngCore> TestRandom<T> for Address {
|
impl TestRandom for Address {
|
||||||
fn random_for_test(rng: &mut T) -> Self {
|
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||||
let mut key_bytes = vec![0; 20];
|
let mut key_bytes = vec![0; 20];
|
||||||
rng.fill_bytes(&mut key_bytes);
|
rng.fill_bytes(&mut key_bytes);
|
||||||
Address::from_slice(&key_bytes[..])
|
Address::from_slice(&key_bytes[..])
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use super::TestRandom;
|
use super::*;
|
||||||
use bls::{AggregateSignature, Signature};
|
use bls::{AggregateSignature, Signature};
|
||||||
use rand::RngCore;
|
|
||||||
|
|
||||||
impl<T: RngCore> TestRandom<T> for AggregateSignature {
|
impl TestRandom for AggregateSignature {
|
||||||
fn random_for_test(rng: &mut T) -> Self {
|
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||||
let signature = Signature::random_for_test(rng);
|
let signature = Signature::random_for_test(rng);
|
||||||
let mut aggregate_signature = AggregateSignature::new();
|
let mut aggregate_signature = AggregateSignature::new();
|
||||||
aggregate_signature.add(&signature);
|
aggregate_signature.add(&signature);
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use super::TestRandom;
|
use super::*;
|
||||||
use crate::Bitfield;
|
use crate::Bitfield;
|
||||||
use rand::RngCore;
|
|
||||||
|
|
||||||
impl<T: RngCore> TestRandom<T> for Bitfield {
|
impl TestRandom for Bitfield {
|
||||||
fn random_for_test(rng: &mut T) -> Self {
|
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||||
let mut raw_bytes = vec![0; 32];
|
let mut raw_bytes = vec![0; 32];
|
||||||
rng.fill_bytes(&mut raw_bytes);
|
rng.fill_bytes(&mut raw_bytes);
|
||||||
Bitfield::from_bytes(&raw_bytes)
|
Bitfield::from_bytes(&raw_bytes)
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use super::TestRandom;
|
use super::*;
|
||||||
use crate::Hash256;
|
use crate::Hash256;
|
||||||
use rand::RngCore;
|
|
||||||
|
|
||||||
impl<T: RngCore> TestRandom<T> for Hash256 {
|
impl TestRandom for Hash256 {
|
||||||
fn random_for_test(rng: &mut T) -> Self {
|
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||||
let mut key_bytes = vec![0; 32];
|
let mut key_bytes = vec![0; 32];
|
||||||
rng.fill_bytes(&mut key_bytes);
|
rng.fill_bytes(&mut key_bytes);
|
||||||
Hash256::from_slice(&key_bytes[..])
|
Hash256::from_slice(&key_bytes[..])
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use super::TestRandom;
|
use super::*;
|
||||||
use bls::{PublicKey, SecretKey};
|
use bls::{PublicKey, SecretKey};
|
||||||
use rand::RngCore;
|
|
||||||
|
|
||||||
impl<T: RngCore> TestRandom<T> for PublicKey {
|
impl TestRandom for PublicKey {
|
||||||
fn random_for_test(rng: &mut T) -> Self {
|
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||||
let secret_key = SecretKey::random_for_test(rng);
|
let secret_key = SecretKey::random_for_test(rng);
|
||||||
PublicKey::from_secret_key(&secret_key)
|
PublicKey::from_secret_key(&secret_key)
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use super::TestRandom;
|
use super::*;
|
||||||
use bls::SecretKey;
|
use bls::SecretKey;
|
||||||
use rand::RngCore;
|
|
||||||
|
|
||||||
impl<T: RngCore> TestRandom<T> for SecretKey {
|
impl TestRandom for SecretKey {
|
||||||
fn random_for_test(rng: &mut T) -> Self {
|
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||||
let mut key_bytes = vec![0; 48];
|
let mut key_bytes = vec![0; 48];
|
||||||
rng.fill_bytes(&mut key_bytes);
|
rng.fill_bytes(&mut key_bytes);
|
||||||
/*
|
/*
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use super::TestRandom;
|
use super::*;
|
||||||
use bls::{SecretKey, Signature};
|
use bls::{SecretKey, Signature};
|
||||||
use rand::RngCore;
|
|
||||||
|
|
||||||
impl<T: RngCore> TestRandom<T> for Signature {
|
impl TestRandom for Signature {
|
||||||
fn random_for_test(rng: &mut T) -> Self {
|
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||||
let secret_key = SecretKey::random_for_test(rng);
|
let secret_key = SecretKey::random_for_test(rng);
|
||||||
let mut message = vec![0; 32];
|
let mut message = vec![0; 32];
|
||||||
rng.fill_bytes(&mut message);
|
rng.fill_bytes(&mut message);
|
||||||
|
@ -12,8 +12,8 @@ pub struct TestingAttestationBuilder {
|
|||||||
|
|
||||||
impl TestingAttestationBuilder {
|
impl TestingAttestationBuilder {
|
||||||
/// Create a new attestation builder.
|
/// Create a new attestation builder.
|
||||||
pub fn new(
|
pub fn new<T: BeaconStateTypes>(
|
||||||
state: &BeaconState,
|
state: &BeaconState<T>,
|
||||||
committee: &[usize],
|
committee: &[usize],
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
shard: u64,
|
shard: u64,
|
||||||
|
@ -10,7 +10,12 @@ pub struct TestingAttestationDataBuilder {
|
|||||||
impl TestingAttestationDataBuilder {
|
impl TestingAttestationDataBuilder {
|
||||||
/// Configures a new `AttestationData` which attests to all of the same parameters as the
|
/// Configures a new `AttestationData` which attests to all of the same parameters as the
|
||||||
/// state.
|
/// state.
|
||||||
pub fn new(state: &BeaconState, shard: u64, slot: Slot, spec: &ChainSpec) -> Self {
|
pub fn new<T: BeaconStateTypes>(
|
||||||
|
state: &BeaconState<T>,
|
||||||
|
shard: u64,
|
||||||
|
slot: Slot,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> Self {
|
||||||
let current_epoch = state.current_epoch(spec);
|
let current_epoch = state.current_epoch(spec);
|
||||||
let previous_epoch = state.previous_epoch(spec);
|
let previous_epoch = state.previous_epoch(spec);
|
||||||
|
|
||||||
|
@ -82,9 +82,9 @@ impl TestingBeaconBlockBuilder {
|
|||||||
///
|
///
|
||||||
/// Note: the signed messages of the split committees will be identical -- it would be possible
|
/// Note: the signed messages of the split committees will be identical -- it would be possible
|
||||||
/// to aggregate these split attestations.
|
/// to aggregate these split attestations.
|
||||||
pub fn insert_attestations(
|
pub fn insert_attestations<T: BeaconStateTypes>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &BeaconState,
|
state: &BeaconState<T>,
|
||||||
secret_keys: &[&SecretKey],
|
secret_keys: &[&SecretKey],
|
||||||
num_attestations: usize,
|
num_attestations: usize,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
@ -171,11 +171,11 @@ impl TestingBeaconBlockBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a `Valid` deposit into the state.
|
/// Insert a `Valid` deposit into the state.
|
||||||
pub fn insert_deposit(
|
pub fn insert_deposit<T: BeaconStateTypes>(
|
||||||
&mut self,
|
&mut self,
|
||||||
amount: u64,
|
amount: u64,
|
||||||
index: u64,
|
index: u64,
|
||||||
state: &BeaconState,
|
state: &BeaconState<T>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) {
|
) {
|
||||||
let keypair = Keypair::random();
|
let keypair = Keypair::random();
|
||||||
@ -193,9 +193,9 @@ impl TestingBeaconBlockBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a `Valid` exit into the state.
|
/// Insert a `Valid` exit into the state.
|
||||||
pub fn insert_exit(
|
pub fn insert_exit<T: BeaconStateTypes>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &BeaconState,
|
state: &BeaconState<T>,
|
||||||
validator_index: u64,
|
validator_index: u64,
|
||||||
secret_key: &SecretKey,
|
secret_key: &SecretKey,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
@ -214,9 +214,9 @@ impl TestingBeaconBlockBuilder {
|
|||||||
///
|
///
|
||||||
/// Note: this will set the validator to be withdrawable by directly modifying the state
|
/// Note: this will set the validator to be withdrawable by directly modifying the state
|
||||||
/// validator registry. This _may_ cause problems historic hashes, etc.
|
/// validator registry. This _may_ cause problems historic hashes, etc.
|
||||||
pub fn insert_transfer(
|
pub fn insert_transfer<T: BeaconStateTypes>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &BeaconState,
|
state: &BeaconState<T>,
|
||||||
from: u64,
|
from: u64,
|
||||||
to: u64,
|
to: u64,
|
||||||
amount: u64,
|
amount: u64,
|
||||||
|
@ -25,12 +25,12 @@ pub fn keypairs_path() -> PathBuf {
|
|||||||
///
|
///
|
||||||
/// This struct should **never be used for production purposes.**
|
/// This struct should **never be used for production purposes.**
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TestingBeaconStateBuilder {
|
pub struct TestingBeaconStateBuilder<T: BeaconStateTypes> {
|
||||||
state: BeaconState,
|
state: BeaconState<T>,
|
||||||
keypairs: Vec<Keypair>,
|
keypairs: Vec<Keypair>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestingBeaconStateBuilder {
|
impl<T: BeaconStateTypes> TestingBeaconStateBuilder<T> {
|
||||||
/// Attempts to load validators from a file in `$HOME/.lighthouse/keypairs.raw_keypairs`. If
|
/// Attempts to load validators from a file in `$HOME/.lighthouse/keypairs.raw_keypairs`. If
|
||||||
/// the file is unavailable, it generates the keys at runtime.
|
/// the file is unavailable, it generates the keys at runtime.
|
||||||
///
|
///
|
||||||
@ -154,7 +154,7 @@ impl TestingBeaconStateBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Consume the builder and return the `BeaconState` and the keypairs for each validator.
|
/// Consume the builder and return the `BeaconState` and the keypairs for each validator.
|
||||||
pub fn build(self) -> (BeaconState, Vec<Keypair>) {
|
pub fn build(self) -> (BeaconState<T>, Vec<Keypair>) {
|
||||||
(self.state, self.keypairs)
|
(self.state, self.keypairs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,12 @@ impl TestingPendingAttestationBuilder {
|
|||||||
///
|
///
|
||||||
/// * The aggregation and custody bitfields will all be empty, they need to be set with
|
/// * The aggregation and custody bitfields will all be empty, they need to be set with
|
||||||
/// `Self::add_committee_participation`.
|
/// `Self::add_committee_participation`.
|
||||||
pub fn new(state: &BeaconState, shard: u64, slot: Slot, spec: &ChainSpec) -> Self {
|
pub fn new<T: BeaconStateTypes>(
|
||||||
|
state: &BeaconState<T>,
|
||||||
|
shard: u64,
|
||||||
|
slot: Slot,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> Self {
|
||||||
let data_builder = TestingAttestationDataBuilder::new(state, shard, slot, spec);
|
let data_builder = TestingAttestationDataBuilder::new(state, shard, slot, spec);
|
||||||
|
|
||||||
let pending_attestation = PendingAttestation {
|
let pending_attestation = PendingAttestation {
|
||||||
|
@ -2,7 +2,7 @@ use super::Slot;
|
|||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
use bls::{PublicKey, Signature};
|
use bls::{PublicKey, Signature};
|
||||||
use derivative::Derivative;
|
use derivative::Derivative;
|
||||||
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;
|
||||||
|
@ -100,11 +100,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RngCore, U> TestRandom<T> for TreeHashVector<U>
|
impl<U> TestRandom for TreeHashVector<U>
|
||||||
where
|
where
|
||||||
U: TestRandom<T>,
|
U: TestRandom,
|
||||||
{
|
{
|
||||||
fn random_for_test(rng: &mut T) -> Self {
|
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||||
TreeHashVector::from(vec![
|
TreeHashVector::from(vec![
|
||||||
U::random_for_test(rng),
|
U::random_for_test(rng),
|
||||||
U::random_for_test(rng),
|
U::random_for_test(rng),
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{test_utils::TestRandom, Epoch, Hash256, PublicKey};
|
use crate::{test_utils::TestRandom, Epoch, Hash256, PublicKey};
|
||||||
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;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{test_utils::TestRandom, Epoch};
|
use crate::{test_utils::TestRandom, Epoch};
|
||||||
use bls::Signature;
|
use bls::Signature;
|
||||||
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;
|
||||||
|
13
eth2/utils/fixed_len_vec/Cargo.toml
Normal file
13
eth2/utils/fixed_len_vec/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "fixed_len_vec"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
cached_tree_hash = { path = "../cached_tree_hash" }
|
||||||
|
tree_hash = { path = "../tree_hash" }
|
||||||
|
serde = "1.0"
|
||||||
|
serde_derive = "1.0"
|
||||||
|
ssz = { path = "../ssz" }
|
||||||
|
typenum = "1.10"
|
70
eth2/utils/fixed_len_vec/src/impls.rs
Normal file
70
eth2/utils/fixed_len_vec/src/impls.rs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
use super::*;
|
||||||
|
// use cached_tree_hash::CachedTreeHash;
|
||||||
|
// use ssz::{Decodable, Encodable};
|
||||||
|
// use tree_hash::TreeHash;
|
||||||
|
|
||||||
|
impl<T, N: Unsigned> tree_hash::TreeHash for FixedLenVec<T, N>
|
||||||
|
where
|
||||||
|
T: tree_hash::TreeHash,
|
||||||
|
{
|
||||||
|
fn tree_hash_type() -> tree_hash::TreeHashType {
|
||||||
|
tree_hash::TreeHashType::Vector
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
|
||||||
|
unreachable!("Vector should never be packed.")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tree_hash_packing_factor() -> usize {
|
||||||
|
unreachable!("Vector should never be packed.")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tree_hash_root(&self) -> Vec<u8> {
|
||||||
|
tree_hash::impls::vec_tree_hash_root(&self.vec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, N: Unsigned> cached_tree_hash::CachedTreeHash for FixedLenVec<T, N>
|
||||||
|
where
|
||||||
|
T: cached_tree_hash::CachedTreeHash + tree_hash::TreeHash,
|
||||||
|
{
|
||||||
|
fn new_tree_hash_cache(
|
||||||
|
&self,
|
||||||
|
depth: usize,
|
||||||
|
) -> Result<cached_tree_hash::TreeHashCache, cached_tree_hash::Error> {
|
||||||
|
let (cache, _overlay) = cached_tree_hash::vec::new_tree_hash_cache(&self.vec, depth)?;
|
||||||
|
|
||||||
|
Ok(cache)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tree_hash_cache_schema(&self, depth: usize) -> cached_tree_hash::BTreeSchema {
|
||||||
|
cached_tree_hash::vec::produce_schema(&self.vec, depth)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_tree_hash_cache(
|
||||||
|
&self,
|
||||||
|
cache: &mut cached_tree_hash::TreeHashCache,
|
||||||
|
) -> Result<(), cached_tree_hash::Error> {
|
||||||
|
cached_tree_hash::vec::update_tree_hash_cache(&self.vec, cache)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, N: Unsigned> ssz::Encodable for FixedLenVec<T, N>
|
||||||
|
where
|
||||||
|
T: ssz::Encodable,
|
||||||
|
{
|
||||||
|
fn ssz_append(&self, s: &mut ssz::SszStream) {
|
||||||
|
s.append_vec(&self.vec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, N: Unsigned> ssz::Decodable for FixedLenVec<T, N>
|
||||||
|
where
|
||||||
|
T: ssz::Decodable + Default,
|
||||||
|
{
|
||||||
|
fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), ssz::DecodeError> {
|
||||||
|
ssz::decode_ssz_list(bytes, index).and_then(|(vec, i)| Ok((vec.into(), i)))
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,14 @@
|
|||||||
use std::borrow::{Borrow, BorrowMut};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::{Deref, Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
use std::slice::SliceIndex;
|
use std::slice::SliceIndex;
|
||||||
use typenum::Unsigned;
|
use typenum::Unsigned;
|
||||||
|
|
||||||
|
pub use typenum;
|
||||||
|
|
||||||
|
mod impls;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||||
pub struct FixedLenVec<T, N>
|
pub struct FixedLenVec<T, N>
|
||||||
where
|
where
|
||||||
N: Unsigned,
|
N: Unsigned,
|
||||||
@ -14,6 +19,7 @@ where
|
|||||||
|
|
||||||
impl<T: Default, N: Unsigned> From<Vec<T>> for FixedLenVec<T, N> {
|
impl<T: Default, N: Unsigned> From<Vec<T>> for FixedLenVec<T, N> {
|
||||||
fn from(mut vec: Vec<T>) -> Self {
|
fn from(mut vec: Vec<T>) -> Self {
|
||||||
|
dbg!(Self::capacity());
|
||||||
vec.resize_with(Self::capacity(), Default::default);
|
vec.resize_with(Self::capacity(), Default::default);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@ -23,6 +29,21 @@ impl<T: Default, N: Unsigned> From<Vec<T>> for FixedLenVec<T, N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T, N: Unsigned> Into<Vec<T>> for FixedLenVec<T, N> {
|
||||||
|
fn into(self) -> Vec<T> {
|
||||||
|
self.vec
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, N: Unsigned> Default for FixedLenVec<T, N> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
vec: Vec::default(),
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T, N: Unsigned> FixedLenVec<T, N> {
|
impl<T, N: Unsigned> FixedLenVec<T, N> {
|
||||||
pub fn capacity() -> usize {
|
pub fn capacity() -> usize {
|
||||||
N::to_usize()
|
N::to_usize()
|
||||||
@ -48,25 +69,43 @@ impl<T, N: Unsigned, I: SliceIndex<[T]>> IndexMut<I> for FixedLenVec<T, N> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use typenum::U8192;
|
use typenum::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn slice_ops() {
|
fn indexing() {
|
||||||
let vec = vec![1, 2];
|
let vec = vec![1, 2];
|
||||||
|
|
||||||
let mut fixed: FixedLenVec<u64, U8192> = vec.clone().into();
|
let mut fixed: FixedLenVec<u64, U8192> = vec.clone().into();
|
||||||
|
|
||||||
assert_eq!(fixed[0], 1);
|
assert_eq!(fixed[0], 1);
|
||||||
assert_eq!(&fixed[0..1], &vec[0..1]);
|
assert_eq!(&fixed[0..1], &vec[0..1]);
|
||||||
assert_eq!(&fixed[..], &vec[..]);
|
assert_eq!((&fixed[..]).len(), 8192);
|
||||||
|
|
||||||
fixed[1] = 3;
|
fixed[1] = 3;
|
||||||
assert_eq!(fixed[1], 3);
|
assert_eq!(fixed[1], 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn length() {
|
||||||
|
let vec = vec![42; 5];
|
||||||
|
let fixed: FixedLenVec<u64, U4> = FixedLenVec::from(vec.clone());
|
||||||
|
assert_eq!(&fixed[..], &vec[0..4]);
|
||||||
|
|
||||||
|
let vec = vec![42; 3];
|
||||||
|
let fixed: FixedLenVec<u64, U4> = FixedLenVec::from(vec.clone());
|
||||||
|
assert_eq!(&fixed[0..3], &vec[..]);
|
||||||
|
assert_eq!(&fixed[..], &vec![42, 42, 42, 0][..]);
|
||||||
|
|
||||||
|
let vec = vec![];
|
||||||
|
let fixed: FixedLenVec<u64, U4> = FixedLenVec::from(vec.clone());
|
||||||
|
assert_eq!(&fixed[..], &vec![0, 0, 0, 0][..]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
#[cfg(test)]
|
||||||
pub trait FixedParams {
|
mod tests {
|
||||||
type LatestCrosslinks:
|
#[test]
|
||||||
|
fn it_works() {
|
||||||
|
assert_eq!(2 + 2, 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
@ -100,6 +100,7 @@ pub fn ssz_encode_derive(input: TokenStream) -> TokenStream {
|
|||||||
let item = parse_macro_input!(input as DeriveInput);
|
let item = parse_macro_input!(input as DeriveInput);
|
||||||
|
|
||||||
let name = &item.ident;
|
let name = &item.ident;
|
||||||
|
let (impl_generics, ty_generics, where_clause) = &item.generics.split_for_impl();
|
||||||
|
|
||||||
let struct_data = match &item.data {
|
let struct_data = match &item.data {
|
||||||
syn::Data::Struct(s) => s,
|
syn::Data::Struct(s) => s,
|
||||||
@ -109,7 +110,7 @@ pub fn ssz_encode_derive(input: TokenStream) -> TokenStream {
|
|||||||
let field_idents = get_serializable_named_field_idents(&struct_data);
|
let field_idents = get_serializable_named_field_idents(&struct_data);
|
||||||
|
|
||||||
let output = quote! {
|
let output = quote! {
|
||||||
impl ssz::Encodable for #name {
|
impl #impl_generics ssz::Encodable for #name #ty_generics #where_clause {
|
||||||
fn ssz_append(&self, s: &mut ssz::SszStream) {
|
fn ssz_append(&self, s: &mut ssz::SszStream) {
|
||||||
#(
|
#(
|
||||||
s.append(&self.#field_idents);
|
s.append(&self.#field_idents);
|
||||||
@ -140,6 +141,7 @@ pub fn ssz_decode_derive(input: TokenStream) -> TokenStream {
|
|||||||
let item = parse_macro_input!(input as DeriveInput);
|
let item = parse_macro_input!(input as DeriveInput);
|
||||||
|
|
||||||
let name = &item.ident;
|
let name = &item.ident;
|
||||||
|
let (impl_generics, ty_generics, where_clause) = &item.generics.split_for_impl();
|
||||||
|
|
||||||
let struct_data = match &item.data {
|
let struct_data = match &item.data {
|
||||||
syn::Data::Struct(s) => s,
|
syn::Data::Struct(s) => s,
|
||||||
@ -169,7 +171,7 @@ pub fn ssz_decode_derive(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let output = quote! {
|
let output = quote! {
|
||||||
impl ssz::Decodable for #name {
|
impl #impl_generics ssz::Decodable for #name #ty_generics #where_clause {
|
||||||
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), ssz::DecodeError> {
|
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), ssz::DecodeError> {
|
||||||
#(
|
#(
|
||||||
#quotes
|
#quotes
|
||||||
|
@ -21,6 +21,7 @@ fn should_use_default(field: &syn::Field) -> bool {
|
|||||||
pub fn test_random_derive(input: TokenStream) -> TokenStream {
|
pub fn test_random_derive(input: TokenStream) -> TokenStream {
|
||||||
let derived_input = parse_macro_input!(input as DeriveInput);
|
let derived_input = parse_macro_input!(input as DeriveInput);
|
||||||
let name = &derived_input.ident;
|
let name = &derived_input.ident;
|
||||||
|
let (impl_generics, ty_generics, where_clause) = &derived_input.generics.split_for_impl();
|
||||||
|
|
||||||
let struct_data = match &derived_input.data {
|
let struct_data = match &derived_input.data {
|
||||||
syn::Data::Struct(s) => s,
|
syn::Data::Struct(s) => s,
|
||||||
@ -48,8 +49,8 @@ pub fn test_random_derive(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let output = quote! {
|
let output = quote! {
|
||||||
impl<T: RngCore> TestRandom<T> for #name {
|
impl #impl_generics TestRandom for #name #ty_generics #where_clause {
|
||||||
fn random_for_test(rng: &mut T) -> Self {
|
fn random_for_test(rng: &mut impl rand::RngCore) -> Self {
|
||||||
Self {
|
Self {
|
||||||
#(
|
#(
|
||||||
#quotes
|
#quotes
|
||||||
|
@ -43,6 +43,7 @@ fn should_skip_hashing(field: &syn::Field) -> bool {
|
|||||||
#[proc_macro_derive(CachedTreeHash, attributes(tree_hash))]
|
#[proc_macro_derive(CachedTreeHash, attributes(tree_hash))]
|
||||||
pub fn subtree_derive(input: TokenStream) -> TokenStream {
|
pub fn subtree_derive(input: TokenStream) -> TokenStream {
|
||||||
let item = parse_macro_input!(input as DeriveInput);
|
let item = parse_macro_input!(input as DeriveInput);
|
||||||
|
let (impl_generics, ty_generics, where_clause) = &item.generics.split_for_impl();
|
||||||
|
|
||||||
let name = &item.ident;
|
let name = &item.ident;
|
||||||
|
|
||||||
@ -56,7 +57,7 @@ pub fn subtree_derive(input: TokenStream) -> TokenStream {
|
|||||||
let idents_c = idents_a.clone();
|
let idents_c = idents_a.clone();
|
||||||
|
|
||||||
let output = quote! {
|
let output = quote! {
|
||||||
impl cached_tree_hash::CachedTreeHash for #name {
|
impl #impl_generics cached_tree_hash::CachedTreeHash for #name #ty_generics #where_clause {
|
||||||
fn new_tree_hash_cache(&self, depth: usize) -> Result<cached_tree_hash::TreeHashCache, cached_tree_hash::Error> {
|
fn new_tree_hash_cache(&self, depth: usize) -> Result<cached_tree_hash::TreeHashCache, cached_tree_hash::Error> {
|
||||||
let tree = cached_tree_hash::TreeHashCache::from_subtrees(
|
let tree = cached_tree_hash::TreeHashCache::from_subtrees(
|
||||||
self,
|
self,
|
||||||
@ -119,6 +120,7 @@ pub fn tree_hash_derive(input: TokenStream) -> TokenStream {
|
|||||||
let item = parse_macro_input!(input as DeriveInput);
|
let item = parse_macro_input!(input as DeriveInput);
|
||||||
|
|
||||||
let name = &item.ident;
|
let name = &item.ident;
|
||||||
|
let (impl_generics, ty_generics, where_clause) = &item.generics.split_for_impl();
|
||||||
|
|
||||||
let struct_data = match &item.data {
|
let struct_data = match &item.data {
|
||||||
syn::Data::Struct(s) => s,
|
syn::Data::Struct(s) => s,
|
||||||
@ -128,7 +130,7 @@ pub fn tree_hash_derive(input: TokenStream) -> TokenStream {
|
|||||||
let idents = get_hashable_named_field_idents(&struct_data);
|
let idents = get_hashable_named_field_idents(&struct_data);
|
||||||
|
|
||||||
let output = quote! {
|
let output = quote! {
|
||||||
impl tree_hash::TreeHash for #name {
|
impl #impl_generics tree_hash::TreeHash for #name #ty_generics #where_clause {
|
||||||
fn tree_hash_type() -> tree_hash::TreeHashType {
|
fn tree_hash_type() -> tree_hash::TreeHashType {
|
||||||
tree_hash::TreeHashType::Container
|
tree_hash::TreeHashType::Container
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user