Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: re-enable evm tests #5079

Merged
merged 1 commit into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions crates/edr_evm/src/mempool.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{cmp::Ordering, fmt::Debug};
use std::{cmp::Ordering, fmt::Debug, num::NonZeroU64};

use edr_eth::{Address, B256, U256};
use indexmap::{map::Entry, IndexMap};
Expand Down Expand Up @@ -84,7 +84,7 @@ pub enum MemPoolAddTransactionError<SE> {
#[error("Transaction gas limit is {transaction_gas_limit} and exceeds block gas limit of {block_gas_limit}")]
ExceedsBlockGasLimit {
/// The block gas limit
block_gas_limit: u64,
block_gas_limit: NonZeroU64,
/// The transaction gas limit
transaction_gas_limit: u64,
},
Expand Down Expand Up @@ -166,7 +166,7 @@ impl OrderedTransaction {
#[derive(Clone, Debug)]
pub struct MemPool {
/// The block's gas limit
block_gas_limit: u64,
block_gas_limit: NonZeroU64,
/// Transactions that can be executed now
pending_transactions: IndexMap<Address, Vec<OrderedTransaction>>,
/// Mapping of transaction hashes to transaction
Expand All @@ -179,7 +179,7 @@ pub struct MemPool {

impl MemPool {
/// Constructs a new [`MemPool`] with the specified block gas limit.
pub fn new(block_gas_limit: u64) -> Self {
pub fn new(block_gas_limit: NonZeroU64) -> Self {
Self {
block_gas_limit,
pending_transactions: IndexMap::new(),
Expand All @@ -190,12 +190,12 @@ impl MemPool {
}

/// Retrieves the instance's block gas limit.
pub fn block_gas_limit(&self) -> u64 {
pub fn block_gas_limit(&self) -> NonZeroU64 {
self.block_gas_limit
}

/// Sets the instance's block gas limit.
pub fn set_block_gas_limit<S>(&mut self, state: &S, limit: u64) -> Result<(), S::Error>
pub fn set_block_gas_limit<S>(&mut self, state: &S, limit: NonZeroU64) -> Result<(), S::Error>
where
S: StateRef + ?Sized,
S::Error: Debug,
Expand Down Expand Up @@ -270,7 +270,7 @@ impl MemPool {
transaction: ExecutableTransaction,
) -> Result<(), MemPoolAddTransactionError<S::Error>> {
let transaction_gas_limit = transaction.gas_limit();
if transaction_gas_limit > self.block_gas_limit {
if transaction_gas_limit > self.block_gas_limit.get() {
return Err(MemPoolAddTransactionError::ExceedsBlockGasLimit {
block_gas_limit: self.block_gas_limit,
transaction_gas_limit,
Expand Down Expand Up @@ -380,10 +380,10 @@ impl MemPool {
{
fn is_valid_tx(
transaction: &ExecutableTransaction,
block_gas_limit: u64,
block_gas_limit: NonZeroU64,
sender: &AccountInfo,
) -> bool {
transaction.gas_limit() <= block_gas_limit
transaction.gas_limit() <= block_gas_limit.get()
&& transaction.upfront_cost() <= sender.balance
// Remove all mined transactions
&& transaction.nonce() >= sender.nonce
Expand Down
7 changes: 5 additions & 2 deletions crates/edr_evm/src/test_utils.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::num::NonZeroU64;

use edr_eth::{
transaction::{Eip1559TransactionRequest, Eip155TransactionRequest, TransactionKind},
AccountInfo, Address, Bytes, HashMap, SpecId, U256,
Expand All @@ -23,7 +25,8 @@ impl MemPoolTestFixture {
let trie = AccountTrie::with_accounts(&accounts);

MemPoolTestFixture {
mem_pool: MemPool::new(10_000_000u64),
// SAFETY: literal is non-zero
mem_pool: MemPool::new(unsafe { NonZeroU64::new_unchecked(10_000_000u64) }),
state: TrieState::with_accounts(trie),
}
}
Expand All @@ -37,7 +40,7 @@ impl MemPoolTestFixture {
}

/// Sets the block gas limit.
pub fn set_block_gas_limit(&mut self, block_gas_limit: u64) -> Result<(), StateError> {
pub fn set_block_gas_limit(&mut self, block_gas_limit: NonZeroU64) -> Result<(), StateError> {
self.mem_pool
.set_block_gas_limit(&self.state, block_gas_limit)
}
Expand Down
19 changes: 12 additions & 7 deletions crates/edr_evm/tests/mem_pool.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#![cfg(feature = "test-utils")]

use std::num::NonZeroU64;

use edr_eth::{AccountInfo, Address, U256};
use edr_evm::{
state::{AccountModifierFn, StateDebug},
Expand Down Expand Up @@ -318,7 +320,7 @@ fn add_transaction_exceeds_block_limit() -> anyhow::Result<()> {

let mut fixture = MemPoolTestFixture::with_accounts(&[(sender, AccountInfo::default())]);

let exceeds_block_limit = fixture.mem_pool.block_gas_limit() + 1;
let exceeds_block_limit = fixture.mem_pool.block_gas_limit().get() + 1;
let transaction = dummy_eip155_transaction_with_limit(sender, 5, exceeds_block_limit)?;
let result = fixture.add_transaction(transaction);

Expand Down Expand Up @@ -625,23 +627,24 @@ fn last_pending_nonce_some_future_to_pending_queue() -> anyhow::Result<()> {

#[test]
fn set_block_gas_limit() -> anyhow::Result<()> {
const NEW_GAS_LIMIT: u64 = 15_000_000;
// SAFETY: literal is non-zero
const NEW_GAS_LIMIT: NonZeroU64 = unsafe { NonZeroU64::new_unchecked(15_000_000) };

let sender = Address::random();

let mut fixture = MemPoolTestFixture::with_accounts(&[(sender, AccountInfo::default())]);
assert_eq!(fixture.mem_pool.block_gas_limit(), 10_000_000);
assert_eq!(fixture.mem_pool.block_gas_limit().get(), 10_000_000);

fixture.set_block_gas_limit(NEW_GAS_LIMIT)?;
assert_eq!(fixture.mem_pool.block_gas_limit(), NEW_GAS_LIMIT);

let transaction = dummy_eip155_transaction_with_limit(sender, 0, NEW_GAS_LIMIT + 1)?;
let transaction = dummy_eip155_transaction_with_limit(sender, 0, NEW_GAS_LIMIT.get() + 1)?;
let result = fixture.add_transaction(transaction);

assert!(matches!(
result,
Err(MemPoolAddTransactionError::ExceedsBlockGasLimit { block_gas_limit, transaction_gas_limit })
if block_gas_limit == NEW_GAS_LIMIT && transaction_gas_limit == NEW_GAS_LIMIT + 1
if block_gas_limit == NEW_GAS_LIMIT && transaction_gas_limit == NEW_GAS_LIMIT.get() + 1
));

Ok(())
Expand All @@ -665,7 +668,8 @@ fn set_block_gas_limit_removes_invalid_transactions() -> anyhow::Result<()> {
let future_transactions = fixture.mem_pool.future_transactions().collect::<Vec<_>>();
assert_eq!(future_transactions.len(), 1);

fixture.set_block_gas_limit(5_000_000)?;
// SAFETY: literal is non-zero
fixture.set_block_gas_limit(unsafe { NonZeroU64::new_unchecked(5_000_000) })?;

let pending_transactions = fixture.mem_pool.pending_transactions().collect::<Vec<_>>();
assert_eq!(pending_transactions.len(), 0);
Expand Down Expand Up @@ -708,7 +712,8 @@ fn set_block_gas_limit_moves_future_to_pending_queue() -> anyhow::Result<()> {
assert_eq!(*future_transactions[0].pending(), transaction4);
assert_eq!(*future_transactions[1].pending(), transaction5);

fixture.set_block_gas_limit(150_000)?;
// SAFETY: literal is non-zero
fixture.set_block_gas_limit(unsafe { NonZeroU64::new_unchecked(150_000) })?;

let pending_transactions = fixture.mem_pool.pending_transactions().collect::<Vec<_>>();
assert_eq!(pending_transactions.len(), 1);
Expand Down
21 changes: 19 additions & 2 deletions crates/edr_napi/src/provider/config.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::{
num::NonZeroU64,
path::PathBuf,
time::{Duration, SystemTime},
};
Expand Down Expand Up @@ -172,7 +173,15 @@ impl TryFrom<MiningConfig> for edr_provider::MiningConfig {
.map(|interval| {
let interval = match interval {
Either::A(interval) => {
edr_provider::IntervalConfig::Fixed(interval.try_cast()?)
let interval = interval.try_cast()?;
let interval = NonZeroU64::new(interval).ok_or_else(|| {
napi::Error::new(
napi::Status::GenericFailure,
"Interval must be greater than 0",
)
})?;

edr_provider::IntervalConfig::Fixed(interval)
}
Either::B(IntervalRange { min, max }) => edr_provider::IntervalConfig::Range {
min: min.try_cast()?,
Expand Down Expand Up @@ -225,6 +234,14 @@ impl TryFrom<ProviderConfig> for edr_provider::ProviderConfig {
)
.collect::<napi::Result<_>>()?;

let block_gas_limit =
NonZeroU64::new(value.block_gas_limit.try_cast()?).ok_or_else(|| {
napi::Error::new(
napi::Status::GenericFailure,
"Block gas limit must be greater than 0",
)
})?;

Ok(Self {
accounts: value
.genesis_accounts
Expand All @@ -235,7 +252,7 @@ impl TryFrom<ProviderConfig> for edr_provider::ProviderConfig {
allow_unlimited_contract_size: value.allow_unlimited_contract_size,
bail_on_call_failure: value.bail_on_call_failure,
bail_on_transaction_failure: value.bail_on_transaction_failure,
block_gas_limit: value.block_gas_limit.try_cast()?,
block_gas_limit,
cache_dir: PathBuf::from(
value
.cache_dir
Expand Down
47 changes: 31 additions & 16 deletions crates/edr_provider/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{path::PathBuf, time::SystemTime};
use std::{num::NonZeroU64, path::PathBuf, time::SystemTime};

use edr_eth::{
block::BlobGas, spec::HardforkActivations, AccountInfo, Address, HashMap, SpecId, B256, U256,
Expand All @@ -7,36 +7,51 @@ use edr_evm::{alloy_primitives::ChainId, MineOrdering};
use rand::Rng;
use serde::{Deserialize, Serialize};

use crate::{requests::hardhat::rpc_types::ForkConfig, OneUsizeOrTwo};
use crate::requests::{hardhat::rpc_types::ForkConfig, IntervalConfig as IntervalConfigRequest};

/// Configuration for interval mining.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum IntervalConfig {
Fixed(u64),
Fixed(NonZeroU64),
Range { min: u64, max: u64 },
}

impl IntervalConfig {
/// Generates a (random) interval based on the configuration.
pub fn generate_interval(&self) -> u64 {
match self {
IntervalConfig::Fixed(interval) => *interval,
IntervalConfig::Fixed(interval) => interval.get(),
IntervalConfig::Range { min, max } => rand::thread_rng().gen_range(*min..=*max),
}
}
}

impl TryFrom<OneUsizeOrTwo> for IntervalConfig {
type Error = ();

fn try_from(value: OneUsizeOrTwo) -> Result<Self, Self::Error> {
match value {
OneUsizeOrTwo::One(0) => Err(()),
OneUsizeOrTwo::One(value) => Ok(Self::Fixed(value as u64)),
OneUsizeOrTwo::Two([min, max]) => Ok(Self::Range {
min: min as u64,
max: max as u64,
}),
/// An error that occurs when trying to convert [`IntervalConfigRequest`] to an
/// `Option<IntervalConfig>`.
#[derive(Debug, thiserror::Error)]
pub enum IntervalConfigConversionError {
/// The minimum value in the range is greater than the maximum value.
#[error("Minimum value in range is greater than maximum value")]
MinGreaterThanMax,
}

impl TryInto<Option<IntervalConfig>> for IntervalConfigRequest {
type Error = IntervalConfigConversionError;

fn try_into(self) -> Result<Option<IntervalConfig>, Self::Error> {
match self {
Self::FixedOrDisabled(0) => Ok(None),
Self::FixedOrDisabled(value) => {
// Zero implies disabled
Ok(NonZeroU64::new(value).map(IntervalConfig::Fixed))
}
Self::Range([min, max]) => {
if max >= min {
Ok(Some(IntervalConfig::Range { min, max }))
} else {
Err(IntervalConfigConversionError::MinGreaterThanMax)
}
}
}
}
}
Expand Down Expand Up @@ -65,7 +80,7 @@ pub struct ProviderConfig {
pub bail_on_call_failure: bool,
/// Whether to return an `Err` when a `eth_sendTransaction` fails
pub bail_on_transaction_failure: bool,
pub block_gas_limit: u64,
pub block_gas_limit: NonZeroU64,
pub cache_dir: PathBuf,
pub chain_id: ChainId,
pub chains: HashMap<ChainId, HardforkActivations>,
Expand Down
26 changes: 13 additions & 13 deletions crates/edr_provider/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ mod call;
mod gas;

use std::{
cmp,
cmp::Ordering,
cmp::{self, Ordering},
collections::BTreeMap,
ffi::OsString,
fmt::Debug,
num::NonZeroUsize,
num::{NonZeroU64, NonZeroUsize},
sync::Arc,
time::{Duration, Instant, SystemTime, UNIX_EPOCH},
};
Expand Down Expand Up @@ -319,7 +318,7 @@ impl<LoggerErrorT: Debug> ProviderData<LoggerErrorT> {

/// Retrieves the gas limit of the next block.
pub fn block_gas_limit(&self) -> u64 {
self.mem_pool.block_gas_limit()
self.mem_pool.block_gas_limit().get()
}

/// Returns the default caller.
Expand Down Expand Up @@ -1527,7 +1526,7 @@ impl<LoggerErrorT: Debug> ProviderData<LoggerErrorT> {
/// Sets the gas limit used for mining new blocks.
pub fn set_block_gas_limit(
&mut self,
gas_limit: u64,
gas_limit: NonZeroU64,
) -> Result<(), ProviderError<LoggerErrorT>> {
let state = self.current_state()?;
self.mem_pool
Expand Down Expand Up @@ -1892,11 +1891,7 @@ impl<LoggerErrorT: Debug> ProviderData<LoggerErrorT> {
) -> Result<DebugMineBlockResultAndState<StateError>, ProviderError<LoggerErrorT>> {
options.base_fee = options.base_fee.or(self.next_block_base_fee_per_gas);
options.beneficiary = Some(options.beneficiary.unwrap_or(self.beneficiary));
options.gas_limit = Some(
options
.gas_limit
.unwrap_or_else(|| self.mem_pool.block_gas_limit()),
);
options.gas_limit = Some(options.gas_limit.unwrap_or_else(|| self.block_gas_limit()));

let evm_config = self.create_evm_config(None)?;

Expand Down Expand Up @@ -2359,7 +2354,7 @@ fn create_blockchain_and_state(
config.chain_id,
config.hardfork,
GenesisBlockOptions {
gas_limit: Some(config.block_gas_limit),
gas_limit: Some(config.block_gas_limit.get()),
timestamp: config.initial_date.map(|d| {
d.duration_since(UNIX_EPOCH)
.expect("initial date must be after UNIX epoch")
Expand Down Expand Up @@ -3014,7 +3009,11 @@ mod tests {
#[test]
fn mine_and_commit_block_leaves_unmined_transactions() -> anyhow::Result<()> {
let mut fixture = ProviderTestFixture::new_local()?;
fixture.provider_data.set_block_gas_limit(55_000)?;

// SAFETY: literal is non-zero
fixture
.provider_data
.set_block_gas_limit(unsafe { NonZeroU64::new_unchecked(55_000) })?;

// Actual gas usage is 21_000
let transaction1 = fixture.signed_dummy_transaction(0, Some(0))?;
Expand Down Expand Up @@ -3581,7 +3580,8 @@ mod tests {
}));

let config = ProviderConfig {
block_gas_limit: 1_000_000,
// SAFETY: literal is non-zero
block_gas_limit: unsafe { NonZeroU64::new_unchecked(1_000_000) },
chain_id: 1,
coinbase: Address::ZERO,
hardfork: SpecId::LONDON,
Expand Down
10 changes: 9 additions & 1 deletion crates/edr_provider/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use edr_evm::{
};
use ethers_core::types::transaction::eip712::Eip712Error;

use crate::data::CreationError;
use crate::{data::CreationError, IntervalConfigConversionError};

#[derive(Debug, thiserror::Error)]
pub enum ProviderError<LoggerErrorT> {
Expand Down Expand Up @@ -131,6 +131,12 @@ pub enum ProviderError<LoggerErrorT> {
/// Cannot set account nonce when the mem pool is not empty
#[error("Cannot set account nonce when the transaction pool is not empty")]
SetAccountNonceWithPendingTransactions,
/// `evm_setBlockGasLimit` was called with a gas limit of zero.
#[error("Block gas limit must be greater than 0")]
SetBlockGasLimitMustBeGreaterThanZero,
/// The `evm_setIntervalMining` method was called with an invalid interval.
#[error(transparent)]
SetIntervalMiningConfigInvalid(#[from] IntervalConfigConversionError),
/// The `hardhat_setNextBlockBaseFeePerGas` method is not supported due to
/// an older hardfork.
#[error("hardhat_setNextBlockBaseFeePerGas is disabled because EIP-1559 is not active")]
Expand Down Expand Up @@ -229,6 +235,8 @@ impl<LoggerErrorT: Debug> From<ProviderError<LoggerErrorT>> for jsonrpc::Error {
ProviderError::Serialization(_) => INVALID_INPUT,
ProviderError::SetAccountNonceLowerThanCurrent { .. } => INVALID_INPUT,
ProviderError::SetAccountNonceWithPendingTransactions => INTERNAL_ERROR,
ProviderError::SetBlockGasLimitMustBeGreaterThanZero => INVALID_INPUT,
ProviderError::SetIntervalMiningConfigInvalid(_) => INVALID_PARAMS,
ProviderError::SetMinGasPriceUnsupported => INVALID_INPUT,
ProviderError::SetNextBlockBaseFeePerGasUnsupported { .. } => INVALID_INPUT,
ProviderError::SetNextPrevRandaoUnsupported { .. } => INVALID_INPUT,
Expand Down
Loading
Loading