Move beacon_chain into lighthouse dir

This commit is contained in:
Paul Hauner
2018-12-30 12:59:24 +11:00
parent dc8fbf813f
commit 2b63ece244
11 changed files with 286 additions and 156 deletions

View File

@@ -1,16 +0,0 @@
[package]
name = "chain"
version = "0.1.0"
authors = ["Paul Hauner <paul@paulhauner.com>"]
edition = "2018"
[dependencies]
bls = { path = "../utils/bls" }
db = { path = "../../lighthouse/db" }
genesis = { path = "../genesis" }
naive_fork_choice = { path = "../naive_fork_choice" }
spec = { path = "../spec" }
ssz = { path = "../utils/ssz" }
types = { path = "../types" }
validator_induction = { path = "../validator_induction" }
validator_shuffling = { path = "../validator_shuffling" }

View File

@@ -1,29 +0,0 @@
use super::BeaconChain;
use db::ClientDB;
use types::Hash256;
pub enum BlockProcessingOutcome {
BlockAlreadyKnown,
NewCanonicalBlock,
NewReorgBlock,
NewForkBlock,
}
pub enum Error {
NotImplemented,
}
impl<T> BeaconChain<T>
where
T: ClientDB + Sized,
{
pub fn process_block(
&mut self,
_ssz: &[u8],
_present_slot: u64,
) -> Result<(BlockProcessingOutcome, Hash256), Error> {
// TODO: block processing has been removed.
// https://github.com/sigp/lighthouse/issues/98
Err(Error::NotImplemented)
}
}

View File

@@ -1,110 +0,0 @@
extern crate db;
extern crate naive_fork_choice;
extern crate genesis;
extern crate spec;
extern crate ssz;
extern crate types;
extern crate validator_induction;
extern crate validator_shuffling;
mod block_processing;
mod maps;
mod stores;
use db::ClientDB;
use crate::maps::{generate_attester_and_proposer_maps, AttesterAndProposerMapError};
use crate::stores::BeaconChainStore;
use genesis::{genesis_beacon_state, GenesisError};
use spec::ChainSpec;
use std::collections::HashMap;
use std::sync::Arc;
use types::{AttesterMap, BeaconState, Hash256, ProposerMap};
#[derive(Debug, PartialEq)]
pub enum BeaconChainError {
InvalidGenesis,
InsufficientValidators,
UnableToGenerateMaps(AttesterAndProposerMapError),
GenesisError(GenesisError),
DBError(String),
}
pub struct BeaconChain<T: ClientDB + Sized> {
/// The last slot which has been finalized, this is common to all forks.
pub last_finalized_slot: u64,
/// A vec of all block heads (tips of chains).
pub head_block_hashes: Vec<Hash256>,
/// The index of the canonical block in `head_block_hashes`.
pub canonical_head_block_hash: usize,
/// An in-memory map of root hash to beacon state.
pub beacon_states: HashMap<Hash256, BeaconState>,
/// A map of crystallized state to a proposer and attester map.
pub attester_proposer_maps: HashMap<Hash256, (Arc<AttesterMap>, Arc<ProposerMap>)>,
/// A collection of database stores used by the chain.
pub store: BeaconChainStore<T>,
/// The chain configuration.
pub spec: ChainSpec,
}
impl<T> BeaconChain<T>
where
T: ClientDB + Sized,
{
pub fn new(store: BeaconChainStore<T>, spec: ChainSpec) -> Result<Self, BeaconChainError> {
if spec.initial_validators.is_empty() {
return Err(BeaconChainError::InsufficientValidators);
}
/*
* Generate and process the genesis state.
*/
let genesis_state = genesis_beacon_state(&spec)?;
let mut beacon_states = HashMap::new();
beacon_states.insert(genesis_state.canonical_root(), genesis_state.clone());
// TODO: implement genesis block
// https://github.com/sigp/lighthouse/issues/105
let canonical_latest_block_hash = Hash256::zero();
let head_block_hashes = vec![canonical_latest_block_hash];
let canonical_head_block_hash = 0;
let mut attester_proposer_maps = HashMap::new();
let (attester_map, proposer_map) = generate_attester_and_proposer_maps(
&genesis_state.shard_committees_at_slots,
0,
)?;
attester_proposer_maps.insert(
canonical_latest_block_hash,
(Arc::new(attester_map), Arc::new(proposer_map)),
);
Ok(Self {
last_finalized_slot: 0,
head_block_hashes,
canonical_head_block_hash,
beacon_states,
attester_proposer_maps,
store,
spec,
})
}
pub fn canonical_block_hash(&self) -> Hash256 {
self.head_block_hashes[self.canonical_head_block_hash]
}
}
impl From<AttesterAndProposerMapError> for BeaconChainError {
fn from(e: AttesterAndProposerMapError) -> BeaconChainError {
BeaconChainError::UnableToGenerateMaps(e)
}
}
impl From<GenesisError> for BeaconChainError {
fn from(e: GenesisError) -> BeaconChainError {
BeaconChainError::GenesisError(e)
}
}

View File

@@ -1,127 +0,0 @@
use types::{AttesterMap, ProposerMap, ShardCommittee};
#[derive(Debug, PartialEq)]
pub enum AttesterAndProposerMapError {
NoShardCommitteeForSlot,
NoAvailableProposer,
}
/// Generate a map of `(slot, shard) |--> committee`.
///
/// The attester map is used to optimise the lookup of a committee.
pub fn generate_attester_and_proposer_maps(
shard_and_committee_for_slots: &Vec<Vec<ShardCommittee>>,
start_slot: u64,
) -> Result<(AttesterMap, ProposerMap), AttesterAndProposerMapError> {
let mut attester_map = AttesterMap::new();
let mut proposer_map = ProposerMap::new();
for (i, slot) in shard_and_committee_for_slots.iter().enumerate() {
/*
* Store the proposer for the block.
*/
let slot_number = (i as u64).saturating_add(start_slot);
let first_committee = &slot
.get(0)
.ok_or(AttesterAndProposerMapError::NoShardCommitteeForSlot)?
.committee;
let proposer_index = (slot_number as usize)
.checked_rem(first_committee.len())
.ok_or(AttesterAndProposerMapError::NoAvailableProposer)?;
proposer_map.insert(slot_number, first_committee[proposer_index]);
/*
* Loop through the shards and extend the attester map.
*/
for shard_and_committee in slot {
let committee = shard_and_committee.committee.clone();
attester_map.insert((slot_number, shard_and_committee.shard), committee);
}
}
Ok((attester_map, proposer_map))
}
#[cfg(test)]
mod tests {
use super::*;
fn sac_generator(
shard_count: u64,
slot_count: usize,
sac_per_slot: usize,
committee_size: usize,
) -> Vec<Vec<ShardCommittee>> {
let mut shard = 0;
let mut validator = 0;
let mut cycle = vec![];
for _ in 0..slot_count {
let mut slot: Vec<ShardCommittee> = vec![];
for _ in 0..sac_per_slot {
let mut sac = ShardCommittee {
shard: shard % shard_count,
committee: vec![],
};
for _ in 0..committee_size {
sac.committee.push(validator);
validator += 1;
}
slot.push(sac);
shard += 1;
}
cycle.push(slot);
}
cycle
}
#[test]
fn test_attester_proposer_maps_empty_slots() {
let sac = sac_generator(4, 4, 0, 1);
let result = generate_attester_and_proposer_maps(&sac, 0);
assert_eq!(
result,
Err(AttesterAndProposerMapError::NoShardCommitteeForSlot)
);
}
#[test]
fn test_attester_proposer_maps_empty_committees() {
let sac = sac_generator(4, 4, 1, 0);
let result = generate_attester_and_proposer_maps(&sac, 0);
assert_eq!(
result,
Err(AttesterAndProposerMapError::NoAvailableProposer)
);
}
#[test]
fn test_attester_proposer_maps_scenario_a() {
let sac = sac_generator(4, 4, 1, 1);
let (a, p) = generate_attester_and_proposer_maps(&sac, 0).unwrap();
assert_eq!(*p.get(&0).unwrap(), 0);
assert_eq!(*p.get(&1).unwrap(), 1);
assert_eq!(*p.get(&2).unwrap(), 2);
assert_eq!(*p.get(&3).unwrap(), 3);
assert_eq!(*a.get(&(0, 0)).unwrap(), vec![0]);
assert_eq!(*a.get(&(1, 1)).unwrap(), vec![1]);
assert_eq!(*a.get(&(2, 2)).unwrap(), vec![2]);
assert_eq!(*a.get(&(3, 3)).unwrap(), vec![3]);
}
#[test]
fn test_attester_proposer_maps_scenario_b() {
let sac = sac_generator(4, 4, 1, 4);
let (a, p) = generate_attester_and_proposer_maps(&sac, 0).unwrap();
assert_eq!(*p.get(&0).unwrap(), 0);
assert_eq!(*p.get(&1).unwrap(), 5);
assert_eq!(*p.get(&2).unwrap(), 10);
assert_eq!(*p.get(&3).unwrap(), 15);
assert_eq!(*a.get(&(0, 0)).unwrap(), vec![0, 1, 2, 3]);
assert_eq!(*a.get(&(1, 1)).unwrap(), vec![4, 5, 6, 7]);
assert_eq!(*a.get(&(2, 2)).unwrap(), vec![8, 9, 10, 11]);
assert_eq!(*a.get(&(3, 3)).unwrap(), vec![12, 13, 14, 15]);
}
}

View File

@@ -1,9 +0,0 @@
use db::stores::{BeaconBlockStore, PoWChainStore, ValidatorStore};
use db::ClientDB;
use std::sync::Arc;
pub struct BeaconChainStore<T: ClientDB + Sized> {
pub block: Arc<BeaconBlockStore<T>>,
pub pow_chain: Arc<PoWChainStore<T>>,
pub validator: Arc<ValidatorStore<T>>,
}

View File

@@ -1,29 +0,0 @@
use super::BeaconChain;
use db::ClientDB;
use state_transition::{extend_active_state, StateTransitionError};
use types::{ActiveState, BeaconBlock, CrystallizedState, Hash256};
impl<T> BeaconChain<T>
where
T: ClientDB + Sized,
{
pub(crate) fn transition_states(
&self,
act_state: &ActiveState,
cry_state: &CrystallizedState,
block: &BeaconBlock,
block_hash: &Hash256,
) -> Result<(ActiveState, Option<CrystallizedState>), StateTransitionError> {
let state_recalc_distance = block
.slot
.checked_sub(cry_state.last_state_recalculation_slot)
.ok_or(StateTransitionError::BlockSlotBeforeRecalcSlot)?;
if state_recalc_distance >= u64::from(self.spec.epoch_length) {
panic!("Not implemented!")
} else {
let new_act_state = extend_active_state(act_state, block, block_hash)?;
Ok((new_act_state, None))
}
}
}