Skip to content

Commit

Permalink
fix(derive): inline blob verification into the blob provider (#175)
Browse files Browse the repository at this point in the history
  • Loading branch information
refcell authored May 7, 2024
1 parent bd7ac13 commit 016f452
Show file tree
Hide file tree
Showing 7 changed files with 248 additions and 272 deletions.
287 changes: 162 additions & 125 deletions crates/derive/src/online/blob_provider.rs

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions crates/derive/src/online/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,3 @@ pub use alloy_providers::{AlloyChainProvider, AlloyL2ChainProvider};

mod blob_provider;
pub use blob_provider::{OnlineBlobProvider, SimpleSlotDerivation};

mod utils;
pub(crate) use utils::blobs_from_sidecars;
140 changes: 0 additions & 140 deletions crates/derive/src/online/utils.rs

This file was deleted.

6 changes: 5 additions & 1 deletion crates/derive/src/sources/blobs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,11 @@ where
return Ok(());
}

let blobs = self.blob_fetcher.get_blobs(&self.block_ref, blob_hashes).await?;
let blobs =
self.blob_fetcher.get_blobs(&self.block_ref, &blob_hashes).await.map_err(|e| {
warn!("Failed to fetch blobs: {e}");
anyhow::anyhow!("Failed to fetch blobs: {e}")
})?;

// Fill the blob pointers.
let mut blob_index = 0;
Expand Down
6 changes: 3 additions & 3 deletions crates/derive/src/traits/data_sources.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Contains traits that describe the functionality of various data sources used in the derivation
//! pipeline's stages.
use crate::types::{Blob, BlockInfo, IndexedBlobHash, StageResult};
use crate::types::{Blob, BlobProviderError, BlockInfo, IndexedBlobHash, StageResult};
use alloc::{boxed::Box, fmt::Debug, vec::Vec};
use alloy_primitives::{Address, Bytes};
use anyhow::Result;
Expand All @@ -14,8 +14,8 @@ pub trait BlobProvider {
async fn get_blobs(
&mut self,
block_ref: &BlockInfo,
blob_hashes: Vec<IndexedBlobHash>,
) -> Result<Vec<Blob>>;
blob_hashes: &[IndexedBlobHash],
) -> Result<Vec<Blob>, BlobProviderError>;
}

/// Describes the functionality of a data source that can provide data availability information.
Expand Down
41 changes: 41 additions & 0 deletions crates/derive/src/types/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,47 @@ impl Display for StageError {
}
}

/// An error returned by the [BlobProviderError].
#[derive(Debug)]
pub enum BlobProviderError {
/// The number of specified blob hashes did not match the number of returned sidecars.
SidecarLengthMismatch(usize, usize),
/// Slot derivation error.
Slot(anyhow::Error),
/// A custom [anyhow::Error] occurred.
Custom(anyhow::Error),
}

impl PartialEq for BlobProviderError {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::SidecarLengthMismatch(a, b), Self::SidecarLengthMismatch(c, d)) => {
a == c && b == d
}
(Self::Slot(_), Self::Slot(_)) | (Self::Custom(_), Self::Custom(_)) => true,
_ => false,
}
}
}

impl Display for BlobProviderError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::SidecarLengthMismatch(a, b) => write!(f, "expected {} sidecars but got {}", a, b),
Self::Slot(e) => {
write!(f, "Slot Derivation Error: {}", e)
}
Self::Custom(err) => write!(f, "{}", err),
}
}
}

impl From<anyhow::Error> for BlobProviderError {
fn from(err: anyhow::Error) -> Self {
Self::Custom(err)
}
}

/// A reset error
#[derive(Debug)]
pub enum ResetError {
Expand Down
37 changes: 37 additions & 0 deletions crates/derive/src/types/sidecar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
use crate::types::Blob;
use alloc::{string::String, vec::Vec};
use alloy_primitives::FixedBytes;

#[cfg(feature = "online")]
use crate::types::IndexedBlobHash;
#[cfg(feature = "online")]
use alloy_primitives::B256;
#[cfg(feature = "online")]
use c_kzg::{Bytes48, KzgProof, KzgSettings};
#[cfg(feature = "online")]
Expand Down Expand Up @@ -37,6 +42,7 @@ where
{
String::deserialize(de)?.parse().map_err(serde::de::Error::custom)
}

/// A blob sidecar.
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
Expand All @@ -55,6 +61,37 @@ pub struct BlobSidecar {
}

impl BlobSidecar {
/// Verify the blob sidecar against it's [IndexedBlobHash].
#[cfg(feature = "online")]
pub fn verify_blob(&self, hash: &IndexedBlobHash) -> anyhow::Result<()> {
if self.index as usize != hash.index {
return Err(anyhow::anyhow!(
"invalid sidecar ordering, blob hash index {} does not match sidecar index {}",
hash.index,
self.index
));
}

// Ensure the blob's kzg commitment hashes to the expected value.
if self.to_kzg_versioned_hash() != hash.hash {
return Err(anyhow::anyhow!(
"expected hash {} for blob at index {} but got {}",
hash.hash,
hash.index,
B256::from(self.to_kzg_versioned_hash())
));
}

// Confirm blob data is valid by verifying its proof against the commitment
match self.verify_blob_kzg_proof() {
Ok(true) => Ok(()),
Ok(false) => Err(anyhow::anyhow!("blob at index {} failed verification", self.index)),
Err(e) => {
Err(anyhow::anyhow!("blob at index {} failed verification: {}", self.index, e))
}
}
}

/// Verifies the blob kzg proof.
#[cfg(feature = "online")]
pub fn verify_blob_kzg_proof(&self) -> anyhow::Result<bool> {
Expand Down

0 comments on commit 016f452

Please sign in to comment.