feat: add blob count checks (#4447)

Co-authored-by: Dan Cline <6798349+Rjected@users.noreply.github.com>
This commit is contained in:
Matthias Seitz
2023-08-31 17:54:46 -07:00
committed by GitHub
parent 89bd024668
commit eb4126b78d
5 changed files with 72 additions and 8 deletions

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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
}
}
}
}

View File

@@ -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>;

View File

@@ -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,
)
}
}