Add progress on op pool test fixes

This commit is contained in:
Paul Hauner 2019-05-09 18:56:41 +10:00
parent 2a938f2fd5
commit 77c4b6eafe
No known key found for this signature in database
GPG Key ID: D362883A9218FCC6
6 changed files with 259 additions and 394 deletions

View File

@ -718,13 +718,16 @@ mod tests {
/// Create a signed attestation for use in tests.
/// Signed by all validators in `committee[signing_range]` and `committee[extra_signer]`.
#[cfg(not(debug_assertions))]
fn signed_attestation<R: std::slice::SliceIndex<[usize], Output = [usize]>>(
// #[cfg(not(debug_assertions))]
fn signed_attestation<
R: std::slice::SliceIndex<[usize], Output = [usize]>,
B: BeaconStateTypes,
>(
committee: &CrosslinkCommittee,
keypairs: &[Keypair],
signing_range: R,
slot: Slot,
state: &BeaconState,
state: &BeaconState<B>,
spec: &ChainSpec,
extra_signer: Option<usize>,
) -> Attestation {
@ -750,26 +753,37 @@ mod tests {
builder.build()
}
/// Test state for attestation-related tests.
#[cfg(not(debug_assertions))]
fn attestation_test_state(
spec: &ChainSpec,
mod release_tests {
use super::*;
/// Test state for attestation-related tests.
fn attestation_test_state<B: BeaconStateTypes>(
num_committees: usize,
) -> (BeaconState, Vec<Keypair>) {
) -> (BeaconState<B>, Vec<Keypair>, ChainSpec) {
let spec = B::spec();
let num_validators =
num_committees * (spec.slots_per_epoch * spec.target_committee_size) as usize;
let mut state_builder =
TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(num_validators, spec);
let mut state_builder = TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(
num_validators,
&spec,
);
let slot_offset = 1000 * spec.slots_per_epoch + spec.slots_per_epoch / 2;
let slot = spec.genesis_slot + slot_offset;
state_builder.teleport_to_slot(slot, spec);
state_builder.build_caches(spec).unwrap();
state_builder.build()
state_builder.teleport_to_slot(slot, &spec);
state_builder.build_caches(&spec).unwrap();
let (state, keypairs) = state_builder.build();
(state, keypairs, FoundationStateTypes::spec())
}
/// Set the latest crosslink in the state to match the attestation.
#[cfg(not(debug_assertions))]
fn fake_latest_crosslink(att: &Attestation, state: &mut BeaconState, spec: &ChainSpec) {
fn fake_latest_crosslink<T: BeaconStateTypes>(
att: &Attestation,
state: &mut BeaconState<B>,
spec: &ChainSpec,
) {
state.latest_crosslinks[att.data.shard as usize] = Crosslink {
crosslink_data_root: att.data.crosslink_data_root,
epoch: att.data.slot.epoch(spec.slots_per_epoch),
@ -777,10 +791,10 @@ mod tests {
}
#[test]
#[cfg(not(debug_assertions))]
fn test_attestation_score() {
let spec = &ChainSpec::foundation();
let (ref mut state, ref keypairs) = attestation_test_state(spec, 1);
let (ref mut state, ref keypairs, ref spec) =
attestation_test_state::<FoundationStateTypes>(1);
let slot = state.slot - 1;
let committees = state
.get_crosslink_committees_at_slot(slot, spec)
@ -809,10 +823,10 @@ mod tests {
/// End-to-end test of basic attestation handling.
#[test]
#[cfg(not(debug_assertions))]
fn attestation_aggregation_insert_get_prune() {
let spec = &ChainSpec::foundation();
let (ref mut state, ref keypairs) = attestation_test_state(spec, 1);
let (ref mut state, ref keypairs, ref spec) =
attestation_test_state::<FoundationStateTypes>(1);
let op_pool = OperationPool::new();
let slot = state.slot - 1;
@ -875,10 +889,10 @@ mod tests {
/// Adding an attestation already in the pool should not increase the size of the pool.
#[test]
#[cfg(not(debug_assertions))]
fn attestation_duplicate() {
let spec = &ChainSpec::foundation();
let (ref mut state, ref keypairs) = attestation_test_state(spec, 1);
let (ref mut state, ref keypairs, ref spec) =
attestation_test_state::<FoundationStateTypes>(1);
let op_pool = OperationPool::new();
let slot = state.slot - 1;
@ -902,10 +916,10 @@ mod tests {
/// Adding lots of attestations that only intersect pairwise should lead to two aggregate
/// attestations.
#[test]
#[cfg(not(debug_assertions))]
fn attestation_pairwise_overlapping() {
let spec = &ChainSpec::foundation();
let (ref mut state, ref keypairs) = attestation_test_state(spec, 1);
let (ref mut state, ref keypairs, ref spec) =
attestation_test_state::<FoundationStateTypes>(1);
let op_pool = OperationPool::new();
let slot = state.slot - 1;
@ -945,7 +959,6 @@ mod tests {
/// high-quality attestations. To ensure that no aggregation occurs, ALL attestations
/// are also signed by the 0th member of the committee.
#[test]
#[cfg(not(debug_assertions))]
fn attestation_get_max() {
let spec = &ChainSpec::foundation();
let small_step_size = 2;
@ -1005,6 +1018,7 @@ mod tests {
assert!(att.aggregation_bitfield.num_set_bits() >= big_step_size);
}
}
}
// TODO: more tests
}

View File

@ -100,7 +100,7 @@ fn verify_deposit_merkle_proof<T: BeaconStateTypes>(
let leaf = hash(&get_serialized_deposit_data(deposit));
verify_merkle_proof(
Hash256::from_slice(&leaf),
&deposit.proof,
&deposit.proof[..],
spec.deposit_contract_tree_depth as usize,
deposit.index as usize,
state.latest_eth1_data.deposit_root,

View File

@ -1,153 +0,0 @@
#![cfg(not(debug_assertions))]
use serde_derive::Deserialize;
use serde_yaml;
use state_processing::{per_block_processing, per_slot_processing};
use std::{fs::File, io::prelude::*, path::PathBuf};
use types::*;
#[derive(Debug, Deserialize)]
pub struct ExpectedState {
pub slot: Option<Slot>,
pub genesis_time: Option<u64>,
pub fork: Option<Fork>,
pub validator_registry: Option<Vec<Validator>>,
pub validator_balances: Option<Vec<u64>>,
pub previous_epoch_attestations: Option<Vec<PendingAttestation>>,
pub current_epoch_attestations: Option<Vec<PendingAttestation>>,
pub historical_roots: Option<Vec<Hash256>>,
pub finalized_epoch: Option<Epoch>,
pub latest_block_roots: Option<TreeHashVector<Hash256>>,
}
impl ExpectedState {
// Return a list of fields that differ, and a string representation of the beacon state's field.
fn check(&self, state: &BeaconState) -> Vec<(&str, String)> {
// Check field equality
macro_rules! cfe {
($field_name:ident) => {
if self.$field_name.as_ref().map_or(true, |$field_name| {
println!(" > Checking {}", stringify!($field_name));
$field_name == &state.$field_name
}) {
vec![]
} else {
vec![(stringify!($field_name), format!("{:#?}", state.$field_name))]
}
};
}
vec![
cfe!(slot),
cfe!(genesis_time),
cfe!(fork),
cfe!(validator_registry),
cfe!(validator_balances),
cfe!(previous_epoch_attestations),
cfe!(current_epoch_attestations),
cfe!(historical_roots),
cfe!(finalized_epoch),
cfe!(latest_block_roots),
]
.into_iter()
.flat_map(|x| x)
.collect()
}
}
#[derive(Debug, Deserialize)]
pub struct TestCase {
pub name: String,
pub config: ChainSpec,
pub verify_signatures: bool,
pub initial_state: BeaconState,
pub blocks: Vec<BeaconBlock>,
pub expected_state: ExpectedState,
}
#[derive(Debug, Deserialize)]
pub struct TestDoc {
pub title: String,
pub summary: String,
pub fork: String,
pub test_cases: Vec<TestCase>,
}
fn load_test_case(test_name: &str) -> TestDoc {
let mut file = {
let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
file_path_buf.push(format!("yaml_utils/specs/{}", test_name));
File::open(file_path_buf).unwrap()
};
let mut yaml_str = String::new();
file.read_to_string(&mut yaml_str).unwrap();
yaml_str = yaml_str.to_lowercase();
serde_yaml::from_str(&yaml_str.as_str()).unwrap()
}
fn run_state_transition_test(test_name: &str) {
let doc = load_test_case(test_name);
// Run Tests
let mut ok = true;
for (i, test_case) in doc.test_cases.iter().enumerate() {
let fake_crypto = cfg!(feature = "fake_crypto");
if !test_case.verify_signatures == fake_crypto {
println!("Running {}", test_case.name);
} else {
println!(
"Skipping {} (fake_crypto: {}, need fake: {})",
test_case.name, fake_crypto, !test_case.verify_signatures
);
continue;
}
let mut state = test_case.initial_state.clone();
for (j, block) in test_case.blocks.iter().enumerate() {
while block.slot > state.slot {
per_slot_processing(&mut state, &test_case.config).unwrap();
}
let res = per_block_processing(&mut state, &block, &test_case.config);
if res.is_err() {
println!("Error in {} (#{}), on block {}", test_case.name, i, j);
println!("{:?}", res);
ok = false;
}
}
let mismatched_fields = test_case.expected_state.check(&state);
if !mismatched_fields.is_empty() {
println!(
"Error in expected state, these fields didn't match: {:?}",
mismatched_fields.iter().map(|(f, _)| f).collect::<Vec<_>>()
);
for (field_name, state_val) in mismatched_fields {
println!("state.{} was: {}", field_name, state_val);
}
ok = false;
}
}
assert!(ok, "one or more tests failed, see above");
}
#[test]
#[cfg(not(debug_assertions))]
fn test_read_yaml() {
load_test_case("sanity-check_small-config_32-vals.yaml");
load_test_case("sanity-check_default-config_100-vals.yaml");
}
#[test]
#[cfg(not(debug_assertions))]
fn run_state_transition_tests_small() {
run_state_transition_test("sanity-check_small-config_32-vals.yaml");
}
// Run with --ignored to run this test
#[test]
#[ignore]
fn run_state_transition_tests_large() {
run_state_transition_test("sanity-check_default-config_100-vals.yaml");
}

View File

@ -1,8 +1,11 @@
use crate::*;
use fixed_len_vec::typenum::{Unsigned, U1024, U8, U8192};
use serde_derive::{Deserialize, Serialize};
use std::fmt::Debug;
pub trait BeaconStateTypes: 'static + Default + Sync + Send + Clone + Debug + PartialEq {
pub trait BeaconStateTypes:
'static + Default + Sync + Send + Clone + Debug + PartialEq + serde::de::DeserializeOwned
{
type ShardCount: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type SlotsPerHistoricalRoot: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type LatestRandaoMixesLength: Unsigned + Clone + Sync + Send + Debug + PartialEq;
@ -13,7 +16,7 @@ pub trait BeaconStateTypes: 'static + Default + Sync + Send + Clone + Debug + Pa
}
/// Ethereum Foundation specifications.
#[derive(Clone, PartialEq, Debug, Default)]
#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)]
pub struct FoundationStateTypes;
impl BeaconStateTypes for FoundationStateTypes {
@ -30,7 +33,7 @@ impl BeaconStateTypes for FoundationStateTypes {
pub type FoundationBeaconState = BeaconState<FoundationStateTypes>;
#[derive(Clone, PartialEq, Debug, Default)]
#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)]
pub struct FewValidatorsStateTypes;
impl BeaconStateTypes for FewValidatorsStateTypes {
@ -47,7 +50,7 @@ impl BeaconStateTypes for FewValidatorsStateTypes {
pub type FewValidatorsBeaconState = BeaconState<FewValidatorsStateTypes>;
#[derive(Clone, PartialEq, Debug, Default)]
#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)]
pub struct LighthouseTestnetStateTypes;
impl BeaconStateTypes for LighthouseTestnetStateTypes {

View File

@ -1,5 +1,6 @@
use super::{DepositData, Hash256, TreeHashVector};
use crate::test_utils::TestRandom;
use crate::*;
use fixed_len_vec::typenum::U32;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
@ -22,7 +23,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
TestRandom,
)]
pub struct Deposit {
pub proof: TreeHashVector<Hash256>,
pub proof: FixedLenVec<Hash256, U32>,
pub index: u64,
pub deposit_data: DepositData,
}

View File

@ -27,7 +27,7 @@ pub mod pending_attestation;
pub mod proposer_slashing;
pub mod slashable_attestation;
pub mod transfer;
pub mod tree_hash_vector;
// pub mod tree_hash_vector;
pub mod voluntary_exit;
#[macro_use]
pub mod slot_epoch_macros;
@ -66,7 +66,7 @@ pub use crate::slashable_attestation::SlashableAttestation;
pub use crate::slot_epoch::{Epoch, Slot};
pub use crate::slot_height::SlotHeight;
pub use crate::transfer::Transfer;
pub use crate::tree_hash_vector::TreeHashVector;
// pub use crate::tree_hash_vector::TreeHashVector;
pub use crate::validator::Validator;
pub use crate::voluntary_exit::VoluntaryExit;