Batch Verify RPC Blobs (#4934)

This commit is contained in:
ethDreamer 2023-12-08 15:48:03 -06:00 committed by GitHub
parent 46184e5ce4
commit 78ffa378b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 22 deletions

View File

@ -17,8 +17,7 @@ use ssz_types::VariableList;
use tree_hash::TreeHash; use tree_hash::TreeHash;
use types::blob_sidecar::BlobIdentifier; use types::blob_sidecar::BlobIdentifier;
use types::{ use types::{
BeaconStateError, BlobSidecar, BlobSidecarList, CloneConfig, EthSpec, Hash256, BeaconStateError, BlobSidecar, CloneConfig, EthSpec, Hash256, SignedBeaconBlockHeader, Slot,
SignedBeaconBlockHeader, Slot,
}; };
/// An error occurred while validating a gossip blob. /// An error occurred while validating a gossip blob.
@ -279,7 +278,6 @@ impl<T: EthSpec> KzgVerifiedBlob<T> {
pub fn new(blob: Arc<BlobSidecar<T>>, kzg: &Kzg) -> Result<Self, KzgError> { pub fn new(blob: Arc<BlobSidecar<T>>, kzg: &Kzg) -> Result<Self, KzgError> {
verify_kzg_for_blob(blob, kzg) verify_kzg_for_blob(blob, kzg)
} }
pub fn to_blob(self) -> Arc<BlobSidecar<T>> { pub fn to_blob(self) -> Arc<BlobSidecar<T>> {
self.blob self.blob
} }
@ -310,21 +308,51 @@ pub fn verify_kzg_for_blob<T: EthSpec>(
kzg: &Kzg, kzg: &Kzg,
) -> Result<KzgVerifiedBlob<T>, KzgError> { ) -> Result<KzgVerifiedBlob<T>, KzgError> {
validate_blob::<T>(kzg, &blob.blob, blob.kzg_commitment, blob.kzg_proof)?; validate_blob::<T>(kzg, &blob.blob, blob.kzg_commitment, blob.kzg_proof)?;
Ok(KzgVerifiedBlob { blob }) Ok(KzgVerifiedBlob { blob })
} }
pub struct KzgVerifiedBlobList<E: EthSpec> {
verified_blobs: Vec<KzgVerifiedBlob<E>>,
}
impl<E: EthSpec> KzgVerifiedBlobList<E> {
pub fn new<I: IntoIterator<Item = Arc<BlobSidecar<E>>>>(
blob_list: I,
kzg: &Kzg,
) -> Result<Self, KzgError> {
let blobs = blob_list.into_iter().collect::<Vec<_>>();
verify_kzg_for_blob_list(blobs.iter(), kzg)?;
Ok(Self {
verified_blobs: blobs
.into_iter()
.map(|blob| KzgVerifiedBlob { blob })
.collect(),
})
}
}
impl<E: EthSpec> IntoIterator for KzgVerifiedBlobList<E> {
type Item = KzgVerifiedBlob<E>;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.verified_blobs.into_iter()
}
}
/// Complete kzg verification for a list of `BlobSidecar`s. /// Complete kzg verification for a list of `BlobSidecar`s.
/// Returns an error if any of the `BlobSidecar`s fails kzg verification. /// Returns an error if any of the `BlobSidecar`s fails kzg verification.
/// ///
/// Note: This function should be preferred over calling `verify_kzg_for_blob` /// 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. /// in a loop since this function kzg verifies a list of blobs more efficiently.
pub fn verify_kzg_for_blob_list<T: EthSpec>( pub fn verify_kzg_for_blob_list<'a, T: EthSpec, I>(
blob_list: &BlobSidecarList<T>, blob_iter: I,
kzg: &Kzg, kzg: &'a Kzg,
) -> Result<(), KzgError> { ) -> Result<(), KzgError>
let (blobs, (commitments, proofs)): (Vec<_>, (Vec<_>, Vec<_>)) = blob_list where
.iter() I: Iterator<Item = &'a Arc<BlobSidecar<T>>>,
{
let (blobs, (commitments, proofs)): (Vec<_>, (Vec<_>, Vec<_>)) = blob_iter
.map(|blob| (&blob.blob, (blob.kzg_commitment, blob.kzg_proof))) .map(|blob| (&blob.blob, (blob.kzg_commitment, blob.kzg_proof)))
.unzip(); .unzip();
validate_blobs::<T>(kzg, commitments.as_slice(), blobs, proofs.as_slice()) validate_blobs::<T>(kzg, commitments.as_slice(), blobs, proofs.as_slice())

View File

@ -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::{ use crate::block_verification_types::{
AvailabilityPendingExecutedBlock, AvailableExecutedBlock, RpcBlock, AvailabilityPendingExecutedBlock, AvailableExecutedBlock, RpcBlock,
}; };
@ -197,15 +197,13 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
block_root: Hash256, block_root: Hash256,
blobs: FixedBlobSidecarList<T::EthSpec>, blobs: FixedBlobSidecarList<T::EthSpec>,
) -> Result<Availability<T::EthSpec>, AvailabilityCheckError> { ) -> Result<Availability<T::EthSpec>, AvailabilityCheckError> {
let mut verified_blobs = vec![]; let Some(kzg) = self.kzg.as_ref() else {
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 {
return Err(AvailabilityCheckError::KzgNotInitialized); return Err(AvailabilityCheckError::KzgNotInitialized);
}; };
let verified_blobs = KzgVerifiedBlobList::new(Vec::from(blobs).into_iter().flatten(), kzg)
.map_err(AvailabilityCheckError::Kzg)?;
self.availability_cache self.availability_cache
.put_kzg_verified_blobs(block_root, verified_blobs) .put_kzg_verified_blobs(block_root, verified_blobs)
} }
@ -261,7 +259,7 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
.kzg .kzg
.as_ref() .as_ref()
.ok_or(AvailabilityCheckError::KzgNotInitialized)?; .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)?; .map_err(AvailabilityCheckError::Kzg)?;
Some(blob_list) Some(blob_list)
} else { } else {
@ -302,7 +300,7 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
.kzg .kzg
.as_ref() .as_ref()
.ok_or(AvailabilityCheckError::KzgNotInitialized)?; .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 { for block in blocks {

View File

@ -414,10 +414,10 @@ impl<T: BeaconChainTypes> OverflowLRUCache<T> {
} }
} }
pub fn put_kzg_verified_blobs( pub fn put_kzg_verified_blobs<I: IntoIterator<Item = KzgVerifiedBlob<T::EthSpec>>>(
&self, &self,
block_root: Hash256, block_root: Hash256,
kzg_verified_blobs: Vec<KzgVerifiedBlob<T::EthSpec>>, kzg_verified_blobs: I,
) -> Result<Availability<T::EthSpec>, AvailabilityCheckError> { ) -> Result<Availability<T::EthSpec>, AvailabilityCheckError> {
let mut fixed_blobs = FixedVector::default(); let mut fixed_blobs = FixedVector::default();