mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-09 19:51:47 +00:00
Add progress on test rig
This commit is contained in:
50
beacon_node/beacon_chain/src/attestation_targets.rs
Normal file
50
beacon_node/beacon_chain/src/attestation_targets.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
use crate::{BeaconChain, CheckPoint, ClientDB, SlotClock};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::RwLockReadGuard;
|
||||
use types::{BeaconBlock, BeaconState, Hash256};
|
||||
|
||||
pub struct AttestationTargets {
|
||||
map: HashMap<u64, Hash256>,
|
||||
}
|
||||
|
||||
impl AttestationTargets {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
map: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, validator_index: u64) -> Option<&Hash256> {
|
||||
self.map.get(&validator_index)
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, validator_index: u64, block_hash: Hash256) -> Option<Hash256> {
|
||||
self.map.insert(validator_index, block_hash)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> BeaconChain<T, U>
|
||||
where
|
||||
T: ClientDB,
|
||||
U: SlotClock,
|
||||
{
|
||||
pub fn insert_latest_attestation_target(&self, validator_index: u64, block_root: Hash256) {
|
||||
let mut targets = self
|
||||
.latest_attestation_targets
|
||||
.write()
|
||||
.expect("CRITICAL: CanonicalHead poisioned.");
|
||||
targets.insert(validator_index, block_root);
|
||||
}
|
||||
|
||||
pub fn get_latest_attestation_target(&self, validator_index: u64) -> Option<Hash256> {
|
||||
let targets = self
|
||||
.latest_attestation_targets
|
||||
.read()
|
||||
.expect("CRITICAL: CanonicalHead poisioned.");
|
||||
|
||||
match targets.get(validator_index) {
|
||||
Some(hash) => Some(hash.clone()),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
37
beacon_node/beacon_chain/src/block_graph.rs
Normal file
37
beacon_node/beacon_chain/src/block_graph.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
use crate::{BeaconChain, CheckPoint, ClientDB, SlotClock};
|
||||
use std::collections::HashSet;
|
||||
use std::sync::{RwLock, RwLockReadGuard};
|
||||
use types::{BeaconBlock, BeaconState, Hash256};
|
||||
|
||||
pub struct BlockGraph {
|
||||
pub leaves: RwLock<HashSet<Hash256>>,
|
||||
}
|
||||
|
||||
impl BlockGraph {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
leaves: RwLock::new(HashSet::new()),
|
||||
}
|
||||
}
|
||||
/// Add a new leaf to the block hash graph. Returns `true` if the leaf was built upon another
|
||||
/// leaf.
|
||||
pub fn add_leaf(&self, parent: &Hash256, leaf: Hash256) -> bool {
|
||||
let mut leaves = self
|
||||
.leaves
|
||||
.write()
|
||||
.expect("CRITICAL: BlockGraph poisioned.");
|
||||
|
||||
if leaves.contains(parent) {
|
||||
leaves.remove(parent);
|
||||
leaves.insert(leaf);
|
||||
true
|
||||
} else {
|
||||
leaves.insert(leaf);
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn leaves(&self) -> RwLockReadGuard<HashSet<Hash256>> {
|
||||
self.leaves.read().expect("CRITICAL: BlockGraph poisioned.")
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ where
|
||||
U: SlotClock,
|
||||
Error: From<<U as SlotClock>::Error>,
|
||||
{
|
||||
pub fn process_block<V>(&mut self, block: V) -> Result<Outcome, Error>
|
||||
pub fn process_block<V>(&self, block: V) -> Result<Outcome, Error>
|
||||
where
|
||||
V: BeaconBlockReader + Encodable + Sized,
|
||||
{
|
||||
@@ -103,14 +103,20 @@ where
|
||||
self.block_store.put(&block_root, &ssz_encode(&block)[..])?;
|
||||
self.state_store.put(&state_root, &ssz_encode(&state)[..])?;
|
||||
|
||||
// Update leaf blocks so the implementation can track the chain heads.
|
||||
if self.leaf_blocks.contains(&block.parent_root()) {
|
||||
self.leaf_blocks.remove(&block.parent_root());
|
||||
self.block_graph
|
||||
.add_leaf(&parent_block_root, block_root.clone());
|
||||
|
||||
// If the parent block was the parent_block, automatically update the canonical head.
|
||||
//
|
||||
// TODO: this is a first-in-best-dressed scenario that is not ideal -- find a solution.
|
||||
if self.canonical_head().beacon_block_root == parent_block_root {
|
||||
self.update_canonical_head(
|
||||
block.clone(),
|
||||
block_root.clone(),
|
||||
state.clone(),
|
||||
state_root.clone(),
|
||||
);
|
||||
}
|
||||
if self.canonical_leaf_block == block.parent_root() {
|
||||
self.canonical_leaf_block = block_root;
|
||||
}
|
||||
self.leaf_blocks.insert(block_root);
|
||||
|
||||
// The block was sucessfully processed.
|
||||
Ok(Outcome::Processed)
|
||||
|
||||
@@ -18,18 +18,22 @@ impl<T, U> BeaconChain<T, U>
|
||||
where
|
||||
T: ClientDB,
|
||||
U: SlotClock,
|
||||
Error: From<<U as SlotClock>::Error>,
|
||||
{
|
||||
pub fn produce_block(
|
||||
&mut self,
|
||||
&self,
|
||||
randao_reveal: Signature,
|
||||
) -> Result<(BeaconBlock, BeaconState), Error> {
|
||||
) -> Result<(BeaconBlock, BeaconState), Error>
|
||||
where
|
||||
Error: From<<U>::Error>,
|
||||
{
|
||||
// TODO: allow producing a block from a previous (or future?) slot.
|
||||
let present_slot = self
|
||||
.slot_clock
|
||||
.present_slot()?
|
||||
.present_slot()
|
||||
.map_err(|e| e.into())?
|
||||
.ok_or(Error::PresentSlotIsNone)?;
|
||||
|
||||
let parent_root = self.canonical_leaf_block;
|
||||
let parent_root = self.canonical_head().beacon_block_root;
|
||||
let parent_block_reader = self
|
||||
.block_store
|
||||
.get_reader(&parent_root)?
|
||||
@@ -43,7 +47,7 @@ where
|
||||
|
||||
let mut block = BeaconBlock {
|
||||
slot: present_slot,
|
||||
parent_root,
|
||||
parent_root: parent_root.clone(),
|
||||
state_root: Hash256::zero(), // Updated after the state is calculated.
|
||||
randao_reveal: randao_reveal,
|
||||
eth1_data: Eth1Data {
|
||||
|
||||
34
beacon_node/beacon_chain/src/canonical_head.rs
Normal file
34
beacon_node/beacon_chain/src/canonical_head.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
use crate::{BeaconChain, CheckPoint, ClientDB, SlotClock};
|
||||
use std::sync::RwLockReadGuard;
|
||||
use types::{BeaconBlock, BeaconState, Hash256};
|
||||
|
||||
impl<T, U> BeaconChain<T, U>
|
||||
where
|
||||
T: ClientDB,
|
||||
U: SlotClock,
|
||||
{
|
||||
pub fn update_canonical_head(
|
||||
&self,
|
||||
new_beacon_block: BeaconBlock,
|
||||
new_beacon_block_root: Hash256,
|
||||
new_beacon_state: BeaconState,
|
||||
new_beacon_state_root: Hash256,
|
||||
) {
|
||||
let mut canonical_head = self
|
||||
.canonical_head
|
||||
.write()
|
||||
.expect("CRITICAL: CanonicalHead poisioned.");
|
||||
canonical_head.update(
|
||||
new_beacon_block,
|
||||
new_beacon_block_root,
|
||||
new_beacon_state,
|
||||
new_beacon_state_root,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn canonical_head(&self) -> RwLockReadGuard<CheckPoint> {
|
||||
self.canonical_head
|
||||
.read()
|
||||
.expect("CRITICAL: CanonicalHead poisioned.")
|
||||
}
|
||||
}
|
||||
49
beacon_node/beacon_chain/src/info.rs
Normal file
49
beacon_node/beacon_chain/src/info.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
use super::{BeaconChain, ClientDB, SlotClock};
|
||||
use types::PublicKey;
|
||||
|
||||
impl<T, U> BeaconChain<T, U>
|
||||
where
|
||||
T: ClientDB,
|
||||
U: SlotClock,
|
||||
{
|
||||
pub fn validator_index(&self, pubkey: &PublicKey) -> Option<usize> {
|
||||
for (i, validator) in self
|
||||
.canonical_head()
|
||||
.beacon_state
|
||||
.validator_registry
|
||||
.iter()
|
||||
.enumerate()
|
||||
{
|
||||
if validator.pubkey == *pubkey {
|
||||
return Some(i);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn proposer_slots(&self, validator_index: usize) -> Option<u64> {
|
||||
if let Some(validator) = self
|
||||
.canonical_head()
|
||||
.beacon_state
|
||||
.validator_registry
|
||||
.get(validator_index)
|
||||
{
|
||||
Some(validator.proposer_slots)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn present_slot(&self) -> Option<u64> {
|
||||
match self.slot_clock.present_slot() {
|
||||
Ok(some_slot) => some_slot,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn block_proposer(&self, slot: u64) -> Option<usize> {
|
||||
//TODO: this is a stub; fix.
|
||||
let validator_count = self.canonical_head().beacon_state.validator_registry.len();
|
||||
Some((slot as usize) % validator_count)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,14 @@
|
||||
mod attestation_targets;
|
||||
mod block_graph;
|
||||
mod block_processing;
|
||||
mod block_production;
|
||||
pub mod block_production;
|
||||
mod canonical_head;
|
||||
mod info;
|
||||
mod lmd_ghost;
|
||||
mod state_transition;
|
||||
|
||||
use self::attestation_targets::AttestationTargets;
|
||||
use self::block_graph::BlockGraph;
|
||||
use db::{
|
||||
stores::{BeaconBlockStore, BeaconStateStore},
|
||||
ClientDB, DBError,
|
||||
@@ -12,18 +18,11 @@ use slot_clock::SlotClock;
|
||||
use spec::ChainSpec;
|
||||
use ssz::ssz_encode;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
use types::Hash256;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use types::{BeaconBlock, BeaconState, Hash256, PublicKey};
|
||||
|
||||
pub use self::block_processing::Outcome as BlockProcessingOutcome;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct CheckPoint {
|
||||
block_root: Hash256,
|
||||
state_root: Hash256,
|
||||
slot: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum BeaconChainError {
|
||||
InsufficientValidators,
|
||||
@@ -31,15 +30,51 @@ pub enum BeaconChainError {
|
||||
DBError(String),
|
||||
}
|
||||
|
||||
pub struct CheckPoint {
|
||||
beacon_block: BeaconBlock,
|
||||
beacon_block_root: Hash256,
|
||||
beacon_state: BeaconState,
|
||||
beacon_state_root: Hash256,
|
||||
}
|
||||
|
||||
impl CheckPoint {
|
||||
pub fn new(
|
||||
beacon_block: BeaconBlock,
|
||||
beacon_block_root: Hash256,
|
||||
beacon_state: BeaconState,
|
||||
beacon_state_root: Hash256,
|
||||
) -> Self {
|
||||
Self {
|
||||
beacon_block,
|
||||
beacon_block_root,
|
||||
beacon_state,
|
||||
beacon_state_root,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
beacon_block: BeaconBlock,
|
||||
beacon_block_root: Hash256,
|
||||
beacon_state: BeaconState,
|
||||
beacon_state_root: Hash256,
|
||||
) {
|
||||
self.beacon_block = beacon_block;
|
||||
self.beacon_block_root = beacon_block_root;
|
||||
self.beacon_state = beacon_state;
|
||||
self.beacon_state_root = beacon_state_root;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BeaconChain<T: ClientDB + Sized, U: SlotClock> {
|
||||
pub block_store: Arc<BeaconBlockStore<T>>,
|
||||
pub state_store: Arc<BeaconStateStore<T>>,
|
||||
pub slot_clock: U,
|
||||
pub leaf_blocks: HashSet<Hash256>,
|
||||
pub canonical_leaf_block: Hash256,
|
||||
pub block_graph: BlockGraph,
|
||||
canonical_head: RwLock<CheckPoint>,
|
||||
finalized_head: RwLock<CheckPoint>,
|
||||
pub latest_attestation_targets: RwLock<AttestationTargets>,
|
||||
pub spec: ChainSpec,
|
||||
latest_attestation_targets: HashMap<usize, Hash256>,
|
||||
finalized_checkpoint: CheckPoint,
|
||||
}
|
||||
|
||||
impl<T, U> BeaconChain<T, U>
|
||||
@@ -65,24 +100,33 @@ where
|
||||
let block_root = genesis_block.canonical_root();
|
||||
block_store.put(&block_root, &ssz_encode(&genesis_block)[..])?;
|
||||
|
||||
let mut leaf_blocks = HashSet::new();
|
||||
leaf_blocks.insert(block_root);
|
||||
let block_graph = BlockGraph::new();
|
||||
block_graph.add_leaf(&Hash256::zero(), block_root.clone());
|
||||
|
||||
let finalized_checkpoint = CheckPoint {
|
||||
block_root,
|
||||
state_root,
|
||||
slot: genesis_block.slot,
|
||||
};
|
||||
let finalized_head = RwLock::new(CheckPoint::new(
|
||||
genesis_block.clone(),
|
||||
block_root.clone(),
|
||||
genesis_state.clone(),
|
||||
state_root.clone(),
|
||||
));
|
||||
let canonical_head = RwLock::new(CheckPoint::new(
|
||||
genesis_block.clone(),
|
||||
block_root.clone(),
|
||||
genesis_state.clone(),
|
||||
state_root.clone(),
|
||||
));
|
||||
|
||||
let latest_attestation_targets = RwLock::new(AttestationTargets::new());
|
||||
|
||||
Ok(Self {
|
||||
block_store,
|
||||
state_store,
|
||||
slot_clock,
|
||||
leaf_blocks,
|
||||
canonical_leaf_block: block_root,
|
||||
spec,
|
||||
latest_attestation_targets: HashMap::new(),
|
||||
finalized_checkpoint,
|
||||
block_graph,
|
||||
finalized_head,
|
||||
canonical_head,
|
||||
latest_attestation_targets,
|
||||
spec: spec,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,12 @@ use db::{
|
||||
ClientDB, DBError,
|
||||
};
|
||||
use slot_clock::TestingSlotClockError;
|
||||
use ssz::{ssz_encode, Encodable};
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
use types::{
|
||||
readers::{BeaconBlockReader, BeaconStateReader},
|
||||
validator_registry::get_active_validator_indices,
|
||||
BeaconBlock, Hash256,
|
||||
Hash256,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@@ -53,7 +52,7 @@ where
|
||||
|
||||
let mut attestation_targets = Vec::with_capacity(active_validator_indices.len());
|
||||
for i in active_validator_indices {
|
||||
if let Some(target) = self.latest_attestation_targets.get(&i) {
|
||||
if let Some(target) = self.get_latest_attestation_target(i as u64) {
|
||||
attestation_targets.push(target);
|
||||
}
|
||||
}
|
||||
@@ -62,8 +61,11 @@ where
|
||||
let mut head_vote_count = 0;
|
||||
|
||||
loop {
|
||||
let child_hashes_and_slots =
|
||||
get_child_hashes_and_slots(&self.block_store, &head_hash, &self.leaf_blocks)?;
|
||||
let child_hashes_and_slots = get_child_hashes_and_slots(
|
||||
&self.block_store,
|
||||
&head_hash,
|
||||
&self.block_graph.leaves(),
|
||||
)?;
|
||||
|
||||
if child_hashes_and_slots.len() == 0 {
|
||||
break;
|
||||
@@ -90,7 +92,7 @@ where
|
||||
|
||||
fn get_vote_count<T: ClientDB>(
|
||||
block_store: &Arc<BeaconBlockStore<T>>,
|
||||
attestation_targets: &[&Hash256],
|
||||
attestation_targets: &[Hash256],
|
||||
block_root: &Hash256,
|
||||
slot: u64,
|
||||
) -> Result<u64, Error> {
|
||||
@@ -99,7 +101,7 @@ fn get_vote_count<T: ClientDB>(
|
||||
let (root_at_slot, _) = block_store
|
||||
.block_at_slot(&block_root, slot)?
|
||||
.ok_or(Error::MissingBeaconBlock(*block_root))?;
|
||||
if root_at_slot == *block_root {
|
||||
if root_at_slot == *target {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user