Add new beacon chain test harness
This commit is contained in:
		
							parent
							
								
									1128de535d
								
							
						
					
					
						commit
						8fb6ffffe2
					
				| @ -88,6 +88,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> { | ||||
|         genesis_block: BeaconBlock, | ||||
|         spec: ChainSpec, | ||||
|     ) -> Result<Self, Error> { | ||||
|         genesis_state.build_all_caches(&spec)?; | ||||
| 
 | ||||
|         let state_root = genesis_state.canonical_root(); | ||||
|         store.put(&state_root, &genesis_state)?; | ||||
| 
 | ||||
| @ -105,8 +107,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> { | ||||
|             state_root, | ||||
|         )); | ||||
| 
 | ||||
|         genesis_state.build_all_caches(&spec)?; | ||||
| 
 | ||||
|         Ok(Self { | ||||
|             spec, | ||||
|             slot_clock, | ||||
|  | ||||
| @ -5,6 +5,7 @@ mod fork_choice; | ||||
| pub mod iter; | ||||
| mod metrics; | ||||
| mod persisted_beacon_chain; | ||||
| mod test_utils; | ||||
| 
 | ||||
| pub use self::beacon_chain::{BeaconChain, BeaconChainTypes, BlockProcessingOutcome}; | ||||
| pub use self::checkpoint::CheckPoint; | ||||
|  | ||||
							
								
								
									
										147
									
								
								beacon_node/beacon_chain/src/test_utils.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								beacon_node/beacon_chain/src/test_utils.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,147 @@ | ||||
| use crate::{BeaconChain, BeaconChainTypes, BlockProcessingOutcome}; | ||||
| use lmd_ghost::{LmdGhost, ThreadSafeReducedTree}; | ||||
| use slot_clock::SlotClock; | ||||
| use slot_clock::TestingSlotClock; | ||||
| use std::marker::PhantomData; | ||||
| use std::sync::Arc; | ||||
| use store::MemoryStore; | ||||
| use tree_hash::{SignedRoot, TreeHash}; | ||||
| use types::{ | ||||
|     test_utils::TestingBeaconStateBuilder, BeaconBlock, ChainSpec, Domain, EthSpec, Hash256, | ||||
|     Keypair, MinimalEthSpec, Signature, | ||||
| }; | ||||
| 
 | ||||
| pub struct CommonTypes<L, E> | ||||
| where | ||||
|     L: LmdGhost<MemoryStore, E>, | ||||
|     E: EthSpec, | ||||
| { | ||||
|     _phantom_l: PhantomData<L>, | ||||
|     _phantom_e: PhantomData<E>, | ||||
| } | ||||
| 
 | ||||
| impl<L, E> BeaconChainTypes for CommonTypes<L, E> | ||||
| where | ||||
|     L: LmdGhost<MemoryStore, E>, | ||||
|     E: EthSpec, | ||||
| { | ||||
|     type Store = MemoryStore; | ||||
|     type SlotClock = TestingSlotClock; | ||||
|     type LmdGhost = L; | ||||
|     type EthSpec = E; | ||||
| } | ||||
| 
 | ||||
| pub struct BeaconChainHarness<L, E> | ||||
| where | ||||
|     L: LmdGhost<MemoryStore, E>, | ||||
|     E: EthSpec, | ||||
| { | ||||
|     chain: BeaconChain<CommonTypes<L, E>>, | ||||
|     keypairs: Vec<Keypair>, | ||||
|     spec: ChainSpec, | ||||
| } | ||||
| 
 | ||||
| impl<L, E> BeaconChainHarness<L, E> | ||||
| where | ||||
|     L: LmdGhost<MemoryStore, E>, | ||||
|     E: EthSpec, | ||||
| { | ||||
|     pub fn new(validator_count: usize) -> Self { | ||||
|         let spec = E::default_spec(); | ||||
| 
 | ||||
|         let store = Arc::new(MemoryStore::open()); | ||||
| 
 | ||||
|         let state_builder = | ||||
|             TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(validator_count, &spec); | ||||
|         let (genesis_state, keypairs) = state_builder.build(); | ||||
| 
 | ||||
|         let mut genesis_block = BeaconBlock::empty(&spec); | ||||
|         genesis_block.state_root = Hash256::from_slice(&genesis_state.tree_hash_root()); | ||||
| 
 | ||||
|         // Slot clock
 | ||||
|         let slot_clock = TestingSlotClock::new( | ||||
|             spec.genesis_slot, | ||||
|             genesis_state.genesis_time, | ||||
|             spec.seconds_per_slot, | ||||
|         ); | ||||
| 
 | ||||
|         let chain = BeaconChain::from_genesis( | ||||
|             store, | ||||
|             slot_clock, | ||||
|             genesis_state, | ||||
|             genesis_block, | ||||
|             spec.clone(), | ||||
|         ) | ||||
|         .expect("Terminate if beacon chain generation fails"); | ||||
| 
 | ||||
|         Self { | ||||
|             chain, | ||||
|             keypairs, | ||||
|             spec, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn extend_canonical_chain(&self) { | ||||
|         self.chain.slot_clock.advance_slot(); | ||||
|         self.chain.catchup_state().expect("should catchup state"); | ||||
| 
 | ||||
|         let block = self.build_block(); | ||||
|         let outcome = self | ||||
|             .chain | ||||
|             .process_block(block) | ||||
|             .expect("should process block"); | ||||
|         assert_eq!(outcome, BlockProcessingOutcome::Processed); | ||||
|     } | ||||
| 
 | ||||
|     fn build_block(&self) -> BeaconBlock { | ||||
|         let slot = self.chain.read_slot_clock().unwrap(); | ||||
| 
 | ||||
|         let sk = { | ||||
|             let proposer = self | ||||
|                 .chain | ||||
|                 .block_proposer(slot) | ||||
|                 .expect("should get block propoer"); | ||||
|             &self.keypairs[proposer].sk | ||||
|         }; | ||||
| 
 | ||||
|         let fork = &self.chain.head().beacon_state.fork; | ||||
| 
 | ||||
|         let randao_reveal = { | ||||
|             let epoch = slot.epoch(E::slots_per_epoch()); | ||||
|             let message = epoch.tree_hash_root(); | ||||
|             let domain = self.spec.get_domain(epoch, Domain::Randao, fork); | ||||
|             Signature::new(&message, domain, sk) | ||||
|         }; | ||||
| 
 | ||||
|         let (mut block, _state) = self | ||||
|             .chain | ||||
|             .produce_block(randao_reveal) | ||||
|             .expect("should producer block"); | ||||
| 
 | ||||
|         block.signature = { | ||||
|             let message = block.signed_root(); | ||||
|             let epoch = block.slot.epoch(E::slots_per_epoch()); | ||||
|             let domain = self.spec.get_domain(epoch, Domain::BeaconProposer, fork); | ||||
|             Signature::new(&message, domain, sk) | ||||
|         }; | ||||
| 
 | ||||
|         block | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[cfg(test)] | ||||
| mod test { | ||||
|     use super::*; | ||||
| 
 | ||||
|     pub const VALIDATOR_COUNT: usize = 16; | ||||
| 
 | ||||
|     #[test] | ||||
|     fn build_on_genesis() { | ||||
|         let harness: BeaconChainHarness< | ||||
|             ThreadSafeReducedTree<MemoryStore, MinimalEthSpec>, | ||||
|             MinimalEthSpec, | ||||
|         > = BeaconChainHarness::new(VALIDATOR_COUNT); | ||||
| 
 | ||||
|         harness.extend_canonical_chain(); | ||||
|     } | ||||
| } | ||||
| @ -15,6 +15,10 @@ impl TestingSlotClock { | ||||
|     pub fn set_slot(&self, slot: u64) { | ||||
|         *self.slot.write().expect("TestingSlotClock poisoned.") = Slot::from(slot); | ||||
|     } | ||||
| 
 | ||||
|     pub fn advance_slot(&self) { | ||||
|         self.set_slot(self.present_slot().unwrap().unwrap().as_u64() + 1) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl SlotClock for TestingSlotClock { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user