Merge remote-tracking branch 'origin/unstable' into tree-states

This commit is contained in:
Michael Sproul
2023-07-03 15:01:21 +10:00
115 changed files with 3678 additions and 548 deletions

View File

@@ -17,12 +17,13 @@ use fork_choice::{
use store::MemoryStore;
use types::{
test_utils::generate_deterministic_keypair, BeaconBlockRef, BeaconState, ChainSpec, Checkpoint,
Epoch, EthSpec, Hash256, IndexedAttestation, MainnetEthSpec, SignedBeaconBlock, Slot, SubnetId,
Epoch, EthSpec, ForkName, Hash256, IndexedAttestation, MainnetEthSpec, ProgressiveBalancesMode,
RelativeEpoch, SignedBeaconBlock, Slot, SubnetId,
};
pub type E = MainnetEthSpec;
pub const VALIDATOR_COUNT: usize = 32;
pub const VALIDATOR_COUNT: usize = 64;
/// Defines some delay between when an attestation is created and when it is mutated.
pub enum MutationDelay {
@@ -68,6 +69,24 @@ impl ForkChoiceTest {
Self { harness }
}
/// Creates a new tester with the specified `ProgressiveBalancesMode` and genesis from latest fork.
fn new_with_progressive_balances_mode(mode: ProgressiveBalancesMode) -> ForkChoiceTest {
// genesis with latest fork (at least altair required to test the cache)
let spec = ForkName::latest().make_genesis_spec(ChainSpec::default());
let harness = BeaconChainHarness::builder(MainnetEthSpec)
.spec(spec)
.chain_config(ChainConfig {
progressive_balances_mode: mode,
..ChainConfig::default()
})
.deterministic_keypairs(VALIDATOR_COUNT)
.fresh_ephemeral_store()
.mock_execution_layer()
.build();
Self { harness }
}
/// Get a value from the `ForkChoice` instantiation.
fn get<T, U>(&self, func: T) -> U
where
@@ -212,6 +231,39 @@ impl ForkChoiceTest {
self
}
/// Slash a validator from the previous epoch committee.
pub async fn add_previous_epoch_attester_slashing(self) -> Self {
let state = self.harness.get_current_state();
let previous_epoch_shuffling = state.get_shuffling(RelativeEpoch::Previous).unwrap();
let validator_indices = previous_epoch_shuffling
.iter()
.map(|idx| *idx as u64)
.take(1)
.collect();
self.harness
.add_attester_slashing(validator_indices)
.unwrap();
self
}
/// Slash the proposer of a block in the previous epoch.
pub async fn add_previous_epoch_proposer_slashing(self, slots_per_epoch: u64) -> Self {
let previous_epoch_slot = self.harness.get_current_slot() - slots_per_epoch;
let previous_epoch_block = self
.harness
.chain
.block_at_slot(previous_epoch_slot, WhenSlotSkipped::None)
.unwrap()
.unwrap();
let proposer_index: u64 = previous_epoch_block.message().proposer_index();
self.harness.add_proposer_slashing(proposer_index).unwrap();
self
}
/// Apply `count` blocks to the chain (without attestations).
pub async fn apply_blocks_without_new_attestations(self, count: usize) -> Self {
self.harness.advance_slot();
@@ -286,7 +338,9 @@ impl ForkChoiceTest {
Duration::from_secs(0),
&state,
PayloadVerificationStatus::Verified,
self.harness.chain.config.progressive_balances_mode,
&self.harness.chain.spec,
self.harness.logger(),
)
.unwrap();
self
@@ -328,7 +382,9 @@ impl ForkChoiceTest {
Duration::from_secs(0),
&state,
PayloadVerificationStatus::Verified,
self.harness.chain.config.progressive_balances_mode,
&self.harness.chain.spec,
self.harness.logger(),
)
.err()
.expect("on_block did not return an error");
@@ -1287,3 +1343,49 @@ async fn weak_subjectivity_check_epoch_boundary_is_skip_slot_failure() {
.assert_finalized_epoch_is_less_than(checkpoint.epoch)
.assert_shutdown_signal_sent();
}
/// Checks that `ProgressiveBalancesCache` is updated correctly after an attester slashing event,
/// where the slashed validator is a target attester in previous / current epoch.
#[tokio::test]
async fn progressive_balances_cache_attester_slashing() {
ForkChoiceTest::new_with_progressive_balances_mode(ProgressiveBalancesMode::Strict)
// first two epochs
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch == 0)
.await
.unwrap()
.add_previous_epoch_attester_slashing()
.await
// expect fork choice to import blocks successfully after a previous epoch attester is
// slashed, i.e. the slashed attester's balance is correctly excluded from
// the previous epoch total balance in `ProgressiveBalancesCache`.
.apply_blocks(1)
.await
// expect fork choice to import another epoch of blocks successfully - the slashed
// attester's balance should be excluded from the current epoch total balance in
// `ProgressiveBalancesCache` as well.
.apply_blocks(MainnetEthSpec::slots_per_epoch() as usize)
.await;
}
/// Checks that `ProgressiveBalancesCache` is updated correctly after a proposer slashing event,
/// where the slashed validator is a target attester in previous / current epoch.
#[tokio::test]
async fn progressive_balances_cache_proposer_slashing() {
ForkChoiceTest::new_with_progressive_balances_mode(ProgressiveBalancesMode::Strict)
// first two epochs
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch == 0)
.await
.unwrap()
.add_previous_epoch_proposer_slashing(MainnetEthSpec::slots_per_epoch())
.await
// expect fork choice to import blocks successfully after a previous epoch proposer is
// slashed, i.e. the slashed proposer's balance is correctly excluded from
// the previous epoch total balance in `ProgressiveBalancesCache`.
.apply_blocks(1)
.await
// expect fork choice to import another epoch of blocks successfully - the slashed
// proposer's balance should be excluded from the current epoch total balance in
// `ProgressiveBalancesCache` as well.
.apply_blocks(MainnetEthSpec::slots_per_epoch() as usize)
.await;
}