mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-15 19:02:42 +00:00
Devnet6 (#4404)
* some blob reprocessing work
* remove ForceBlockLookup
* reorder enum match arms in sync manager
* a lot more reprocessing work
* impl logic for triggerng blob lookups along with block lookups
* deal with rpc blobs in groups per block in the da checker. don't cache missing blob ids in the da checker.
* make single block lookup generic
* more work
* add delayed processing logic and combine some requests
* start fixing some compile errors
* fix compilation in main block lookup mod
* much work
* get things compiling
* parent blob lookups
* fix compile
* revert red/stevie changes
* fix up sync manager delay message logic
* add peer usefulness enum
* should remove lookup refactor
* consolidate retry error handling
* improve peer scoring during certain failures in parent lookups
* improve retry code
* drop parent lookup if either req has a peer disconnect during download
* refactor single block processed method
* processing peer refactor
* smol bugfix
* fix some todos
* fix lints
* fix lints
* fix compile in lookup tests
* fix lints
* fix lints
* fix existing block lookup tests
* renamings
* fix after merge
* cargo fmt
* compilation fix in beacon chain tests
* fix
* refactor lookup tests to work with multiple forks and response types
* make tests into macros
* wrap availability check error
* fix compile after merge
* add random blobs
* start fixing up lookup verify error handling
* some bug fixes and the start of deneb only tests
* make tests work for all forks
* track information about peer source
* error refactoring
* improve peer scoring
* fix test compilation
* make sure blobs are sent for processing after stream termination, delete copied tests
* add some tests and fix a bug
* smol bugfixes and moar tests
* add tests and fix some things
* compile after merge
* lots of refactoring
* retry on invalid block/blob
* merge unknown parent messages before current slot lookup
* get tests compiling
* penalize blob peer on invalid blobs
* Check disk on in-memory cache miss
* Update beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs
* Update beacon_node/network/src/sync/network_context.rs
Co-authored-by: Divma <26765164+divagant-martian@users.noreply.github.com>
* fix bug in matching blocks and blobs in range sync
* pr feedback
* fix conflicts
* upgrade logs from warn to crit when we receive incorrect response in range
* synced_and_connected_within_tolerance -> should_search_for_block
* remove todo
* add data gas used and update excess data gas to u64
* Fix Broken Overflow Tests
* payload verification with commitments
* fix merge conflicts
* restore payload file
* Restore payload file
* remove todo
* add max blob commitments per block
* c-kzg lib update
* Fix ef tests
* Abstract over minimal/mainnet spec in kzg crate
* Start integrating new KZG
* checkpoint sync without alignment
* checkpoint sync without alignment
* add import
* add import
* query for checkpoint state by slot rather than state root (teku doesn't serve by state root)
* query for checkpoint state by slot rather than state root (teku doesn't serve by state root)
* loosen check
* get state first and query by most recent block root
* Revert "loosen check"
This reverts commit 069d13dd63.
* get state first and query by most recent block root
* merge max blobs change
* simplify delay logic
* rename unknown parent sync message variants
* rename parameter, block_slot -> slot
* add some docs to the lookup module
* use interval instead of sleep
* drop request if blocks and blobs requests both return `None` for `Id`
* clean up `find_single_lookup` logic
* add lookup source enum
* clean up `find_single_lookup` logic
* add docs to find_single_lookup_request
* move LookupSource our of param where unnecessary
* remove unnecessary todo
* query for block by `state.latest_block_header.slot`
* fix lint
* fix merge transition ef tests
* fix test
* fix test
* fix observed blob sidecars test
* Add some metrics (#33)
* fix protocol limits for blobs by root
* Update Engine API for 1:1 Structure Method
* make beacon chain tests to fix devnet 6 changes
* get ckzg working and fix some tests
* fix remaining tests
* fix lints
* Fix KZG linking issues
* remove unused dep
* lockfile
* test fixes
* remove dbgs
* remove unwrap
* cleanup tx generator
* small fixes
* fixing fixes
* more self reivew
* more self review
* refactor genesis header initialization
* refactor mock el instantiations
* fix compile
* fix network test, make sure they run for each fork
* pr feedback
* fix last test (hopefully)
---------
Co-authored-by: Pawan Dhananjay <pawandhananjay@gmail.com>
Co-authored-by: Mark Mackey <mark@sigmaprime.io>
Co-authored-by: Divma <26765164+divagant-martian@users.noreply.github.com>
Co-authored-by: Michael Sproul <michael@sigmaprime.io>
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
#![cfg(not(debug_assertions))] // Tests are too slow in debug.
|
||||
#![cfg(test)]
|
||||
|
||||
use crate::beacon_processor::work_reprocessing_queue::{
|
||||
@@ -7,14 +6,16 @@ use crate::beacon_processor::work_reprocessing_queue::{
|
||||
use crate::beacon_processor::*;
|
||||
use crate::{service::NetworkMessage, sync::SyncMessage};
|
||||
use beacon_chain::test_utils::{
|
||||
AttestationStrategy, BeaconChainHarness, BlockStrategy, EphemeralHarnessType,
|
||||
test_spec, AttestationStrategy, BeaconChainHarness, BlockStrategy, EphemeralHarnessType,
|
||||
};
|
||||
use beacon_chain::{BeaconChain, ChainConfig, MAXIMUM_GOSSIP_CLOCK_DISPARITY};
|
||||
use beacon_chain::{BeaconChain, ChainConfig, WhenSlotSkipped, MAXIMUM_GOSSIP_CLOCK_DISPARITY};
|
||||
use lighthouse_network::discovery::ConnectionId;
|
||||
use lighthouse_network::rpc::SubstreamId;
|
||||
use lighthouse_network::{
|
||||
discv5::enr::{CombinedKey, EnrBuilder},
|
||||
rpc::methods::{MetaData, MetaDataV2},
|
||||
types::{EnrAttestationBitfield, EnrSyncCommitteeBitfield},
|
||||
MessageId, NetworkGlobals, PeerId,
|
||||
MessageId, NetworkGlobals, PeerId, Response,
|
||||
};
|
||||
use slot_clock::SlotClock;
|
||||
use std::cmp;
|
||||
@@ -23,8 +24,8 @@ use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tokio::sync::mpsc;
|
||||
use types::{
|
||||
Attestation, AttesterSlashing, Epoch, EthSpec, MainnetEthSpec, ProposerSlashing,
|
||||
SignedBeaconBlock, SignedVoluntaryExit, SubnetId,
|
||||
Attestation, AttesterSlashing, Epoch, MainnetEthSpec, ProposerSlashing, SignedBeaconBlock,
|
||||
SignedBlobSidecarList, SignedVoluntaryExit, Slot, SubnetId,
|
||||
};
|
||||
|
||||
type E = MainnetEthSpec;
|
||||
@@ -45,6 +46,7 @@ const STANDARD_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
struct TestRig {
|
||||
chain: Arc<BeaconChain<T>>,
|
||||
next_block: Arc<SignedBeaconBlock<E>>,
|
||||
next_blobs: Option<SignedBlobSidecarList<E>>,
|
||||
attestations: Vec<(Attestation<E>, SubnetId)>,
|
||||
next_block_attestations: Vec<(Attestation<E>, SubnetId)>,
|
||||
next_block_aggregate_attestations: Vec<SignedAggregateAndProof<E>>,
|
||||
@@ -74,14 +76,15 @@ impl TestRig {
|
||||
}
|
||||
|
||||
pub async fn new_with_chain_config(chain_length: u64, chain_config: ChainConfig) -> Self {
|
||||
let mut spec = test_spec::<MainnetEthSpec>();
|
||||
// This allows for testing voluntary exits without building out a massive chain.
|
||||
let mut spec = E::default_spec();
|
||||
spec.shard_committee_period = 2;
|
||||
|
||||
let harness = BeaconChainHarness::builder(MainnetEthSpec)
|
||||
.spec(spec)
|
||||
.deterministic_keypairs(VALIDATOR_COUNT)
|
||||
.fresh_ephemeral_store()
|
||||
.mock_execution_layer()
|
||||
.chain_config(chain_config)
|
||||
.build();
|
||||
|
||||
@@ -211,6 +214,7 @@ impl TestRig {
|
||||
Self {
|
||||
chain,
|
||||
next_block: Arc::new(next_block_tuple.0),
|
||||
next_blobs: next_block_tuple.1,
|
||||
attestations,
|
||||
next_block_attestations,
|
||||
next_block_aggregate_attestations,
|
||||
@@ -246,6 +250,22 @@ impl TestRig {
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn enqueue_gossip_blob(&self, blob_index: usize) {
|
||||
if let Some(blobs) = self.next_blobs.as_ref() {
|
||||
let blob = blobs.get(blob_index).unwrap();
|
||||
self.beacon_processor_tx
|
||||
.try_send(WorkEvent::gossip_signed_blob_sidecar(
|
||||
junk_message_id(),
|
||||
junk_peer_id(),
|
||||
Client::default(),
|
||||
blob_index as u64,
|
||||
blob.clone(),
|
||||
Duration::from_secs(0),
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enqueue_rpc_block(&self) {
|
||||
let event = WorkEvent::rpc_beacon_block(
|
||||
self.next_block.canonical_root(),
|
||||
@@ -268,6 +288,36 @@ impl TestRig {
|
||||
self.beacon_processor_tx.try_send(event).unwrap();
|
||||
}
|
||||
|
||||
pub fn enqueue_single_lookup_rpc_blobs(&self) {
|
||||
if let Some(blobs) = self.next_blobs.clone() {
|
||||
let blobs = FixedBlobSidecarList::from(
|
||||
blobs
|
||||
.into_iter()
|
||||
.map(|b| Some(b.message))
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
let event = WorkEvent::rpc_blobs(
|
||||
self.next_block.canonical_root(),
|
||||
blobs,
|
||||
std::time::Duration::default(),
|
||||
BlockProcessType::SingleBlock { id: 1 },
|
||||
);
|
||||
self.beacon_processor_tx.try_send(event).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enqueue_blobs_by_range_request(&self, count: u64) {
|
||||
let event = WorkEvent::blobs_by_range_request(
|
||||
PeerId::random(),
|
||||
(ConnectionId::new(42), SubstreamId::new(24)),
|
||||
BlobsByRangeRequest {
|
||||
start_slot: 0,
|
||||
count,
|
||||
},
|
||||
);
|
||||
self.beacon_processor_tx.try_send(event).unwrap();
|
||||
}
|
||||
|
||||
pub fn enqueue_backfill_batch(&self) {
|
||||
let event = WorkEvent::chain_segment(
|
||||
ChainSegmentProcessId::BackSyncBatchId(Epoch::default()),
|
||||
@@ -491,6 +541,13 @@ async fn import_gossip_block_acceptably_early() {
|
||||
rig.assert_event_journal(&[GOSSIP_BLOCK, WORKER_FREED, NOTHING_TO_DO])
|
||||
.await;
|
||||
|
||||
let num_blobs = rig.next_blobs.as_ref().map(|b| b.len()).unwrap_or(0);
|
||||
for i in 0..num_blobs {
|
||||
rig.enqueue_gossip_blob(i);
|
||||
rig.assert_event_journal(&[GOSSIP_BLOBS_SIDECAR, WORKER_FREED, NOTHING_TO_DO])
|
||||
.await;
|
||||
}
|
||||
|
||||
// Note: this section of the code is a bit race-y. We're assuming that we can set the slot clock
|
||||
// and check the head in the time between the block arrived early and when its due for
|
||||
// processing.
|
||||
@@ -499,6 +556,7 @@ async fn import_gossip_block_acceptably_early() {
|
||||
// processing, instead of just ADDITIONAL_QUEUED_BLOCK_DELAY. Speak to @paulhauner if this test
|
||||
// starts failing.
|
||||
rig.chain.slot_clock.set_slot(rig.next_block.slot().into());
|
||||
|
||||
assert!(
|
||||
rig.head_root() != rig.next_block.canonical_root(),
|
||||
"block not yet imported"
|
||||
@@ -566,6 +624,19 @@ async fn import_gossip_block_at_current_slot() {
|
||||
rig.assert_event_journal(&[GOSSIP_BLOCK, WORKER_FREED, NOTHING_TO_DO])
|
||||
.await;
|
||||
|
||||
let num_blobs = rig
|
||||
.next_blobs
|
||||
.as_ref()
|
||||
.map(|blobs| blobs.len())
|
||||
.unwrap_or(0);
|
||||
|
||||
for i in 0..num_blobs {
|
||||
rig.enqueue_gossip_blob(i);
|
||||
|
||||
rig.assert_event_journal(&[GOSSIP_BLOBS_SIDECAR, WORKER_FREED, NOTHING_TO_DO])
|
||||
.await;
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
rig.head_root(),
|
||||
rig.next_block.canonical_root(),
|
||||
@@ -618,20 +689,34 @@ async fn attestation_to_unknown_block_processed(import_method: BlockImportMethod
|
||||
);
|
||||
|
||||
// Send the block and ensure that the attestation is received back and imported.
|
||||
|
||||
let block_event = match import_method {
|
||||
let num_blobs = rig
|
||||
.next_blobs
|
||||
.as_ref()
|
||||
.map(|blobs| blobs.len())
|
||||
.unwrap_or(0);
|
||||
let mut events = vec![];
|
||||
match import_method {
|
||||
BlockImportMethod::Gossip => {
|
||||
rig.enqueue_gossip_block();
|
||||
GOSSIP_BLOCK
|
||||
events.push(GOSSIP_BLOCK);
|
||||
for i in 0..num_blobs {
|
||||
rig.enqueue_gossip_blob(i);
|
||||
events.push(GOSSIP_BLOBS_SIDECAR);
|
||||
}
|
||||
}
|
||||
BlockImportMethod::Rpc => {
|
||||
rig.enqueue_rpc_block();
|
||||
RPC_BLOCK
|
||||
events.push(RPC_BLOCK);
|
||||
rig.enqueue_single_lookup_rpc_blobs();
|
||||
if num_blobs > 0 {
|
||||
events.push(RPC_BLOB);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
rig.assert_event_journal_contains_ordered(&[block_event, UNKNOWN_BLOCK_ATTESTATION])
|
||||
.await;
|
||||
events.push(UNKNOWN_BLOCK_ATTESTATION);
|
||||
|
||||
rig.assert_event_journal_contains_ordered(&events).await;
|
||||
|
||||
// Run fork choice, since it isn't run when processing an RPC block. At runtime it is the
|
||||
// responsibility of the sync manager to do this.
|
||||
@@ -687,20 +772,34 @@ async fn aggregate_attestation_to_unknown_block(import_method: BlockImportMethod
|
||||
);
|
||||
|
||||
// Send the block and ensure that the attestation is received back and imported.
|
||||
|
||||
let block_event = match import_method {
|
||||
let num_blobs = rig
|
||||
.next_blobs
|
||||
.as_ref()
|
||||
.map(|blobs| blobs.len())
|
||||
.unwrap_or(0);
|
||||
let mut events = vec![];
|
||||
match import_method {
|
||||
BlockImportMethod::Gossip => {
|
||||
rig.enqueue_gossip_block();
|
||||
GOSSIP_BLOCK
|
||||
events.push(GOSSIP_BLOCK);
|
||||
for i in 0..num_blobs {
|
||||
rig.enqueue_gossip_blob(i);
|
||||
events.push(GOSSIP_BLOBS_SIDECAR);
|
||||
}
|
||||
}
|
||||
BlockImportMethod::Rpc => {
|
||||
rig.enqueue_rpc_block();
|
||||
RPC_BLOCK
|
||||
events.push(RPC_BLOCK);
|
||||
rig.enqueue_single_lookup_rpc_blobs();
|
||||
if num_blobs > 0 {
|
||||
events.push(RPC_BLOB);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
rig.assert_event_journal_contains_ordered(&[block_event, UNKNOWN_BLOCK_AGGREGATE])
|
||||
.await;
|
||||
events.push(UNKNOWN_BLOCK_AGGREGATE);
|
||||
|
||||
rig.assert_event_journal_contains_ordered(&events).await;
|
||||
|
||||
// Run fork choice, since it isn't run when processing an RPC block. At runtime it is the
|
||||
// responsibility of the sync manager to do this.
|
||||
@@ -868,9 +967,15 @@ async fn test_rpc_block_reprocessing() {
|
||||
// Insert the next block into the duplicate cache manually
|
||||
let handle = rig.duplicate_cache.check_and_insert(next_block_root);
|
||||
rig.enqueue_single_lookup_rpc_block();
|
||||
|
||||
rig.assert_event_journal(&[RPC_BLOCK, WORKER_FREED, NOTHING_TO_DO])
|
||||
.await;
|
||||
|
||||
rig.enqueue_single_lookup_rpc_blobs();
|
||||
if rig.next_blobs.as_ref().map(|b| b.len()).unwrap_or(0) > 0 {
|
||||
rig.assert_event_journal(&[RPC_BLOB, WORKER_FREED, NOTHING_TO_DO])
|
||||
.await;
|
||||
}
|
||||
|
||||
// next_block shouldn't be processed since it couldn't get the
|
||||
// duplicate cache handle
|
||||
assert_ne!(next_block_root, rig.head_root());
|
||||
@@ -934,3 +1039,47 @@ async fn test_backfill_sync_processing_rate_limiting_disabled() {
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_blobs_by_range() {
|
||||
if test_spec::<E>().deneb_fork_epoch.is_none() {
|
||||
return;
|
||||
};
|
||||
let mut rig = TestRig::new(64).await;
|
||||
let slot_count = 32;
|
||||
rig.enqueue_blobs_by_range_request(slot_count);
|
||||
|
||||
let mut blob_count = 0;
|
||||
for slot in 0..slot_count {
|
||||
let root = rig
|
||||
.chain
|
||||
.block_root_at_slot(Slot::new(slot), WhenSlotSkipped::None)
|
||||
.unwrap();
|
||||
blob_count += root
|
||||
.and_then(|root| {
|
||||
rig.chain
|
||||
.get_blobs(&root)
|
||||
.unwrap_or_default()
|
||||
.map(|blobs| blobs.len())
|
||||
})
|
||||
.unwrap_or(0);
|
||||
}
|
||||
let mut actual_count = 0;
|
||||
while let Some(next) = rig._network_rx.recv().await {
|
||||
if let NetworkMessage::SendResponse {
|
||||
peer_id: _,
|
||||
response: Response::BlobsByRange(blob),
|
||||
id: _,
|
||||
} = next
|
||||
{
|
||||
if blob.is_some() {
|
||||
actual_count += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
panic!("unexpected message {:?}", next);
|
||||
}
|
||||
}
|
||||
assert_eq!(blob_count, actual_count);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user