Batch Verify RPC Blobs (#4934)
This commit is contained in:
parent
46184e5ce4
commit
78ffa378b4
@ -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())
|
||||||
|
@ -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 {
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user