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
|
- slot: 5
|
||||||
amount: 32
|
amount: 32
|
||||||
merkle_index: 2
|
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:
|
results:
|
||||||
num_validators: 1000
|
num_validators: 1000
|
||||||
- config:
|
- config:
|
||||||
|
@ -10,6 +10,7 @@ use fork_choice::BitwiseLMDGhost;
|
|||||||
use log::debug;
|
use log::debug;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use slot_clock::TestingSlotClock;
|
use slot_clock::TestingSlotClock;
|
||||||
|
use ssz::TreeHash;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
@ -242,7 +243,7 @@ impl BeaconChainHarness {
|
|||||||
debug!("Free attestations processed.");
|
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);
|
self.beacon_chain.receive_deposit_for_inclusion(deposit);
|
||||||
|
|
||||||
// If a keypair is present, add a new `ValidatorHarness` to the rig.
|
// 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) {
|
pub fn run_fork_choice(&mut self) {
|
||||||
self.beacon_chain.fork_choice().unwrap()
|
self.beacon_chain.fork_choice().unwrap()
|
||||||
}
|
}
|
||||||
|
@ -85,12 +85,25 @@ impl Manifest {
|
|||||||
info!("Starting simulation across {} slots...", slots);
|
info!("Starting simulation across {} slots...", slots);
|
||||||
|
|
||||||
for slot_height in 0..slots {
|
for slot_height in 0..slots {
|
||||||
// Include deposits
|
// Feed deposits to the BeaconChain.
|
||||||
if let Some(ref deposits) = self.config.deposits {
|
if let Some(ref deposits) = self.config.deposits {
|
||||||
for (slot, deposit, keypair) in deposits {
|
for (slot, deposit, keypair) in deposits {
|
||||||
if *slot == slot_height {
|
if *slot == slot_height {
|
||||||
info!("Including deposit at slot height {}.", 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 DepositTuple = (u64, Deposit, Keypair);
|
||||||
|
pub type ProposerSlashingTuple = (u64, ProposerSlashing);
|
||||||
|
|
||||||
struct ExecutionResult {
|
struct ExecutionResult {
|
||||||
pub chain: Vec<CheckPoint>,
|
pub chain: Vec<CheckPoint>,
|
||||||
@ -190,6 +204,7 @@ struct Config {
|
|||||||
pub num_slots: u64,
|
pub num_slots: u64,
|
||||||
pub skip_slots: Option<Vec<u64>>,
|
pub skip_slots: Option<Vec<u64>>,
|
||||||
pub deposits: Option<Vec<DepositTuple>>,
|
pub deposits: Option<Vec<DepositTuple>>,
|
||||||
|
pub proposer_slashings: Option<Vec<ProposerSlashingTuple>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
@ -200,12 +215,52 @@ impl Config {
|
|||||||
epoch_length: as_u64(&yaml, "epoch_length"),
|
epoch_length: as_u64(&yaml, "epoch_length"),
|
||||||
num_slots: as_u64(&yaml, "num_slots").expect("Must specify `config.num_slots`"),
|
num_slots: as_u64(&yaml, "num_slots").expect("Must specify `config.num_slots`"),
|
||||||
skip_slots: as_vec_u64(yaml, "skip_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![];
|
let mut deposits = vec![];
|
||||||
|
|
||||||
for deposit in yaml["deposits"].as_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))
|
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>> {
|
fn as_vec_u64(yaml: &Yaml, key: &str) -> Option<Vec<u64>> {
|
||||||
yaml[key].clone().into_vec().and_then(|vec| {
|
yaml[key].clone().into_vec().and_then(|vec| {
|
||||||
Some(
|
Some(
|
||||||
|
Loading…
Reference in New Issue
Block a user