Skip to content

Commit 73cb982

Browse files
committed
Try pushing blob timing down into verification
1 parent d21a7f1 commit 73cb982

File tree

5 files changed

+112
-157
lines changed

5 files changed

+112
-157
lines changed

beacon_node/beacon_chain/src/beacon_chain.rs

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2891,15 +2891,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
28912891
return Err(BlockError::BlockIsAlreadyKnown(blob.block_root()));
28922892
}
28932893

2894-
// Record the delay for receiving this blob
2895-
if let Some(seen_timestamp) = self.slot_clock.now_duration() {
2896-
self.block_times_cache.write().set_time_blob_observed(
2897-
block_root,
2898-
blob.slot(),
2899-
seen_timestamp,
2900-
);
2901-
}
2902-
29032894
if let Some(event_handler) = self.event_handler.as_ref() {
29042895
if event_handler.has_blob_sidecar_subscribers() {
29052896
event_handler.register(EventKind::BlobSidecar(SseBlobSidecar::from_blob_sidecar(
@@ -3268,17 +3259,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
32683259
consensus_context,
32693260
} = import_data;
32703261

3271-
// This is the time since start of the slot where all the components of the block have become available
3272-
metrics::set_gauge(
3273-
&metrics::BLOCK_AVAILABILITY_DELAY,
3274-
block.available_timestamp().as_millis() as i64,
3275-
);
3276-
// Record the time at which this block became available.
3277-
self.block_times_cache.write().set_time_available(
3278-
block_root,
3279-
block.slot(),
3280-
block.available_timestamp(),
3281-
);
3262+
// Record the time at which this block's blobs became available.
3263+
if let Some(blobs_available) = block.blobs_available_timestamp() {
3264+
self.block_times_cache.write().set_time_blob_observed(
3265+
block_root,
3266+
block.slot(),
3267+
blobs_available,
3268+
);
3269+
}
32823270

32833271
// import
32843272
let chain = self.clone();

beacon_node/beacon_chain/src/blob_verification.rs

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use merkle_proof::MerkleTreeError;
1414
use slog::{debug, warn};
1515
use ssz_derive::{Decode, Encode};
1616
use ssz_types::VariableList;
17+
use std::time::Duration;
1718
use tree_hash::TreeHash;
1819
use types::blob_sidecar::BlobIdentifier;
1920
use types::{
@@ -214,7 +215,10 @@ impl<T: BeaconChainTypes> GossipVerifiedBlob<T> {
214215
pub fn __assumed_valid(blob: Arc<BlobSidecar<T::EthSpec>>) -> Self {
215216
Self {
216217
block_root: blob.block_root(),
217-
blob: KzgVerifiedBlob { blob },
218+
blob: KzgVerifiedBlob {
219+
blob,
220+
seen_timestamp: Duration::from_secs(0),
221+
},
218222
}
219223
}
220224
pub fn id(&self) -> BlobIdentifier {
@@ -260,6 +264,8 @@ impl<T: BeaconChainTypes> GossipVerifiedBlob<T> {
260264
#[ssz(struct_behaviour = "transparent")]
261265
pub struct KzgVerifiedBlob<E: EthSpec> {
262266
blob: Arc<BlobSidecar<E>>,
267+
#[ssz(skip_serializing, skip_deserializing)]
268+
seen_timestamp: Duration,
263269
}
264270

265271
impl<E: EthSpec> PartialOrd for KzgVerifiedBlob<E> {
@@ -275,8 +281,12 @@ impl<E: EthSpec> Ord for KzgVerifiedBlob<E> {
275281
}
276282

277283
impl<E: EthSpec> KzgVerifiedBlob<E> {
278-
pub fn new(blob: Arc<BlobSidecar<E>>, kzg: &Kzg) -> Result<Self, KzgError> {
279-
verify_kzg_for_blob(blob, kzg)
284+
pub fn new(
285+
blob: Arc<BlobSidecar<E>>,
286+
kzg: &Kzg,
287+
seen_timestamp: Duration,
288+
) -> Result<Self, KzgError> {
289+
verify_kzg_for_blob(blob, kzg, seen_timestamp)
280290
}
281291
pub fn to_blob(self) -> Arc<BlobSidecar<E>> {
282292
self.blob
@@ -294,12 +304,18 @@ impl<E: EthSpec> KzgVerifiedBlob<E> {
294304
pub fn blob_index(&self) -> u64 {
295305
self.blob.index
296306
}
307+
pub fn seen_timestamp(&self) -> Duration {
308+
self.seen_timestamp
309+
}
297310
/// Construct a `KzgVerifiedBlob` that is assumed to be valid.
298311
///
299312
/// This should ONLY be used for testing.
300313
#[cfg(test)]
301314
pub fn __assumed_valid(blob: Arc<BlobSidecar<E>>) -> Self {
302-
Self { blob }
315+
Self {
316+
blob,
317+
seen_timestamp: Duration::from_secs(0),
318+
}
303319
}
304320
}
305321

@@ -309,9 +325,13 @@ impl<E: EthSpec> KzgVerifiedBlob<E> {
309325
pub fn verify_kzg_for_blob<E: EthSpec>(
310326
blob: Arc<BlobSidecar<E>>,
311327
kzg: &Kzg,
328+
seen_timestamp: Duration,
312329
) -> Result<KzgVerifiedBlob<E>, KzgError> {
313330
validate_blob::<E>(kzg, &blob.blob, blob.kzg_commitment, blob.kzg_proof)?;
314-
Ok(KzgVerifiedBlob { blob })
331+
Ok(KzgVerifiedBlob {
332+
blob,
333+
seen_timestamp,
334+
})
315335
}
316336

317337
pub struct KzgVerifiedBlobList<E: EthSpec> {
@@ -322,13 +342,17 @@ impl<E: EthSpec> KzgVerifiedBlobList<E> {
322342
pub fn new<I: IntoIterator<Item = Arc<BlobSidecar<E>>>>(
323343
blob_list: I,
324344
kzg: &Kzg,
345+
seen_timestamp: Duration,
325346
) -> Result<Self, KzgError> {
326347
let blobs = blob_list.into_iter().collect::<Vec<_>>();
327348
verify_kzg_for_blob_list(blobs.iter(), kzg)?;
328349
Ok(Self {
329350
verified_blobs: blobs
330351
.into_iter()
331-
.map(|blob| KzgVerifiedBlob { blob })
352+
.map(|blob| KzgVerifiedBlob {
353+
blob,
354+
seen_timestamp,
355+
})
332356
.collect(),
333357
})
334358
}
@@ -374,6 +398,8 @@ pub fn validate_blob_sidecar_for_gossip<T: BeaconChainTypes>(
374398
let blob_epoch = blob_slot.epoch(T::EthSpec::slots_per_epoch());
375399
let signed_block_header = &blob_sidecar.signed_block_header;
376400

401+
let seen_timestamp = chain.slot_clock.now_duration().unwrap_or_default();
402+
377403
// This condition is not possible if we have received the blob from the network
378404
// since we only subscribe to `MaxBlobsPerBlock` subnets over gossip network.
379405
// We include this check only for completeness.
@@ -641,8 +667,8 @@ pub fn validate_blob_sidecar_for_gossip<T: BeaconChainTypes>(
641667
.kzg
642668
.as_ref()
643669
.ok_or(GossipBlobError::KzgNotInitialized)?;
644-
let kzg_verified_blob =
645-
KzgVerifiedBlob::new(blob_sidecar, kzg).map_err(GossipBlobError::KzgError)?;
670+
let kzg_verified_blob = KzgVerifiedBlob::new(blob_sidecar, kzg, seen_timestamp)
671+
.map_err(GossipBlobError::KzgError)?;
646672

647673
Ok(GossipVerifiedBlob {
648674
block_root,

beacon_node/beacon_chain/src/block_times_cache.rs

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ pub struct Timestamps {
2020
pub observed: Option<Duration>,
2121
pub all_blobs_observed: Option<Duration>,
2222
pub execution_time: Option<Duration>,
23-
pub available: Option<Duration>,
2423
pub attestable: Option<Duration>,
2524
pub imported: Option<Duration>,
2625
pub set_as_head: Option<Duration>,
@@ -35,7 +34,9 @@ pub struct BlockDelays {
3534
pub all_blobs_observed: Option<Duration>,
3635
/// The time it took to get verification from the EL for the block.
3736
pub execution_time: Option<Duration>,
38-
/// Time after max(`observed + execution_time`, `all_blobs_observed`) the block became available.
37+
/// The delay from the start of the slot before the block became available
38+
///
39+
/// Equal to max(`observed + execution_time`, `all_blobs_observed`).
3940
pub available: Option<Duration>,
4041
/// Time after `available`.
4142
pub attestable: Option<Duration>,
@@ -60,23 +61,31 @@ impl BlockDelays {
6061
let execution_time = times
6162
.execution_time
6263
.and_then(|execution_time| execution_time.checked_sub(times.observed?));
63-
let available = times
64-
.available
65-
.and_then(|available_time| available_time.checked_sub(slot_start_time));
64+
// Duration since UNIX epoch at which block became available.
65+
let available_time = times.execution_time.and_then(|execution_time| {
66+
if let Some(all_blobs_observed) = times.all_blobs_observed {
67+
Some(std::cmp::max(execution_time, all_blobs_observed))
68+
} else {
69+
Some(execution_time)
70+
}
71+
});
72+
// Duration from the start of the slot until the block became available.
73+
let available_delay =
74+
available_time.and_then(|available_time| available_time.checked_sub(slot_start_time));
6675
let attestable = times
6776
.attestable
6877
.and_then(|attestable_time| attestable_time.checked_sub(slot_start_time));
6978
let imported = times
7079
.imported
71-
.and_then(|imported_time| imported_time.checked_sub(times.available?));
80+
.and_then(|imported_time| imported_time.checked_sub(available_time?));
7281
let set_as_head = times
7382
.set_as_head
7483
.and_then(|set_as_head_time| set_as_head_time.checked_sub(times.imported?));
7584
BlockDelays {
7685
observed,
7786
all_blobs_observed,
7887
execution_time,
79-
available,
88+
available: available_delay,
8089
attestable,
8190
imported,
8291
set_as_head,
@@ -177,20 +186,6 @@ impl BlockTimesCache {
177186
}
178187
}
179188

180-
pub fn set_time_available(&mut self, block_root: BlockRoot, slot: Slot, timestamp: Duration) {
181-
let block_times = self
182-
.cache
183-
.entry(block_root)
184-
.or_insert_with(|| BlockTimesCacheValue::new(slot));
185-
if block_times
186-
.timestamps
187-
.available
188-
.map_or(true, |prev| timestamp < prev)
189-
{
190-
block_times.timestamps.available = Some(timestamp);
191-
}
192-
}
193-
194189
pub fn set_time_attestable(&mut self, block_root: BlockRoot, slot: Slot, timestamp: Duration) {
195190
let block_times = self
196191
.cache

beacon_node/beacon_chain/src/data_availability_checker.rs

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,17 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
177177
return Err(AvailabilityCheckError::KzgNotInitialized);
178178
};
179179

180-
let verified_blobs = KzgVerifiedBlobList::new(Vec::from(blobs).into_iter().flatten(), kzg)
181-
.map_err(AvailabilityCheckError::Kzg)?;
180+
let seen_timestamp = self
181+
.slot_clock
182+
.now_duration()
183+
.ok_or(AvailabilityCheckError::SlotClockError)?;
184+
185+
let verified_blobs =
186+
KzgVerifiedBlobList::new(Vec::from(blobs).into_iter().flatten(), kzg, seen_timestamp)
187+
.map_err(AvailabilityCheckError::Kzg)?;
182188

183189
self.availability_cache
184-
.put_kzg_verified_blobs(block_root, verified_blobs, &self.slot_clock)
190+
.put_kzg_verified_blobs(block_root, verified_blobs)
185191
}
186192

187193
/// Check if we've cached other blobs for this block. If it completes a set and we also
@@ -193,11 +199,8 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
193199
&self,
194200
gossip_blob: GossipVerifiedBlob<T>,
195201
) -> Result<Availability<T::EthSpec>, AvailabilityCheckError> {
196-
self.availability_cache.put_kzg_verified_blobs(
197-
gossip_blob.block_root(),
198-
vec![gossip_blob.into_inner()],
199-
&self.slot_clock,
200-
)
202+
self.availability_cache
203+
.put_kzg_verified_blobs(gossip_blob.block_root(), vec![gossip_blob.into_inner()])
201204
}
202205

203206
/// Check if we have all the blobs for a block. Returns `Availability` which has information
@@ -207,7 +210,7 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
207210
executed_block: AvailabilityPendingExecutedBlock<T::EthSpec>,
208211
) -> Result<Availability<T::EthSpec>, AvailabilityCheckError> {
209212
self.availability_cache
210-
.put_pending_executed_block(executed_block, &self.slot_clock)
213+
.put_pending_executed_block(executed_block)
211214
}
212215

213216
/// Verifies kzg commitments for an RpcBlock, returns a `MaybeAvailableBlock` that may
@@ -225,15 +228,11 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
225228
if self.blobs_required_for_block(&block) {
226229
Ok(MaybeAvailableBlock::AvailabilityPending { block_root, block })
227230
} else {
228-
let available_timestamp = self
229-
.slot_clock
230-
.now_duration()
231-
.ok_or(AvailabilityCheckError::SlotClockError)?;
232231
Ok(MaybeAvailableBlock::Available(AvailableBlock {
233232
block_root,
234233
block,
235234
blobs: None,
236-
available_timestamp,
235+
blobs_available_timestamp: None,
237236
}))
238237
}
239238
}
@@ -249,15 +248,11 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
249248
} else {
250249
None
251250
};
252-
let available_timestamp = self
253-
.slot_clock
254-
.now_duration()
255-
.ok_or(AvailabilityCheckError::SlotClockError)?;
256251
Ok(MaybeAvailableBlock::Available(AvailableBlock {
257252
block_root,
258253
block,
259254
blobs: verified_blobs,
260-
available_timestamp,
255+
blobs_available_timestamp: None,
261256
}))
262257
}
263258
}
@@ -299,15 +294,11 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
299294
if self.blobs_required_for_block(&block) {
300295
results.push(MaybeAvailableBlock::AvailabilityPending { block_root, block })
301296
} else {
302-
let available_timestamp = self
303-
.slot_clock
304-
.now_duration()
305-
.ok_or(AvailabilityCheckError::SlotClockError)?;
306297
results.push(MaybeAvailableBlock::Available(AvailableBlock {
307298
block_root,
308299
block,
309300
blobs: None,
310-
available_timestamp,
301+
blobs_available_timestamp: None,
311302
}))
312303
}
313304
}
@@ -318,15 +309,11 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
318309
None
319310
};
320311
// already verified kzg for all blobs
321-
let available_timestamp = self
322-
.slot_clock
323-
.now_duration()
324-
.ok_or(AvailabilityCheckError::SlotClockError)?;
325312
results.push(MaybeAvailableBlock::Available(AvailableBlock {
326313
block_root,
327314
block,
328315
blobs: verified_blobs,
329-
available_timestamp,
316+
blobs_available_timestamp: None,
330317
}))
331318
}
332319
}
@@ -487,7 +474,7 @@ pub struct AvailableBlock<E: EthSpec> {
487474
block: Arc<SignedBeaconBlock<E>>,
488475
blobs: Option<BlobSidecarList<E>>,
489476
/// Timestamp at which this block first became available (UNIX timestamp, time since 1970).
490-
available_timestamp: Duration,
477+
blobs_available_timestamp: Option<Duration>,
491478
}
492479

493480
impl<E: EthSpec> AvailableBlock<E> {
@@ -500,7 +487,7 @@ impl<E: EthSpec> AvailableBlock<E> {
500487
block_root,
501488
block,
502489
blobs,
503-
available_timestamp: Duration::from_millis(0),
490+
blobs_available_timestamp: None,
504491
}
505492
}
506493

@@ -515,8 +502,8 @@ impl<E: EthSpec> AvailableBlock<E> {
515502
self.blobs.as_ref()
516503
}
517504

518-
pub fn available_timestamp(&self) -> Duration {
519-
self.available_timestamp
505+
pub fn blobs_available_timestamp(&self) -> Option<Duration> {
506+
self.blobs_available_timestamp
520507
}
521508

522509
pub fn deconstruct(
@@ -530,7 +517,7 @@ impl<E: EthSpec> AvailableBlock<E> {
530517
block_root,
531518
block,
532519
blobs,
533-
available_timestamp: _,
520+
blobs_available_timestamp: _,
534521
} = self;
535522
(block_root, block, blobs)
536523
}

0 commit comments

Comments
 (0)