Skip to content

Commit

Permalink
decouple env, use storage for era_test_node block and timestamp
Browse files Browse the repository at this point in the history
  • Loading branch information
nbaztec committed Dec 13, 2023
1 parent 3fb6c03 commit 8e52d1b
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 32 deletions.
43 changes: 35 additions & 8 deletions crates/evm/core/src/era_revm/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use zksync_utils::{address_to_h256, h256_to_u256, u256_to_h256};
#[derive(Default)]
pub struct RevmDatabaseForEra<DB> {
pub db: Arc<Mutex<Box<DB>>>,
pub current_block: u64,
current_block: u64,
}

impl<Db> Clone for RevmDatabaseForEra<Db> {
Expand All @@ -55,9 +55,26 @@ impl<DB: Database + Send> RevmDatabaseForEra<DB>
where
<DB as revm::Database>::Error: Debug,
{
/// Returns the current block number and timestamp from the database.
/// Create a new instance of [RevmDatabaseForEra] caching the current l2 block.
pub fn new(db: Arc<Mutex<Box<DB>>>) -> Self {
let db_inner = db.clone();
let current_block = {
let mut db = db_inner.lock().unwrap();
let result = db
.storage(h160_to_address(SYSTEM_CONTEXT_ADDRESS), u256_to_revm_u256(U256::from(9)))
.unwrap();
let num_and_ts = revm_u256_to_h256(result);
let num_and_ts_bytes = num_and_ts.as_fixed_bytes();
let num: [u8; 8] = num_and_ts_bytes[24..32].try_into().unwrap();
u64::from_be_bytes(num)
};

Self { db, current_block }
}

/// Returns the current L1 block number and timestamp from the database.
/// Reads it directly from the SYSTEM_CONTEXT storage.
pub fn block_number_and_timestamp(&self) -> (u64, u64) {
pub fn get_l1_block_number_and_timestamp(&self) -> (u64, u64) {
let num_and_ts = self.read_storage_internal(SYSTEM_CONTEXT_ADDRESS, U256::from(7));
let num_and_ts_bytes = num_and_ts.as_fixed_bytes();
let num: [u8; 8] = num_and_ts_bytes[24..32].try_into().unwrap();
Expand All @@ -66,6 +83,17 @@ where
(u64::from_be_bytes(num), u64::from_be_bytes(ts))
}

/// Returns the current L2 block number and timestamp from the database.
/// Reads it directly from the SYSTEM_CONTEXT storage.
pub fn get_l2_block_number_and_timestamp(&self) -> (u64, u64) {
let num_and_ts = self.read_storage_internal(SYSTEM_CONTEXT_ADDRESS, U256::from(9));
let num_and_ts_bytes = num_and_ts.as_fixed_bytes();
let num: [u8; 8] = num_and_ts_bytes[24..32].try_into().unwrap();
let ts: [u8; 8] = num_and_ts_bytes[8..16].try_into().unwrap();

(u64::from_be_bytes(num), u64::from_be_bytes(ts))
}

/// Returns the nonce for a given account from NonceHolder storage.
pub fn get_nonce_for_address(&self, address: H160) -> u64 {
// Nonce is stored in the first mapping of the Nonce contract.
Expand Down Expand Up @@ -155,14 +183,13 @@ where
idx: U256,
block: Option<BlockIdVariant>,
) -> eyre::Result<H256> {
// We cannot support historical lookups. Only the most recent block is supported.
let current_block = self.current_block;
// We cannot support historical lookups. Only the most recent L2 block is supported.
if let Some(block) = &block {
match block {
BlockIdVariant::BlockNumber(zksync_types::api::BlockNumber::Number(num)) => {
let current_block_number_l2 = current_block * 2;
if num.as_u64() != current_block_number_l2 {
eyre::bail!("Only fetching of the most recent L2 block {} is supported - but queried for {}", current_block_number_l2, num)
// let current_block_number_l2 = current_l1_block * 2;
if num.as_u64() != self.current_block {
eyre::bail!("Only fetching of the most recent L2 block {} is supported - but queried for {}", self.current_block, num)
}
}
_ => eyre::bail!("Only fetching most recent block is implemented"),
Expand Down
13 changes: 6 additions & 7 deletions crates/evm/core/src/era_revm/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,9 @@ where
<DB as revm::Database>::Error: Debug,
INSP: ToTracerPointer<StorageView<ForkStorage<RevmDatabaseForEra<DB>>>, HistoryDisabled>,
{
let (num, ts) = (env.block.number.to::<u64>(), env.block.timestamp.to::<u64>());
let era_db = RevmDatabaseForEra { db: Arc::new(Mutex::new(Box::new(db))), current_block: num };

let era_db = RevmDatabaseForEra::new(Arc::new(Mutex::new(Box::new(db))));
let nonces = era_db.get_nonce_for_address(address_to_h160(env.tx.caller));
let (num, ts) = era_db.get_l2_block_number_and_timestamp();

debug!(
"*** Starting ERA transaction: block: {:?} timestamp: {:?} - but using {:?} and {:?} instead with nonce {:?}",
Expand All @@ -161,14 +160,14 @@ where
31337
};

let (l2_num, l2_ts) = (num * 2, ts * 2);
let l1_num = num / 2;
let fork_details = ForkDetails {
fork_source: era_db.clone(),
l1_block: L1BatchNumber(num as u32),
l1_block: L1BatchNumber(l1_num as u32),
l2_block: Block::default(),
l2_miniblock: l2_num,
l2_miniblock: num,
l2_miniblock_hash: Default::default(),
block_timestamp: l2_ts,
block_timestamp: ts,
overwrite_chain_id: Some(L2ChainId::from(chain_id_u32)),
// Make sure that l1 gas price is set to reasonable values.
l1_gas_price: u64::max(env.block.basefee.to::<u64>(), 1000),
Expand Down
22 changes: 5 additions & 17 deletions crates/evm/evm/src/executors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,15 +147,6 @@ impl Executor {
self
}

// Record any changes made to the block's environment during setup,
// and also the chainid, which can be set manually.
pub fn record_env_changes(&mut self, env: &Env) {
// record any changes made to the block's environment during setup
self.env.block = env.block.clone();
// and also the chainid, which can be set manually
self.env.cfg.chain_id = env.cfg.chain_id;
}

/// Calls the `setUp()` function on a contract.
///
/// This will commit any state changes to the underlying database.
Expand All @@ -169,7 +160,10 @@ impl Executor {
self.backend.set_test_contract(to).set_caller(from);
let res = self.call_committing::<_, _>(from, to, "setUp()", vec![], U256::ZERO, None)?;

self.record_env_changes(&res.env);
// record any changes made to the block's environment during setup
self.env.block = env.block.clone();

Check failure on line 164 in crates/evm/evm/src/executors/mod.rs

View workflow job for this annotation

GitHub Actions / cheatcode-test

expected value, found macro `env`
// and also the chainid, which can be set manually
self.env.cfg.chain_id = env.cfg.chain_id;

Check failure on line 166 in crates/evm/evm/src/executors/mod.rs

View workflow job for this annotation

GitHub Actions / cheatcode-test

expected value, found macro `env`

match res.state_changeset.as_ref() {
Some(changeset) => {
Expand Down Expand Up @@ -249,7 +243,6 @@ impl Executor {
// execute the call
let env = self.build_test_env(from, TransactTo::Call(test_contract), calldata, value);
let call_result = self.call_raw_with_env(env)?;
self.record_env_changes(&call_result.env);
convert_call_result(abi, &func, call_result)
}

Expand Down Expand Up @@ -432,12 +425,7 @@ impl Executor {
abi: Option<&Abi>,
) -> Result<DeployResult, EvmError> {
let env = self.build_test_env(from, TransactTo::Create(CreateScheme::Create), code, value);
let res = self.deploy_with_env(env, abi);
if let Ok(DeployResult { env, .. }) = &res {
self.record_env_changes(env);
}

res
self.deploy_with_env(env, abi)
}

/// Check if a call to a test contract was successful.
Expand Down

0 comments on commit 8e52d1b

Please sign in to comment.