Skip to content

Commit 1ef3ce7

Browse files
committed
superstruct columns and blobs and delete unused codepaths
1 parent 58b153c commit 1ef3ce7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1079
-2326
lines changed

beacon_node/beacon_chain/src/beacon_chain.rs

Lines changed: 72 additions & 104 deletions
Large diffs are not rendered by default.

beacon_node/beacon_chain/src/blob_verification.rs

Lines changed: 4 additions & 308 deletions
Original file line numberDiff line numberDiff line change
@@ -156,93 +156,6 @@ impl From<BeaconStateError> for GossipBlobError {
156156
}
157157
}
158158

159-
/// A wrapper around a `BlobSidecar` that indicates it has been approved for re-gossiping on
160-
/// the p2p network.
161-
#[derive(Debug)]
162-
pub struct GossipVerifiedBlob<T: BeaconChainTypes, O: ObservationStrategy = Observe> {
163-
block_root: Hash256,
164-
blob: KzgVerifiedBlob<T::EthSpec>,
165-
_phantom: PhantomData<O>,
166-
}
167-
168-
impl<T: BeaconChainTypes, O: ObservationStrategy> Clone for GossipVerifiedBlob<T, O> {
169-
fn clone(&self) -> Self {
170-
Self {
171-
block_root: self.block_root,
172-
blob: self.blob.clone(),
173-
_phantom: PhantomData,
174-
}
175-
}
176-
}
177-
178-
impl<T: BeaconChainTypes, O: ObservationStrategy> GossipVerifiedBlob<T, O> {
179-
pub fn new(
180-
blob: Arc<BlobSidecar<T::EthSpec>>,
181-
subnet_id: u64,
182-
chain: &BeaconChain<T>,
183-
) -> Result<Self, GossipBlobError> {
184-
let header = blob.signed_block_header.clone();
185-
// We only process slashing info if the gossip verification failed
186-
// since we do not process the blob any further in that case.
187-
validate_blob_sidecar_for_gossip::<T, O>(blob, subnet_id, chain).map_err(|e| {
188-
process_block_slash_info::<_, GossipBlobError>(
189-
chain,
190-
BlockSlashInfo::from_early_error_blob(header, e),
191-
)
192-
})
193-
}
194-
/// Construct a `GossipVerifiedBlob` that is assumed to be valid.
195-
///
196-
/// This should ONLY be used for testing.
197-
pub fn __assumed_valid(blob: Arc<BlobSidecar<T::EthSpec>>) -> Self {
198-
Self {
199-
block_root: blob.block_root(),
200-
blob: KzgVerifiedBlob {
201-
blob,
202-
seen_timestamp: Duration::from_secs(0),
203-
},
204-
_phantom: PhantomData,
205-
}
206-
}
207-
pub fn id(&self) -> BlobIdentifier {
208-
BlobIdentifier {
209-
block_root: self.block_root,
210-
index: self.blob.blob_index(),
211-
}
212-
}
213-
pub fn block_root(&self) -> Hash256 {
214-
self.block_root
215-
}
216-
pub fn slot(&self) -> Slot {
217-
self.blob.blob.slot()
218-
}
219-
pub fn epoch(&self) -> Epoch {
220-
self.blob.blob.epoch()
221-
}
222-
pub fn index(&self) -> u64 {
223-
self.blob.blob.index
224-
}
225-
pub fn kzg_commitment(&self) -> KzgCommitment {
226-
self.blob.blob.kzg_commitment
227-
}
228-
pub fn signed_block_header(&self) -> SignedBeaconBlockHeader {
229-
self.blob.blob.signed_block_header.clone()
230-
}
231-
pub fn block_proposer_index(&self) -> u64 {
232-
self.blob.blob.block_proposer_index()
233-
}
234-
pub fn into_inner(self) -> KzgVerifiedBlob<T::EthSpec> {
235-
self.blob
236-
}
237-
pub fn as_blob(&self) -> &BlobSidecar<T::EthSpec> {
238-
self.blob.as_blob()
239-
}
240-
/// This is cheap as we're calling clone on an Arc
241-
pub fn clone_blob(&self) -> Arc<BlobSidecar<T::EthSpec>> {
242-
self.blob.clone_blob()
243-
}
244-
}
245-
246159
/// Wrapper over a `BlobSidecar` for which we have completed kzg verification.
247160
/// i.e. `verify_blob_kzg_proof(blob, commitment, proof) == true`.
248161
#[derive(Debug, Educe, Clone, Encode, Decode)]
@@ -281,14 +194,14 @@ impl<E: EthSpec> KzgVerifiedBlob<E> {
281194
&self.blob
282195
}
283196
pub fn get_commitment(&self) -> &KzgCommitment {
284-
&self.blob.kzg_commitment
197+
&self.blob.kzg_commitment()
285198
}
286199
/// This is cheap as we're calling clone on an Arc
287200
pub fn clone_blob(&self) -> Arc<BlobSidecar<E>> {
288201
self.blob.clone()
289202
}
290203
pub fn blob_index(&self) -> u64 {
291-
self.blob.index
204+
*self.blob.index()
292205
}
293206
pub fn seen_timestamp(&self) -> Duration {
294207
self.seen_timestamp
@@ -321,7 +234,7 @@ pub fn verify_kzg_for_blob<E: EthSpec>(
321234
kzg: &Kzg,
322235
seen_timestamp: Duration,
323236
) -> Result<KzgVerifiedBlob<E>, KzgError> {
324-
validate_blob::<E>(kzg, &blob.blob, blob.kzg_commitment, blob.kzg_proof)?;
237+
validate_blob::<E>(kzg, blob.blob(), *blob.kzg_commitment(), *blob.kzg_proof())?;
325238
Ok(KzgVerifiedBlob {
326239
blob,
327240
seen_timestamp,
@@ -382,228 +295,11 @@ where
382295
I: Iterator<Item = &'a Arc<BlobSidecar<E>>>,
383296
{
384297
let (blobs, (commitments, proofs)): (Vec<_>, (Vec<_>, Vec<_>)) = blob_iter
385-
.map(|blob| (&blob.blob, (blob.kzg_commitment, blob.kzg_proof)))
298+
.map(|blob| (blob.blob(), (*blob.kzg_commitment(), *blob.kzg_proof())))
386299
.unzip();
387300
validate_blobs::<E>(kzg, commitments.as_slice(), blobs, proofs.as_slice())
388301
}
389302

390-
pub fn validate_blob_sidecar_for_gossip<T: BeaconChainTypes, O: ObservationStrategy>(
391-
blob_sidecar: Arc<BlobSidecar<T::EthSpec>>,
392-
subnet: u64,
393-
chain: &BeaconChain<T>,
394-
) -> Result<GossipVerifiedBlob<T, O>, GossipBlobError> {
395-
let blob_slot = blob_sidecar.slot();
396-
let blob_index = blob_sidecar.index;
397-
let block_parent_root = blob_sidecar.block_parent_root();
398-
let blob_proposer_index = blob_sidecar.block_proposer_index();
399-
let block_root = blob_sidecar.block_root();
400-
let blob_epoch = blob_slot.epoch(T::EthSpec::slots_per_epoch());
401-
let signed_block_header = &blob_sidecar.signed_block_header;
402-
403-
let seen_timestamp = chain.slot_clock.now_duration().unwrap_or_default();
404-
405-
// This condition is not possible if we have received the blob from the network
406-
// since we only subscribe to `MaxBlobsPerBlock` subnets over gossip network.
407-
// We include this check only for completeness.
408-
// Getting this error would imply something very wrong with our networking decoding logic.
409-
if blob_index >= chain.spec.max_blobs_per_block(blob_epoch) {
410-
return Err(GossipBlobError::InvalidSubnet {
411-
expected: subnet,
412-
received: blob_index,
413-
});
414-
}
415-
416-
// Verify that the blob_sidecar was received on the correct subnet.
417-
if blob_index != subnet {
418-
return Err(GossipBlobError::InvalidSubnet {
419-
expected: subnet,
420-
received: blob_index,
421-
});
422-
}
423-
424-
// Verify that the sidecar is not from a future slot.
425-
let latest_permissible_slot = chain
426-
.slot_clock
427-
.now_with_future_tolerance(chain.spec.maximum_gossip_clock_disparity())
428-
.ok_or(BeaconChainError::UnableToReadSlot)?;
429-
if blob_slot > latest_permissible_slot {
430-
return Err(GossipBlobError::FutureSlot {
431-
message_slot: blob_slot,
432-
latest_permissible_slot,
433-
});
434-
}
435-
436-
// Verify that the sidecar slot is greater than the latest finalized slot
437-
let latest_finalized_slot = chain
438-
.head()
439-
.finalized_checkpoint()
440-
.epoch
441-
.start_slot(T::EthSpec::slots_per_epoch());
442-
if blob_slot <= latest_finalized_slot {
443-
return Err(GossipBlobError::PastFinalizedSlot {
444-
blob_slot,
445-
finalized_slot: latest_finalized_slot,
446-
});
447-
}
448-
449-
// Verify that this is the first blob sidecar received for the tuple:
450-
// (block_header.slot, block_header.proposer_index, blob_sidecar.index)
451-
if chain
452-
.observed_blob_sidecars
453-
.read()
454-
.proposer_is_known(&blob_sidecar)
455-
.map_err(|e| GossipBlobError::BeaconChainError(Box::new(e.into())))?
456-
{
457-
return Err(GossipBlobError::RepeatBlob {
458-
proposer: blob_proposer_index,
459-
slot: blob_slot,
460-
index: blob_index,
461-
});
462-
}
463-
464-
// Verify the inclusion proof in the sidecar
465-
let _timer = metrics::start_timer(&metrics::BLOB_SIDECAR_INCLUSION_PROOF_VERIFICATION);
466-
if !blob_sidecar.verify_blob_sidecar_inclusion_proof() {
467-
return Err(GossipBlobError::InvalidInclusionProof);
468-
}
469-
drop(_timer);
470-
471-
let fork_choice = chain.canonical_head.fork_choice_read_lock();
472-
473-
// We have already verified that the blob is past finalization, so we can
474-
// just check fork choice for the block's parent.
475-
let Some(parent_block) = fork_choice.get_block(&block_parent_root) else {
476-
return Err(GossipBlobError::ParentUnknown {
477-
parent_root: block_parent_root,
478-
});
479-
};
480-
481-
// Do not process a blob that does not descend from the finalized root.
482-
// We just loaded the parent_block, so we can be sure that it exists in fork choice.
483-
if !fork_choice.is_finalized_checkpoint_or_descendant(block_parent_root) {
484-
return Err(GossipBlobError::NotFinalizedDescendant { block_parent_root });
485-
}
486-
drop(fork_choice);
487-
488-
if parent_block.slot >= blob_slot {
489-
return Err(GossipBlobError::BlobIsNotLaterThanParent {
490-
blob_slot,
491-
parent_slot: parent_block.slot,
492-
});
493-
}
494-
495-
let proposer_shuffling_root =
496-
parent_block.proposer_shuffling_root_for_child_block(blob_epoch, &chain.spec);
497-
498-
let proposer = chain.with_proposer_cache(
499-
proposer_shuffling_root,
500-
blob_epoch,
501-
|proposers| proposers.get_slot::<T::EthSpec>(blob_slot),
502-
|| {
503-
debug!(
504-
%block_root,
505-
index = %blob_index,
506-
"Proposer shuffling cache miss for blob verification"
507-
);
508-
chain
509-
.store
510-
.get_advanced_hot_state(block_parent_root, blob_slot, parent_block.state_root)
511-
.map_err(|e| GossipBlobError::BeaconChainError(Box::new(e.into())))?
512-
.ok_or_else(|| {
513-
GossipBlobError::BeaconChainError(Box::new(BeaconChainError::DBInconsistent(
514-
format!("Missing state for parent block {block_parent_root:?}",),
515-
)))
516-
})
517-
},
518-
)?;
519-
let proposer_index = proposer.index;
520-
let fork = proposer.fork;
521-
522-
// Signature verify the signed block header.
523-
let signature_is_valid = {
524-
let pubkey_cache =
525-
get_validator_pubkey_cache(chain).map_err(|_| GossipBlobError::PubkeyCacheTimeout)?;
526-
527-
let pubkey = pubkey_cache
528-
.get(proposer_index)
529-
.ok_or_else(|| GossipBlobError::UnknownValidator(proposer_index as u64))?;
530-
signed_block_header.verify_signature::<T::EthSpec>(
531-
pubkey,
532-
&fork,
533-
chain.genesis_validators_root,
534-
&chain.spec,
535-
)
536-
};
537-
538-
if !signature_is_valid {
539-
return Err(GossipBlobError::ProposalSignatureInvalid);
540-
}
541-
542-
if proposer_index != blob_proposer_index as usize {
543-
return Err(GossipBlobError::ProposerIndexMismatch {
544-
sidecar: blob_proposer_index as usize,
545-
local: proposer_index,
546-
});
547-
}
548-
549-
// Kzg verification for gossip blob sidecar
550-
let kzg = chain.kzg.as_ref();
551-
552-
let kzg_verified_blob = KzgVerifiedBlob::new(blob_sidecar.clone(), kzg, seen_timestamp)
553-
.map_err(GossipBlobError::KzgError)?;
554-
let blob_sidecar = &kzg_verified_blob.blob;
555-
556-
chain
557-
.observed_slashable
558-
.write()
559-
.observe_slashable(
560-
blob_sidecar.slot(),
561-
blob_sidecar.block_proposer_index(),
562-
block_root,
563-
)
564-
.map_err(|e| GossipBlobError::BeaconChainError(Box::new(e.into())))?;
565-
566-
if O::observe() {
567-
observe_gossip_blob(&kzg_verified_blob.blob, chain)?;
568-
}
569-
570-
Ok(GossipVerifiedBlob {
571-
block_root,
572-
blob: kzg_verified_blob,
573-
_phantom: PhantomData,
574-
})
575-
}
576-
577-
pub fn observe_gossip_blob<T: BeaconChainTypes>(
578-
blob_sidecar: &BlobSidecar<T::EthSpec>,
579-
chain: &BeaconChain<T>,
580-
) -> Result<(), GossipBlobError> {
581-
// Now the signature is valid, store the proposal so we don't accept another blob sidecar
582-
// with the same `BlobIdentifier`. It's important to double-check that the proposer still
583-
// hasn't been observed so we don't have a race-condition when verifying two blocks
584-
// simultaneously.
585-
//
586-
// Note: If this BlobSidecar goes on to fail full verification, we do not evict it from the
587-
// seen_cache as alternate blob_sidecars for the same identifier can still be retrieved over
588-
// rpc. Evicting them from this cache would allow faster propagation over gossip. So we
589-
// allow retrieval of potentially valid blocks over rpc, but try to punish the proposer for
590-
// signing invalid messages. Issue for more background
591-
// https://github.com/ethereum/consensus-specs/issues/3261
592-
if chain
593-
.observed_blob_sidecars
594-
.write()
595-
.observe_sidecar(blob_sidecar)
596-
.map_err(|e| GossipBlobError::BeaconChainError(Box::new(e.into())))?
597-
{
598-
return Err(GossipBlobError::RepeatBlob {
599-
proposer: blob_sidecar.block_proposer_index(),
600-
slot: blob_sidecar.slot(),
601-
index: blob_sidecar.index,
602-
});
603-
}
604-
Ok(())
605-
}
606-
607303
/// Returns the canonical root of the given `blob`.
608304
///
609305
/// Use this function to ensure that we report the blob hashing time Prometheus metric.

beacon_node/beacon_chain/src/block_verification_types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ impl<E: EthSpec> RpcBlock<E> {
129129
return Err(AvailabilityCheckError::MissingBlobs);
130130
}
131131
for (blob, &block_commitment) in blobs.iter().zip(block_commitments.iter()) {
132-
let blob_commitment = blob.kzg_commitment;
132+
let blob_commitment = *blob.kzg_commitment();
133133
if blob_commitment != block_commitment {
134134
return Err(AvailabilityCheckError::KzgCommitmentMismatch {
135135
block_commitment,

0 commit comments

Comments
 (0)