mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-08 09:16:00 +00:00
Add attestation simulator (#4880)
* basic scaffold * remove unnecessary ? * check if committee cache is init * typed ValidatorMonitor with ethspecs + store attestations within * nits * process unaggregated attestation * typo * extract in func * add tests * better naming * better naming 2 * less verbose * use same naming as validator monitor * use attestation_simulator * add metrics * remove cache * refacto flag_indices process * add lag * remove copying state * clean and lint * extract metrics * nits * compare prom metrics in tests * implement lag * nits * nits * add attestation simulator service * fmt * return beacon_chain as arc * nit: debug * sed s/unaggregated/unagg.// * fmt * fmt * nit: remove unused comments * increase max unaggregated attestation hashmap to 64 * nit: sed s/clone/copied// * improve perf: remove unecessary hashmap copy * fix flag indices comp * start service in client builder * remove // * cargo fmt * lint * cloned keys * fmt * use Slot value instead of pointer * Update beacon_node/beacon_chain/src/attestation_simulator.rs Co-authored-by: Paul Hauner <paul@paulhauner.com> --------- Co-authored-by: Paul Hauner <paul@paulhauner.com>
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
#![cfg(not(debug_assertions))]
|
||||
|
||||
use beacon_chain::attestation_simulator::produce_unaggregated_attestation;
|
||||
use beacon_chain::block_verification_types::RpcBlock;
|
||||
use beacon_chain::test_utils::{AttestationStrategy, BeaconChainHarness, BlockStrategy};
|
||||
use beacon_chain::{StateSkipConfig, WhenSlotSkipped};
|
||||
use beacon_chain::validator_monitor::UNAGGREGATED_ATTESTATION_LAG_SLOTS;
|
||||
use beacon_chain::{metrics, StateSkipConfig, WhenSlotSkipped};
|
||||
use lazy_static::lazy_static;
|
||||
use std::sync::Arc;
|
||||
use tree_hash::TreeHash;
|
||||
@@ -15,6 +17,91 @@ lazy_static! {
|
||||
static ref KEYPAIRS: Vec<Keypair> = types::test_utils::generate_deterministic_keypairs(VALIDATOR_COUNT);
|
||||
}
|
||||
|
||||
/// This test builds a chain that is testing the performance of the unaggregated attestations
|
||||
/// produced by the attestation simulator service.
|
||||
#[tokio::test]
|
||||
async fn produces_attestations_from_attestation_simulator_service() {
|
||||
// Produce 2 epochs, or 64 blocks
|
||||
let num_blocks_produced = MainnetEthSpec::slots_per_epoch() * 2;
|
||||
|
||||
let harness = BeaconChainHarness::builder(MainnetEthSpec)
|
||||
.default_spec()
|
||||
.keypairs(KEYPAIRS[..].to_vec())
|
||||
.fresh_ephemeral_store()
|
||||
.mock_execution_layer()
|
||||
.build();
|
||||
|
||||
let chain = &harness.chain;
|
||||
|
||||
// Test all valid committee indices and their rewards for all slots in the chain
|
||||
// using validator monitor
|
||||
for slot in 0..=num_blocks_produced {
|
||||
// We do not produce at slot=0, and there's no committe cache available anyway
|
||||
if slot > 0 && slot <= num_blocks_produced {
|
||||
harness.advance_slot();
|
||||
|
||||
harness
|
||||
.extend_chain(
|
||||
1,
|
||||
BlockStrategy::OnCanonicalHead,
|
||||
AttestationStrategy::AllValidators,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
// Set the state to the current slot
|
||||
let slot = Slot::from(slot);
|
||||
let mut state = chain
|
||||
.state_at_slot(slot, StateSkipConfig::WithStateRoots)
|
||||
.expect("should get state");
|
||||
|
||||
// Prebuild the committee cache for the current epoch
|
||||
state
|
||||
.build_committee_cache(RelativeEpoch::Current, &harness.chain.spec)
|
||||
.unwrap();
|
||||
|
||||
// Produce an unaggragetated attestation
|
||||
produce_unaggregated_attestation(chain.clone(), chain.slot().unwrap());
|
||||
|
||||
// Verify that the ua is stored in validator monitor
|
||||
let validator_monitor = chain.validator_monitor.read();
|
||||
validator_monitor
|
||||
.get_unaggregated_attestation(slot)
|
||||
.expect("should get unaggregated attestation");
|
||||
}
|
||||
|
||||
// Compare the prometheus metrics that evaluates the performance of the unaggregated attestations
|
||||
let hit_prometheus_metrics = vec![
|
||||
metrics::VALIDATOR_MONITOR_ATTESTATION_SIMULATOR_HEAD_ATTESTER_HIT_TOTAL,
|
||||
metrics::VALIDATOR_MONITOR_ATTESTATION_SIMULATOR_TARGET_ATTESTER_HIT_TOTAL,
|
||||
metrics::VALIDATOR_MONITOR_ATTESTATION_SIMULATOR_SOURCE_ATTESTER_HIT_TOTAL,
|
||||
];
|
||||
let miss_prometheus_metrics = vec![
|
||||
metrics::VALIDATOR_MONITOR_ATTESTATION_SIMULATOR_HEAD_ATTESTER_MISS_TOTAL,
|
||||
metrics::VALIDATOR_MONITOR_ATTESTATION_SIMULATOR_TARGET_ATTESTER_MISS_TOTAL,
|
||||
metrics::VALIDATOR_MONITOR_ATTESTATION_SIMULATOR_SOURCE_ATTESTER_MISS_TOTAL,
|
||||
];
|
||||
|
||||
// Expected metrics count should only apply to hit metrics as miss metrics are never set, nor can be found
|
||||
// when gathering prometheus metrics. If they are found, which should not, it will diff from 0 and fail the test
|
||||
let expected_miss_metrics_count = 0;
|
||||
let expected_hit_metrics_count =
|
||||
num_blocks_produced - UNAGGREGATED_ATTESTATION_LAG_SLOTS as u64;
|
||||
lighthouse_metrics::gather().iter().for_each(|mf| {
|
||||
if hit_prometheus_metrics.contains(&mf.get_name()) {
|
||||
assert_eq!(
|
||||
mf.get_metric()[0].get_counter().get_value() as u64,
|
||||
expected_hit_metrics_count
|
||||
);
|
||||
}
|
||||
if miss_prometheus_metrics.contains(&mf.get_name()) {
|
||||
assert_eq!(
|
||||
mf.get_metric()[0].get_counter().get_value() as u64,
|
||||
expected_miss_metrics_count
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// This test builds a chain that is just long enough to finalize an epoch then it produces an
|
||||
/// attestation at each slot from genesis through to three epochs past the head.
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user