mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-30 09:38:24 -05:00
feat: add blob count checks (#4447)
Co-authored-by: Dan Cline <6798349+Rjected@users.noreply.github.com>
This commit is contained in:
@@ -20,7 +20,7 @@ pub const MAX_DATA_GAS_PER_BLOCK: u64 = 786_432u64; // 0xC0000
|
||||
pub const TARGET_DATA_GAS_PER_BLOCK: u64 = 393_216u64; // 0x60000
|
||||
|
||||
/// Maximum number of data blobs in a single block.
|
||||
pub const MAX_BLOBS_PER_BLOCK: u64 = MAX_DATA_GAS_PER_BLOCK / DATA_GAS_PER_BLOB; // 786432 / 131072 = 6
|
||||
pub const MAX_BLOBS_PER_BLOCK: usize = (MAX_DATA_GAS_PER_BLOCK / DATA_GAS_PER_BLOB) as usize; // 786432 / 131072 = 6
|
||||
|
||||
/// Target number of data blobs in a single block.
|
||||
pub const TARGET_BLOBS_PER_BLOCK: u64 = TARGET_DATA_GAS_PER_BLOCK / DATA_GAS_PER_BLOB; // 393216 / 131072 = 3
|
||||
|
||||
@@ -473,8 +473,19 @@ pub enum RpcPoolError {
|
||||
#[error("{0:?}")]
|
||||
PoolTransactionError(Box<dyn PoolTransactionError>),
|
||||
/// Unable to find the blob for an EIP4844 transaction
|
||||
#[error("blob not found for EIP4844 transaction")]
|
||||
#[error("blob sidecar not found for EIP4844 transaction")]
|
||||
MissingEip4844Blob,
|
||||
/// Thrown if an EIP-4844 without any blobs arrives
|
||||
#[error("blobless blob transaction")]
|
||||
NoEip4844Blobs,
|
||||
/// Thrown if an EIP-4844 without any blobs arrives
|
||||
#[error("too many blobs in transaction: have {have}, permitted {permitted}")]
|
||||
TooManyEip4844Blobs {
|
||||
/// Number of blobs the transaction has
|
||||
have: usize,
|
||||
/// Number of maximum blobs the transaction can have
|
||||
permitted: usize,
|
||||
},
|
||||
/// Thrown if validating the blob sidecar for the transaction failed.
|
||||
#[error(transparent)]
|
||||
InvalidEip4844Blob(BlobTransactionValidationError),
|
||||
@@ -516,7 +527,13 @@ impl From<InvalidPoolTransactionError> for RpcPoolError {
|
||||
InvalidPoolTransactionError::OversizedData(_, _) => RpcPoolError::OversizedData,
|
||||
InvalidPoolTransactionError::Underpriced => RpcPoolError::Underpriced,
|
||||
InvalidPoolTransactionError::Other(err) => RpcPoolError::PoolTransactionError(err),
|
||||
InvalidPoolTransactionError::MissingEip4844Blob => RpcPoolError::MissingEip4844Blob,
|
||||
InvalidPoolTransactionError::MissingEip4844BlobSidecar => {
|
||||
RpcPoolError::MissingEip4844Blob
|
||||
}
|
||||
InvalidPoolTransactionError::NoEip4844Blobs => RpcPoolError::NoEip4844Blobs,
|
||||
InvalidPoolTransactionError::TooManyEip4844Blobs { have, permitted } => {
|
||||
RpcPoolError::TooManyEip4844Blobs { have, permitted }
|
||||
}
|
||||
InvalidPoolTransactionError::InvalidEip4844Blob(err) => {
|
||||
RpcPoolError::InvalidEip4844Blob(err)
|
||||
}
|
||||
|
||||
@@ -139,8 +139,19 @@ pub enum InvalidPoolTransactionError {
|
||||
#[error("transaction underpriced")]
|
||||
Underpriced,
|
||||
/// Thrown if we're unable to find the blob for a transaction that was previously extracted
|
||||
#[error("blob not found for EIP4844 transaction")]
|
||||
MissingEip4844Blob,
|
||||
#[error("blob sidecar not found for EIP4844 transaction")]
|
||||
MissingEip4844BlobSidecar,
|
||||
/// Thrown if an EIP-4844 without any blobs arrives
|
||||
#[error("blobless blob transaction")]
|
||||
NoEip4844Blobs,
|
||||
/// Thrown if an EIP-4844 without any blobs arrives
|
||||
#[error("too many blobs in transaction: have {have}, permitted {permitted}")]
|
||||
TooManyEip4844Blobs {
|
||||
/// Number of blobs the transaction has
|
||||
have: usize,
|
||||
/// Number of maximum blobs the transaction can have
|
||||
permitted: usize,
|
||||
},
|
||||
/// Thrown if validating the blob sidecar for the transaction failed.
|
||||
#[error(transparent)]
|
||||
InvalidEip4844Blob(BlobTransactionValidationError),
|
||||
@@ -209,7 +220,7 @@ impl InvalidPoolTransactionError {
|
||||
false
|
||||
}
|
||||
InvalidPoolTransactionError::Other(err) => err.is_bad_transaction(),
|
||||
InvalidPoolTransactionError::MissingEip4844Blob => {
|
||||
InvalidPoolTransactionError::MissingEip4844BlobSidecar => {
|
||||
// this is only reachable when blob transactions are reinjected and we're unable to
|
||||
// find the previously extracted blob
|
||||
false
|
||||
@@ -223,6 +234,14 @@ impl InvalidPoolTransactionError {
|
||||
// thrown for valid(good) blob transactions
|
||||
false
|
||||
}
|
||||
InvalidPoolTransactionError::NoEip4844Blobs => {
|
||||
// this is a malformed transaction and should not be sent over the network
|
||||
true
|
||||
}
|
||||
InvalidPoolTransactionError::TooManyEip4844Blobs { .. } => {
|
||||
// this is a malformed transaction and should not be sent over the network
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -666,6 +666,11 @@ pub trait EthPoolTransaction: PoolTransaction {
|
||||
/// Extracts the blob sidecar from the transaction.
|
||||
fn take_blob(&mut self) -> EthBlobTransactionSidecar;
|
||||
|
||||
/// Returns the number of blobs this transaction has.
|
||||
fn blob_count(&self) -> usize {
|
||||
self.as_eip4844().map(|tx| tx.blob_versioned_hashes.len()).unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Returns the transaction as EIP-4844 transaction if it is one.
|
||||
fn as_eip4844(&self) -> Option<&TxEip4844>;
|
||||
|
||||
|
||||
@@ -9,7 +9,10 @@ use crate::{
|
||||
TransactionValidationTaskExecutor, TransactionValidator,
|
||||
};
|
||||
use reth_primitives::{
|
||||
constants::{eip4844::MAINNET_KZG_TRUSTED_SETUP, ETHEREUM_BLOCK_GAS_LIMIT},
|
||||
constants::{
|
||||
eip4844::{MAINNET_KZG_TRUSTED_SETUP, MAX_BLOBS_PER_BLOCK},
|
||||
ETHEREUM_BLOCK_GAS_LIMIT,
|
||||
},
|
||||
kzg::KzgSettings,
|
||||
ChainSpec, InvalidTransactionError, SealedBlock, EIP1559_TX_TYPE_ID, EIP2930_TX_TYPE_ID,
|
||||
EIP4844_TX_TYPE_ID, LEGACY_TX_TYPE_ID,
|
||||
@@ -209,6 +212,26 @@ where
|
||||
)
|
||||
}
|
||||
|
||||
let blob_count = transaction.blob_count();
|
||||
if blob_count == 0 {
|
||||
// no blobs
|
||||
return TransactionValidationOutcome::Invalid(
|
||||
transaction,
|
||||
InvalidPoolTransactionError::NoEip4844Blobs,
|
||||
)
|
||||
}
|
||||
|
||||
if blob_count > MAX_BLOBS_PER_BLOCK {
|
||||
// too many blobs
|
||||
return TransactionValidationOutcome::Invalid(
|
||||
transaction,
|
||||
InvalidPoolTransactionError::TooManyEip4844Blobs {
|
||||
have: blob_count,
|
||||
permitted: MAX_BLOBS_PER_BLOCK,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// extract the blob from the transaction
|
||||
match transaction.take_blob() {
|
||||
EthBlobTransactionSidecar::None => {
|
||||
@@ -224,7 +247,7 @@ where
|
||||
} else {
|
||||
return TransactionValidationOutcome::Invalid(
|
||||
transaction,
|
||||
InvalidPoolTransactionError::MissingEip4844Blob,
|
||||
InvalidPoolTransactionError::MissingEip4844BlobSidecar,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user