Merge branch 'master' into ssz-derive
This commit is contained in:
commit
a78256c778
@ -1,7 +1,7 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
"eth2/attester",
|
"eth2/attester",
|
||||||
"eth2/block_producer",
|
"eth2/block_proposer",
|
||||||
"eth2/fork_choice",
|
"eth2/fork_choice",
|
||||||
"eth2/state_processing",
|
"eth2/state_processing",
|
||||||
"eth2/types",
|
"eth2/types",
|
||||||
|
@ -5,7 +5,7 @@ authors = ["Paul Hauner <paul@paulhauner.com>"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
block_producer = { path = "../../eth2/block_producer" }
|
block_proposer = { path = "../../eth2/block_proposer" }
|
||||||
bls = { path = "../../eth2/utils/bls" }
|
bls = { path = "../../eth2/utils/bls" }
|
||||||
boolean-bitfield = { path = "../../eth2/utils/boolean-bitfield" }
|
boolean-bitfield = { path = "../../eth2/utils/boolean-bitfield" }
|
||||||
db = { path = "../db" }
|
db = { path = "../db" }
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::cached_beacon_state::CachedBeaconState;
|
||||||
use state_processing::validate_attestation_without_signature;
|
use state_processing::validate_attestation_without_signature;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use types::{
|
use types::{
|
||||||
@ -76,12 +77,12 @@ impl AttestationAggregator {
|
|||||||
/// - The signature is verified against that of the validator at `validator_index`.
|
/// - The signature is verified against that of the validator at `validator_index`.
|
||||||
pub fn process_free_attestation(
|
pub fn process_free_attestation(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &BeaconState,
|
cached_state: &CachedBeaconState,
|
||||||
free_attestation: &FreeAttestation,
|
free_attestation: &FreeAttestation,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<Outcome, BeaconStateError> {
|
) -> Result<Outcome, BeaconStateError> {
|
||||||
let (slot, shard, committee_index) = some_or_invalid!(
|
let (slot, shard, committee_index) = some_or_invalid!(
|
||||||
state.attestation_slot_and_shard_for_validator(
|
cached_state.attestation_slot_and_shard_for_validator(
|
||||||
free_attestation.validator_index as usize,
|
free_attestation.validator_index as usize,
|
||||||
spec,
|
spec,
|
||||||
)?,
|
)?,
|
||||||
@ -104,7 +105,8 @@ impl AttestationAggregator {
|
|||||||
let signable_message = free_attestation.data.signable_message(PHASE_0_CUSTODY_BIT);
|
let signable_message = free_attestation.data.signable_message(PHASE_0_CUSTODY_BIT);
|
||||||
|
|
||||||
let validator_record = some_or_invalid!(
|
let validator_record = some_or_invalid!(
|
||||||
state
|
cached_state
|
||||||
|
.state
|
||||||
.validator_registry
|
.validator_registry
|
||||||
.get(free_attestation.validator_index as usize),
|
.get(free_attestation.validator_index as usize),
|
||||||
Message::BadValidatorIndex
|
Message::BadValidatorIndex
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::attestation_aggregator::{AttestationAggregator, Outcome as AggregationOutcome};
|
use crate::attestation_aggregator::{AttestationAggregator, Outcome as AggregationOutcome};
|
||||||
|
use crate::cached_beacon_state::CachedBeaconState;
|
||||||
use crate::checkpoint::CheckPoint;
|
use crate::checkpoint::CheckPoint;
|
||||||
use db::{
|
use db::{
|
||||||
stores::{BeaconBlockStore, BeaconStateStore},
|
stores::{BeaconBlockStore, BeaconStateStore},
|
||||||
@ -69,6 +70,7 @@ pub struct BeaconChain<T: ClientDB + Sized, U: SlotClock, F: ForkChoice> {
|
|||||||
canonical_head: RwLock<CheckPoint>,
|
canonical_head: RwLock<CheckPoint>,
|
||||||
finalized_head: RwLock<CheckPoint>,
|
finalized_head: RwLock<CheckPoint>,
|
||||||
pub state: RwLock<BeaconState>,
|
pub state: RwLock<BeaconState>,
|
||||||
|
pub cached_state: RwLock<CachedBeaconState>,
|
||||||
pub spec: ChainSpec,
|
pub spec: ChainSpec,
|
||||||
pub fork_choice: RwLock<F>,
|
pub fork_choice: RwLock<F>,
|
||||||
}
|
}
|
||||||
@ -107,6 +109,11 @@ where
|
|||||||
let block_root = genesis_block.canonical_root();
|
let block_root = genesis_block.canonical_root();
|
||||||
block_store.put(&block_root, &ssz_encode(&genesis_block)[..])?;
|
block_store.put(&block_root, &ssz_encode(&genesis_block)[..])?;
|
||||||
|
|
||||||
|
let cached_state = RwLock::new(CachedBeaconState::from_beacon_state(
|
||||||
|
genesis_state.clone(),
|
||||||
|
spec.clone(),
|
||||||
|
)?);
|
||||||
|
|
||||||
let finalized_head = RwLock::new(CheckPoint::new(
|
let finalized_head = RwLock::new(CheckPoint::new(
|
||||||
genesis_block.clone(),
|
genesis_block.clone(),
|
||||||
block_root,
|
block_root,
|
||||||
@ -127,6 +134,7 @@ where
|
|||||||
slot_clock,
|
slot_clock,
|
||||||
attestation_aggregator,
|
attestation_aggregator,
|
||||||
state: RwLock::new(genesis_state.clone()),
|
state: RwLock::new(genesis_state.clone()),
|
||||||
|
cached_state,
|
||||||
finalized_head,
|
finalized_head,
|
||||||
canonical_head,
|
canonical_head,
|
||||||
spec,
|
spec,
|
||||||
@ -253,6 +261,7 @@ where
|
|||||||
/// Information is read from the present `beacon_state` shuffling, so only information from the
|
/// Information is read from the present `beacon_state` shuffling, so only information from the
|
||||||
/// present and prior epoch is available.
|
/// present and prior epoch is available.
|
||||||
pub fn block_proposer(&self, slot: Slot) -> Result<usize, BeaconStateError> {
|
pub fn block_proposer(&self, slot: Slot) -> Result<usize, BeaconStateError> {
|
||||||
|
trace!("BeaconChain::block_proposer: slot: {}", slot);
|
||||||
let index = self
|
let index = self
|
||||||
.state
|
.state
|
||||||
.read()
|
.read()
|
||||||
@ -274,8 +283,12 @@ where
|
|||||||
&self,
|
&self,
|
||||||
validator_index: usize,
|
validator_index: usize,
|
||||||
) -> Result<Option<(Slot, u64)>, BeaconStateError> {
|
) -> Result<Option<(Slot, u64)>, BeaconStateError> {
|
||||||
|
trace!(
|
||||||
|
"BeaconChain::validator_attestion_slot_and_shard: validator_index: {}",
|
||||||
|
validator_index
|
||||||
|
);
|
||||||
if let Some((slot, shard, _committee)) = self
|
if let Some((slot, shard, _committee)) = self
|
||||||
.state
|
.cached_state
|
||||||
.read()
|
.read()
|
||||||
.attestation_slot_and_shard_for_validator(validator_index, &self.spec)?
|
.attestation_slot_and_shard_for_validator(validator_index, &self.spec)?
|
||||||
{
|
{
|
||||||
@ -287,6 +300,7 @@ where
|
|||||||
|
|
||||||
/// Produce an `AttestationData` that is valid for the present `slot` and given `shard`.
|
/// Produce an `AttestationData` that is valid for the present `slot` and given `shard`.
|
||||||
pub fn produce_attestation_data(&self, shard: u64) -> Result<AttestationData, Error> {
|
pub fn produce_attestation_data(&self, shard: u64) -> Result<AttestationData, Error> {
|
||||||
|
trace!("BeaconChain::produce_attestation_data: shard: {}", shard);
|
||||||
let justified_epoch = self.justified_epoch();
|
let justified_epoch = self.justified_epoch();
|
||||||
let justified_block_root = *self
|
let justified_block_root = *self
|
||||||
.state
|
.state
|
||||||
@ -332,9 +346,7 @@ where
|
|||||||
let aggregation_outcome = self
|
let aggregation_outcome = self
|
||||||
.attestation_aggregator
|
.attestation_aggregator
|
||||||
.write()
|
.write()
|
||||||
.process_free_attestation(&self.state.read(), &free_attestation, &self.spec)?;
|
.process_free_attestation(&self.cached_state.read(), &free_attestation, &self.spec)?;
|
||||||
// TODO: Check this comment
|
|
||||||
//.map_err(|e| e.into())?;
|
|
||||||
|
|
||||||
// return if the attestation is invalid
|
// return if the attestation is invalid
|
||||||
if !aggregation_outcome.valid {
|
if !aggregation_outcome.valid {
|
||||||
@ -489,6 +501,9 @@ where
|
|||||||
);
|
);
|
||||||
// Update the local state variable.
|
// Update the local state variable.
|
||||||
*self.state.write() = state.clone();
|
*self.state.write() = state.clone();
|
||||||
|
// Update the cached state variable.
|
||||||
|
*self.cached_state.write() =
|
||||||
|
CachedBeaconState::from_beacon_state(state.clone(), self.spec.clone())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(BlockProcessingOutcome::ValidBlock(ValidBlock::Processed))
|
Ok(BlockProcessingOutcome::ValidBlock(ValidBlock::Processed))
|
||||||
@ -537,9 +552,15 @@ where
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
state
|
trace!("BeaconChain::produce_block: updating state for new block.",);
|
||||||
.per_block_processing_without_verifying_block_signature(&block, &self.spec)
|
|
||||||
.ok()?;
|
let result =
|
||||||
|
state.per_block_processing_without_verifying_block_signature(&block, &self.spec);
|
||||||
|
trace!(
|
||||||
|
"BeaconNode::produce_block: state processing result: {:?}",
|
||||||
|
result
|
||||||
|
);
|
||||||
|
result.ok()?;
|
||||||
|
|
||||||
let state_root = state.canonical_root();
|
let state_root = state.canonical_root();
|
||||||
|
|
||||||
|
150
beacon_node/beacon_chain/src/cached_beacon_state.rs
Normal file
150
beacon_node/beacon_chain/src/cached_beacon_state.rs
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
use log::{debug, trace};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use types::{beacon_state::BeaconStateError, BeaconState, ChainSpec, Epoch, Slot};
|
||||||
|
|
||||||
|
pub const CACHE_PREVIOUS: bool = false;
|
||||||
|
pub const CACHE_CURRENT: bool = true;
|
||||||
|
pub const CACHE_NEXT: bool = false;
|
||||||
|
|
||||||
|
pub type CrosslinkCommittees = Vec<(Vec<usize>, u64)>;
|
||||||
|
pub type Shard = u64;
|
||||||
|
pub type CommitteeIndex = u64;
|
||||||
|
pub type AttestationDuty = (Slot, Shard, CommitteeIndex);
|
||||||
|
pub type AttestationDutyMap = HashMap<u64, AttestationDuty>;
|
||||||
|
|
||||||
|
// TODO: CachedBeaconState is presently duplicating `BeaconState` and `ChainSpec`. This is a
|
||||||
|
// massive memory waste, switch them to references.
|
||||||
|
|
||||||
|
pub struct CachedBeaconState {
|
||||||
|
pub state: BeaconState,
|
||||||
|
committees: Vec<Vec<CrosslinkCommittees>>,
|
||||||
|
attestation_duties: Vec<AttestationDutyMap>,
|
||||||
|
next_epoch: Epoch,
|
||||||
|
current_epoch: Epoch,
|
||||||
|
previous_epoch: Epoch,
|
||||||
|
spec: ChainSpec,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CachedBeaconState {
|
||||||
|
pub fn from_beacon_state(
|
||||||
|
state: BeaconState,
|
||||||
|
spec: ChainSpec,
|
||||||
|
) -> Result<Self, BeaconStateError> {
|
||||||
|
let current_epoch = state.current_epoch(&spec);
|
||||||
|
let previous_epoch = if current_epoch == spec.genesis_epoch {
|
||||||
|
current_epoch
|
||||||
|
} else {
|
||||||
|
current_epoch.saturating_sub(1_u64)
|
||||||
|
};
|
||||||
|
let next_epoch = state.next_epoch(&spec);
|
||||||
|
|
||||||
|
let mut committees: Vec<Vec<CrosslinkCommittees>> = Vec::with_capacity(3);
|
||||||
|
let mut attestation_duties: Vec<AttestationDutyMap> = Vec::with_capacity(3);
|
||||||
|
|
||||||
|
if CACHE_PREVIOUS {
|
||||||
|
debug!("from_beacon_state: building previous epoch cache.");
|
||||||
|
let cache = build_epoch_cache(&state, previous_epoch, &spec)?;
|
||||||
|
committees.push(cache.committees);
|
||||||
|
attestation_duties.push(cache.attestation_duty_map);
|
||||||
|
} else {
|
||||||
|
committees.push(vec![]);
|
||||||
|
attestation_duties.push(HashMap::new());
|
||||||
|
}
|
||||||
|
if CACHE_CURRENT {
|
||||||
|
debug!("from_beacon_state: building current epoch cache.");
|
||||||
|
let cache = build_epoch_cache(&state, current_epoch, &spec)?;
|
||||||
|
committees.push(cache.committees);
|
||||||
|
attestation_duties.push(cache.attestation_duty_map);
|
||||||
|
} else {
|
||||||
|
committees.push(vec![]);
|
||||||
|
attestation_duties.push(HashMap::new());
|
||||||
|
}
|
||||||
|
if CACHE_NEXT {
|
||||||
|
debug!("from_beacon_state: building next epoch cache.");
|
||||||
|
let cache = build_epoch_cache(&state, next_epoch, &spec)?;
|
||||||
|
committees.push(cache.committees);
|
||||||
|
attestation_duties.push(cache.attestation_duty_map);
|
||||||
|
} else {
|
||||||
|
committees.push(vec![]);
|
||||||
|
attestation_duties.push(HashMap::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
state,
|
||||||
|
committees,
|
||||||
|
attestation_duties,
|
||||||
|
next_epoch,
|
||||||
|
current_epoch,
|
||||||
|
previous_epoch,
|
||||||
|
spec,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn slot_to_cache_index(&self, slot: Slot) -> Option<usize> {
|
||||||
|
trace!("slot_to_cache_index: cache lookup");
|
||||||
|
match slot.epoch(self.spec.epoch_length) {
|
||||||
|
epoch if (epoch == self.previous_epoch) & CACHE_PREVIOUS => Some(0),
|
||||||
|
epoch if (epoch == self.current_epoch) & CACHE_CURRENT => Some(1),
|
||||||
|
epoch if (epoch == self.next_epoch) & CACHE_NEXT => Some(2),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the `slot`, `shard` and `committee_index` for which a validator must produce an
|
||||||
|
/// attestation.
|
||||||
|
///
|
||||||
|
/// Cached method.
|
||||||
|
///
|
||||||
|
/// Spec v0.2.0
|
||||||
|
pub fn attestation_slot_and_shard_for_validator(
|
||||||
|
&self,
|
||||||
|
validator_index: usize,
|
||||||
|
_spec: &ChainSpec,
|
||||||
|
) -> Result<Option<(Slot, u64, u64)>, BeaconStateError> {
|
||||||
|
// Get the result for this epoch.
|
||||||
|
let cache_index = self
|
||||||
|
.slot_to_cache_index(self.state.slot)
|
||||||
|
.expect("Current epoch should always have a cache index.");
|
||||||
|
|
||||||
|
let duties = self.attestation_duties[cache_index]
|
||||||
|
.get(&(validator_index as u64))
|
||||||
|
.and_then(|tuple| Some(*tuple));
|
||||||
|
|
||||||
|
Ok(duties)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EpochCacheResult {
|
||||||
|
committees: Vec<CrosslinkCommittees>,
|
||||||
|
attestation_duty_map: AttestationDutyMap,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_epoch_cache(
|
||||||
|
state: &BeaconState,
|
||||||
|
epoch: Epoch,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> Result<EpochCacheResult, BeaconStateError> {
|
||||||
|
let mut epoch_committees: Vec<CrosslinkCommittees> =
|
||||||
|
Vec::with_capacity(spec.epoch_length as usize);
|
||||||
|
let mut attestation_duty_map: AttestationDutyMap = HashMap::new();
|
||||||
|
|
||||||
|
for slot in epoch.slot_iter(spec.epoch_length) {
|
||||||
|
let slot_committees = state.get_crosslink_committees_at_slot(slot, false, spec)?;
|
||||||
|
|
||||||
|
for (committee, shard) in slot_committees {
|
||||||
|
for (committee_index, validator_index) in committee.iter().enumerate() {
|
||||||
|
attestation_duty_map.insert(
|
||||||
|
*validator_index as u64,
|
||||||
|
(slot, shard, committee_index as u64),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
epoch_committees.push(state.get_crosslink_committees_at_slot(slot, false, spec)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(EpochCacheResult {
|
||||||
|
committees: epoch_committees,
|
||||||
|
attestation_duty_map,
|
||||||
|
})
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
mod attestation_aggregator;
|
mod attestation_aggregator;
|
||||||
mod beacon_chain;
|
mod beacon_chain;
|
||||||
|
mod cached_beacon_state;
|
||||||
mod checkpoint;
|
mod checkpoint;
|
||||||
|
|
||||||
pub use self::beacon_chain::{BeaconChain, Error};
|
pub use self::beacon_chain::{BeaconChain, Error};
|
||||||
|
@ -14,7 +14,7 @@ criterion = "0.2"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
attester = { path = "../../../eth2/attester" }
|
attester = { path = "../../../eth2/attester" }
|
||||||
beacon_chain = { path = "../../beacon_chain" }
|
beacon_chain = { path = "../../beacon_chain" }
|
||||||
block_producer = { path = "../../../eth2/block_producer" }
|
block_proposer = { path = "../../../eth2/block_proposer" }
|
||||||
bls = { path = "../../../eth2/utils/bls" }
|
bls = { path = "../../../eth2/utils/bls" }
|
||||||
boolean-bitfield = { path = "../../../eth2/utils/boolean-bitfield" }
|
boolean-bitfield = { path = "../../../eth2/utils/boolean-bitfield" }
|
||||||
db = { path = "../../db" }
|
db = { path = "../../db" }
|
||||||
|
@ -128,7 +128,18 @@ impl BeaconChainHarness {
|
|||||||
pub fn increment_beacon_chain_slot(&mut self) -> Slot {
|
pub fn increment_beacon_chain_slot(&mut self) -> Slot {
|
||||||
let slot = self.beacon_chain.present_slot() + 1;
|
let slot = self.beacon_chain.present_slot() + 1;
|
||||||
|
|
||||||
debug!("Incrementing BeaconChain slot to {}.", slot);
|
let nth_slot = slot
|
||||||
|
- slot
|
||||||
|
.epoch(self.spec.epoch_length)
|
||||||
|
.start_slot(self.spec.epoch_length);
|
||||||
|
let nth_epoch = slot.epoch(self.spec.epoch_length) - self.spec.genesis_epoch;
|
||||||
|
debug!(
|
||||||
|
"Advancing BeaconChain to slot {}, epoch {} (epoch height: {}, slot {} in epoch.).",
|
||||||
|
slot,
|
||||||
|
slot.epoch(self.spec.epoch_length),
|
||||||
|
nth_epoch,
|
||||||
|
nth_slot
|
||||||
|
);
|
||||||
|
|
||||||
self.beacon_chain.slot_clock.set_slot(slot.as_u64());
|
self.beacon_chain.slot_clock.set_slot(slot.as_u64());
|
||||||
self.beacon_chain.advance_state(slot).unwrap();
|
self.beacon_chain.advance_state(slot).unwrap();
|
||||||
@ -209,6 +220,7 @@ impl BeaconChainHarness {
|
|||||||
self.increment_beacon_chain_slot();
|
self.increment_beacon_chain_slot();
|
||||||
|
|
||||||
// Produce a new block.
|
// Produce a new block.
|
||||||
|
debug!("Producing block...");
|
||||||
let block = self.produce_block();
|
let block = self.produce_block();
|
||||||
debug!("Submitting block for processing...");
|
debug!("Submitting block for processing...");
|
||||||
self.beacon_chain.process_block(block).unwrap();
|
self.beacon_chain.process_block(block).unwrap();
|
||||||
|
@ -3,7 +3,7 @@ use attester::{
|
|||||||
PublishOutcome as AttestationPublishOutcome,
|
PublishOutcome as AttestationPublishOutcome,
|
||||||
};
|
};
|
||||||
use beacon_chain::BeaconChain;
|
use beacon_chain::BeaconChain;
|
||||||
use block_producer::{
|
use block_proposer::{
|
||||||
BeaconNode as BeaconBlockNode, BeaconNodeError as BeaconBlockNodeError,
|
BeaconNode as BeaconBlockNode, BeaconNodeError as BeaconBlockNodeError,
|
||||||
PublishOutcome as BlockPublishOutcome,
|
PublishOutcome as BlockPublishOutcome,
|
||||||
};
|
};
|
||||||
|
@ -2,7 +2,7 @@ use attester::{
|
|||||||
DutiesReader as AttesterDutiesReader, DutiesReaderError as AttesterDutiesReaderError,
|
DutiesReader as AttesterDutiesReader, DutiesReaderError as AttesterDutiesReaderError,
|
||||||
};
|
};
|
||||||
use beacon_chain::BeaconChain;
|
use beacon_chain::BeaconChain;
|
||||||
use block_producer::{
|
use block_proposer::{
|
||||||
DutiesReader as ProducerDutiesReader, DutiesReaderError as ProducerDutiesReaderError,
|
DutiesReader as ProducerDutiesReader, DutiesReaderError as ProducerDutiesReaderError,
|
||||||
};
|
};
|
||||||
use db::ClientDB;
|
use db::ClientDB;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use attester::Signer as AttesterSigner;
|
use attester::Signer as AttesterSigner;
|
||||||
use block_producer::Signer as BlockProposerSigner;
|
use block_proposer::Signer as BlockProposerSigner;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
use types::{Keypair, Signature};
|
use types::{Keypair, Signature};
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@ mod local_signer;
|
|||||||
use attester::PollOutcome as AttestationPollOutcome;
|
use attester::PollOutcome as AttestationPollOutcome;
|
||||||
use attester::{Attester, Error as AttestationPollError};
|
use attester::{Attester, Error as AttestationPollError};
|
||||||
use beacon_chain::BeaconChain;
|
use beacon_chain::BeaconChain;
|
||||||
use block_producer::PollOutcome as BlockPollOutcome;
|
use block_proposer::PollOutcome as BlockPollOutcome;
|
||||||
use block_producer::{BlockProducer, Error as BlockPollError};
|
use block_proposer::{BlockProducer, Error as BlockPollError};
|
||||||
use db::MemoryDB;
|
use db::MemoryDB;
|
||||||
use direct_beacon_node::DirectBeaconNode;
|
use direct_beacon_node::DirectBeaconNode;
|
||||||
use direct_duties::DirectDuties;
|
use direct_duties::DirectDuties;
|
||||||
|
@ -1,19 +1,14 @@
|
|||||||
use env_logger::{Builder, Env};
|
use env_logger::{Builder, Env};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use test_harness::BeaconChainHarness;
|
use test_harness::BeaconChainHarness;
|
||||||
use types::{ChainSpec, Slot};
|
use types::ChainSpec;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
|
||||||
fn it_can_build_on_genesis_block() {
|
fn it_can_build_on_genesis_block() {
|
||||||
let mut spec = ChainSpec::foundation();
|
Builder::from_env(Env::default().default_filter_or("info")).init();
|
||||||
spec.genesis_slot = Slot::new(spec.epoch_length * 8);
|
|
||||||
|
|
||||||
/*
|
let spec = ChainSpec::few_validators();
|
||||||
spec.shard_count = spec.shard_count / 8;
|
let validator_count = 8;
|
||||||
spec.target_committee_size = spec.target_committee_size / 8;
|
|
||||||
*/
|
|
||||||
let validator_count = 1000;
|
|
||||||
|
|
||||||
let mut harness = BeaconChainHarness::new(spec, validator_count as usize);
|
let mut harness = BeaconChainHarness::new(spec, validator_count as usize);
|
||||||
|
|
||||||
@ -23,21 +18,22 @@ fn it_can_build_on_genesis_block() {
|
|||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn it_can_produce_past_first_epoch_boundary() {
|
fn it_can_produce_past_first_epoch_boundary() {
|
||||||
Builder::from_env(Env::default().default_filter_or("debug")).init();
|
Builder::from_env(Env::default().default_filter_or("info")).init();
|
||||||
|
|
||||||
let validator_count = 100;
|
let spec = ChainSpec::few_validators();
|
||||||
|
let validator_count = 8;
|
||||||
|
|
||||||
debug!("Starting harness build...");
|
debug!("Starting harness build...");
|
||||||
|
|
||||||
let mut harness = BeaconChainHarness::new(ChainSpec::foundation(), validator_count);
|
let mut harness = BeaconChainHarness::new(spec, validator_count);
|
||||||
|
|
||||||
debug!("Harness built, tests starting..");
|
debug!("Harness built, tests starting..");
|
||||||
|
|
||||||
let blocks = harness.spec.epoch_length * 3 + 1;
|
let blocks = harness.spec.epoch_length * 2 + 1;
|
||||||
|
|
||||||
for i in 0..blocks {
|
for i in 0..blocks {
|
||||||
harness.advance_chain_with_block();
|
harness.advance_chain_with_block();
|
||||||
debug!("Produced block {}/{}.", i, blocks);
|
debug!("Produced block {}/{}.", i + 1, blocks);
|
||||||
}
|
}
|
||||||
let dump = harness.chain_dump().expect("Chain dump failed.");
|
let dump = harness.chain_dump().expect("Chain dump failed.");
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "block_producer"
|
name = "block_proposer"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
@ -236,7 +236,7 @@ mod tests {
|
|||||||
epoch_map.map.insert(produce_epoch, produce_slot);
|
epoch_map.map.insert(produce_epoch, produce_slot);
|
||||||
let epoch_map = Arc::new(epoch_map);
|
let epoch_map = Arc::new(epoch_map);
|
||||||
|
|
||||||
let mut block_producer = BlockProducer::new(
|
let mut block_proposer = BlockProducer::new(
|
||||||
spec.clone(),
|
spec.clone(),
|
||||||
epoch_map.clone(),
|
epoch_map.clone(),
|
||||||
slot_clock.clone(),
|
slot_clock.clone(),
|
||||||
@ -251,28 +251,28 @@ mod tests {
|
|||||||
// One slot before production slot...
|
// One slot before production slot...
|
||||||
slot_clock.set_slot(produce_slot.as_u64() - 1);
|
slot_clock.set_slot(produce_slot.as_u64() - 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
block_producer.poll(),
|
block_proposer.poll(),
|
||||||
Ok(PollOutcome::BlockProductionNotRequired(produce_slot - 1))
|
Ok(PollOutcome::BlockProductionNotRequired(produce_slot - 1))
|
||||||
);
|
);
|
||||||
|
|
||||||
// On the produce slot...
|
// On the produce slot...
|
||||||
slot_clock.set_slot(produce_slot.as_u64());
|
slot_clock.set_slot(produce_slot.as_u64());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
block_producer.poll(),
|
block_proposer.poll(),
|
||||||
Ok(PollOutcome::BlockProduced(produce_slot.into()))
|
Ok(PollOutcome::BlockProduced(produce_slot.into()))
|
||||||
);
|
);
|
||||||
|
|
||||||
// Trying the same produce slot again...
|
// Trying the same produce slot again...
|
||||||
slot_clock.set_slot(produce_slot.as_u64());
|
slot_clock.set_slot(produce_slot.as_u64());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
block_producer.poll(),
|
block_proposer.poll(),
|
||||||
Ok(PollOutcome::SlotAlreadyProcessed(produce_slot))
|
Ok(PollOutcome::SlotAlreadyProcessed(produce_slot))
|
||||||
);
|
);
|
||||||
|
|
||||||
// One slot after the produce slot...
|
// One slot after the produce slot...
|
||||||
slot_clock.set_slot(produce_slot.as_u64() + 1);
|
slot_clock.set_slot(produce_slot.as_u64() + 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
block_producer.poll(),
|
block_proposer.poll(),
|
||||||
Ok(PollOutcome::BlockProductionNotRequired(produce_slot + 1))
|
Ok(PollOutcome::BlockProductionNotRequired(produce_slot + 1))
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -280,7 +280,7 @@ mod tests {
|
|||||||
let slot = (produce_epoch.as_u64() + 1) * spec.epoch_length;
|
let slot = (produce_epoch.as_u64() + 1) * spec.epoch_length;
|
||||||
slot_clock.set_slot(slot);
|
slot_clock.set_slot(slot);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
block_producer.poll(),
|
block_proposer.poll(),
|
||||||
Ok(PollOutcome::ProducerDutiesUnknown(Slot::new(slot)))
|
Ok(PollOutcome::ProducerDutiesUnknown(Slot::new(slot)))
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
use crate::SlotProcessingError;
|
use crate::SlotProcessingError;
|
||||||
use hashing::hash;
|
use hashing::hash;
|
||||||
use int_to_bytes::int_to_bytes32;
|
use int_to_bytes::int_to_bytes32;
|
||||||
use log::debug;
|
use log::{debug, trace};
|
||||||
use ssz::{ssz_encode, TreeHash};
|
use ssz::{ssz_encode, TreeHash};
|
||||||
use types::{
|
use types::{
|
||||||
beacon_state::{AttestationParticipantsError, BeaconStateError},
|
beacon_state::{AttestationParticipantsError, BeaconStateError},
|
||||||
@ -219,6 +219,8 @@ fn per_block_processing_signature_optional(
|
|||||||
Error::MaxAttestationsExceeded
|
Error::MaxAttestationsExceeded
|
||||||
);
|
);
|
||||||
|
|
||||||
|
debug!("Verifying {} attestations.", block.body.attestations.len());
|
||||||
|
|
||||||
for attestation in &block.body.attestations {
|
for attestation in &block.body.attestations {
|
||||||
validate_attestation(&state, attestation, spec)?;
|
validate_attestation(&state, attestation, spec)?;
|
||||||
|
|
||||||
@ -231,11 +233,6 @@ fn per_block_processing_signature_optional(
|
|||||||
state.latest_attestations.push(pending_attestation);
|
state.latest_attestations.push(pending_attestation);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!(
|
|
||||||
"{} attestations verified & processed.",
|
|
||||||
block.body.attestations.len()
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deposits
|
* Deposits
|
||||||
*/
|
*/
|
||||||
@ -312,6 +309,10 @@ fn validate_attestation_signature_optional(
|
|||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
verify_signature: bool,
|
verify_signature: bool,
|
||||||
) -> Result<(), AttestationValidationError> {
|
) -> Result<(), AttestationValidationError> {
|
||||||
|
trace!(
|
||||||
|
"validate_attestation_signature_optional: attestation epoch: {}",
|
||||||
|
attestation.data.slot.epoch(spec.epoch_length)
|
||||||
|
);
|
||||||
ensure!(
|
ensure!(
|
||||||
attestation.data.slot + spec.min_attestation_inclusion_delay <= state.slot,
|
attestation.data.slot + spec.min_attestation_inclusion_delay <= state.slot,
|
||||||
AttestationValidationError::IncludedTooEarly
|
AttestationValidationError::IncludedTooEarly
|
||||||
|
@ -144,8 +144,10 @@ impl EpochProcessable for BeaconState {
|
|||||||
|
|
||||||
let previous_epoch_attester_indices =
|
let previous_epoch_attester_indices =
|
||||||
self.get_attestation_participants_union(&previous_epoch_attestations[..], spec)?;
|
self.get_attestation_participants_union(&previous_epoch_attestations[..], spec)?;
|
||||||
let previous_total_balance =
|
let previous_total_balance = self.get_total_balance(
|
||||||
self.get_total_balance(&previous_epoch_attester_indices[..], spec);
|
&get_active_validator_indices(&self.validator_registry, previous_epoch),
|
||||||
|
spec,
|
||||||
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Validators targetting the previous justified slot
|
* Validators targetting the previous justified slot
|
||||||
@ -315,6 +317,11 @@ impl EpochProcessable for BeaconState {
|
|||||||
|
|
||||||
// for slot in self.slot.saturating_sub(2 * spec.epoch_length)..self.slot {
|
// for slot in self.slot.saturating_sub(2 * spec.epoch_length)..self.slot {
|
||||||
for slot in self.previous_epoch(spec).slot_iter(spec.epoch_length) {
|
for slot in self.previous_epoch(spec).slot_iter(spec.epoch_length) {
|
||||||
|
trace!(
|
||||||
|
"Finding winning root for slot: {} (epoch: {})",
|
||||||
|
slot,
|
||||||
|
slot.epoch(spec.epoch_length)
|
||||||
|
);
|
||||||
let crosslink_committees_at_slot =
|
let crosslink_committees_at_slot =
|
||||||
self.get_crosslink_committees_at_slot(slot, false, spec)?;
|
self.get_crosslink_committees_at_slot(slot, false, spec)?;
|
||||||
|
|
||||||
@ -352,7 +359,8 @@ impl EpochProcessable for BeaconState {
|
|||||||
/*
|
/*
|
||||||
* Rewards and Penalities
|
* Rewards and Penalities
|
||||||
*/
|
*/
|
||||||
let base_reward_quotient = previous_total_balance.integer_sqrt();
|
let base_reward_quotient =
|
||||||
|
previous_total_balance.integer_sqrt() / spec.base_reward_quotient;
|
||||||
if base_reward_quotient == 0 {
|
if base_reward_quotient == 0 {
|
||||||
return Err(Error::BaseRewardQuotientIsZero);
|
return Err(Error::BaseRewardQuotientIsZero);
|
||||||
}
|
}
|
||||||
@ -539,6 +547,12 @@ impl EpochProcessable for BeaconState {
|
|||||||
*/
|
*/
|
||||||
self.previous_calculation_epoch = self.current_calculation_epoch;
|
self.previous_calculation_epoch = self.current_calculation_epoch;
|
||||||
self.previous_epoch_start_shard = self.current_epoch_start_shard;
|
self.previous_epoch_start_shard = self.current_epoch_start_shard;
|
||||||
|
|
||||||
|
debug!(
|
||||||
|
"setting previous_epoch_seed to : {}",
|
||||||
|
self.current_epoch_seed
|
||||||
|
);
|
||||||
|
|
||||||
self.previous_epoch_seed = self.current_epoch_seed;
|
self.previous_epoch_seed = self.current_epoch_seed;
|
||||||
|
|
||||||
let should_update_validator_registy = if self.finalized_epoch
|
let should_update_validator_registy = if self.finalized_epoch
|
||||||
@ -553,6 +567,7 @@ impl EpochProcessable for BeaconState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if should_update_validator_registy {
|
if should_update_validator_registy {
|
||||||
|
trace!("updating validator registry.");
|
||||||
self.update_validator_registry(spec);
|
self.update_validator_registry(spec);
|
||||||
|
|
||||||
self.current_calculation_epoch = next_epoch;
|
self.current_calculation_epoch = next_epoch;
|
||||||
@ -561,6 +576,7 @@ impl EpochProcessable for BeaconState {
|
|||||||
% spec.shard_count;
|
% spec.shard_count;
|
||||||
self.current_epoch_seed = self.generate_seed(self.current_calculation_epoch, spec)?
|
self.current_epoch_seed = self.generate_seed(self.current_calculation_epoch, spec)?
|
||||||
} else {
|
} else {
|
||||||
|
trace!("not updating validator registry.");
|
||||||
let epochs_since_last_registry_update =
|
let epochs_since_last_registry_update =
|
||||||
current_epoch - self.validator_registry_update_epoch;
|
current_epoch - self.validator_registry_update_epoch;
|
||||||
if (epochs_since_last_registry_update > 1)
|
if (epochs_since_last_registry_update > 1)
|
||||||
|
@ -35,12 +35,12 @@ impl Attestation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for Attestation {
|
impl TreeHash for Attestation {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.aggregation_bitfield.hash_tree_root());
|
result.append(&mut self.aggregation_bitfield.hash_tree_root_internal());
|
||||||
result.append(&mut self.data.hash_tree_root());
|
result.append(&mut self.data.hash_tree_root_internal());
|
||||||
result.append(&mut self.custody_bitfield.hash_tree_root());
|
result.append(&mut self.custody_bitfield.hash_tree_root_internal());
|
||||||
result.append(&mut self.aggregate_signature.hash_tree_root());
|
result.append(&mut self.aggregate_signature.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,11 +74,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = Attestation::random_for_test(&mut rng);
|
let original = Attestation::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -45,16 +45,16 @@ impl AttestationData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for AttestationData {
|
impl TreeHash for AttestationData {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.slot.hash_tree_root());
|
result.append(&mut self.slot.hash_tree_root_internal());
|
||||||
result.append(&mut self.shard.hash_tree_root());
|
result.append(&mut self.shard.hash_tree_root_internal());
|
||||||
result.append(&mut self.beacon_block_root.hash_tree_root());
|
result.append(&mut self.beacon_block_root.hash_tree_root_internal());
|
||||||
result.append(&mut self.epoch_boundary_root.hash_tree_root());
|
result.append(&mut self.epoch_boundary_root.hash_tree_root_internal());
|
||||||
result.append(&mut self.shard_block_root.hash_tree_root());
|
result.append(&mut self.shard_block_root.hash_tree_root_internal());
|
||||||
result.append(&mut self.latest_crosslink.hash_tree_root());
|
result.append(&mut self.latest_crosslink.hash_tree_root_internal());
|
||||||
result.append(&mut self.justified_epoch.hash_tree_root());
|
result.append(&mut self.justified_epoch.hash_tree_root_internal());
|
||||||
result.append(&mut self.justified_block_root.hash_tree_root());
|
result.append(&mut self.justified_block_root.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,11 +92,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = AttestationData::random_for_test(&mut rng);
|
let original = AttestationData::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -12,11 +12,11 @@ pub struct AttestationDataAndCustodyBit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for AttestationDataAndCustodyBit {
|
impl TreeHash for AttestationDataAndCustodyBit {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.data.hash_tree_root());
|
result.append(&mut self.data.hash_tree_root_internal());
|
||||||
// TODO: add bool ssz
|
// TODO: add bool ssz
|
||||||
// result.append(custody_bit.hash_tree_root());
|
// result.append(custody_bit.hash_tree_root_internal());
|
||||||
ssz::hash(&result)
|
ssz::hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,11 +51,11 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = AttestationDataAndCustodyBit::random_for_test(&mut rng);
|
let original = AttestationDataAndCustodyBit::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -11,10 +11,10 @@ pub struct AttesterSlashing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for AttesterSlashing {
|
impl TreeHash for AttesterSlashing {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.slashable_attestation_1.hash_tree_root());
|
result.append(&mut self.slashable_attestation_1.hash_tree_root_internal());
|
||||||
result.append(&mut self.slashable_attestation_2.hash_tree_root());
|
result.append(&mut self.slashable_attestation_2.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,11 +46,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = AttesterSlashing::random_for_test(&mut rng);
|
let original = AttesterSlashing::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -61,15 +61,15 @@ impl BeaconBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for BeaconBlock {
|
impl TreeHash for BeaconBlock {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.slot.hash_tree_root());
|
result.append(&mut self.slot.hash_tree_root_internal());
|
||||||
result.append(&mut self.parent_root.hash_tree_root());
|
result.append(&mut self.parent_root.hash_tree_root_internal());
|
||||||
result.append(&mut self.state_root.hash_tree_root());
|
result.append(&mut self.state_root.hash_tree_root_internal());
|
||||||
result.append(&mut self.randao_reveal.hash_tree_root());
|
result.append(&mut self.randao_reveal.hash_tree_root_internal());
|
||||||
result.append(&mut self.eth1_data.hash_tree_root());
|
result.append(&mut self.eth1_data.hash_tree_root_internal());
|
||||||
result.append(&mut self.signature.hash_tree_root());
|
result.append(&mut self.signature.hash_tree_root_internal());
|
||||||
result.append(&mut self.body.hash_tree_root());
|
result.append(&mut self.body.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,11 +106,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = BeaconBlock::random_for_test(&mut rng);
|
let original = BeaconBlock::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -15,13 +15,13 @@ pub struct BeaconBlockBody {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for BeaconBlockBody {
|
impl TreeHash for BeaconBlockBody {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.proposer_slashings.hash_tree_root());
|
result.append(&mut self.proposer_slashings.hash_tree_root_internal());
|
||||||
result.append(&mut self.attester_slashings.hash_tree_root());
|
result.append(&mut self.attester_slashings.hash_tree_root_internal());
|
||||||
result.append(&mut self.attestations.hash_tree_root());
|
result.append(&mut self.attestations.hash_tree_root_internal());
|
||||||
result.append(&mut self.deposits.hash_tree_root());
|
result.append(&mut self.deposits.hash_tree_root_internal());
|
||||||
result.append(&mut self.exits.hash_tree_root());
|
result.append(&mut self.exits.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,11 +56,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = BeaconBlockBody::random_for_test(&mut rng);
|
let original = BeaconBlockBody::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -6,6 +6,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use bls::verify_proof_of_possession;
|
use bls::verify_proof_of_possession;
|
||||||
use honey_badger_split::SplitExt;
|
use honey_badger_split::SplitExt;
|
||||||
|
use log::trace;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use serde_derive::Serialize;
|
use serde_derive::Serialize;
|
||||||
use ssz::{hash, Decodable, DecodeError, Encodable, SszStream, TreeHash};
|
use ssz::{hash, Decodable, DecodeError, Encodable, SszStream, TreeHash};
|
||||||
@ -205,7 +206,12 @@ impl BeaconState {
|
|||||||
///
|
///
|
||||||
/// Spec v0.2.0
|
/// Spec v0.2.0
|
||||||
pub fn previous_epoch(&self, spec: &ChainSpec) -> Epoch {
|
pub fn previous_epoch(&self, spec: &ChainSpec) -> Epoch {
|
||||||
self.current_epoch(spec).saturating_sub(1_u64)
|
let current_epoch = self.current_epoch(&spec);
|
||||||
|
if current_epoch == spec.genesis_epoch {
|
||||||
|
current_epoch
|
||||||
|
} else {
|
||||||
|
current_epoch - 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The epoch following `self.current_epoch()`.
|
/// The epoch following `self.current_epoch()`.
|
||||||
@ -262,11 +268,25 @@ impl BeaconState {
|
|||||||
let active_validator_indices =
|
let active_validator_indices =
|
||||||
get_active_validator_indices(&self.validator_registry, epoch);
|
get_active_validator_indices(&self.validator_registry, epoch);
|
||||||
|
|
||||||
|
if active_validator_indices.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace!(
|
||||||
|
"get_shuffling: active_validator_indices.len() == {}",
|
||||||
|
active_validator_indices.len()
|
||||||
|
);
|
||||||
|
|
||||||
let committees_per_epoch =
|
let committees_per_epoch =
|
||||||
self.get_epoch_committee_count(active_validator_indices.len(), spec);
|
self.get_epoch_committee_count(active_validator_indices.len(), spec);
|
||||||
|
|
||||||
let mut shuffled_active_validator_indices =
|
trace!(
|
||||||
Vec::with_capacity(active_validator_indices.len());
|
"get_shuffling: active_validator_indices.len() == {}, committees_per_epoch: {}",
|
||||||
|
active_validator_indices.len(),
|
||||||
|
committees_per_epoch
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut shuffled_active_validator_indices = vec![0; active_validator_indices.len()];
|
||||||
for &i in &active_validator_indices {
|
for &i in &active_validator_indices {
|
||||||
let shuffled_i = get_permutated_index(
|
let shuffled_i = get_permutated_index(
|
||||||
i,
|
i,
|
||||||
@ -320,9 +340,17 @@ impl BeaconState {
|
|||||||
+ 1;
|
+ 1;
|
||||||
let latest_index_root = current_epoch + spec.entry_exit_delay;
|
let latest_index_root = current_epoch + spec.entry_exit_delay;
|
||||||
|
|
||||||
|
trace!(
|
||||||
|
"get_active_index_root: epoch: {}, earliest: {}, latest: {}",
|
||||||
|
epoch,
|
||||||
|
earliest_index_root,
|
||||||
|
latest_index_root
|
||||||
|
);
|
||||||
|
|
||||||
if (epoch >= earliest_index_root) & (epoch <= latest_index_root) {
|
if (epoch >= earliest_index_root) & (epoch <= latest_index_root) {
|
||||||
Some(self.latest_index_roots[epoch.as_usize() % spec.latest_index_roots_length])
|
Some(self.latest_index_roots[epoch.as_usize() % spec.latest_index_roots_length])
|
||||||
} else {
|
} else {
|
||||||
|
trace!("get_active_index_root: epoch out of range.");
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -367,29 +395,28 @@ impl BeaconState {
|
|||||||
) -> Result<Vec<(Vec<usize>, u64)>, BeaconStateError> {
|
) -> Result<Vec<(Vec<usize>, u64)>, BeaconStateError> {
|
||||||
let epoch = slot.epoch(spec.epoch_length);
|
let epoch = slot.epoch(spec.epoch_length);
|
||||||
let current_epoch = self.current_epoch(spec);
|
let current_epoch = self.current_epoch(spec);
|
||||||
let previous_epoch = if current_epoch == spec.genesis_epoch {
|
let previous_epoch = self.previous_epoch(spec);
|
||||||
current_epoch
|
|
||||||
} else {
|
|
||||||
current_epoch.saturating_sub(1_u64)
|
|
||||||
};
|
|
||||||
let next_epoch = self.next_epoch(spec);
|
let next_epoch = self.next_epoch(spec);
|
||||||
|
|
||||||
let (committees_per_epoch, seed, shuffling_epoch, shuffling_start_shard) =
|
let (committees_per_epoch, seed, shuffling_epoch, shuffling_start_shard) =
|
||||||
if epoch == previous_epoch {
|
if epoch == current_epoch {
|
||||||
(
|
trace!("get_crosslink_committees_at_slot: current_epoch");
|
||||||
self.get_previous_epoch_committee_count(spec),
|
|
||||||
self.previous_epoch_seed,
|
|
||||||
self.previous_calculation_epoch,
|
|
||||||
self.previous_epoch_start_shard,
|
|
||||||
)
|
|
||||||
} else if epoch == current_epoch {
|
|
||||||
(
|
(
|
||||||
self.get_current_epoch_committee_count(spec),
|
self.get_current_epoch_committee_count(spec),
|
||||||
self.current_epoch_seed,
|
self.current_epoch_seed,
|
||||||
self.current_calculation_epoch,
|
self.current_calculation_epoch,
|
||||||
self.current_epoch_start_shard,
|
self.current_epoch_start_shard,
|
||||||
)
|
)
|
||||||
|
} else if epoch == previous_epoch {
|
||||||
|
trace!("get_crosslink_committees_at_slot: previous_epoch");
|
||||||
|
(
|
||||||
|
self.get_previous_epoch_committee_count(spec),
|
||||||
|
self.previous_epoch_seed,
|
||||||
|
self.previous_calculation_epoch,
|
||||||
|
self.previous_epoch_start_shard,
|
||||||
|
)
|
||||||
} else if epoch == next_epoch {
|
} else if epoch == next_epoch {
|
||||||
|
trace!("get_crosslink_committees_at_slot: next_epoch");
|
||||||
let current_committees_per_epoch = self.get_current_epoch_committee_count(spec);
|
let current_committees_per_epoch = self.get_current_epoch_committee_count(spec);
|
||||||
let epochs_since_last_registry_update =
|
let epochs_since_last_registry_update =
|
||||||
current_epoch - self.validator_registry_update_epoch;
|
current_epoch - self.validator_registry_update_epoch;
|
||||||
@ -426,6 +453,13 @@ impl BeaconState {
|
|||||||
let slot_start_shard =
|
let slot_start_shard =
|
||||||
(shuffling_start_shard + committees_per_slot * offset) % spec.shard_count;
|
(shuffling_start_shard + committees_per_slot * offset) % spec.shard_count;
|
||||||
|
|
||||||
|
trace!(
|
||||||
|
"get_crosslink_committees_at_slot: committees_per_slot: {}, slot_start_shard: {}, seed: {}",
|
||||||
|
committees_per_slot,
|
||||||
|
slot_start_shard,
|
||||||
|
seed
|
||||||
|
);
|
||||||
|
|
||||||
let mut crosslinks_at_slot = vec![];
|
let mut crosslinks_at_slot = vec![];
|
||||||
for i in 0..committees_per_slot {
|
for i in 0..committees_per_slot {
|
||||||
let tuple = (
|
let tuple = (
|
||||||
@ -477,6 +511,11 @@ impl BeaconState {
|
|||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<usize, BeaconStateError> {
|
) -> Result<usize, BeaconStateError> {
|
||||||
let committees = self.get_crosslink_committees_at_slot(slot, false, spec)?;
|
let committees = self.get_crosslink_committees_at_slot(slot, false, spec)?;
|
||||||
|
trace!(
|
||||||
|
"get_beacon_proposer_index: slot: {}, committees_count: {}",
|
||||||
|
slot,
|
||||||
|
committees.len()
|
||||||
|
);
|
||||||
committees
|
committees
|
||||||
.first()
|
.first()
|
||||||
.ok_or(BeaconStateError::InsufficientValidators)
|
.ok_or(BeaconStateError::InsufficientValidators)
|
||||||
@ -930,33 +969,37 @@ impl From<AttestationParticipantsError> for InclusionError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for BeaconState {
|
impl TreeHash for BeaconState {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.slot.hash_tree_root());
|
result.append(&mut self.slot.hash_tree_root_internal());
|
||||||
result.append(&mut self.genesis_time.hash_tree_root());
|
result.append(&mut self.genesis_time.hash_tree_root_internal());
|
||||||
result.append(&mut self.fork.hash_tree_root());
|
result.append(&mut self.fork.hash_tree_root_internal());
|
||||||
result.append(&mut self.validator_registry.hash_tree_root());
|
result.append(&mut self.validator_registry.hash_tree_root_internal());
|
||||||
result.append(&mut self.validator_balances.hash_tree_root());
|
result.append(&mut self.validator_balances.hash_tree_root_internal());
|
||||||
result.append(&mut self.validator_registry_update_epoch.hash_tree_root());
|
result.append(
|
||||||
result.append(&mut self.latest_randao_mixes.hash_tree_root());
|
&mut self
|
||||||
result.append(&mut self.previous_epoch_start_shard.hash_tree_root());
|
.validator_registry_update_epoch
|
||||||
result.append(&mut self.current_epoch_start_shard.hash_tree_root());
|
.hash_tree_root_internal(),
|
||||||
result.append(&mut self.previous_calculation_epoch.hash_tree_root());
|
);
|
||||||
result.append(&mut self.current_calculation_epoch.hash_tree_root());
|
result.append(&mut self.latest_randao_mixes.hash_tree_root_internal());
|
||||||
result.append(&mut self.previous_epoch_seed.hash_tree_root());
|
result.append(&mut self.previous_epoch_start_shard.hash_tree_root_internal());
|
||||||
result.append(&mut self.current_epoch_seed.hash_tree_root());
|
result.append(&mut self.current_epoch_start_shard.hash_tree_root_internal());
|
||||||
result.append(&mut self.previous_justified_epoch.hash_tree_root());
|
result.append(&mut self.previous_calculation_epoch.hash_tree_root_internal());
|
||||||
result.append(&mut self.justified_epoch.hash_tree_root());
|
result.append(&mut self.current_calculation_epoch.hash_tree_root_internal());
|
||||||
result.append(&mut self.justification_bitfield.hash_tree_root());
|
result.append(&mut self.previous_epoch_seed.hash_tree_root_internal());
|
||||||
result.append(&mut self.finalized_epoch.hash_tree_root());
|
result.append(&mut self.current_epoch_seed.hash_tree_root_internal());
|
||||||
result.append(&mut self.latest_crosslinks.hash_tree_root());
|
result.append(&mut self.previous_justified_epoch.hash_tree_root_internal());
|
||||||
result.append(&mut self.latest_block_roots.hash_tree_root());
|
result.append(&mut self.justified_epoch.hash_tree_root_internal());
|
||||||
result.append(&mut self.latest_index_roots.hash_tree_root());
|
result.append(&mut self.justification_bitfield.hash_tree_root_internal());
|
||||||
result.append(&mut self.latest_penalized_balances.hash_tree_root());
|
result.append(&mut self.finalized_epoch.hash_tree_root_internal());
|
||||||
result.append(&mut self.latest_attestations.hash_tree_root());
|
result.append(&mut self.latest_crosslinks.hash_tree_root_internal());
|
||||||
result.append(&mut self.batched_block_roots.hash_tree_root());
|
result.append(&mut self.latest_block_roots.hash_tree_root_internal());
|
||||||
result.append(&mut self.latest_eth1_data.hash_tree_root());
|
result.append(&mut self.latest_index_roots.hash_tree_root_internal());
|
||||||
result.append(&mut self.eth1_data_votes.hash_tree_root());
|
result.append(&mut self.latest_penalized_balances.hash_tree_root_internal());
|
||||||
|
result.append(&mut self.latest_attestations.hash_tree_root_internal());
|
||||||
|
result.append(&mut self.batched_block_roots.hash_tree_root_internal());
|
||||||
|
result.append(&mut self.latest_eth1_data.hash_tree_root_internal());
|
||||||
|
result.append(&mut self.eth1_data_votes.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,11 +85,11 @@ pub fn test_ssz_round_trip() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = BeaconState::random_for_test(&mut rng);
|
let original = BeaconState::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -12,10 +12,10 @@ pub struct CasperSlashing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for CasperSlashing {
|
impl TreeHash for CasperSlashing {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.slashable_vote_data_1.hash_tree_root());
|
result.append(&mut self.slashable_vote_data_1.hash_tree_root_internal());
|
||||||
result.append(&mut self.slashable_vote_data_2.hash_tree_root());
|
result.append(&mut self.slashable_vote_data_2.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -47,11 +47,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = CasperSlashing::random_for_test(&mut rng);
|
let original = CasperSlashing::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -1,7 +1,96 @@
|
|||||||
use crate::{Address, ChainSpec, Epoch, Hash256, Signature, Slot};
|
use crate::{Address, Epoch, Hash256, Slot};
|
||||||
|
use bls::Signature;
|
||||||
|
|
||||||
const GWEI: u64 = 1_000_000_000;
|
const GWEI: u64 = 1_000_000_000;
|
||||||
|
|
||||||
|
/// Holds all the "constants" for a BeaconChain.
|
||||||
|
///
|
||||||
|
/// Spec v0.2.0
|
||||||
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
|
pub struct ChainSpec {
|
||||||
|
/*
|
||||||
|
* Misc
|
||||||
|
*/
|
||||||
|
pub shard_count: u64,
|
||||||
|
pub target_committee_size: u64,
|
||||||
|
pub max_balance_churn_quotient: u64,
|
||||||
|
pub beacon_chain_shard_number: u64,
|
||||||
|
pub max_indices_per_slashable_vote: u64,
|
||||||
|
pub max_withdrawals_per_epoch: u64,
|
||||||
|
pub shuffle_round_count: u8,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deposit contract
|
||||||
|
*/
|
||||||
|
pub deposit_contract_address: Address,
|
||||||
|
pub deposit_contract_tree_depth: u64,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gwei values
|
||||||
|
*/
|
||||||
|
pub min_deposit_amount: u64,
|
||||||
|
pub max_deposit_amount: u64,
|
||||||
|
pub fork_choice_balance_increment: u64,
|
||||||
|
pub ejection_balance: u64,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initial Values
|
||||||
|
*/
|
||||||
|
pub genesis_fork_version: u64,
|
||||||
|
pub genesis_slot: Slot,
|
||||||
|
pub genesis_epoch: Epoch,
|
||||||
|
pub genesis_start_shard: u64,
|
||||||
|
pub far_future_epoch: Epoch,
|
||||||
|
pub zero_hash: Hash256,
|
||||||
|
pub empty_signature: Signature,
|
||||||
|
pub bls_withdrawal_prefix_byte: u8,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Time parameters
|
||||||
|
*/
|
||||||
|
pub slot_duration: u64,
|
||||||
|
pub min_attestation_inclusion_delay: u64,
|
||||||
|
pub epoch_length: u64,
|
||||||
|
pub seed_lookahead: Epoch,
|
||||||
|
pub entry_exit_delay: u64,
|
||||||
|
pub eth1_data_voting_period: u64,
|
||||||
|
pub min_validator_withdrawal_epochs: Epoch,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* State list lengths
|
||||||
|
*/
|
||||||
|
pub latest_block_roots_length: usize,
|
||||||
|
pub latest_randao_mixes_length: usize,
|
||||||
|
pub latest_index_roots_length: usize,
|
||||||
|
pub latest_penalized_exit_length: usize,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reward and penalty quotients
|
||||||
|
*/
|
||||||
|
pub base_reward_quotient: u64,
|
||||||
|
pub whistleblower_reward_quotient: u64,
|
||||||
|
pub includer_reward_quotient: u64,
|
||||||
|
pub inactivity_penalty_quotient: u64,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Max operations per block
|
||||||
|
*/
|
||||||
|
pub max_proposer_slashings: u64,
|
||||||
|
pub max_attester_slashings: u64,
|
||||||
|
pub max_attestations: u64,
|
||||||
|
pub max_deposits: u64,
|
||||||
|
pub max_exits: u64,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signature domains
|
||||||
|
*/
|
||||||
|
pub domain_deposit: u64,
|
||||||
|
pub domain_attestation: u64,
|
||||||
|
pub domain_proposal: u64,
|
||||||
|
pub domain_exit: u64,
|
||||||
|
pub domain_randao: u64,
|
||||||
|
}
|
||||||
|
|
||||||
impl ChainSpec {
|
impl ChainSpec {
|
||||||
/// Returns a `ChainSpec` compatible with the specification from Ethereum Foundation.
|
/// Returns a `ChainSpec` compatible with the specification from Ethereum Foundation.
|
||||||
///
|
///
|
||||||
@ -100,6 +189,26 @@ impl ChainSpec {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ChainSpec {
|
||||||
|
/// Returns a `ChainSpec` compatible with the specification suitable for 8 validators.
|
||||||
|
///
|
||||||
|
/// Spec v0.2.0
|
||||||
|
pub fn few_validators() -> Self {
|
||||||
|
let genesis_slot = Slot::new(2_u64.pow(19));
|
||||||
|
let epoch_length = 8;
|
||||||
|
let genesis_epoch = genesis_slot.epoch(epoch_length);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
shard_count: 1,
|
||||||
|
target_committee_size: 1,
|
||||||
|
genesis_slot,
|
||||||
|
genesis_epoch,
|
||||||
|
epoch_length,
|
||||||
|
..ChainSpec::foundation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
@ -22,10 +22,10 @@ impl Crosslink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for Crosslink {
|
impl TreeHash for Crosslink {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.epoch.hash_tree_root());
|
result.append(&mut self.epoch.hash_tree_root_internal());
|
||||||
result.append(&mut self.shard_block_root.hash_tree_root());
|
result.append(&mut self.shard_block_root.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,11 +57,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = Crosslink::random_for_test(&mut rng);
|
let original = Crosslink::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -13,11 +13,11 @@ pub struct Deposit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for Deposit {
|
impl TreeHash for Deposit {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.branch.hash_tree_root());
|
result.append(&mut self.branch.hash_tree_root_internal());
|
||||||
result.append(&mut self.index.hash_tree_root());
|
result.append(&mut self.index.hash_tree_root_internal());
|
||||||
result.append(&mut self.deposit_data.hash_tree_root());
|
result.append(&mut self.deposit_data.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,11 +50,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = Deposit::random_for_test(&mut rng);
|
let original = Deposit::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -13,11 +13,11 @@ pub struct DepositData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for DepositData {
|
impl TreeHash for DepositData {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.amount.hash_tree_root());
|
result.append(&mut self.amount.hash_tree_root_internal());
|
||||||
result.append(&mut self.timestamp.hash_tree_root());
|
result.append(&mut self.timestamp.hash_tree_root_internal());
|
||||||
result.append(&mut self.deposit_input.hash_tree_root());
|
result.append(&mut self.deposit_input.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,11 +50,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = DepositData::random_for_test(&mut rng);
|
let original = DepositData::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -14,11 +14,11 @@ pub struct DepositInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for DepositInput {
|
impl TreeHash for DepositInput {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.pubkey.hash_tree_root());
|
result.append(&mut self.pubkey.hash_tree_root_internal());
|
||||||
result.append(&mut self.withdrawal_credentials.hash_tree_root());
|
result.append(&mut self.withdrawal_credentials.hash_tree_root_internal());
|
||||||
result.append(&mut self.proof_of_possession.hash_tree_root());
|
result.append(&mut self.proof_of_possession.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,11 +51,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = DepositInput::random_for_test(&mut rng);
|
let original = DepositInput::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -13,10 +13,10 @@ pub struct Eth1Data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for Eth1Data {
|
impl TreeHash for Eth1Data {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.deposit_root.hash_tree_root());
|
result.append(&mut self.deposit_root.hash_tree_root_internal());
|
||||||
result.append(&mut self.block_hash.hash_tree_root());
|
result.append(&mut self.block_hash.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,11 +48,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = Eth1Data::random_for_test(&mut rng);
|
let original = Eth1Data::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -13,10 +13,10 @@ pub struct Eth1DataVote {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for Eth1DataVote {
|
impl TreeHash for Eth1DataVote {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.eth1_data.hash_tree_root());
|
result.append(&mut self.eth1_data.hash_tree_root_internal());
|
||||||
result.append(&mut self.vote_count.hash_tree_root());
|
result.append(&mut self.vote_count.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,11 +48,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = Eth1DataVote::random_for_test(&mut rng);
|
let original = Eth1DataVote::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -13,11 +13,11 @@ pub struct Exit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for Exit {
|
impl TreeHash for Exit {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.epoch.hash_tree_root());
|
result.append(&mut self.epoch.hash_tree_root_internal());
|
||||||
result.append(&mut self.validator_index.hash_tree_root());
|
result.append(&mut self.validator_index.hash_tree_root_internal());
|
||||||
result.append(&mut self.signature.hash_tree_root());
|
result.append(&mut self.signature.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,11 +50,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = Exit::random_for_test(&mut rng);
|
let original = Exit::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -12,11 +12,11 @@ pub struct Fork {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for Fork {
|
impl TreeHash for Fork {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.previous_version.hash_tree_root());
|
result.append(&mut self.previous_version.hash_tree_root_internal());
|
||||||
result.append(&mut self.current_version.hash_tree_root());
|
result.append(&mut self.current_version.hash_tree_root_internal());
|
||||||
result.append(&mut self.epoch.hash_tree_root());
|
result.append(&mut self.epoch.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,11 +49,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = Fork::random_for_test(&mut rng);
|
let original = Fork::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -8,6 +8,7 @@ pub mod beacon_block;
|
|||||||
pub mod beacon_block_body;
|
pub mod beacon_block_body;
|
||||||
pub mod beacon_state;
|
pub mod beacon_state;
|
||||||
pub mod casper_slashing;
|
pub mod casper_slashing;
|
||||||
|
pub mod chain_spec;
|
||||||
pub mod crosslink;
|
pub mod crosslink;
|
||||||
pub mod deposit;
|
pub mod deposit;
|
||||||
pub mod deposit_data;
|
pub mod deposit_data;
|
||||||
@ -28,7 +29,6 @@ pub mod slashable_vote_data;
|
|||||||
pub mod slot_epoch_macros;
|
pub mod slot_epoch_macros;
|
||||||
pub mod slot_epoch;
|
pub mod slot_epoch;
|
||||||
pub mod slot_height;
|
pub mod slot_height;
|
||||||
pub mod spec;
|
|
||||||
pub mod validator;
|
pub mod validator;
|
||||||
pub mod validator_registry;
|
pub mod validator_registry;
|
||||||
pub mod validator_registry_delta_block;
|
pub mod validator_registry_delta_block;
|
||||||
@ -44,6 +44,7 @@ pub use crate::beacon_block::BeaconBlock;
|
|||||||
pub use crate::beacon_block_body::BeaconBlockBody;
|
pub use crate::beacon_block_body::BeaconBlockBody;
|
||||||
pub use crate::beacon_state::BeaconState;
|
pub use crate::beacon_state::BeaconState;
|
||||||
pub use crate::casper_slashing::CasperSlashing;
|
pub use crate::casper_slashing::CasperSlashing;
|
||||||
|
pub use crate::chain_spec::ChainSpec;
|
||||||
pub use crate::crosslink::Crosslink;
|
pub use crate::crosslink::Crosslink;
|
||||||
pub use crate::deposit::Deposit;
|
pub use crate::deposit::Deposit;
|
||||||
pub use crate::deposit_data::DepositData;
|
pub use crate::deposit_data::DepositData;
|
||||||
@ -60,7 +61,6 @@ pub use crate::slashable_attestation::SlashableAttestation;
|
|||||||
pub use crate::slashable_vote_data::SlashableVoteData;
|
pub use crate::slashable_vote_data::SlashableVoteData;
|
||||||
pub use crate::slot_epoch::{Epoch, Slot};
|
pub use crate::slot_epoch::{Epoch, Slot};
|
||||||
pub use crate::slot_height::SlotHeight;
|
pub use crate::slot_height::SlotHeight;
|
||||||
pub use crate::spec::ChainSpec;
|
|
||||||
pub use crate::validator::{StatusFlags as ValidatorStatusFlags, Validator};
|
pub use crate::validator::{StatusFlags as ValidatorStatusFlags, Validator};
|
||||||
pub use crate::validator_registry_delta_block::ValidatorRegistryDeltaBlock;
|
pub use crate::validator_registry_delta_block::ValidatorRegistryDeltaBlock;
|
||||||
|
|
||||||
|
@ -14,12 +14,12 @@ pub struct PendingAttestation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for PendingAttestation {
|
impl TreeHash for PendingAttestation {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.aggregation_bitfield.hash_tree_root());
|
result.append(&mut self.aggregation_bitfield.hash_tree_root_internal());
|
||||||
result.append(&mut self.data.hash_tree_root());
|
result.append(&mut self.data.hash_tree_root_internal());
|
||||||
result.append(&mut self.custody_bitfield.hash_tree_root());
|
result.append(&mut self.custody_bitfield.hash_tree_root_internal());
|
||||||
result.append(&mut self.inclusion_slot.hash_tree_root());
|
result.append(&mut self.inclusion_slot.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,11 +53,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = PendingAttestation::random_for_test(&mut rng);
|
let original = PendingAttestation::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -13,11 +13,11 @@ pub struct ProposalSignedData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for ProposalSignedData {
|
impl TreeHash for ProposalSignedData {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.slot.hash_tree_root());
|
result.append(&mut self.slot.hash_tree_root_internal());
|
||||||
result.append(&mut self.shard.hash_tree_root());
|
result.append(&mut self.shard.hash_tree_root_internal());
|
||||||
result.append(&mut self.block_root.hash_tree_root());
|
result.append(&mut self.block_root.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,11 +50,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = ProposalSignedData::random_for_test(&mut rng);
|
let original = ProposalSignedData::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -16,13 +16,13 @@ pub struct ProposerSlashing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for ProposerSlashing {
|
impl TreeHash for ProposerSlashing {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.proposer_index.hash_tree_root());
|
result.append(&mut self.proposer_index.hash_tree_root_internal());
|
||||||
result.append(&mut self.proposal_data_1.hash_tree_root());
|
result.append(&mut self.proposal_data_1.hash_tree_root_internal());
|
||||||
result.append(&mut self.proposal_signature_1.hash_tree_root());
|
result.append(&mut self.proposal_signature_1.hash_tree_root_internal());
|
||||||
result.append(&mut self.proposal_data_2.hash_tree_root());
|
result.append(&mut self.proposal_data_2.hash_tree_root_internal());
|
||||||
result.append(&mut self.proposal_signature_2.hash_tree_root());
|
result.append(&mut self.proposal_signature_2.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,11 +57,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = ProposerSlashing::random_for_test(&mut rng);
|
let original = ProposerSlashing::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -12,11 +12,11 @@ pub struct ShardReassignmentRecord {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for ShardReassignmentRecord {
|
impl TreeHash for ShardReassignmentRecord {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.validator_index.hash_tree_root());
|
result.append(&mut self.validator_index.hash_tree_root_internal());
|
||||||
result.append(&mut self.shard.hash_tree_root());
|
result.append(&mut self.shard.hash_tree_root_internal());
|
||||||
result.append(&mut self.slot.hash_tree_root());
|
result.append(&mut self.slot.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,11 +49,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = ShardReassignmentRecord::random_for_test(&mut rng);
|
let original = ShardReassignmentRecord::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -13,12 +13,12 @@ pub struct SlashableAttestation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for SlashableAttestation {
|
impl TreeHash for SlashableAttestation {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.validator_indices.hash_tree_root());
|
result.append(&mut self.validator_indices.hash_tree_root_internal());
|
||||||
result.append(&mut self.data.hash_tree_root());
|
result.append(&mut self.data.hash_tree_root_internal());
|
||||||
result.append(&mut self.custody_bitfield.hash_tree_root());
|
result.append(&mut self.custody_bitfield.hash_tree_root_internal());
|
||||||
result.append(&mut self.aggregate_signature.hash_tree_root());
|
result.append(&mut self.aggregate_signature.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,11 +52,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = SlashableAttestation::random_for_test(&mut rng);
|
let original = SlashableAttestation::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use super::AttestationData;
|
use super::AttestationData;
|
||||||
|
use crate::chain_spec::ChainSpec;
|
||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
use bls::AggregateSignature;
|
use bls::AggregateSignature;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
@ -14,13 +15,34 @@ pub struct SlashableVoteData {
|
|||||||
pub aggregate_signature: AggregateSignature,
|
pub aggregate_signature: AggregateSignature,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SlashableVoteData {
|
||||||
|
/// Check if ``attestation_data_1`` and ``attestation_data_2`` have the same target.
|
||||||
|
///
|
||||||
|
/// Spec v0.3.0
|
||||||
|
pub fn is_double_vote(&self, other: &SlashableVoteData, spec: &ChainSpec) -> bool {
|
||||||
|
self.data.slot.epoch(spec.epoch_length) == other.data.slot.epoch(spec.epoch_length)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if ``attestation_data_1`` surrounds ``attestation_data_2``.
|
||||||
|
///
|
||||||
|
/// Spec v0.3.0
|
||||||
|
pub fn is_surround_vote(&self, other: &SlashableVoteData, spec: &ChainSpec) -> bool {
|
||||||
|
let source_epoch_1 = self.data.justified_epoch;
|
||||||
|
let source_epoch_2 = other.data.justified_epoch;
|
||||||
|
let target_epoch_1 = self.data.slot.epoch(spec.epoch_length);
|
||||||
|
let target_epoch_2 = other.data.slot.epoch(spec.epoch_length);
|
||||||
|
|
||||||
|
(source_epoch_1 < source_epoch_2) && (target_epoch_2 < target_epoch_1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TreeHash for SlashableVoteData {
|
impl TreeHash for SlashableVoteData {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.custody_bit_0_indices.hash_tree_root());
|
result.append(&mut self.custody_bit_0_indices.hash_tree_root_internal());
|
||||||
result.append(&mut self.custody_bit_1_indices.hash_tree_root());
|
result.append(&mut self.custody_bit_1_indices.hash_tree_root_internal());
|
||||||
result.append(&mut self.data.hash_tree_root());
|
result.append(&mut self.data.hash_tree_root_internal());
|
||||||
result.append(&mut self.aggregate_signature.hash_tree_root());
|
result.append(&mut self.aggregate_signature.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -39,9 +61,83 @@ impl<T: RngCore> TestRandom<T> for SlashableVoteData {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::chain_spec::ChainSpec;
|
||||||
|
use crate::slot_epoch::{Epoch, Slot};
|
||||||
use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng};
|
use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng};
|
||||||
use ssz::ssz_encode;
|
use ssz::ssz_encode;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn test_is_double_vote_true() {
|
||||||
|
let spec = ChainSpec::foundation();
|
||||||
|
let slashable_vote_first = create_slashable_vote_data(1, 1, &spec);
|
||||||
|
let slashable_vote_second = create_slashable_vote_data(1, 1, &spec);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
slashable_vote_first.is_double_vote(&slashable_vote_second, &spec),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn test_is_double_vote_false() {
|
||||||
|
let spec = ChainSpec::foundation();
|
||||||
|
let slashable_vote_first = create_slashable_vote_data(1, 1, &spec);
|
||||||
|
let slashable_vote_second = create_slashable_vote_data(2, 1, &spec);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
slashable_vote_first.is_double_vote(&slashable_vote_second, &spec),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn test_is_surround_vote_true() {
|
||||||
|
let spec = ChainSpec::foundation();
|
||||||
|
let slashable_vote_first = create_slashable_vote_data(2, 1, &spec);
|
||||||
|
let slashable_vote_second = create_slashable_vote_data(1, 2, &spec);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn test_is_surround_vote_true_realistic() {
|
||||||
|
let spec = ChainSpec::foundation();
|
||||||
|
let slashable_vote_first = create_slashable_vote_data(4, 1, &spec);
|
||||||
|
let slashable_vote_second = create_slashable_vote_data(3, 2, &spec);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn test_is_surround_vote_false_source_epoch_fails() {
|
||||||
|
let spec = ChainSpec::foundation();
|
||||||
|
let slashable_vote_first = create_slashable_vote_data(2, 2, &spec);
|
||||||
|
let slashable_vote_second = create_slashable_vote_data(1, 1, &spec);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn test_is_surround_vote_false_target_epoch_fails() {
|
||||||
|
let spec = ChainSpec::foundation();
|
||||||
|
let slashable_vote_first = create_slashable_vote_data(1, 1, &spec);
|
||||||
|
let slashable_vote_second = create_slashable_vote_data(2, 2, &spec);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_ssz_round_trip() {
|
pub fn test_ssz_round_trip() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
@ -54,14 +150,27 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = SlashableVoteData::random_for_test(&mut rng);
|
let original = SlashableVoteData::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
// https://github.com/sigp/lighthouse/issues/170
|
// https://github.com/sigp/lighthouse/issues/170
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_slashable_vote_data(
|
||||||
|
slot_factor: u64,
|
||||||
|
justified_epoch: u64,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> SlashableVoteData {
|
||||||
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
|
let mut slashable_vote = SlashableVoteData::random_for_test(&mut rng);
|
||||||
|
|
||||||
|
slashable_vote.data.slot = Slot::new(slot_factor * spec.epoch_length);
|
||||||
|
slashable_vote.data.justified_epoch = Epoch::new(justified_epoch);
|
||||||
|
slashable_vote
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,9 +224,9 @@ macro_rules! impl_ssz {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for $type {
|
impl TreeHash for $type {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.0.hash_tree_root());
|
result.append(&mut self.0.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -560,11 +560,11 @@ macro_rules! ssz_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = $type::random_for_test(&mut rng);
|
let original = $type::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -1,92 +0,0 @@
|
|||||||
mod foundation;
|
|
||||||
|
|
||||||
use crate::{Address, Epoch, Hash256, Slot};
|
|
||||||
use bls::Signature;
|
|
||||||
|
|
||||||
/// Holds all the "constants" for a BeaconChain.
|
|
||||||
///
|
|
||||||
/// Spec v0.2.0
|
|
||||||
#[derive(PartialEq, Debug, Clone)]
|
|
||||||
pub struct ChainSpec {
|
|
||||||
/*
|
|
||||||
* Misc
|
|
||||||
*/
|
|
||||||
pub shard_count: u64,
|
|
||||||
pub target_committee_size: u64,
|
|
||||||
pub max_balance_churn_quotient: u64,
|
|
||||||
pub beacon_chain_shard_number: u64,
|
|
||||||
pub max_indices_per_slashable_vote: u64,
|
|
||||||
pub max_withdrawals_per_epoch: u64,
|
|
||||||
pub shuffle_round_count: u8,
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Deposit contract
|
|
||||||
*/
|
|
||||||
pub deposit_contract_address: Address,
|
|
||||||
pub deposit_contract_tree_depth: u64,
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Gwei values
|
|
||||||
*/
|
|
||||||
pub min_deposit_amount: u64,
|
|
||||||
pub max_deposit_amount: u64,
|
|
||||||
pub fork_choice_balance_increment: u64,
|
|
||||||
pub ejection_balance: u64,
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initial Values
|
|
||||||
*/
|
|
||||||
pub genesis_fork_version: u64,
|
|
||||||
pub genesis_slot: Slot,
|
|
||||||
pub genesis_epoch: Epoch,
|
|
||||||
pub genesis_start_shard: u64,
|
|
||||||
pub far_future_epoch: Epoch,
|
|
||||||
pub zero_hash: Hash256,
|
|
||||||
pub empty_signature: Signature,
|
|
||||||
pub bls_withdrawal_prefix_byte: u8,
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Time parameters
|
|
||||||
*/
|
|
||||||
pub slot_duration: u64,
|
|
||||||
pub min_attestation_inclusion_delay: u64,
|
|
||||||
pub epoch_length: u64,
|
|
||||||
pub seed_lookahead: Epoch,
|
|
||||||
pub entry_exit_delay: u64,
|
|
||||||
pub eth1_data_voting_period: u64,
|
|
||||||
pub min_validator_withdrawal_epochs: Epoch,
|
|
||||||
|
|
||||||
/*
|
|
||||||
* State list lengths
|
|
||||||
*/
|
|
||||||
pub latest_block_roots_length: usize,
|
|
||||||
pub latest_randao_mixes_length: usize,
|
|
||||||
pub latest_index_roots_length: usize,
|
|
||||||
pub latest_penalized_exit_length: usize,
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reward and penalty quotients
|
|
||||||
*/
|
|
||||||
pub base_reward_quotient: u64,
|
|
||||||
pub whistleblower_reward_quotient: u64,
|
|
||||||
pub includer_reward_quotient: u64,
|
|
||||||
pub inactivity_penalty_quotient: u64,
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Max operations per block
|
|
||||||
*/
|
|
||||||
pub max_proposer_slashings: u64,
|
|
||||||
pub max_attester_slashings: u64,
|
|
||||||
pub max_attestations: u64,
|
|
||||||
pub max_deposits: u64,
|
|
||||||
pub max_exits: u64,
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Signature domains
|
|
||||||
*/
|
|
||||||
pub domain_deposit: u64,
|
|
||||||
pub domain_attestation: u64,
|
|
||||||
pub domain_proposal: u64,
|
|
||||||
pub domain_exit: u64,
|
|
||||||
pub domain_randao: u64,
|
|
||||||
}
|
|
@ -122,15 +122,17 @@ impl Decodable for Validator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for Validator {
|
impl TreeHash for Validator {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.pubkey.hash_tree_root());
|
result.append(&mut self.pubkey.hash_tree_root_internal());
|
||||||
result.append(&mut self.withdrawal_credentials.hash_tree_root());
|
result.append(&mut self.withdrawal_credentials.hash_tree_root_internal());
|
||||||
result.append(&mut self.activation_epoch.hash_tree_root());
|
result.append(&mut self.activation_epoch.hash_tree_root_internal());
|
||||||
result.append(&mut self.exit_epoch.hash_tree_root());
|
result.append(&mut self.exit_epoch.hash_tree_root_internal());
|
||||||
result.append(&mut self.withdrawal_epoch.hash_tree_root());
|
result.append(&mut self.withdrawal_epoch.hash_tree_root_internal());
|
||||||
result.append(&mut self.penalized_epoch.hash_tree_root());
|
result.append(&mut self.penalized_epoch.hash_tree_root_internal());
|
||||||
result.append(&mut u64::from(status_flag_to_byte(self.status_flags)).hash_tree_root());
|
result.append(
|
||||||
|
&mut u64::from(status_flag_to_byte(self.status_flags)).hash_tree_root_internal(),
|
||||||
|
);
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,11 +192,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = Validator::random_for_test(&mut rng);
|
let original = Validator::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -29,13 +29,13 @@ impl Default for ValidatorRegistryDeltaBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for ValidatorRegistryDeltaBlock {
|
impl TreeHash for ValidatorRegistryDeltaBlock {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut result: Vec<u8> = vec![];
|
let mut result: Vec<u8> = vec![];
|
||||||
result.append(&mut self.latest_registry_delta_root.hash_tree_root());
|
result.append(&mut self.latest_registry_delta_root.hash_tree_root_internal());
|
||||||
result.append(&mut self.validator_index.hash_tree_root());
|
result.append(&mut self.validator_index.hash_tree_root_internal());
|
||||||
result.append(&mut self.pubkey.hash_tree_root());
|
result.append(&mut self.pubkey.hash_tree_root_internal());
|
||||||
result.append(&mut self.slot.hash_tree_root());
|
result.append(&mut self.slot.hash_tree_root_internal());
|
||||||
result.append(&mut self.flag.hash_tree_root());
|
result.append(&mut self.flag.hash_tree_root_internal());
|
||||||
hash(&result)
|
hash(&result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,11 +70,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_hash_tree_root() {
|
pub fn test_hash_tree_root_internal() {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let original = ValidatorRegistryDeltaBlock::random_for_test(&mut rng);
|
let original = ValidatorRegistryDeltaBlock::random_for_test(&mut rng);
|
||||||
|
|
||||||
let result = original.hash_tree_root();
|
let result = original.hash_tree_root_internal();
|
||||||
|
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
// TODO: Add further tests
|
// TODO: Add further tests
|
||||||
|
@ -57,7 +57,7 @@ impl Serialize for AggregateSignature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for AggregateSignature {
|
impl TreeHash for AggregateSignature {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
hash(&self.0.as_bytes())
|
hash(&self.0.as_bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ impl Serialize for PublicKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for PublicKey {
|
impl TreeHash for PublicKey {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
hash(&self.0.as_bytes())
|
hash(&self.0.as_bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ impl Decodable for SecretKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for SecretKey {
|
impl TreeHash for SecretKey {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
self.0.as_bytes().clone()
|
self.0.as_bytes().clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ impl Decodable for Signature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for Signature {
|
impl TreeHash for Signature {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
hash(&self.0.as_bytes())
|
hash(&self.0.as_bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,8 +187,8 @@ impl Serialize for BooleanBitfield {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ssz::TreeHash for BooleanBitfield {
|
impl ssz::TreeHash for BooleanBitfield {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
self.to_bytes().hash_tree_root()
|
self.to_bytes().hash_tree_root_internal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,49 +3,49 @@ use super::{merkle_hash, ssz_encode, TreeHash};
|
|||||||
use hashing::hash;
|
use hashing::hash;
|
||||||
|
|
||||||
impl TreeHash for u8 {
|
impl TreeHash for u8 {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
ssz_encode(self)
|
ssz_encode(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for u16 {
|
impl TreeHash for u16 {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
ssz_encode(self)
|
ssz_encode(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for u32 {
|
impl TreeHash for u32 {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
ssz_encode(self)
|
ssz_encode(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for u64 {
|
impl TreeHash for u64 {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
ssz_encode(self)
|
ssz_encode(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for usize {
|
impl TreeHash for usize {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
ssz_encode(self)
|
ssz_encode(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for Address {
|
impl TreeHash for Address {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
ssz_encode(self)
|
ssz_encode(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for H256 {
|
impl TreeHash for H256 {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
ssz_encode(self)
|
ssz_encode(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for [u8] {
|
impl TreeHash for [u8] {
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
if self.len() > 32 {
|
if self.len() > 32 {
|
||||||
return hash(&self);
|
return hash(&self);
|
||||||
}
|
}
|
||||||
@ -57,12 +57,12 @@ impl<T> TreeHash for Vec<T>
|
|||||||
where
|
where
|
||||||
T: TreeHash,
|
T: TreeHash,
|
||||||
{
|
{
|
||||||
/// Returns the merkle_hash of a list of hash_tree_root values created
|
/// Returns the merkle_hash of a list of hash_tree_root_internal values created
|
||||||
/// from the given list.
|
/// from the given list.
|
||||||
/// Note: A byte vector, Vec<u8>, must be converted to a slice (as_slice())
|
/// Note: A byte vector, Vec<u8>, must be converted to a slice (as_slice())
|
||||||
/// to be handled properly (i.e. hashed) as byte array.
|
/// to be handled properly (i.e. hashed) as byte array.
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn hash_tree_root_internal(&self) -> Vec<u8> {
|
||||||
let mut tree_hashes = self.iter().map(|x| x.hash_tree_root()).collect();
|
let mut tree_hashes = self.iter().map(|x| x.hash_tree_root_internal()).collect();
|
||||||
merkle_hash(&mut tree_hashes)
|
merkle_hash(&mut tree_hashes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_impl_tree_hash_vec() {
|
fn test_impl_tree_hash_vec() {
|
||||||
let result = vec![1u32, 2, 3, 4, 5, 6, 7].hash_tree_root();
|
let result = vec![1u32, 2, 3, 4, 5, 6, 7].hash_tree_root_internal();
|
||||||
assert_eq!(result.len(), 32);
|
assert_eq!(result.len(), 32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,14 @@ const SSZ_CHUNK_SIZE: usize = 128;
|
|||||||
const HASHSIZE: usize = 32;
|
const HASHSIZE: usize = 32;
|
||||||
|
|
||||||
pub trait TreeHash {
|
pub trait TreeHash {
|
||||||
fn hash_tree_root(&self) -> Vec<u8>;
|
fn hash_tree_root_internal(&self) -> Vec<u8>;
|
||||||
|
fn hash_tree_root(&self) -> Vec<u8> {
|
||||||
|
let mut result = self.hash_tree_root_internal();
|
||||||
|
if result.len() < HASHSIZE {
|
||||||
|
zpad(&mut result, HASHSIZE);
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a 32 byte hash of 'list' - a vector of byte vectors.
|
/// Returns a 32 byte hash of 'list' - a vector of byte vectors.
|
||||||
@ -14,7 +21,8 @@ pub fn merkle_hash(list: &mut Vec<Vec<u8>>) -> Vec<u8> {
|
|||||||
let (mut chunk_size, mut chunkz) = list_to_blob(list);
|
let (mut chunk_size, mut chunkz) = list_to_blob(list);
|
||||||
|
|
||||||
// get data_len as bytes. It will hashed will the merkle root
|
// get data_len as bytes. It will hashed will the merkle root
|
||||||
let datalen = list.len().to_le_bytes();
|
let mut datalen = list.len().to_le_bytes().to_vec();
|
||||||
|
zpad(&mut datalen, 32);
|
||||||
|
|
||||||
// Tree-hash
|
// Tree-hash
|
||||||
while chunkz.len() > HASHSIZE {
|
while chunkz.len() > HASHSIZE {
|
||||||
@ -36,33 +44,68 @@ pub fn merkle_hash(list: &mut Vec<Vec<u8>>) -> Vec<u8> {
|
|||||||
chunkz = new_chunkz;
|
chunkz = new_chunkz;
|
||||||
}
|
}
|
||||||
|
|
||||||
chunkz.append(&mut datalen.to_vec());
|
chunkz.append(&mut datalen);
|
||||||
hash(&chunkz)
|
hash(&chunkz)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn list_to_blob(list: &mut Vec<Vec<u8>>) -> (usize, Vec<u8>) {
|
fn list_to_blob(list: &mut Vec<Vec<u8>>) -> (usize, Vec<u8>) {
|
||||||
let chunk_size = if list.is_empty() {
|
let chunk_size = if list.is_empty() || list[0].len() < SSZ_CHUNK_SIZE {
|
||||||
SSZ_CHUNK_SIZE
|
SSZ_CHUNK_SIZE
|
||||||
} else if list[0].len() < SSZ_CHUNK_SIZE {
|
|
||||||
let items_per_chunk = SSZ_CHUNK_SIZE / list[0].len();
|
|
||||||
items_per_chunk * list[0].len()
|
|
||||||
} else {
|
} else {
|
||||||
list[0].len()
|
list[0].len()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut data = Vec::new();
|
let (items_per_chunk, chunk_count) = if list.is_empty() {
|
||||||
|
(1, 1)
|
||||||
|
} else {
|
||||||
|
let items_per_chunk = SSZ_CHUNK_SIZE / list[0].len();
|
||||||
|
let chunk_count = list.len() / items_per_chunk;
|
||||||
|
(items_per_chunk, chunk_count)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut chunkz = Vec::new();
|
||||||
if list.is_empty() {
|
if list.is_empty() {
|
||||||
// handle and empty list
|
// handle and empty list
|
||||||
data.append(&mut vec![0; SSZ_CHUNK_SIZE]);
|
chunkz.append(&mut vec![0; SSZ_CHUNK_SIZE]);
|
||||||
} else {
|
} else if list[0].len() <= SSZ_CHUNK_SIZE {
|
||||||
// just create a blob here; we'll divide into
|
// just create a blob here; we'll divide into
|
||||||
// chunked slices when we merklize
|
// chunked slices when we merklize
|
||||||
data.reserve(list[0].len() * list.len());
|
let mut chunk = Vec::with_capacity(chunk_size);
|
||||||
|
let mut item_count_in_chunk = 0;
|
||||||
|
chunkz.reserve(chunk_count * chunk_size);
|
||||||
for item in list.iter_mut() {
|
for item in list.iter_mut() {
|
||||||
data.append(item);
|
item_count_in_chunk += 1;
|
||||||
|
chunk.append(item);
|
||||||
|
|
||||||
|
// completed chunk?
|
||||||
|
if item_count_in_chunk == items_per_chunk {
|
||||||
|
zpad(&mut chunk, chunk_size);
|
||||||
|
chunkz.append(&mut chunk);
|
||||||
|
item_count_in_chunk = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(chunk_size, data)
|
|
||||||
|
// left-over uncompleted chunk?
|
||||||
|
if item_count_in_chunk != 0 {
|
||||||
|
zpad(&mut chunk, chunk_size);
|
||||||
|
chunkz.append(&mut chunk);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// chunks larger than SSZ_CHUNK_SIZE
|
||||||
|
chunkz.reserve(chunk_count * chunk_size);
|
||||||
|
for item in list.iter_mut() {
|
||||||
|
chunkz.append(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(chunk_size, chunkz)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// right pads with zeros making 'bytes' 'size' in length
|
||||||
|
fn zpad(bytes: &mut Vec<u8>, size: usize) {
|
||||||
|
if bytes.len() < size {
|
||||||
|
bytes.resize(size, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -5,7 +5,7 @@ authors = ["Paul Hauner <paul@paulhauner.com>"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
block_producer = { path = "../eth2/block_producer" }
|
block_proposer = { path = "../eth2/block_proposer" }
|
||||||
bls = { path = "../eth2/utils/bls" }
|
bls = { path = "../eth2/utils/bls" }
|
||||||
clap = "2.32.0"
|
clap = "2.32.0"
|
||||||
dirs = "1.0.3"
|
dirs = "1.0.3"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use block_producer::{BeaconNode, BeaconNodeError, PublishOutcome};
|
use block_proposer::{BeaconNode, BeaconNodeError, PublishOutcome};
|
||||||
use protos::services::{
|
use protos::services::{
|
||||||
BeaconBlock as GrpcBeaconBlock, ProduceBeaconBlockRequest, PublishBeaconBlockRequest,
|
BeaconBlock as GrpcBeaconBlock, ProduceBeaconBlockRequest, PublishBeaconBlockRequest,
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
mod beacon_block_grpc_client;
|
mod beacon_block_grpc_client;
|
||||||
// mod block_producer_service;
|
// mod block_producer_service;
|
||||||
|
|
||||||
use block_producer::{
|
use block_proposer::{
|
||||||
BeaconNode, BlockProducer, DutiesReader, PollOutcome as BlockProducerPollOutcome, Signer,
|
BeaconNode, BlockProducer, DutiesReader, PollOutcome as BlockProducerPollOutcome, Signer,
|
||||||
};
|
};
|
||||||
use slog::{error, info, warn, Logger};
|
use slog::{error, info, warn, Logger};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use block_producer::{DutiesReader, DutiesReaderError};
|
use block_proposer::{DutiesReader, DutiesReaderError};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
use types::{Epoch, Slot};
|
use types::{Epoch, Slot};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use self::block_producer_service::{BeaconBlockGrpcClient, BlockProducerService};
|
use self::block_producer_service::{BeaconBlockGrpcClient, BlockProducerService};
|
||||||
use self::duties::{DutiesManager, DutiesManagerService, EpochDutiesMap};
|
use self::duties::{DutiesManager, DutiesManagerService, EpochDutiesMap};
|
||||||
use crate::config::ClientConfig;
|
use crate::config::ClientConfig;
|
||||||
use block_producer::{test_utils::LocalSigner, BlockProducer};
|
use block_proposer::{test_utils::LocalSigner, BlockProducer};
|
||||||
use bls::Keypair;
|
use bls::Keypair;
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use grpcio::{ChannelBuilder, EnvBuilder};
|
use grpcio::{ChannelBuilder, EnvBuilder};
|
||||||
|
Loading…
Reference in New Issue
Block a user