From 50ba82803d40b70e4fd9fc2c0510e2d5db072d74 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Fri, 25 Aug 2023 04:51:23 +0200 Subject: [PATCH] feat: add validate-blob to extension trait (#4355) --- crates/primitives/src/lib.rs | 10 +++---- crates/primitives/src/transaction/eip4844.rs | 30 ++++++++++++++------ crates/primitives/src/transaction/mod.rs | 4 ++- crates/transaction-pool/src/traits.rs | 28 +++++++++++++++--- 4 files changed, 53 insertions(+), 19 deletions(-) diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 22435f436b..ffbc27a171 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -91,11 +91,11 @@ pub use storage::StorageEntry; pub use transaction::{ util::secp256k1::{public_key_to_address, recover_signer, sign_message}, AccessList, AccessListItem, AccessListWithGasUsed, BlobTransaction, BlobTransactionSidecar, - FromRecoveredPooledTransaction, FromRecoveredTransaction, IntoRecoveredTransaction, - InvalidTransactionError, PooledTransactionsElement, PooledTransactionsElementEcRecovered, - Signature, Transaction, TransactionKind, TransactionMeta, TransactionSigned, - TransactionSignedEcRecovered, TransactionSignedNoHash, TxEip1559, TxEip2930, TxEip4844, - TxLegacy, TxType, EIP1559_TX_TYPE_ID, EIP2930_TX_TYPE_ID, EIP4844_TX_TYPE_ID, + BlobTransactionValidationError, FromRecoveredPooledTransaction, FromRecoveredTransaction, + IntoRecoveredTransaction, InvalidTransactionError, PooledTransactionsElement, + PooledTransactionsElementEcRecovered, Signature, Transaction, TransactionKind, TransactionMeta, + TransactionSigned, TransactionSignedEcRecovered, TransactionSignedNoHash, TxEip1559, TxEip2930, + TxEip4844, TxLegacy, TxType, EIP1559_TX_TYPE_ID, EIP2930_TX_TYPE_ID, EIP4844_TX_TYPE_ID, LEGACY_TX_TYPE_ID, }; pub use withdrawal::Withdrawal; diff --git a/crates/primitives/src/transaction/eip4844.rs b/crates/primitives/src/transaction/eip4844.rs index b569b3a407..1278e75e3b 100644 --- a/crates/primitives/src/transaction/eip4844.rs +++ b/crates/primitives/src/transaction/eip4844.rs @@ -115,13 +115,14 @@ impl TxEip4844 { /// 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. + /// Returns [BlobTransactionValidationError::InvalidProof] 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 { + ) -> Result<(), BlobTransactionValidationError> { // 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!( @@ -146,18 +147,24 @@ impl TxEip4844 { // validation failed? let calculated_versioned_hash = kzg_to_versioned_hash(commitment); if *versioned_hash != calculated_versioned_hash { - return Ok(false) + return Err(BlobTransactionValidationError::InvalidProof) } } // Verify as a batch - KzgProof::verify_blob_kzg_proof_batch( + let res = KzgProof::verify_blob_kzg_proof_batch( sidecar.blobs.as_slice(), sidecar.commitments.as_slice(), sidecar.proofs.as_slice(), proof_settings, ) - .map_err(Into::into) + .map_err(BlobTransactionValidationError::KZGError)?; + + if res { + Ok(()) + } else { + Err(BlobTransactionValidationError::InvalidProof) + } } /// Returns the total gas for all blobs in this transaction. @@ -307,12 +314,17 @@ impl TxEip4844 { } /// An error that can occur when validating a [BlobTransaction]. -#[derive(Debug)] +#[derive(Debug, thiserror::Error)] pub enum BlobTransactionValidationError { + /// Proof validation failed. + #[error("invalid kzg proof")] + InvalidProof, /// An error returned by the [kzg] library + #[error("kzg error: {0:?}")] KZGError(kzg::Error), /// The inner transaction is not a blob transaction - NotBlobTransaction(TxType), + #[error("unable to verify proof for non blob transaction: {0}")] + NotBlobTransaction(u8), } impl From for BlobTransactionValidationError { @@ -367,7 +379,7 @@ impl BlobTransaction { pub fn validate( &self, proof_settings: &KzgSettings, - ) -> Result { + ) -> Result<(), BlobTransactionValidationError> { self.transaction.validate_blob(&self.sidecar, proof_settings) } diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs index 97afe6c79a..bce71de9a0 100644 --- a/crates/primitives/src/transaction/mod.rs +++ b/crates/primitives/src/transaction/mod.rs @@ -20,7 +20,9 @@ pub use tx_type::{ pub use eip1559::TxEip1559; pub use eip2930::TxEip2930; -pub use eip4844::{BlobTransaction, BlobTransactionSidecar, TxEip4844}; +pub use eip4844::{ + BlobTransaction, BlobTransactionSidecar, BlobTransactionValidationError, TxEip4844, +}; pub use legacy::TxLegacy; pub use pooled::{PooledTransactionsElement, PooledTransactionsElementEcRecovered}; diff --git a/crates/transaction-pool/src/traits.rs b/crates/transaction-pool/src/traits.rs index 7540a6340f..7ad245b7fe 100644 --- a/crates/transaction-pool/src/traits.rs +++ b/crates/transaction-pool/src/traits.rs @@ -6,10 +6,11 @@ use crate::{ }; use futures_util::{ready, Stream}; use reth_primitives::{ - Address, BlobTransactionSidecar, FromRecoveredPooledTransaction, FromRecoveredTransaction, - IntoRecoveredTransaction, PeerId, PooledTransactionsElement, - PooledTransactionsElementEcRecovered, SealedBlock, Transaction, TransactionKind, - TransactionSignedEcRecovered, TxHash, EIP1559_TX_TYPE_ID, EIP4844_TX_TYPE_ID, H256, U256, + Address, BlobTransactionSidecar, BlobTransactionValidationError, + FromRecoveredPooledTransaction, FromRecoveredTransaction, IntoRecoveredTransaction, PeerId, + PooledTransactionsElement, PooledTransactionsElementEcRecovered, SealedBlock, Transaction, + TransactionKind, TransactionSignedEcRecovered, TxHash, EIP1559_TX_TYPE_ID, EIP4844_TX_TYPE_ID, + H256, U256, }; use reth_rlp::Encodable; use std::{ @@ -22,6 +23,7 @@ use std::{ use tokio::sync::mpsc::Receiver; use crate::blobstore::BlobStoreError; +use reth_primitives::kzg::KzgSettings; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -645,6 +647,13 @@ pub trait PoolTransaction: pub trait EthPoolTransaction: PoolTransaction { /// Extracts the blob sidecar from the transaction. fn take_blob(&mut self) -> EthBlobTransactionSidecar; + + /// Validates the blob sidecar of the transaction with the given settings. + fn validate_blob( + &self, + blob: &BlobTransactionSidecar, + settings: &KzgSettings, + ) -> Result<(), BlobTransactionValidationError>; } /// The default [PoolTransaction] for the [Pool](crate::Pool) for Ethereum. @@ -827,6 +836,17 @@ impl EthPoolTransaction for EthPooledTransaction { EthBlobTransactionSidecar::None } } + + fn validate_blob( + &self, + sidecar: &BlobTransactionSidecar, + settings: &KzgSettings, + ) -> Result<(), BlobTransactionValidationError> { + match &self.transaction.transaction { + Transaction::Eip4844(tx) => tx.validate_blob(sidecar, settings), + _ => Err(BlobTransactionValidationError::NotBlobTransaction(self.tx_type())), + } + } } impl FromRecoveredTransaction for EthPooledTransaction {