mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-21 22:04:44 +00:00
Merge latest master in v0.2.0
This commit is contained in:
@@ -32,9 +32,12 @@ impl AggregateSignature {
|
||||
|
||||
/// Add (aggregate) a signature to the `AggregateSignature`.
|
||||
pub fn add(&mut self, signature: &Signature) {
|
||||
if !self.is_empty {
|
||||
self.aggregate_signature.add(signature.as_raw())
|
||||
if self.is_empty {
|
||||
self.aggregate_signature = RawAggregateSignature::new();
|
||||
self.is_empty = false;
|
||||
}
|
||||
|
||||
self.aggregate_signature.add(signature.as_raw())
|
||||
}
|
||||
|
||||
/// Add (aggregate) another `AggregateSignature`.
|
||||
|
||||
@@ -22,6 +22,13 @@ impl FakeAggregatePublicKey {
|
||||
Self::zero()
|
||||
}
|
||||
|
||||
pub fn empty_signature() -> Self {
|
||||
Self {
|
||||
bytes: vec![0; BLS_PUBLIC_KEY_BYTE_SIZE],
|
||||
point: G1Point::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
|
||||
if bytes.len() != BLS_PUBLIC_KEY_BYTE_SIZE {
|
||||
Err(DecodeError::InvalidByteLength {
|
||||
|
||||
@@ -14,4 +14,4 @@ serde_json = "1.0"
|
||||
types = { path = "../../types"}
|
||||
eth2_ssz = { path = "../ssz"}
|
||||
tree_hash = { path = "../tree_hash"}
|
||||
ethabi = "9.0"
|
||||
ethabi = "11.0"
|
||||
|
||||
@@ -9,9 +9,9 @@ use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
const TAG: &str = "v0.10.1";
|
||||
const TAG: &str = "v0.11.1";
|
||||
// NOTE: the version of the unsafe contract lags the main tag, but the v0.9.2.1 code is compatible
|
||||
// with the unmodified v0.10.1 contract
|
||||
// with the unmodified v0.11.1 contract
|
||||
const UNSAFE_TAG: &str = "v0.9.2.1";
|
||||
|
||||
fn spec_url() -> String {
|
||||
|
||||
@@ -1,23 +1,40 @@
|
||||
use ethabi::{Contract, Token};
|
||||
use ssz::Encode;
|
||||
use ssz::{Decode, DecodeError as SszDecodeError, Encode};
|
||||
use tree_hash::TreeHash;
|
||||
use types::DepositData;
|
||||
use types::{DepositData, Hash256, PublicKeyBytes, SignatureBytes};
|
||||
|
||||
pub use ethabi::Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DecodeError {
|
||||
EthabiError(ethabi::Error),
|
||||
SszDecodeError(SszDecodeError),
|
||||
MissingField,
|
||||
UnableToGetBytes,
|
||||
MissingToken,
|
||||
InadequateBytes,
|
||||
}
|
||||
|
||||
impl From<ethabi::Error> for DecodeError {
|
||||
fn from(e: ethabi::Error) -> DecodeError {
|
||||
DecodeError::EthabiError(e)
|
||||
}
|
||||
}
|
||||
|
||||
pub const CONTRACT_DEPLOY_GAS: usize = 4_000_000;
|
||||
pub const DEPOSIT_GAS: usize = 4_000_000;
|
||||
pub const ABI: &[u8] = include_bytes!("../contracts/v0.10.1_validator_registration.json");
|
||||
pub const BYTECODE: &[u8] = include_bytes!("../contracts/v0.10.1_validator_registration.bytecode");
|
||||
pub const ABI: &[u8] = include_bytes!("../contracts/v0.11.1_validator_registration.json");
|
||||
pub const BYTECODE: &[u8] = include_bytes!("../contracts/v0.11.1_validator_registration.bytecode");
|
||||
pub const DEPOSIT_DATA_LEN: usize = 420; // lol
|
||||
|
||||
pub mod testnet {
|
||||
pub const ABI: &[u8] =
|
||||
include_bytes!("../contracts/v0.10.1_testnet_validator_registration.json");
|
||||
include_bytes!("../contracts/v0.11.1_testnet_validator_registration.json");
|
||||
pub const BYTECODE: &[u8] =
|
||||
include_bytes!("../contracts/v0.10.1_testnet_validator_registration.bytecode");
|
||||
include_bytes!("../contracts/v0.11.1_testnet_validator_registration.bytecode");
|
||||
}
|
||||
|
||||
pub fn eth1_tx_data(deposit_data: &DepositData) -> Result<Vec<u8>, Error> {
|
||||
pub fn encode_eth1_tx_data(deposit_data: &DepositData) -> Result<Vec<u8>, Error> {
|
||||
let params = vec![
|
||||
Token::Bytes(deposit_data.pubkey.as_ssz_bytes()),
|
||||
Token::Bytes(deposit_data.withdrawal_credentials.as_ssz_bytes()),
|
||||
@@ -32,6 +49,40 @@ pub fn eth1_tx_data(deposit_data: &DepositData) -> Result<Vec<u8>, Error> {
|
||||
function.encode_input(¶ms)
|
||||
}
|
||||
|
||||
pub fn decode_eth1_tx_data(
|
||||
bytes: &[u8],
|
||||
amount: u64,
|
||||
) -> Result<(DepositData, Hash256), DecodeError> {
|
||||
let abi = Contract::load(ABI)?;
|
||||
let function = abi.function("deposit")?;
|
||||
let mut tokens =
|
||||
function.decode_input(bytes.get(4..).ok_or_else(|| DecodeError::InadequateBytes)?)?;
|
||||
|
||||
macro_rules! decode_token {
|
||||
($type: ty, $to_fn: ident) => {
|
||||
<$type>::from_ssz_bytes(
|
||||
&tokens
|
||||
.pop()
|
||||
.ok_or_else(|| DecodeError::MissingToken)?
|
||||
.$to_fn()
|
||||
.ok_or_else(|| DecodeError::UnableToGetBytes)?,
|
||||
)
|
||||
.map_err(DecodeError::SszDecodeError)?
|
||||
};
|
||||
};
|
||||
|
||||
let root = decode_token!(Hash256, to_fixed_bytes);
|
||||
|
||||
let deposit_data = DepositData {
|
||||
amount,
|
||||
signature: decode_token!(SignatureBytes, to_bytes),
|
||||
withdrawal_credentials: decode_token!(Hash256, to_bytes),
|
||||
pubkey: decode_token!(PublicKeyBytes, to_bytes),
|
||||
};
|
||||
|
||||
Ok((deposit_data, root))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -54,14 +105,27 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic() {
|
||||
fn round_trip() {
|
||||
let spec = &E::default_spec();
|
||||
|
||||
let keypair = generate_deterministic_keypair(42);
|
||||
let deposit = get_deposit(keypair, spec);
|
||||
let original = get_deposit(keypair, spec);
|
||||
|
||||
let data = eth1_tx_data(&deposit).expect("should produce tx data");
|
||||
let data = encode_eth1_tx_data(&original).expect("should produce tx data");
|
||||
|
||||
assert_eq!(data.len(), 420, "bytes should be correct length");
|
||||
assert_eq!(
|
||||
data.len(),
|
||||
DEPOSIT_DATA_LEN,
|
||||
"bytes should be correct length"
|
||||
);
|
||||
|
||||
let (decoded, root) = decode_eth1_tx_data(&data, original.amount).expect("should decode");
|
||||
|
||||
assert_eq!(decoded, original, "decoded should match original");
|
||||
assert_eq!(
|
||||
root,
|
||||
original.tree_hash_root(),
|
||||
"decode root should match original root"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,23 +8,29 @@ use std::path::PathBuf;
|
||||
const TESTNET_ID: &str = "testnet5";
|
||||
|
||||
fn main() {
|
||||
match get_all_files() {
|
||||
Ok(()) => (),
|
||||
Err(e) => panic!(e),
|
||||
if !base_dir().exists() {
|
||||
std::fs::create_dir_all(base_dir()).expect(&format!("Unable to create {:?}", base_dir()));
|
||||
|
||||
match get_all_files() {
|
||||
Ok(()) => (),
|
||||
Err(e) => {
|
||||
std::fs::remove_dir_all(base_dir()).expect(&format!(
|
||||
"{}. Failed to remove {:?}, please remove the directory manually because it may contains incomplete testnet data.",
|
||||
e,
|
||||
base_dir(),
|
||||
));
|
||||
panic!(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_all_files() -> Result<(), String> {
|
||||
if !base_dir().exists() {
|
||||
std::fs::create_dir_all(base_dir())
|
||||
.map_err(|e| format!("Unable to create {:?}: {}", base_dir(), e))?;
|
||||
|
||||
get_file("boot_enr.yaml")?;
|
||||
get_file("config.yaml")?;
|
||||
get_file("deploy_block.txt")?;
|
||||
get_file("deposit_contract.txt")?;
|
||||
get_file("genesis.ssz")?;
|
||||
}
|
||||
get_file("boot_enr.yaml")?;
|
||||
get_file("config.yaml")?;
|
||||
get_file("deploy_block.txt")?;
|
||||
get_file("deposit_contract.txt")?;
|
||||
get_file("genesis.ssz")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -156,11 +156,11 @@ impl<E: EthSpec> Eth2TestnetConfig<E> {
|
||||
let yaml_config = optional_load_from_file!(YAML_CONFIG_FILE);
|
||||
|
||||
// The genesis state is a special case because it uses SSZ, not YAML.
|
||||
let file = base_dir.join(GENESIS_STATE_FILE);
|
||||
let genesis_state = if base_dir.join(&file).exists() {
|
||||
let genesis_file_path = base_dir.join(GENESIS_STATE_FILE);
|
||||
let genesis_state = if genesis_file_path.exists() {
|
||||
Some(
|
||||
File::open(base_dir.join(&file))
|
||||
.map_err(|e| format!("Unable to open {:?}: {:?}", file, e))
|
||||
File::open(&genesis_file_path)
|
||||
.map_err(|e| format!("Unable to open {:?}: {:?}", genesis_file_path, e))
|
||||
.and_then(|mut file| {
|
||||
let mut bytes = vec![];
|
||||
file.read_to_end(&mut bytes)
|
||||
@@ -202,6 +202,7 @@ mod tests {
|
||||
|
||||
type E = MainnetEthSpec;
|
||||
|
||||
/* TODO: disabled until testnet config is updated for v0.11
|
||||
#[test]
|
||||
fn hard_coded_works() {
|
||||
let dir: Eth2TestnetConfig<E> =
|
||||
@@ -211,6 +212,7 @@ mod tests {
|
||||
assert!(dir.genesis_state.is_some());
|
||||
assert!(dir.yaml_config.is_some());
|
||||
}
|
||||
*/
|
||||
|
||||
#[test]
|
||||
fn round_trip() {
|
||||
|
||||
@@ -32,10 +32,8 @@ pub fn int_to_bytes3(int: u32) -> Option<Vec<u8>> {
|
||||
}
|
||||
|
||||
/// Returns `int` as little-endian bytes with a length of 4.
|
||||
pub fn int_to_bytes4(int: u32) -> Vec<u8> {
|
||||
let mut bytes = BytesMut::with_capacity(4);
|
||||
bytes.put_u32_le(int);
|
||||
bytes.to_vec()
|
||||
pub fn int_to_bytes4(int: u32) -> [u8; 4] {
|
||||
int.to_le_bytes()
|
||||
}
|
||||
|
||||
/// Returns `int` as little-endian bytes with a length of 8.
|
||||
@@ -128,7 +126,7 @@ mod tests {
|
||||
1 => assert_eq!(int_to_bytes1(int as u8), bytes),
|
||||
2 => assert_eq!(int_to_bytes2(int as u16), bytes),
|
||||
3 => assert_eq!(int_to_bytes3(int as u32), Some(bytes)),
|
||||
4 => assert_eq!(int_to_bytes4(int as u32), bytes),
|
||||
4 => assert_eq!(&int_to_bytes4(int as u32)[..], &bytes[..]),
|
||||
8 => assert_eq!(int_to_bytes8(int), bytes),
|
||||
32 => assert_eq!(int_to_bytes32(int), bytes),
|
||||
48 => assert_eq!(int_to_bytes48(int), bytes),
|
||||
|
||||
@@ -15,16 +15,17 @@ use std::marker::PhantomData;
|
||||
use std::time::Duration;
|
||||
use types::{
|
||||
Attestation, AttestationData, AttesterSlashing, BeaconBlock, BeaconState, CommitteeIndex,
|
||||
Epoch, EthSpec, Fork, Hash256, ProposerSlashing, PublicKey, Signature, SignedAggregateAndProof,
|
||||
SignedBeaconBlock, Slot,
|
||||
Epoch, EthSpec, Fork, Hash256, ProposerSlashing, PublicKey, PublicKeyBytes, Signature,
|
||||
SignedAggregateAndProof, SignedBeaconBlock, Slot,
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
pub use operation_pool::PersistedOperationPool;
|
||||
pub use proto_array_fork_choice::core::ProtoArray;
|
||||
pub use rest_types::{
|
||||
CanonicalHeadResponse, Committee, HeadBeaconBlock, ValidatorDutiesRequest, ValidatorDutyBytes,
|
||||
ValidatorRequest, ValidatorResponse, ValidatorSubscription,
|
||||
CanonicalHeadResponse, Committee, HeadBeaconBlock, IndividualVotesRequest,
|
||||
IndividualVotesResponse, ValidatorDutiesRequest, ValidatorDutyBytes, ValidatorRequest,
|
||||
ValidatorResponse, ValidatorSubscription,
|
||||
};
|
||||
|
||||
// Setting a long timeout for debug ensures that crypto-heavy operations can still succeed.
|
||||
@@ -110,6 +111,10 @@ impl<E: EthSpec> HttpClient<E> {
|
||||
Advanced(self.clone())
|
||||
}
|
||||
|
||||
pub fn consensus(&self) -> Consensus<E> {
|
||||
Consensus(self.clone())
|
||||
}
|
||||
|
||||
fn url(&self, path: &str) -> Result<Url, Error> {
|
||||
self.url.join(path).map_err(|e| e.into())
|
||||
}
|
||||
@@ -388,6 +393,14 @@ impl<E: EthSpec> Beacon<E> {
|
||||
.and_then(move |url| client.json_get(url, vec![]))
|
||||
}
|
||||
|
||||
/// Returns the genesis validators root.
|
||||
pub fn get_genesis_validators_root(&self) -> impl Future<Item = Hash256, Error = Error> {
|
||||
let client = self.0.clone();
|
||||
self.url("genesis_validators_root")
|
||||
.into_future()
|
||||
.and_then(move |url| client.json_get(url, vec![]))
|
||||
}
|
||||
|
||||
/// Returns the fork at the head of the beacon chain.
|
||||
pub fn get_fork(&self) -> impl Future<Item = Fork, Error = Error> {
|
||||
let client = self.0.clone();
|
||||
@@ -674,6 +687,47 @@ impl<E: EthSpec> Advanced<E> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides the functions on the `/consensus` endpoint of the node.
|
||||
#[derive(Clone)]
|
||||
pub struct Consensus<E>(HttpClient<E>);
|
||||
|
||||
impl<E: EthSpec> Consensus<E> {
|
||||
fn url(&self, path: &str) -> Result<Url, Error> {
|
||||
self.0
|
||||
.url("consensus/")
|
||||
.and_then(move |url| url.join(path).map_err(Error::from))
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Gets a `IndividualVote` for each of the given `pubkeys`.
|
||||
pub fn get_individual_votes(
|
||||
&self,
|
||||
epoch: Epoch,
|
||||
pubkeys: Vec<PublicKeyBytes>,
|
||||
) -> impl Future<Item = IndividualVotesResponse, Error = Error> {
|
||||
let client = self.0.clone();
|
||||
let req_body = IndividualVotesRequest { epoch, pubkeys };
|
||||
|
||||
self.url("individual_votes")
|
||||
.into_future()
|
||||
.and_then(move |url| client.json_post::<_>(url, req_body))
|
||||
.and_then(|response| error_for_status(response).map_err(Error::from))
|
||||
.and_then(|mut success| success.json().map_err(Error::from))
|
||||
}
|
||||
|
||||
/// Gets a `VoteCount` for the given `epoch`.
|
||||
pub fn get_vote_count(
|
||||
&self,
|
||||
epoch: Epoch,
|
||||
) -> impl Future<Item = IndividualVotesResponse, Error = Error> {
|
||||
let client = self.0.clone();
|
||||
let query_params = vec![("epoch".into(), format!("{}", epoch.as_u64()))];
|
||||
self.url("vote_count")
|
||||
.into_future()
|
||||
.and_then(move |url| client.json_get(url, query_params))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(bound = "T: EthSpec")]
|
||||
pub struct BlockResponse<T: EthSpec> {
|
||||
|
||||
@@ -10,6 +10,7 @@ eth2_ssz_derive = { path = "../ssz_derive" }
|
||||
eth2_ssz = { path = "../ssz" }
|
||||
eth2_hashing = { path = "../eth2_hashing" }
|
||||
tree_hash = { path = "../tree_hash" }
|
||||
state_processing = { path = "../../state_processing" }
|
||||
bls = { path = "../bls" }
|
||||
serde = { version = "1.0.102", features = ["derive"] }
|
||||
rayon = "1.3.0"
|
||||
|
||||
66
eth2/utils/rest_types/src/consensus.rs
Normal file
66
eth2/utils/rest_types/src/consensus.rs
Normal file
@@ -0,0 +1,66 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use state_processing::per_epoch_processing::ValidatorStatus;
|
||||
use types::{Epoch, PublicKeyBytes};
|
||||
|
||||
#[derive(PartialEq, Debug, Serialize, Deserialize, Clone, Encode, Decode)]
|
||||
pub struct IndividualVotesRequest {
|
||||
pub epoch: Epoch,
|
||||
pub pubkeys: Vec<PublicKeyBytes>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Serialize, Deserialize, Clone, Encode, Decode)]
|
||||
pub struct IndividualVote {
|
||||
/// True if the validator has been slashed, ever.
|
||||
pub is_slashed: bool,
|
||||
/// True if the validator can withdraw in the current epoch.
|
||||
pub is_withdrawable_in_current_epoch: bool,
|
||||
/// True if the validator was active in the state's _current_ epoch.
|
||||
pub is_active_in_current_epoch: bool,
|
||||
/// True if the validator was active in the state's _previous_ epoch.
|
||||
pub is_active_in_previous_epoch: bool,
|
||||
/// The validator's effective balance in the _current_ epoch.
|
||||
pub current_epoch_effective_balance_gwei: u64,
|
||||
/// True if the validator had an attestation included in the _current_ epoch.
|
||||
pub is_current_epoch_attester: bool,
|
||||
/// True if the validator's beacon block root attestation for the first slot of the _current_
|
||||
/// epoch matches the block root known to the state.
|
||||
pub is_current_epoch_target_attester: bool,
|
||||
/// True if the validator had an attestation included in the _previous_ epoch.
|
||||
pub is_previous_epoch_attester: bool,
|
||||
/// True if the validator's beacon block root attestation for the first slot of the _previous_
|
||||
/// epoch matches the block root known to the state.
|
||||
pub is_previous_epoch_target_attester: bool,
|
||||
/// True if the validator's beacon block root attestation in the _previous_ epoch at the
|
||||
/// attestation's slot (`attestation_data.slot`) matches the block root known to the state.
|
||||
pub is_previous_epoch_head_attester: bool,
|
||||
}
|
||||
|
||||
impl Into<IndividualVote> for ValidatorStatus {
|
||||
fn into(self) -> IndividualVote {
|
||||
IndividualVote {
|
||||
is_slashed: self.is_slashed,
|
||||
is_withdrawable_in_current_epoch: self.is_withdrawable_in_current_epoch,
|
||||
is_active_in_current_epoch: self.is_active_in_current_epoch,
|
||||
is_active_in_previous_epoch: self.is_active_in_previous_epoch,
|
||||
current_epoch_effective_balance_gwei: self.current_epoch_effective_balance,
|
||||
is_current_epoch_attester: self.is_current_epoch_attester,
|
||||
is_current_epoch_target_attester: self.is_current_epoch_target_attester,
|
||||
is_previous_epoch_attester: self.is_previous_epoch_attester,
|
||||
is_previous_epoch_target_attester: self.is_previous_epoch_target_attester,
|
||||
is_previous_epoch_head_attester: self.is_previous_epoch_head_attester,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Serialize, Deserialize, Clone, Encode, Decode)]
|
||||
pub struct IndividualVotesResponse {
|
||||
/// The epoch which is considered the "current" epoch.
|
||||
pub epoch: Epoch,
|
||||
/// The validators public key.
|
||||
pub pubkey: PublicKeyBytes,
|
||||
/// The index of the validator in state.validators.
|
||||
pub validator_index: Option<usize>,
|
||||
/// Voting statistics for the validator, if they voted in the given epoch.
|
||||
pub vote: Option<IndividualVote>,
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
//! This is primarily used by the validator client and the beacon node rest API.
|
||||
|
||||
mod beacon;
|
||||
mod consensus;
|
||||
mod validator;
|
||||
|
||||
pub use beacon::{
|
||||
@@ -13,3 +14,5 @@ pub use beacon::{
|
||||
pub use validator::{
|
||||
ValidatorDutiesRequest, ValidatorDuty, ValidatorDutyBytes, ValidatorSubscription,
|
||||
};
|
||||
|
||||
pub use consensus::{IndividualVote, IndividualVotesRequest, IndividualVotesResponse};
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
//! format designed for use in Ethereum 2.0.
|
||||
//!
|
||||
//! Adheres to the Ethereum 2.0 [SSZ
|
||||
//! specification](https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/ssz/simple-serialize.md)
|
||||
//! at v0.10.1.
|
||||
//! specification](https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/ssz/simple-serialize.md)
|
||||
//! at v0.11.1.
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
//! for padding and verification.
|
||||
//!
|
||||
//! Adheres to the Ethereum 2.0 [SSZ
|
||||
//! specification](https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/ssz/simple-serialize.md)
|
||||
//! at v0.10.1.
|
||||
//! specification](https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/ssz/simple-serialize.md)
|
||||
//! at v0.11.1.
|
||||
//!
|
||||
//! ## Example
|
||||
//! ```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! Provides list-shuffling functions matching the Ethereum 2.0 specification.
|
||||
//!
|
||||
//! See
|
||||
//! [compute_shuffled_index](https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/specs/phase0/beacon-chain.md#compute_shuffled_index)
|
||||
//! [compute_shuffled_index](https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/specs/phase0/beacon-chain.md#compute_shuffled_index)
|
||||
//! for specifications.
|
||||
//!
|
||||
//! There are two functions exported by this crate:
|
||||
|
||||
@@ -54,7 +54,7 @@ fn bench_suite<T: EthSpec>(c: &mut Criterion, spec_desc: &str, validator_count:
|
||||
b.iter_batched_ref(
|
||||
|| state2.clone(),
|
||||
|state| {
|
||||
assert!(!state.tree_hash_cache.is_initialized());
|
||||
assert!(state.tree_hash_cache.is_none());
|
||||
black_box(state.update_tree_hash_cache().unwrap())
|
||||
},
|
||||
criterion::BatchSize::SmallInput,
|
||||
@@ -72,7 +72,7 @@ fn bench_suite<T: EthSpec>(c: &mut Criterion, spec_desc: &str, validator_count:
|
||||
b.iter_batched_ref(
|
||||
|| state3.clone(),
|
||||
|state| {
|
||||
assert!(state.tree_hash_cache.is_initialized());
|
||||
assert!(state.tree_hash_cache.is_some());
|
||||
black_box(state.update_tree_hash_cache().unwrap())
|
||||
},
|
||||
criterion::BatchSize::SmallInput,
|
||||
|
||||
Reference in New Issue
Block a user