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, |         genesis_block: BeaconBlock, | ||||||
|         spec: ChainSpec, |         spec: ChainSpec, | ||||||
|     ) -> Result<Self, Error> { |     ) -> Result<Self, Error> { | ||||||
|  |         genesis_state.build_all_caches(&spec)?; | ||||||
|  | 
 | ||||||
|         let state_root = genesis_state.canonical_root(); |         let state_root = genesis_state.canonical_root(); | ||||||
|         store.put(&state_root, &genesis_state)?; |         store.put(&state_root, &genesis_state)?; | ||||||
| 
 | 
 | ||||||
| @ -105,8 +107,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> { | |||||||
|             state_root, |             state_root, | ||||||
|         )); |         )); | ||||||
| 
 | 
 | ||||||
|         genesis_state.build_all_caches(&spec)?; |  | ||||||
| 
 |  | ||||||
|         Ok(Self { |         Ok(Self { | ||||||
|             spec, |             spec, | ||||||
|             slot_clock, |             slot_clock, | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ mod fork_choice; | |||||||
| pub mod iter; | pub mod iter; | ||||||
| mod metrics; | mod metrics; | ||||||
| mod persisted_beacon_chain; | mod persisted_beacon_chain; | ||||||
|  | mod test_utils; | ||||||
| 
 | 
 | ||||||
| pub use self::beacon_chain::{BeaconChain, BeaconChainTypes, BlockProcessingOutcome}; | pub use self::beacon_chain::{BeaconChain, BeaconChainTypes, BlockProcessingOutcome}; | ||||||
| pub use self::checkpoint::CheckPoint; | 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) { |     pub fn set_slot(&self, slot: u64) { | ||||||
|         *self.slot.write().expect("TestingSlotClock poisoned.") = Slot::from(slot); |         *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 { | impl SlotClock for TestingSlotClock { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user