Move beacon_chain into lighthouse dir
This commit is contained in:
		
							parent
							
								
									dc8fbf813f
								
							
						
					
					
						commit
						2b63ece244
					
				| @ -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" } | ||||
| @ -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) | ||||
|     } | ||||
| } | ||||
| @ -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) | ||||
|     } | ||||
| } | ||||
							
								
								
									
										17
									
								
								lighthouse/beacon_chain/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								lighthouse/beacon_chain/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| [package] | ||||
| name = "chain" | ||||
| version = "0.1.0" | ||||
| authors = ["Paul Hauner <paul@paulhauner.com>"] | ||||
| edition = "2018" | ||||
| 
 | ||||
| [dependencies] | ||||
| bls = { path = "../../beacon_chain/utils/bls" } | ||||
| db = { path = "../db" } | ||||
| genesis = { path = "../../beacon_chain/genesis" } | ||||
| naive_fork_choice = { path = "../../beacon_chain/naive_fork_choice" } | ||||
| slot_clock = { path = "../../beacon_chain/utils/slot_clock" } | ||||
| spec = { path = "../../beacon_chain/spec" } | ||||
| ssz = { path = "../../beacon_chain/utils/ssz" } | ||||
| types = { path = "../../beacon_chain/types" } | ||||
| validator_induction = { path = "../../beacon_chain/validator_induction" } | ||||
| validator_shuffling = { path = "../../beacon_chain/validator_shuffling" } | ||||
							
								
								
									
										72
									
								
								lighthouse/beacon_chain/src/block_processing.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								lighthouse/beacon_chain/src/block_processing.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,72 @@ | ||||
| use super::{BeaconChain, ClientDB, DBError, SlotClock}; | ||||
| use slot_clock::TestingSlotClockError; | ||||
| use ssz::{ssz_encode, Encodable}; | ||||
| use types::{readers::BeaconBlockReader, Hash256}; | ||||
| 
 | ||||
| #[derive(Debug, PartialEq)] | ||||
| pub enum Outcome { | ||||
|     FutureSlot, | ||||
|     Processed, | ||||
| 
 | ||||
|     NewCanonicalBlock, | ||||
|     NewReorgBlock, | ||||
|     NewForkBlock, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, PartialEq)] | ||||
| pub enum Error { | ||||
|     DBError(String), | ||||
|     NotImplemented, | ||||
|     PresentSlotIsNone, | ||||
| } | ||||
| 
 | ||||
| impl<T, U> BeaconChain<T, U> | ||||
| where | ||||
|     T: ClientDB, | ||||
|     U: SlotClock, | ||||
|     Error: From<<U as SlotClock>::Error>, | ||||
| { | ||||
|     pub fn process_block<V>(&mut self, block: &V) -> Result<(Outcome, Hash256), Error> | ||||
|     where | ||||
|         V: BeaconBlockReader + Encodable + Sized, | ||||
|     { | ||||
|         let block_root = block.canonical_root(); | ||||
| 
 | ||||
|         let present_slot = self | ||||
|             .slot_clock | ||||
|             .present_slot()? | ||||
|             .ok_or(Error::PresentSlotIsNone)?; | ||||
| 
 | ||||
|         // Block from future slots (i.e., greater than the present slot) should not be processed.
 | ||||
|         if block.slot() > present_slot { | ||||
|             return Ok((Outcome::FutureSlot, block_root)); | ||||
|         } | ||||
| 
 | ||||
|         // TODO: block processing has been removed.
 | ||||
|         // https://github.com/sigp/lighthouse/issues/98
 | ||||
| 
 | ||||
|         // Update leaf blocks.
 | ||||
|         self.block_store.put(&block_root, &ssz_encode(block)[..])?; | ||||
|         if self.leaf_blocks.contains(&block.parent_root()) { | ||||
|             self.leaf_blocks.remove(&block.parent_root()); | ||||
|         } | ||||
|         if self.canonical_leaf_block == block.parent_root() { | ||||
|             self.canonical_leaf_block = block_root; | ||||
|         } | ||||
|         self.leaf_blocks.insert(block_root); | ||||
| 
 | ||||
|         Ok((Outcome::Processed, block_root)) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<DBError> for Error { | ||||
|     fn from(e: DBError) -> Error { | ||||
|         Error::DBError(e.message) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<TestingSlotClockError> for Error { | ||||
|     fn from(_: TestingSlotClockError) -> Error { | ||||
|         unreachable!(); // Testing clock never throws an error.
 | ||||
|     } | ||||
| } | ||||
							
								
								
									
										64
									
								
								lighthouse/beacon_chain/src/block_production.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								lighthouse/beacon_chain/src/block_production.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,64 @@ | ||||
| use super::{BeaconChain, ClientDB, DBError, SlotClock}; | ||||
| use slot_clock::TestingSlotClockError; | ||||
| use types::{ | ||||
|     readers::{BeaconBlockReader, BeaconStateReader}, | ||||
|     BeaconBlock, BeaconState, Hash256, | ||||
| }; | ||||
| 
 | ||||
| #[derive(Debug, PartialEq)] | ||||
| pub enum Error { | ||||
|     DBError(String), | ||||
|     PresentSlotIsNone, | ||||
| } | ||||
| 
 | ||||
| impl<T, U> BeaconChain<T, U> | ||||
| where | ||||
|     T: ClientDB, | ||||
|     U: SlotClock, | ||||
|     Error: From<<U as SlotClock>::Error>, | ||||
| { | ||||
|     pub fn produce_block(&mut self) -> Result<(BeaconBlock, BeaconState), Error> { | ||||
|         let present_slot = self | ||||
|             .slot_clock | ||||
|             .present_slot()? | ||||
|             .ok_or(Error::PresentSlotIsNone)?; | ||||
|         let parent_root = self.canonical_leaf_block; | ||||
|         let parent_block = self | ||||
|             .block_store | ||||
|             .get_deserialized(&parent_root)? | ||||
|             .ok_or(Error::DBError("Block not found.".to_string()))?; | ||||
|         let parent_state = self | ||||
|             .state_store | ||||
|             .get_deserialized(&parent_block.state_root())? | ||||
|             .ok_or(Error::DBError("State not found.".to_string()))?; | ||||
| 
 | ||||
|         let mut block = BeaconBlock { | ||||
|             slot: present_slot, | ||||
|             parent_root, | ||||
|             state_root: Hash256::zero(), // Updated after the state is calculated.
 | ||||
|             ..parent_block.to_beacon_block() | ||||
|         }; | ||||
| 
 | ||||
|         let state = BeaconState { | ||||
|             slot: present_slot, | ||||
|             ..parent_state.to_beacon_state() | ||||
|         }; | ||||
|         let state_root = state.canonical_root(); | ||||
| 
 | ||||
|         block.state_root = state_root; | ||||
| 
 | ||||
|         Ok((block, state)) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<DBError> for Error { | ||||
|     fn from(e: DBError) -> Error { | ||||
|         Error::DBError(e.message) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<TestingSlotClockError> for Error { | ||||
|     fn from(_: TestingSlotClockError) -> Error { | ||||
|         unreachable!(); // Testing clock never throws an error.
 | ||||
|     } | ||||
| } | ||||
							
								
								
									
										83
									
								
								lighthouse/beacon_chain/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								lighthouse/beacon_chain/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,83 @@ | ||||
| mod block_processing; | ||||
| mod block_production; | ||||
| mod maps; | ||||
| mod stores; | ||||
| 
 | ||||
| use db::{ | ||||
|     stores::{BeaconBlockStore, BeaconStateStore}, | ||||
|     ClientDB, DBError, | ||||
| }; | ||||
| use genesis::{genesis_beacon_block, genesis_beacon_state, GenesisError}; | ||||
| use slot_clock::{SlotClock, TestingSlotClockError}; | ||||
| use spec::ChainSpec; | ||||
| use ssz::ssz_encode; | ||||
| use std::collections::HashSet; | ||||
| use std::sync::Arc; | ||||
| use types::Hash256; | ||||
| 
 | ||||
| pub use crate::block_processing::Outcome as BlockProcessingOutcome; | ||||
| 
 | ||||
| #[derive(Debug, PartialEq)] | ||||
| pub enum BeaconChainError { | ||||
|     InsufficientValidators, | ||||
|     GenesisError(GenesisError), | ||||
|     DBError(String), | ||||
| } | ||||
| 
 | ||||
| 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 spec: ChainSpec, | ||||
| } | ||||
| 
 | ||||
| impl<T, U> BeaconChain<T, U> | ||||
| where | ||||
|     T: ClientDB, | ||||
|     U: SlotClock, | ||||
| { | ||||
|     pub fn genesis( | ||||
|         state_store: Arc<BeaconStateStore<T>>, | ||||
|         block_store: Arc<BeaconBlockStore<T>>, | ||||
|         slot_clock: U, | ||||
|         spec: ChainSpec, | ||||
|     ) -> Result<Self, BeaconChainError> { | ||||
|         if spec.initial_validators.is_empty() { | ||||
|             return Err(BeaconChainError::InsufficientValidators); | ||||
|         } | ||||
| 
 | ||||
|         let genesis_state = genesis_beacon_state(&spec)?; | ||||
|         let state_root = genesis_state.canonical_root(); | ||||
|         state_store.put(&state_root, &ssz_encode(&genesis_state)[..])?; | ||||
| 
 | ||||
|         let genesis_block = genesis_beacon_block(state_root, &spec); | ||||
|         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.clone()); | ||||
| 
 | ||||
|         Ok(Self { | ||||
|             block_store, | ||||
|             state_store, | ||||
|             slot_clock, | ||||
|             leaf_blocks, | ||||
|             canonical_leaf_block: block_root, | ||||
|             spec, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<DBError> for BeaconChainError { | ||||
|     fn from(e: DBError) -> BeaconChainError { | ||||
|         BeaconChainError::DBError(e.message) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<GenesisError> for BeaconChainError { | ||||
|     fn from(e: GenesisError) -> BeaconChainError { | ||||
|         BeaconChainError::GenesisError(e) | ||||
|     } | ||||
| } | ||||
| @ -3,7 +3,7 @@ use db::ClientDB; | ||||
| use state_transition::{extend_active_state, StateTransitionError}; | ||||
| use types::{ActiveState, BeaconBlock, CrystallizedState, Hash256}; | ||||
| 
 | ||||
| impl<T> BeaconChain<T> | ||||
| impl<T, U> BeaconChain<T, U> | ||||
| where | ||||
|     T: ClientDB + Sized, | ||||
| { | ||||
							
								
								
									
										49
									
								
								lighthouse/beacon_chain/tests/chain_test.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								lighthouse/beacon_chain/tests/chain_test.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| use chain::{BlockProcessingOutcome, BeaconChain}; | ||||
| use db::{ | ||||
|     stores::{BeaconBlockStore, BeaconStateStore}, | ||||
|     MemoryDB, | ||||
| }; | ||||
| use slot_clock::TestingSlotClock; | ||||
| use spec::ChainSpec; | ||||
| use std::sync::Arc; | ||||
| 
 | ||||
| fn in_memory_test_stores() -> ( | ||||
|     Arc<MemoryDB>, | ||||
|     Arc<BeaconBlockStore<MemoryDB>>, | ||||
|     Arc<BeaconStateStore<MemoryDB>>, | ||||
| ) { | ||||
|     let db = Arc::new(MemoryDB::open()); | ||||
|     let block_store = Arc::new(BeaconBlockStore::new(db.clone())); | ||||
|     let state_store = Arc::new(BeaconStateStore::new(db.clone())); | ||||
|     (db, block_store, state_store) | ||||
| } | ||||
| 
 | ||||
| fn in_memory_test_chain( | ||||
|     spec: ChainSpec, | ||||
| ) -> (Arc<MemoryDB>, BeaconChain<MemoryDB, TestingSlotClock>) { | ||||
|     let (db, block_store, state_store) = in_memory_test_stores(); | ||||
|     let slot_clock = TestingSlotClock::new(0); | ||||
| 
 | ||||
|     let chain = BeaconChain::genesis(state_store, block_store, slot_clock, spec); | ||||
|     (db, chain.unwrap()) | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn it_constructs() { | ||||
|     let (_db, _chain) = in_memory_test_chain(ChainSpec::foundation()); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn it_produces() { | ||||
|     let (_db, mut chain) = in_memory_test_chain(ChainSpec::foundation()); | ||||
|     let (_block, _state) = chain.produce_block().unwrap(); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn it_processes_a_block_it_produces() { | ||||
|     let (_db, mut chain) = in_memory_test_chain(ChainSpec::foundation()); | ||||
|     let (block, _state) = chain.produce_block().unwrap(); | ||||
|     let (outcome, new_block_hash) = chain.process_block(&block).unwrap(); | ||||
|     assert_eq!(outcome, BlockProcessingOutcome::Processed); | ||||
|     assert_eq!(chain.canonical_leaf_block, new_block_hash); | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user