From 2801e686f1e5ab42f3190c20d1a002c4854fb8cf Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Thu, 24 Aug 2023 16:15:28 +0200 Subject: [PATCH] chore: add TxEip4844::validate_blob (#4345) --- crates/primitives/src/transaction/eip4844.rs | 104 ++++++++++--------- 1 file changed, 57 insertions(+), 47 deletions(-) diff --git a/crates/primitives/src/transaction/eip4844.rs b/crates/primitives/src/transaction/eip4844.rs index 3db0bd36a1c6..b569b3a4070d 100644 --- a/crates/primitives/src/transaction/eip4844.rs +++ b/crates/primitives/src/transaction/eip4844.rs @@ -105,6 +105,61 @@ impl TxEip4844 { } } + /// Verifies that the given blob data, commitments, and proofs are all valid for this + /// transaction. + /// + /// Takes as input the [KzgSettings], which should contain the the parameters derived from the + /// KZG trusted setup. + /// + /// This ensures that the blob transaction payload has the same number of blob data elements, + /// commitments, and proofs. Each blob data element is verified against its commitment and + /// proof. + /// + /// Returns `false` if any blob KZG proof in the response fails to verify, or if the versioned + /// hashes in the transaction do not match the actual commitment versioned hashes. + pub fn validate_blob( + &self, + sidecar: &BlobTransactionSidecar, + proof_settings: &KzgSettings, + ) -> Result { + // Ensure the versioned hashes and commitments have the same length + if self.blob_versioned_hashes.len() != sidecar.commitments.len() { + return Err(kzg::Error::MismatchLength(format!( + "There are {} versioned commitment hashes and {} commitments", + self.blob_versioned_hashes.len(), + sidecar.commitments.len() + )) + .into()) + } + + // zip and iterate, calculating versioned hashes + for (versioned_hash, commitment) in + self.blob_versioned_hashes.iter().zip(sidecar.commitments.iter()) + { + // convert to KzgCommitment + let commitment = KzgCommitment::from(*commitment.deref()); + + // Calculate the versioned hash + // + // TODO: should this method distinguish the type of validation failure? For example + // whether a certain versioned hash does not match, or whether the blob proof + // validation failed? + let calculated_versioned_hash = kzg_to_versioned_hash(commitment); + if *versioned_hash != calculated_versioned_hash { + return Ok(false) + } + } + + // Verify as a batch + KzgProof::verify_blob_kzg_proof_batch( + sidecar.blobs.as_slice(), + sidecar.commitments.as_slice(), + sidecar.proofs.as_slice(), + proof_settings, + ) + .map_err(Into::into) + } + /// Returns the total gas for all blobs in this transaction. #[inline] pub fn blob_gas(&self) -> u64 { @@ -308,57 +363,12 @@ impl BlobTransaction { /// Verifies that the transaction's blob data, commitments, and proofs are all valid. /// - /// Takes as input the [KzgSettings], which should contain the the parameters derived from the - /// KZG trusted setup. - /// - /// This ensures that the blob transaction payload has the same number of blob data elements, - /// commitments, and proofs. Each blob data element is verified against its commitment and - /// proof. - /// - /// Returns `false` if any blob KZG proof in the response fails to verify, or if the versioned - /// hashes in the transaction do not match the actual commitment versioned hashes. + /// See also [TxEip4844::validate_blob] pub fn validate( &self, proof_settings: &KzgSettings, ) -> Result { - let inner_tx = &self.transaction; - - // Ensure the versioned hashes and commitments have the same length - if inner_tx.blob_versioned_hashes.len() != self.sidecar.commitments.len() { - return Err(kzg::Error::MismatchLength(format!( - "There are {} versioned commitment hashes and {} commitments", - inner_tx.blob_versioned_hashes.len(), - self.sidecar.commitments.len() - )) - .into()) - } - - // zip and iterate, calculating versioned hashes - for (versioned_hash, commitment) in - inner_tx.blob_versioned_hashes.iter().zip(self.sidecar.commitments.iter()) - { - // convert to KzgCommitment - let commitment = KzgCommitment::from(*commitment.deref()); - - // Calculate the versioned hash - // - // TODO: should this method distinguish the type of validation failure? For example - // whether a certain versioned hash does not match, or whether the blob proof - // validation failed? - let calculated_versioned_hash = kzg_to_versioned_hash(commitment); - if *versioned_hash != calculated_versioned_hash { - return Ok(false) - } - } - - // Verify as a batch - KzgProof::verify_blob_kzg_proof_batch( - self.sidecar.blobs.as_slice(), - self.sidecar.commitments.as_slice(), - self.sidecar.proofs.as_slice(), - proof_settings, - ) - .map_err(Into::into) + self.transaction.validate_blob(&self.sidecar, proof_settings) } /// Splits the [BlobTransaction] into its [TransactionSigned] and [BlobTransactionSidecar]