Skip to content

Commit b7da075

Browse files
committed
More test fixes for Fulu.
1 parent 6d5b5ed commit b7da075

File tree

16 files changed

+408
-174
lines changed

16 files changed

+408
-174
lines changed

beacon_node/beacon_chain/src/beacon_chain.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,6 +1249,17 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
12491249
self.store.get_blobs(block_root).map_err(Error::from)
12501250
}
12511251

1252+
/// Returns the data columns at the given root, if any.
1253+
///
1254+
/// ## Errors
1255+
/// May return a database error.
1256+
pub fn get_data_columns(
1257+
&self,
1258+
block_root: &Hash256,
1259+
) -> Result<Option<DataColumnSidecarList<T::EthSpec>>, Error> {
1260+
self.store.get_data_columns(block_root).map_err(Error::from)
1261+
}
1262+
12521263
/// Returns the data columns at the given root, if any.
12531264
///
12541265
/// ## Errors
@@ -5850,6 +5861,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
58505861

58515862
let kzg = self.kzg.as_ref();
58525863

5864+
// TODO(fulu): we no longer need blob proofs from PeerDAS and could avoid computing.
58535865
kzg_utils::validate_blobs::<T::EthSpec>(
58545866
kzg,
58555867
expected_kzg_commitments,

beacon_node/beacon_chain/src/data_column_verification.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ mod test {
699699

700700
#[tokio::test]
701701
async fn empty_data_column_sidecars_fails_validation() {
702-
let spec = ForkName::latest().make_genesis_spec(E::default_spec());
702+
let spec = ForkName::Fulu.make_genesis_spec(E::default_spec());
703703
let harness = BeaconChainHarness::builder(E::default())
704704
.spec(spec.into())
705705
.deterministic_keypairs(64)

beacon_node/beacon_chain/src/fetch_blobs.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::{metrics, AvailabilityProcessingStatus, BeaconChain, BeaconChainTypes
1414
use execution_layer::json_structures::BlobAndProofV1;
1515
use execution_layer::Error as ExecutionLayerError;
1616
use metrics::{inc_counter, inc_counter_by, TryExt};
17-
use slog::{debug, error, o, Logger};
17+
use slog::{debug, error, o, warn, Logger};
1818
use ssz_types::FixedVector;
1919
use state_processing::per_block_processing::deneb::kzg_commitment_to_versioned_hash;
2020
use std::sync::Arc;
@@ -248,8 +248,14 @@ fn spawn_compute_and_publish_data_columns_task<T: BeaconChainTypes>(
248248
}
249249
};
250250

251-
if let Err(e) = data_columns_sender.send(all_data_columns.clone()) {
252-
error!(log, "Failed to send computed data columns"; "error" => ?e);
251+
if data_columns_sender.send(all_data_columns.clone()).is_err() {
252+
// Data column receiver have been dropped - this may not be an issue if the block is
253+
// already fully imported. This should not happen after the race condition
254+
// described in #6816 is fixed.
255+
warn!(
256+
log,
257+
"Failed to send computed data columns";
258+
);
253259
};
254260

255261
// Check indices from cache before sending the columns, to make sure we don't

beacon_node/beacon_chain/src/test_utils.rs

Lines changed: 96 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
use crate::blob_verification::GossipVerifiedBlob;
12
use crate::block_verification_types::{AsBlock, RpcBlock};
23
use crate::data_column_verification::CustodyDataColumn;
34
use crate::kzg_utils::blobs_to_data_column_sidecars;
45
use crate::observed_operations::ObservationOutcome;
56
pub use crate::persisted_beacon_chain::PersistedBeaconChain;
6-
use crate::BeaconBlockResponseWrapper;
77
pub use crate::{
88
beacon_chain::{BEACON_CHAIN_DB_KEY, ETH1_CACHE_DB_KEY, FORK_CHOICE_DB_KEY, OP_POOL_DB_KEY},
99
migrate::MigratorConfig,
@@ -17,6 +17,7 @@ use crate::{
1717
BeaconChain, BeaconChainTypes, BlockError, ChainConfig, ServerSentEventHandler,
1818
StateSkipConfig,
1919
};
20+
use crate::{get_block_root, BeaconBlockResponseWrapper};
2021
use bls::get_withdrawal_credentials;
2122
use eth2::types::SignedBlockContentsTuple;
2223
use execution_layer::test_utils::generate_genesis_header;
@@ -756,15 +757,13 @@ where
756757
pub fn get_head_block(&self) -> RpcBlock<E> {
757758
let block = self.chain.head_beacon_block();
758759
let block_root = block.canonical_root();
759-
let blobs = self.chain.get_blobs(&block_root).unwrap().blobs();
760-
RpcBlock::new(Some(block_root), block, blobs).unwrap()
760+
self.build_rpc_block_from_store_blobs(Some(block_root), block)
761761
}
762762

763763
pub fn get_full_block(&self, block_root: &Hash256) -> RpcBlock<E> {
764764
let block = self.chain.get_blinded_block(block_root).unwrap().unwrap();
765765
let full_block = self.chain.store.make_full_block(block_root, block).unwrap();
766-
let blobs = self.chain.get_blobs(block_root).unwrap().blobs();
767-
RpcBlock::new(Some(*block_root), Arc::new(full_block), blobs).unwrap()
766+
self.build_rpc_block_from_store_blobs(Some(*block_root), Arc::new(full_block))
768767
}
769768

770769
pub fn get_all_validators(&self) -> Vec<usize> {
@@ -2265,7 +2264,7 @@ where
22652264
self.set_current_slot(slot);
22662265
let (block, blob_items) = block_contents;
22672266

2268-
let rpc_block = self.build_rpc_block(block_root, block, blob_items)?;
2267+
let rpc_block = self.build_rpc_block_from_blobs(block_root, block, blob_items)?;
22692268
let block_hash: SignedBeaconBlockHash = self
22702269
.chain
22712270
.process_block(
@@ -2289,7 +2288,7 @@ where
22892288
let (block, blob_items) = block_contents;
22902289

22912290
let block_root = block.canonical_root();
2292-
let rpc_block = self.build_rpc_block(block_root, block, blob_items)?;
2291+
let rpc_block = self.build_rpc_block_from_blobs(block_root, block, blob_items)?;
22932292
let block_hash: SignedBeaconBlockHash = self
22942293
.chain
22952294
.process_block(
@@ -2306,13 +2305,51 @@ where
23062305
Ok(block_hash)
23072306
}
23082307

2309-
fn build_rpc_block(
2308+
/// Builds an `Rpc` block from a `SignedBeaconBlock` and blobs or data columns retrieved from
2309+
/// the database.
2310+
pub fn build_rpc_block_from_store_blobs(
2311+
&self,
2312+
block_root: Option<Hash256>,
2313+
block: Arc<SignedBeaconBlock<E>>,
2314+
) -> RpcBlock<E> {
2315+
let block_root = block_root.unwrap_or_else(|| get_block_root(&block));
2316+
let has_blobs = block
2317+
.message()
2318+
.body()
2319+
.blob_kzg_commitments()
2320+
.is_ok_and(|c| !c.is_empty());
2321+
if !has_blobs {
2322+
return RpcBlock::new_without_blobs(Some(block_root), block);
2323+
}
2324+
2325+
// Blobs are stored as data columns from Fulu (PeerDAS)
2326+
if self.spec.is_peer_das_enabled_for_epoch(block.epoch()) {
2327+
let columns = self.chain.get_data_columns(&block_root).unwrap().unwrap();
2328+
let custody_columns = columns
2329+
.into_iter()
2330+
.map(CustodyDataColumn::from_asserted_custody)
2331+
.collect::<Vec<_>>();
2332+
RpcBlock::new_with_custody_columns(Some(block_root), block, custody_columns, &self.spec)
2333+
.unwrap()
2334+
} else {
2335+
let blobs = self.chain.get_blobs(&block_root).unwrap().blobs();
2336+
RpcBlock::new(Some(block_root), block, blobs).unwrap()
2337+
}
2338+
}
2339+
2340+
/// Builds an `RpcBlock` from a `SignedBeaconBlock` and `BlobsList`.
2341+
fn build_rpc_block_from_blobs(
23102342
&self,
23112343
block_root: Hash256,
23122344
block: Arc<SignedBeaconBlock<E, FullPayload<E>>>,
23132345
blob_items: Option<(KzgProofs<E>, BlobsList<E>)>,
23142346
) -> Result<RpcBlock<E>, BlockError> {
23152347
Ok(if self.spec.is_peer_das_enabled_for_epoch(block.epoch()) {
2348+
let sampling_column_count = self
2349+
.chain
2350+
.data_availability_checker
2351+
.get_sampling_column_count();
2352+
23162353
let columns = blob_items
23172354
.map(|(_proofs, blobs)| {
23182355
blobs_to_data_column_sidecars(
@@ -2324,6 +2361,7 @@ where
23242361
.map(|column_sidecars| {
23252362
column_sidecars
23262363
.into_iter()
2364+
.take(sampling_column_count)
23272365
.map(CustodyDataColumn::from_asserted_custody)
23282366
.collect::<Vec<_>>()
23292367
})
@@ -3016,6 +3054,56 @@ where
30163054

30173055
Ok(())
30183056
}
3057+
3058+
/// Simulate some of the blobs / data columns being seen on gossip.
3059+
/// Converts the blobs to data columns if the slot is Fulu or later.
3060+
pub async fn process_gossip_blobs_or_columns<'a>(
3061+
&self,
3062+
block: &SignedBeaconBlock<E>,
3063+
blobs: impl Iterator<Item = &'a Blob<E>>,
3064+
proofs: impl Iterator<Item = &'a KzgProof>,
3065+
custody_columns_opt: Option<HashSet<ColumnIndex>>,
3066+
) {
3067+
let is_peerdas_enabled = self.chain.spec.is_peer_das_enabled_for_epoch(block.epoch());
3068+
if is_peerdas_enabled {
3069+
let sidecars = blobs_to_data_column_sidecars(
3070+
&blobs.collect::<Vec<_>>(),
3071+
block,
3072+
&self.chain.kzg,
3073+
&self.spec,
3074+
)
3075+
.unwrap();
3076+
3077+
let custody_columns = custody_columns_opt.unwrap_or_else(|| {
3078+
let spec = &self.chain.spec;
3079+
let sampling_size = spec.sampling_size(spec.custody_requirement).unwrap();
3080+
(0..sampling_size).collect()
3081+
});
3082+
3083+
let verified_columns = sidecars
3084+
.into_iter()
3085+
.filter(|c| custody_columns.contains(&c.index))
3086+
.map(|sidecar| {
3087+
let column_index = sidecar.index;
3088+
self.chain
3089+
.verify_data_column_sidecar_for_gossip(sidecar, column_index)
3090+
})
3091+
.collect::<Result<Vec<_>, _>>()
3092+
.unwrap();
3093+
3094+
self.chain
3095+
.process_gossip_data_columns(verified_columns, || Ok(()))
3096+
.await
3097+
.unwrap();
3098+
} else {
3099+
for (i, (kzg_proof, blob)) in proofs.into_iter().zip(blobs).enumerate() {
3100+
let sidecar =
3101+
Arc::new(BlobSidecar::new(i, blob.clone(), block, *kzg_proof).unwrap());
3102+
let gossip_blob = GossipVerifiedBlob::new(sidecar, i as u64, &self.chain).unwrap();
3103+
self.chain.process_gossip_blob(gossip_blob).await.unwrap();
3104+
}
3105+
}
3106+
}
30193107
}
30203108

30213109
// Junk `Debug` impl to satistfy certain trait bounds during testing.

beacon_node/beacon_chain/tests/attestation_production.rs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#![cfg(not(debug_assertions))]
22

33
use beacon_chain::attestation_simulator::produce_unaggregated_attestation;
4-
use beacon_chain::block_verification_types::RpcBlock;
54
use beacon_chain::test_utils::{AttestationStrategy, BeaconChainHarness, BlockStrategy};
65
use beacon_chain::validator_monitor::UNAGGREGATED_ATTESTATION_LAG_SLOTS;
76
use beacon_chain::{metrics, StateSkipConfig, WhenSlotSkipped};
@@ -155,7 +154,6 @@ async fn produces_attestations() {
155154
.store
156155
.make_full_block(&block_root, blinded_block)
157156
.unwrap();
158-
let blobs = chain.get_blobs(&block_root).unwrap().blobs();
159157

160158
let epoch_boundary_slot = state
161159
.current_epoch()
@@ -223,8 +221,7 @@ async fn produces_attestations() {
223221
assert_eq!(data.target.root, target_root, "bad target root");
224222

225223
let rpc_block =
226-
RpcBlock::<MainnetEthSpec>::new(None, Arc::new(block.clone()), blobs.clone())
227-
.unwrap();
224+
harness.build_rpc_block_from_store_blobs(Some(block_root), Arc::new(block.clone()));
228225
let beacon_chain::data_availability_checker::MaybeAvailableBlock::Available(
229226
available_block,
230227
) = chain
@@ -296,14 +293,8 @@ async fn early_attester_cache_old_request() {
296293
.get_block(&head.beacon_block_root)
297294
.unwrap();
298295

299-
let head_blobs = harness
300-
.chain
301-
.get_blobs(&head.beacon_block_root)
302-
.expect("should get blobs")
303-
.blobs();
304-
305-
let rpc_block =
306-
RpcBlock::<MainnetEthSpec>::new(None, head.beacon_block.clone(), head_blobs).unwrap();
296+
let rpc_block = harness
297+
.build_rpc_block_from_store_blobs(Some(head.beacon_block_root), head.beacon_block.clone());
307298
let beacon_chain::data_availability_checker::MaybeAvailableBlock::Available(available_block) =
308299
harness
309300
.chain

0 commit comments

Comments
 (0)