mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-16 11:22:56 +00:00
Altair consensus changes and refactors (#2279)
## Proposed Changes Implement the consensus changes necessary for the upcoming Altair hard fork. ## Additional Info This is quite a heavy refactor, with pivotal types like the `BeaconState` and `BeaconBlock` changing from structs to enums. This ripples through the whole codebase with field accesses changing to methods, e.g. `state.slot` => `state.slot()`. Co-authored-by: realbigsean <seananderson33@gmail.com>
This commit is contained in:
@@ -1,23 +1,165 @@
|
||||
#![cfg(test)]
|
||||
use crate::per_epoch_processing::per_epoch_processing;
|
||||
use crate::per_epoch_processing::process_epoch;
|
||||
use beacon_chain::store::StoreConfig;
|
||||
use beacon_chain::test_utils::BeaconChainHarness;
|
||||
use beacon_chain::types::{EthSpec, MinimalEthSpec};
|
||||
use bls::Hash256;
|
||||
use env_logger::{Builder, Env};
|
||||
use types::test_utils::TestingBeaconStateBuilder;
|
||||
use types::*;
|
||||
use types::Slot;
|
||||
|
||||
#[test]
|
||||
fn runs_without_error() {
|
||||
Builder::from_env(Env::default().default_filter_or("error")).init();
|
||||
|
||||
let harness = BeaconChainHarness::new_with_store_config(
|
||||
MinimalEthSpec,
|
||||
None,
|
||||
types::test_utils::generate_deterministic_keypairs(8),
|
||||
StoreConfig::default(),
|
||||
);
|
||||
harness.advance_slot();
|
||||
|
||||
let spec = MinimalEthSpec::default_spec();
|
||||
|
||||
let mut builder: TestingBeaconStateBuilder<MinimalEthSpec> =
|
||||
TestingBeaconStateBuilder::from_deterministic_keypairs(8, &spec);
|
||||
|
||||
let target_slot =
|
||||
(MinimalEthSpec::genesis_epoch() + 4).end_slot(MinimalEthSpec::slots_per_epoch());
|
||||
builder.teleport_to_slot(target_slot);
|
||||
|
||||
let (mut state, _keypairs) = builder.build();
|
||||
let state = harness.get_current_state();
|
||||
harness.add_attested_blocks_at_slots(
|
||||
state,
|
||||
Hash256::zero(),
|
||||
(1..target_slot.as_u64())
|
||||
.map(Slot::new)
|
||||
.collect::<Vec<_>>()
|
||||
.as_slice(),
|
||||
(0..8).collect::<Vec<_>>().as_slice(),
|
||||
);
|
||||
let mut new_head_state = harness.get_current_state();
|
||||
|
||||
per_epoch_processing(&mut state, &spec).unwrap();
|
||||
process_epoch(&mut new_head_state, &spec).unwrap();
|
||||
}
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
mod release_tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
per_slot_processing::per_slot_processing, EpochProcessingError, SlotProcessingError,
|
||||
};
|
||||
use beacon_chain::test_utils::{AttestationStrategy, BlockStrategy};
|
||||
use types::{Epoch, ForkName, InconsistentFork, MainnetEthSpec};
|
||||
|
||||
#[test]
|
||||
fn altair_state_on_base_fork() {
|
||||
let mut spec = MainnetEthSpec::default_spec();
|
||||
let slots_per_epoch = MainnetEthSpec::slots_per_epoch();
|
||||
// The Altair fork happens at epoch 1.
|
||||
spec.altair_fork_epoch = Some(Epoch::new(1));
|
||||
|
||||
let altair_state = {
|
||||
let harness = BeaconChainHarness::new(
|
||||
MainnetEthSpec,
|
||||
Some(spec.clone()),
|
||||
types::test_utils::generate_deterministic_keypairs(8),
|
||||
);
|
||||
|
||||
harness.advance_slot();
|
||||
|
||||
harness.extend_chain(
|
||||
// Build out enough blocks so we get an Altair block at the very end of an epoch.
|
||||
(slots_per_epoch * 2 - 1) as usize,
|
||||
BlockStrategy::OnCanonicalHead,
|
||||
AttestationStrategy::AllValidators,
|
||||
);
|
||||
|
||||
harness.get_current_state()
|
||||
};
|
||||
|
||||
// Pre-conditions for a valid test.
|
||||
assert_eq!(altair_state.fork_name(&spec).unwrap(), ForkName::Altair);
|
||||
assert_eq!(
|
||||
altair_state.slot(),
|
||||
altair_state.current_epoch().end_slot(slots_per_epoch)
|
||||
);
|
||||
|
||||
// Check the state is valid before starting this test.
|
||||
process_epoch(&mut altair_state.clone(), &spec)
|
||||
.expect("state passes intial epoch processing");
|
||||
per_slot_processing(&mut altair_state.clone(), None, &spec)
|
||||
.expect("state passes intial slot processing");
|
||||
|
||||
// Modify the spec so altair never happens.
|
||||
spec.altair_fork_epoch = None;
|
||||
|
||||
let expected_err = InconsistentFork {
|
||||
fork_at_slot: ForkName::Base,
|
||||
object_fork: ForkName::Altair,
|
||||
};
|
||||
|
||||
assert_eq!(altair_state.fork_name(&spec), Err(expected_err));
|
||||
assert_eq!(
|
||||
process_epoch(&mut altair_state.clone(), &spec),
|
||||
Err(EpochProcessingError::InconsistentStateFork(expected_err))
|
||||
);
|
||||
assert_eq!(
|
||||
per_slot_processing(&mut altair_state.clone(), None, &spec),
|
||||
Err(SlotProcessingError::InconsistentStateFork(expected_err))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn base_state_on_altair_fork() {
|
||||
let mut spec = MainnetEthSpec::default_spec();
|
||||
let slots_per_epoch = MainnetEthSpec::slots_per_epoch();
|
||||
// The Altair fork never happens.
|
||||
spec.altair_fork_epoch = None;
|
||||
|
||||
let base_state = {
|
||||
let harness = BeaconChainHarness::new(
|
||||
MainnetEthSpec,
|
||||
Some(spec.clone()),
|
||||
types::test_utils::generate_deterministic_keypairs(8),
|
||||
);
|
||||
|
||||
harness.advance_slot();
|
||||
|
||||
harness.extend_chain(
|
||||
// Build out enough blocks so we get a block at the very end of an epoch.
|
||||
(slots_per_epoch * 2 - 1) as usize,
|
||||
BlockStrategy::OnCanonicalHead,
|
||||
AttestationStrategy::AllValidators,
|
||||
);
|
||||
|
||||
harness.get_current_state()
|
||||
};
|
||||
|
||||
// Pre-conditions for a valid test.
|
||||
assert_eq!(base_state.fork_name(&spec).unwrap(), ForkName::Base);
|
||||
assert_eq!(
|
||||
base_state.slot(),
|
||||
base_state.current_epoch().end_slot(slots_per_epoch)
|
||||
);
|
||||
|
||||
// Check the state is valid before starting this test.
|
||||
process_epoch(&mut base_state.clone(), &spec)
|
||||
.expect("state passes intial epoch processing");
|
||||
per_slot_processing(&mut base_state.clone(), None, &spec)
|
||||
.expect("state passes intial slot processing");
|
||||
|
||||
// Modify the spec so Altair happens at the first epoch.
|
||||
spec.altair_fork_epoch = Some(Epoch::new(1));
|
||||
|
||||
let expected_err = InconsistentFork {
|
||||
fork_at_slot: ForkName::Altair,
|
||||
object_fork: ForkName::Base,
|
||||
};
|
||||
|
||||
assert_eq!(base_state.fork_name(&spec), Err(expected_err));
|
||||
assert_eq!(
|
||||
process_epoch(&mut base_state.clone(), &spec),
|
||||
Err(EpochProcessingError::InconsistentStateFork(expected_err))
|
||||
);
|
||||
assert_eq!(
|
||||
per_slot_processing(&mut base_state.clone(), None, &spec),
|
||||
Err(SlotProcessingError::InconsistentStateFork(expected_err))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user