feat(txpool): add gas limit check when inserting new transactions (#780)

* Add gas limit check when inserting transaction

Part of the code was copied from an issue comment:
https://github.com/paradigmxyz/reth/issues/76#issuecomment-1345281800

Co-authored-by: Eduardo <96149783+elprogramadorgt@users.noreply.github.com>

* Add test for gas limit check

Co-authored-by: Eduardo <96149783+elprogramadorgt@users.noreply.github.com>
This commit is contained in:
LambdaClass
2023-01-09 16:50:06 -03:00
committed by GitHub
parent 2b3dfe93a7
commit 7c9c2fea50
3 changed files with 45 additions and 2 deletions

View File

@ -21,6 +21,10 @@ pub enum PoolError {
/// respect the size limits of the pool.
#[error("[{0:?}] Transaction discarded outright due to pool size constraints.")]
DiscardedOnInsert(TxHash),
/// Thrown when a new transaction is added to the pool, but then immediately discarded to
/// respect the size limits of the pool.
#[error("[{0:?}] Transaction's gas limit {1} exceeds block's gas limit {2}.")]
TxExceedsGasLimit(TxHash, u64, u64),
}
// === impl PoolError ===
@ -33,6 +37,7 @@ impl PoolError {
PoolError::ProtocolFeeCapTooLow(hash, _) => hash,
PoolError::SpammerExceededCapacity(_, hash) => hash,
PoolError::DiscardedOnInsert(hash) => hash,
PoolError::TxExceedsGasLimit(hash, _, _) => hash,
}
}
}

View File

@ -256,6 +256,15 @@ impl<T: TransactionOrdering> TxPool<T> {
*transaction.hash(),
))
}
InsertErr::TxGasLimitMoreThanAvailableBlockGas {
transaction,
block_gas_limit,
tx_gas_limit,
} => Err(PoolError::TxExceedsGasLimit(
*transaction.hash(),
block_gas_limit,
tx_gas_limit,
)),
}
}
}
@ -770,6 +779,7 @@ impl<T: PoolTransaction> AllTransactions<T> {
/// This will enforce all additional rules in the context of this pool, such as:
/// - Spam protection: reject new non-local transaction from a sender that exhausted its slot
/// capacity.
/// - Gas limit: reject transactions if they exceed a block's maximum gas.
fn ensure_valid(
&self,
transaction: ValidPoolTransaction<T>,
@ -783,6 +793,13 @@ impl<T: PoolTransaction> AllTransactions<T> {
})
}
}
if transaction.gas_limit() > self.block_gas_limit {
return Err(InsertErr::TxGasLimitMoreThanAvailableBlockGas {
block_gas_limit: self.block_gas_limit,
tx_gas_limit: transaction.gas_limit(),
transaction: Arc::new(transaction),
})
}
Ok(transaction)
}
@ -1006,6 +1023,12 @@ pub(crate) enum InsertErr<T: PoolTransaction> {
///
/// The sender can be considered a spammer at this point.
ExceededSenderTransactionsCapacity { transaction: Arc<ValidPoolTransaction<T>> },
/// Transaction gas limit exceeds block's gas limit
TxGasLimitMoreThanAvailableBlockGas {
transaction: Arc<ValidPoolTransaction<T>>,
block_gas_limit: u64,
tx_gas_limit: u64,
},
}
/// Transaction was successfully inserted into the pool
@ -1340,4 +1363,19 @@ mod tests {
)
.unwrap();
}
#[test]
fn reject_tx_over_gas_limit() {
let on_chain_balance = U256::from(1_000);
let on_chain_nonce = 0;
let mut f = MockTransactionFactory::default();
let mut pool = AllTransactions::default();
let tx = MockTransaction::eip1559().with_gas_limit(30_000_001);
assert!(matches!(
pool.insert_tx(f.validated(tx), on_chain_balance, on_chain_nonce),
Err(InsertErr::TxGasLimitMoreThanAvailableBlockGas { .. })
));
}
}

View File

@ -56,7 +56,7 @@ pub trait TransactionValidator: Send + Sync {
) -> TransactionValidationOutcome<Self::Transaction>;
}
/// A valida transaction in the pool.
/// A valid transaction in the pool.
pub struct ValidPoolTransaction<T: PoolTransaction> {
/// The transaction
pub transaction: T,
@ -64,7 +64,7 @@ pub struct ValidPoolTransaction<T: PoolTransaction> {
pub transaction_id: TransactionId,
/// Whether to propagate the transaction.
pub propagate: bool,
/// Total cost of the transaction: `feeCap x gasLimit + transferred_value`.
/// Total cost of the transaction: `feeCap x gasLimit + transferredValue`.
pub cost: U256,
/// Timestamp when this was added to the pool.
pub timestamp: Instant,