From 78ffa378b40e91cff23fdfdeb3c2dbb6a5520597 Mon Sep 17 00:00:00 2001 From: ethDreamer <37123614+ethDreamer@users.noreply.github.com> Date: Fri, 8 Dec 2023 15:48:03 -0600 Subject: [PATCH] Batch Verify RPC Blobs (#4934) --- .../beacon_chain/src/blob_verification.rs | 48 +++++++++++++++---- .../src/data_availability_checker.rs | 18 ++++--- .../overflow_lru_cache.rs | 4 +- 3 files changed, 48 insertions(+), 22 deletions(-) diff --git a/beacon_node/beacon_chain/src/blob_verification.rs b/beacon_node/beacon_chain/src/blob_verification.rs index 05457adab32..cc087e74a07 100644 --- a/beacon_node/beacon_chain/src/blob_verification.rs +++ b/beacon_node/beacon_chain/src/blob_verification.rs @@ -17,8 +17,7 @@ use ssz_types::VariableList; use tree_hash::TreeHash; use types::blob_sidecar::BlobIdentifier; use types::{ - BeaconStateError, BlobSidecar, BlobSidecarList, CloneConfig, EthSpec, Hash256, - SignedBeaconBlockHeader, Slot, + BeaconStateError, BlobSidecar, CloneConfig, EthSpec, Hash256, SignedBeaconBlockHeader, Slot, }; /// An error occurred while validating a gossip blob. @@ -279,7 +278,6 @@ impl KzgVerifiedBlob { pub fn new(blob: Arc>, kzg: &Kzg) -> Result { verify_kzg_for_blob(blob, kzg) } - pub fn to_blob(self) -> Arc> { self.blob } @@ -310,21 +308,51 @@ pub fn verify_kzg_for_blob( kzg: &Kzg, ) -> Result, KzgError> { validate_blob::(kzg, &blob.blob, blob.kzg_commitment, blob.kzg_proof)?; - Ok(KzgVerifiedBlob { blob }) } +pub struct KzgVerifiedBlobList { + verified_blobs: Vec>, +} + +impl KzgVerifiedBlobList { + pub fn new>>>( + blob_list: I, + kzg: &Kzg, + ) -> Result { + let blobs = blob_list.into_iter().collect::>(); + verify_kzg_for_blob_list(blobs.iter(), kzg)?; + Ok(Self { + verified_blobs: blobs + .into_iter() + .map(|blob| KzgVerifiedBlob { blob }) + .collect(), + }) + } +} + +impl IntoIterator for KzgVerifiedBlobList { + type Item = KzgVerifiedBlob; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.verified_blobs.into_iter() + } +} + /// Complete kzg verification for a list of `BlobSidecar`s. /// Returns an error if any of the `BlobSidecar`s fails kzg verification. /// /// Note: This function should be preferred over calling `verify_kzg_for_blob` /// in a loop since this function kzg verifies a list of blobs more efficiently. -pub fn verify_kzg_for_blob_list( - blob_list: &BlobSidecarList, - kzg: &Kzg, -) -> Result<(), KzgError> { - let (blobs, (commitments, proofs)): (Vec<_>, (Vec<_>, Vec<_>)) = blob_list - .iter() +pub fn verify_kzg_for_blob_list<'a, T: EthSpec, I>( + blob_iter: I, + kzg: &'a Kzg, +) -> Result<(), KzgError> +where + I: Iterator>>, +{ + let (blobs, (commitments, proofs)): (Vec<_>, (Vec<_>, Vec<_>)) = blob_iter .map(|blob| (&blob.blob, (blob.kzg_commitment, blob.kzg_proof))) .unzip(); validate_blobs::(kzg, commitments.as_slice(), blobs, proofs.as_slice()) diff --git a/beacon_node/beacon_chain/src/data_availability_checker.rs b/beacon_node/beacon_chain/src/data_availability_checker.rs index 67e98a01c1a..eff8d1d9d09 100644 --- a/beacon_node/beacon_chain/src/data_availability_checker.rs +++ b/beacon_node/beacon_chain/src/data_availability_checker.rs @@ -1,4 +1,4 @@ -use crate::blob_verification::{verify_kzg_for_blob_list, GossipVerifiedBlob, KzgVerifiedBlob}; +use crate::blob_verification::{verify_kzg_for_blob_list, GossipVerifiedBlob, KzgVerifiedBlobList}; use crate::block_verification_types::{ AvailabilityPendingExecutedBlock, AvailableExecutedBlock, RpcBlock, }; @@ -197,15 +197,13 @@ impl DataAvailabilityChecker { block_root: Hash256, blobs: FixedBlobSidecarList, ) -> Result, AvailabilityCheckError> { - let mut verified_blobs = vec![]; - if let Some(kzg) = self.kzg.as_ref() { - for blob in Vec::from(blobs).into_iter().flatten() { - verified_blobs - .push(KzgVerifiedBlob::new(blob, kzg).map_err(AvailabilityCheckError::Kzg)?); - } - } else { + let Some(kzg) = self.kzg.as_ref() else { return Err(AvailabilityCheckError::KzgNotInitialized); }; + + let verified_blobs = KzgVerifiedBlobList::new(Vec::from(blobs).into_iter().flatten(), kzg) + .map_err(AvailabilityCheckError::Kzg)?; + self.availability_cache .put_kzg_verified_blobs(block_root, verified_blobs) } @@ -261,7 +259,7 @@ impl DataAvailabilityChecker { .kzg .as_ref() .ok_or(AvailabilityCheckError::KzgNotInitialized)?; - verify_kzg_for_blob_list(&blob_list, kzg) + verify_kzg_for_blob_list(blob_list.iter(), kzg) .map_err(AvailabilityCheckError::Kzg)?; Some(blob_list) } else { @@ -302,7 +300,7 @@ impl DataAvailabilityChecker { .kzg .as_ref() .ok_or(AvailabilityCheckError::KzgNotInitialized)?; - verify_kzg_for_blob_list(&all_blobs, kzg)?; + verify_kzg_for_blob_list(all_blobs.iter(), kzg)?; } for block in blocks { diff --git a/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs b/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs index 7997a2e5e36..290be988c33 100644 --- a/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs +++ b/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs @@ -414,10 +414,10 @@ impl OverflowLRUCache { } } - pub fn put_kzg_verified_blobs( + pub fn put_kzg_verified_blobs>>( &self, block_root: Hash256, - kzg_verified_blobs: Vec>, + kzg_verified_blobs: I, ) -> Result, AvailabilityCheckError> { let mut fixed_blobs = FixedVector::default();