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 pub const TARGET_DATA_GAS_PER_BLOCK: u64 = 393_216u64; // 0x60000
/// Maximum number of data blobs in a single block. /// 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. /// 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 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:?}")] #[error("{0:?}")]
PoolTransactionError(Box<dyn PoolTransactionError>), PoolTransactionError(Box<dyn PoolTransactionError>),
/// Unable to find the blob for an EIP4844 transaction /// 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, 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. /// Thrown if validating the blob sidecar for the transaction failed.
#[error(transparent)] #[error(transparent)]
InvalidEip4844Blob(BlobTransactionValidationError), InvalidEip4844Blob(BlobTransactionValidationError),
@ -516,7 +527,13 @@ impl From<InvalidPoolTransactionError> for RpcPoolError {
InvalidPoolTransactionError::OversizedData(_, _) => RpcPoolError::OversizedData, InvalidPoolTransactionError::OversizedData(_, _) => RpcPoolError::OversizedData,
InvalidPoolTransactionError::Underpriced => RpcPoolError::Underpriced, InvalidPoolTransactionError::Underpriced => RpcPoolError::Underpriced,
InvalidPoolTransactionError::Other(err) => RpcPoolError::PoolTransactionError(err), 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) => { InvalidPoolTransactionError::InvalidEip4844Blob(err) => {
RpcPoolError::InvalidEip4844Blob(err) RpcPoolError::InvalidEip4844Blob(err)
} }

View File

@ -139,8 +139,19 @@ pub enum InvalidPoolTransactionError {
#[error("transaction underpriced")] #[error("transaction underpriced")]
Underpriced, Underpriced,
/// Thrown if we're unable to find the blob for a transaction that was previously extracted /// Thrown if we're unable to find the blob for a transaction that was previously extracted
#[error("blob not found for EIP4844 transaction")] #[error("blob sidecar not found for EIP4844 transaction")]
MissingEip4844Blob, 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. /// Thrown if validating the blob sidecar for the transaction failed.
#[error(transparent)] #[error(transparent)]
InvalidEip4844Blob(BlobTransactionValidationError), InvalidEip4844Blob(BlobTransactionValidationError),
@ -209,7 +220,7 @@ impl InvalidPoolTransactionError {
false false
} }
InvalidPoolTransactionError::Other(err) => err.is_bad_transaction(), 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 // this is only reachable when blob transactions are reinjected and we're unable to
// find the previously extracted blob // find the previously extracted blob
false false
@ -223,6 +234,14 @@ impl InvalidPoolTransactionError {
// thrown for valid(good) blob transactions // thrown for valid(good) blob transactions
false 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. /// Extracts the blob sidecar from the transaction.
fn take_blob(&mut self) -> EthBlobTransactionSidecar; 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. /// Returns the transaction as EIP-4844 transaction if it is one.
fn as_eip4844(&self) -> Option<&TxEip4844>; fn as_eip4844(&self) -> Option<&TxEip4844>;

View File

@ -9,7 +9,10 @@ use crate::{
TransactionValidationTaskExecutor, TransactionValidator, TransactionValidationTaskExecutor, TransactionValidator,
}; };
use reth_primitives::{ 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, kzg::KzgSettings,
ChainSpec, InvalidTransactionError, SealedBlock, EIP1559_TX_TYPE_ID, EIP2930_TX_TYPE_ID, ChainSpec, InvalidTransactionError, SealedBlock, EIP1559_TX_TYPE_ID, EIP2930_TX_TYPE_ID,
EIP4844_TX_TYPE_ID, LEGACY_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 // extract the blob from the transaction
match transaction.take_blob() { match transaction.take_blob() {
EthBlobTransactionSidecar::None => { EthBlobTransactionSidecar::None => {
@ -224,7 +247,7 @@ where
} else { } else {
return TransactionValidationOutcome::Invalid( return TransactionValidationOutcome::Invalid(
transaction, transaction,
InvalidPoolTransactionError::MissingEip4844Blob, InvalidPoolTransactionError::MissingEip4844BlobSidecar,
) )
} }
} }