Add proposer slashing support to test_harness
Test harness will now add signatures to a ProposerSlashing and submit it to the BeaconChain
This commit is contained in:
		
							parent
							
								
									fd819fb7ca
								
							
						
					
					
						commit
						7f1e40a8c6
					
				| @ -19,6 +19,17 @@ test_cases: | ||||
|         - slot: 5 | ||||
|           amount: 32 | ||||
|           merkle_index: 2 | ||||
|       proposer_slashings: | ||||
|         - slot: 8 # At slot 8, we trigger a proposal slashing occurring | ||||
|           proposer_index: 42 # We penalize the validator at position 42 | ||||
|           proposal_1_shard: 0 | ||||
|           proposal_1_slot: 15 | ||||
|           proposal_1_root: !!binary | | ||||
|             LkmqmqoodLKAslkjdkajsdljasdkajlksjdasldjasdd | ||||
|           proposal_2_shard: 0 | ||||
|           proposal_2_slot: 15 | ||||
|           proposal_2_root: !!binary | | ||||
|             DIFFERENTKAslkjdkajsdljasdkajlksjdasldjasdd | ||||
|     results: | ||||
|       num_validators: 1000 | ||||
|   - config: | ||||
|  | ||||
| @ -10,6 +10,7 @@ use fork_choice::BitwiseLMDGhost; | ||||
| use log::debug; | ||||
| use rayon::prelude::*; | ||||
| use slot_clock::TestingSlotClock; | ||||
| use ssz::TreeHash; | ||||
| use std::collections::HashSet; | ||||
| use std::fs::File; | ||||
| use std::io::prelude::*; | ||||
| @ -242,7 +243,7 @@ impl BeaconChainHarness { | ||||
|         debug!("Free attestations processed."); | ||||
|     } | ||||
| 
 | ||||
|     pub fn process_deposit(&mut self, deposit: Deposit, keypair: Option<Keypair>) { | ||||
|     pub fn add_deposit(&mut self, deposit: Deposit, keypair: Option<Keypair>) { | ||||
|         self.beacon_chain.receive_deposit_for_inclusion(deposit); | ||||
| 
 | ||||
|         // If a keypair is present, add a new `ValidatorHarness` to the rig.
 | ||||
| @ -253,6 +254,36 @@ impl BeaconChainHarness { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn add_proposer_slashing(&mut self, mut proposer_slashing: ProposerSlashing) { | ||||
|         let validator = &self.validators[proposer_slashing.proposer_index as usize]; | ||||
| 
 | ||||
|         // This following code is a little awkward, but managing the data_1 and data_1 was getting
 | ||||
|         // rather confusing. I think this is better
 | ||||
|         let proposals = vec![ | ||||
|             &proposer_slashing.proposal_data_1, | ||||
|             &proposer_slashing.proposal_data_2, | ||||
|         ]; | ||||
|         let signatures: Vec<Signature> = proposals | ||||
|             .iter() | ||||
|             .map(|proposal_data| { | ||||
|                 let message = proposal_data.hash_tree_root(); | ||||
|                 let epoch = proposal_data.slot.epoch(self.spec.epoch_length); | ||||
|                 let domain = self | ||||
|                     .beacon_chain | ||||
|                     .state | ||||
|                     .read() | ||||
|                     .fork | ||||
|                     .get_domain(epoch, self.spec.domain_proposal); | ||||
|                 Signature::new(&message[..], domain, &validator.keypair.sk) | ||||
|             }) | ||||
|             .collect(); | ||||
|         proposer_slashing.proposal_signature_1 = signatures[0].clone(); | ||||
|         proposer_slashing.proposal_signature_2 = signatures[1].clone(); | ||||
| 
 | ||||
|         self.beacon_chain | ||||
|             .receive_proposer_slashing_for_inclusion(proposer_slashing); | ||||
|     } | ||||
| 
 | ||||
|     pub fn run_fork_choice(&mut self) { | ||||
|         self.beacon_chain.fork_choice().unwrap() | ||||
|     } | ||||
|  | ||||
| @ -85,12 +85,25 @@ impl Manifest { | ||||
|         info!("Starting simulation across {} slots...", slots); | ||||
| 
 | ||||
|         for slot_height in 0..slots { | ||||
|             // Include deposits
 | ||||
|             // Feed deposits to the BeaconChain.
 | ||||
|             if let Some(ref deposits) = self.config.deposits { | ||||
|                 for (slot, deposit, keypair) in deposits { | ||||
|                     if *slot == slot_height { | ||||
|                         info!("Including deposit at slot height {}.", slot_height); | ||||
|                         harness.process_deposit(deposit.clone(), Some(keypair.clone())); | ||||
|                         harness.add_deposit(deposit.clone(), Some(keypair.clone())); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             // Feed proposer slashings to the BeaconChain.
 | ||||
|             if let Some(ref slashings) = self.config.proposer_slashings { | ||||
|                 for (slot, slashing) in slashings { | ||||
|                     if *slot == slot_height { | ||||
|                         info!( | ||||
|                             "Including proposer slashing at slot height {}.", | ||||
|                             slot_height | ||||
|                         ); | ||||
|                         harness.add_proposer_slashing(slashing.clone()); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| @ -163,6 +176,7 @@ impl Manifest { | ||||
| } | ||||
| 
 | ||||
| pub type DepositTuple = (u64, Deposit, Keypair); | ||||
| pub type ProposerSlashingTuple = (u64, ProposerSlashing); | ||||
| 
 | ||||
| struct ExecutionResult { | ||||
|     pub chain: Vec<CheckPoint>, | ||||
| @ -190,6 +204,7 @@ struct Config { | ||||
|     pub num_slots: u64, | ||||
|     pub skip_slots: Option<Vec<u64>>, | ||||
|     pub deposits: Option<Vec<DepositTuple>>, | ||||
|     pub proposer_slashings: Option<Vec<ProposerSlashingTuple>>, | ||||
| } | ||||
| 
 | ||||
| impl Config { | ||||
| @ -200,12 +215,52 @@ impl Config { | ||||
|             epoch_length: as_u64(&yaml, "epoch_length"), | ||||
|             num_slots: as_u64(&yaml, "num_slots").expect("Must specify `config.num_slots`"), | ||||
|             skip_slots: as_vec_u64(yaml, "skip_slots"), | ||||
|             deposits: process_deposits(&yaml), | ||||
|             deposits: parse_deposits(&yaml), | ||||
|             proposer_slashings: parse_proposer_slashings(&yaml), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn process_deposits(yaml: &Yaml) -> Option<Vec<DepositTuple>> { | ||||
| fn parse_proposer_slashings(yaml: &Yaml) -> Option<Vec<ProposerSlashingTuple>> { | ||||
|     let mut slashings = vec![]; | ||||
| 
 | ||||
|     for slashing in yaml["proposer_slashings"].as_vec()? { | ||||
|         let slot = as_u64(slashing, "slot").expect("Incomplete slashing"); | ||||
| 
 | ||||
|         let slashing = ProposerSlashing { | ||||
|             proposer_index: as_u64(slashing, "proposer_index") | ||||
|                 .expect("Incomplete slashing (proposer_index)"), | ||||
|             proposal_data_1: ProposalSignedData { | ||||
|                 slot: Slot::from( | ||||
|                     as_u64(slashing, "proposal_1_slot") | ||||
|                         .expect("Incomplete slashing (proposal_1_slot)."), | ||||
|                 ), | ||||
|                 shard: as_u64(slashing, "proposal_1_shard") | ||||
|                     .expect("Incomplete slashing (proposal_1_shard)."), | ||||
|                 block_root: as_hash256(slashing, "proposal_1_root") | ||||
|                     .expect("Incomplete slashing (proposal_1_root)."), | ||||
|             }, | ||||
|             proposal_signature_1: Signature::empty_signature(), // Will be replaced with real signature at runtime.
 | ||||
|             proposal_data_2: ProposalSignedData { | ||||
|                 slot: Slot::from( | ||||
|                     as_u64(slashing, "proposal_2_slot") | ||||
|                         .expect("Incomplete slashing (proposal_2_slot)."), | ||||
|                 ), | ||||
|                 shard: as_u64(slashing, "proposal_2_shard") | ||||
|                     .expect("Incomplete slashing (proposal_2_shard)."), | ||||
|                 block_root: as_hash256(slashing, "proposal_2_root") | ||||
|                     .expect("Incomplete slashing (proposal_2_root)."), | ||||
|             }, | ||||
|             proposal_signature_2: Signature::empty_signature(), // Will be replaced with real signature at runtime.
 | ||||
|         }; | ||||
| 
 | ||||
|         slashings.push((slot, slashing)); | ||||
|     } | ||||
| 
 | ||||
|     Some(slashings) | ||||
| } | ||||
| 
 | ||||
| fn parse_deposits(yaml: &Yaml) -> Option<Vec<DepositTuple>> { | ||||
|     let mut deposits = vec![]; | ||||
| 
 | ||||
|     for deposit in yaml["deposits"].as_vec()? { | ||||
| @ -241,6 +296,12 @@ fn as_u64(yaml: &Yaml, key: &str) -> Option<u64> { | ||||
|     yaml[key].as_i64().and_then(|n| Some(n as u64)) | ||||
| } | ||||
| 
 | ||||
| fn as_hash256(yaml: &Yaml, key: &str) -> Option<Hash256> { | ||||
|     yaml[key] | ||||
|         .as_str() | ||||
|         .and_then(|s| Some(Hash256::from(s.as_bytes()))) | ||||
| } | ||||
| 
 | ||||
| fn as_vec_u64(yaml: &Yaml, key: &str) -> Option<Vec<u64>> { | ||||
|     yaml[key].clone().into_vec().and_then(|vec| { | ||||
|         Some( | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user