Add genesis()
to BeaconState
This commit is contained in:
parent
f3e556bca3
commit
3b75e93122
@ -1,10 +1,10 @@
|
|||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
use crate::{
|
use crate::{
|
||||||
validator::StatusFlags, validator_registry::get_active_validator_indices, AggregatePublicKey,
|
validator::StatusFlags, validator_registry::get_active_validator_indices, AttestationData,
|
||||||
Attestation, AttestationData, Bitfield, ChainSpec, Crosslink, Epoch, Eth1Data, Eth1DataVote,
|
Bitfield, ChainSpec, Crosslink, Deposit, Epoch, Eth1Data, Eth1DataVote, Fork, Hash256,
|
||||||
Fork, Hash256, PendingAttestation, Slot, Validator,
|
PendingAttestation, PublicKey, Signature, Slot, Validator,
|
||||||
};
|
};
|
||||||
use bls::bls_verify_aggregate;
|
use bls::verify_proof_of_possession;
|
||||||
use honey_badger_split::SplitExt;
|
use honey_badger_split::SplitExt;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use serde_derive::Serialize;
|
use serde_derive::Serialize;
|
||||||
@ -12,10 +12,6 @@ use ssz::{hash, Decodable, DecodeError, Encodable, SszStream, TreeHash};
|
|||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use vec_shuffle::shuffle;
|
use vec_shuffle::shuffle;
|
||||||
|
|
||||||
// TODO: define elsehwere.
|
|
||||||
const PHASE_0_CUSTODY_BIT: bool = false;
|
|
||||||
const DOMAIN_ATTESTATION: u64 = 1;
|
|
||||||
|
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
InsufficientValidators,
|
InsufficientValidators,
|
||||||
BadBlockSignature,
|
BadBlockSignature,
|
||||||
@ -65,14 +61,6 @@ pub enum AttestationValidationError {
|
|||||||
AttestationParticipantsError(AttestationParticipantsError),
|
AttestationParticipantsError(AttestationParticipantsError),
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! ensure {
|
|
||||||
($condition: expr, $result: expr) => {
|
|
||||||
if !$condition {
|
|
||||||
return Err($result);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! safe_add_assign {
|
macro_rules! safe_add_assign {
|
||||||
($a: expr, $b: expr) => {
|
($a: expr, $b: expr) => {
|
||||||
$a = $a.saturating_add($b);
|
$a = $a.saturating_add($b);
|
||||||
@ -125,6 +113,103 @@ pub struct BeaconState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BeaconState {
|
impl BeaconState {
|
||||||
|
/// Produce the first state of the Beacon Chain.
|
||||||
|
pub fn genesis(
|
||||||
|
genesis_time: u64,
|
||||||
|
initial_validator_deposits: Vec<Deposit>,
|
||||||
|
latest_eth1_data: Eth1Data,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> BeaconState {
|
||||||
|
let initial_crosslink = Crosslink {
|
||||||
|
epoch: spec.genesis_epoch,
|
||||||
|
shard_block_root: spec.zero_hash,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut genesis_state = BeaconState {
|
||||||
|
/*
|
||||||
|
* Misc
|
||||||
|
*/
|
||||||
|
slot: spec.genesis_slot,
|
||||||
|
genesis_time,
|
||||||
|
fork: Fork {
|
||||||
|
previous_version: spec.genesis_fork_version,
|
||||||
|
current_version: spec.genesis_fork_version,
|
||||||
|
epoch: spec.genesis_epoch,
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Validator registry
|
||||||
|
*/
|
||||||
|
validator_registry: vec![], // Set later in the function.
|
||||||
|
validator_balances: vec![], // Set later in the function.
|
||||||
|
validator_registry_update_epoch: spec.genesis_epoch,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Randomness and committees
|
||||||
|
*/
|
||||||
|
latest_randao_mixes: vec![spec.zero_hash; spec.latest_randao_mixes_length as usize],
|
||||||
|
previous_epoch_start_shard: spec.genesis_start_shard,
|
||||||
|
current_epoch_start_shard: spec.genesis_start_shard,
|
||||||
|
previous_calculation_epoch: spec.genesis_epoch,
|
||||||
|
current_calculation_epoch: spec.genesis_epoch,
|
||||||
|
previous_epoch_seed: spec.zero_hash,
|
||||||
|
current_epoch_seed: spec.zero_hash,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finality
|
||||||
|
*/
|
||||||
|
previous_justified_epoch: spec.genesis_epoch,
|
||||||
|
justified_epoch: spec.genesis_epoch,
|
||||||
|
justification_bitfield: 0,
|
||||||
|
finalized_epoch: spec.genesis_epoch,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Recent state
|
||||||
|
*/
|
||||||
|
latest_crosslinks: vec![initial_crosslink; spec.shard_count as usize],
|
||||||
|
latest_block_roots: vec![spec.zero_hash; spec.latest_block_roots_length as usize],
|
||||||
|
latest_index_roots: vec![spec.zero_hash; spec.latest_index_roots_length as usize],
|
||||||
|
latest_penalized_balances: vec![0; spec.latest_penalized_exit_length as usize],
|
||||||
|
latest_attestations: vec![],
|
||||||
|
batched_block_roots: vec![],
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PoW receipt root
|
||||||
|
*/
|
||||||
|
latest_eth1_data,
|
||||||
|
eth1_data_votes: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
for deposit in initial_validator_deposits {
|
||||||
|
let _index = genesis_state.process_deposit(
|
||||||
|
deposit.deposit_data.deposit_input.pubkey,
|
||||||
|
deposit.deposit_data.amount,
|
||||||
|
deposit.deposit_data.deposit_input.proof_of_possession,
|
||||||
|
deposit.deposit_data.deposit_input.withdrawal_credentials,
|
||||||
|
spec,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for validator_index in 0..genesis_state.validator_registry.len() {
|
||||||
|
if genesis_state.get_effective_balance(validator_index, spec) >= spec.max_deposit_amount
|
||||||
|
{
|
||||||
|
genesis_state.activate_validator(validator_index, true, spec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let genesis_active_index_root = hash_tree_root(get_active_validator_indices(
|
||||||
|
&genesis_state.validator_registry,
|
||||||
|
spec.genesis_epoch,
|
||||||
|
));
|
||||||
|
genesis_state.latest_index_roots =
|
||||||
|
vec![genesis_active_index_root; spec.latest_index_roots_length];
|
||||||
|
genesis_state.current_epoch_seed = genesis_state
|
||||||
|
.generate_seed(spec.genesis_epoch, spec)
|
||||||
|
.expect("Unable to generate seed.");
|
||||||
|
|
||||||
|
genesis_state
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the tree hash root for this `BeaconState`.
|
/// Return the tree hash root for this `BeaconState`.
|
||||||
///
|
///
|
||||||
/// Spec v0.2.0
|
/// Spec v0.2.0
|
||||||
@ -512,6 +597,48 @@ impl BeaconState {
|
|||||||
|
|
||||||
self.validator_registry_update_epoch = current_epoch;
|
self.validator_registry_update_epoch = current_epoch;
|
||||||
}
|
}
|
||||||
|
/// Process a validator deposit, returning the validator index if the deposit is valid.
|
||||||
|
///
|
||||||
|
/// Spec v0.2.0
|
||||||
|
pub fn process_deposit(
|
||||||
|
&mut self,
|
||||||
|
pubkey: PublicKey,
|
||||||
|
amount: u64,
|
||||||
|
proof_of_possession: Signature,
|
||||||
|
withdrawal_credentials: Hash256,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> Result<usize, ()> {
|
||||||
|
// TODO: ensure verify proof-of-possession represents the spec accurately.
|
||||||
|
if !verify_proof_of_possession(&proof_of_possession, &pubkey) {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(index) = self
|
||||||
|
.validator_registry
|
||||||
|
.iter()
|
||||||
|
.position(|v| v.pubkey == pubkey)
|
||||||
|
{
|
||||||
|
if self.validator_registry[index].withdrawal_credentials == withdrawal_credentials {
|
||||||
|
safe_add_assign!(self.validator_balances[index], amount);
|
||||||
|
Ok(index)
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let validator = Validator {
|
||||||
|
pubkey,
|
||||||
|
withdrawal_credentials,
|
||||||
|
activation_epoch: spec.far_future_epoch,
|
||||||
|
exit_epoch: spec.far_future_epoch,
|
||||||
|
withdrawal_epoch: spec.far_future_epoch,
|
||||||
|
penalized_epoch: spec.far_future_epoch,
|
||||||
|
status_flags: None,
|
||||||
|
};
|
||||||
|
self.validator_registry.push(validator);
|
||||||
|
self.validator_balances.push(amount);
|
||||||
|
Ok(self.validator_registry.len() - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Activate the validator of the given ``index``.
|
/// Activate the validator of the given ``index``.
|
||||||
///
|
///
|
||||||
@ -790,6 +917,10 @@ impl BeaconState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn hash_tree_root<T: TreeHash>(input: Vec<T>) -> Hash256 {
|
||||||
|
Hash256::from(&input.hash_tree_root()[..])
|
||||||
|
}
|
||||||
|
|
||||||
impl From<AttestationParticipantsError> for AttestationValidationError {
|
impl From<AttestationParticipantsError> for AttestationValidationError {
|
||||||
fn from(e: AttestationParticipantsError) -> AttestationValidationError {
|
fn from(e: AttestationParticipantsError) -> AttestationValidationError {
|
||||||
AttestationValidationError::AttestationParticipantsError(e)
|
AttestationValidationError::AttestationParticipantsError(e)
|
||||||
|
Loading…
Reference in New Issue
Block a user