Skip to content

Commit

Permalink
chore: run more stuff in CI, format code
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes committed Mar 28, 2024
1 parent 72b6130 commit f6e2163
Show file tree
Hide file tree
Showing 11 changed files with 179 additions and 82 deletions.
42 changes: 40 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: rust

on:
push:
branches: [ master ]
branches: [master]
pull_request:
branches: [ '*' ]
branches: ["*"]

jobs:
tests:
Expand All @@ -27,3 +27,41 @@ jobs:

- name: cargo test
run: cargo test

clippy:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
- run: cargo clippy --workspace --all-targets --all-features
env:
RUSTFLAGS: -Dwarnings

docs:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
- run: cargo doc --workspace --all-features --no-deps --document-private-items
env:
RUSTDOCFLAGS: "--cfg docsrs -D warnings"

fmt:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
with:
components: rustfmt
- run: cargo fmt --all --check
16 changes: 8 additions & 8 deletions src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ use std::sync::Arc;
use ethers_core::types::BlockId;
use ethers_providers::{Http, Provider};
use pyo3::{PyErr, PyResult};
use revm::Database;
use revm::db::{CacheDB, DbAccount, EthersDB};
use revm::precompile::{Address, B256};
use revm::primitives::{AccountInfo, Bytecode, HashMap, State};
use revm::Database;
use revm_interpreter::primitives::db::{DatabaseCommit, DatabaseRef};
use ruint::aliases::U256;

Expand All @@ -17,7 +17,6 @@ use crate::utils::pyerr;
type MemDB = CacheDB<EmptyDBWrapper>;
type ForkDB = CacheDB<EthersDB<Provider<Http>>>;


/// A wrapper around the `CacheDB` and `EthersDB` to provide a common interface
/// without needing dynamic lifetime and generic parameters (unsupported in PyO3)
#[derive(Clone, Debug)]
Expand All @@ -31,13 +30,14 @@ impl DB {
DB::Memory(MemDB::new(EmptyDBWrapper::default()))
}

pub(crate) fn new_fork(
fork_url: &str,
fork_block_number: Option<&str>,
) -> PyResult<Self> {
pub(crate) fn new_fork(fork_url: &str, fork_block_number: Option<&str>) -> PyResult<Self> {
let provider = Provider::<Http>::try_from(fork_url).map_err(pyerr)?;
let block = fork_block_number.map(BlockId::from_str).map_or(Ok(None), |v| v.map(Some)).map_err(pyerr)?;
let db = EthersDB::new(Arc::new(provider), block).unwrap_or_else(|| panic!("Could not create EthersDB"));
let block = fork_block_number
.map(BlockId::from_str)
.map_or(Ok(None), |v| v.map(Some))
.map_err(pyerr)?;
let db = EthersDB::new(Arc::new(provider), block)
.unwrap_or_else(|| panic!("Could not create EthersDB"));
Ok(DB::Fork(CacheDB::new(db)))
}

Expand Down
8 changes: 4 additions & 4 deletions src/empty_db_wrapper.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use std::convert::Infallible;
use revm::primitives::{Address, B256, U256};
use revm::{
db::{DatabaseRef, EmptyDB},
primitives::{AccountInfo, Bytecode},
};
use revm::primitives::{Address, B256, U256};
use std::convert::Infallible;

/// An empty database that always returns default values when queried.
/// This will also _always_ return `Some(AccountInfo)`.
/// Copied from Foundry: https://github.com/foundry-rs/foundry/blob/9e3ab9b3aff21c6e5ef/crates/evm/core/src/backend/in_memory_db.rs#L83-L92
///
/// Copied from Foundry: <https://github.com/foundry-rs/foundry/blob/9e3ab9b3aff21c6e5ef/crates/evm/core/src/backend/in_memory_db.rs#L83-L92>
#[derive(Clone, Debug, Default)]
pub(crate) struct EmptyDBWrapper(EmptyDB);

Expand Down
89 changes: 58 additions & 31 deletions src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@ use std::collections::{HashMap, HashSet};
use std::fmt::Debug;
use std::mem::replace;

use pyo3::{pyclass, pymethods, PyObject, PyResult, Python};
use pyo3::exceptions::{PyKeyError, PyOverflowError};
use pyo3::types::PyBytes;
use revm::{Evm, EvmContext, JournalCheckpoint as RevmCheckpoint, primitives::U256};
use pyo3::{pyclass, pymethods, PyObject, PyResult, Python};
use revm::precompile::{Address, Bytes};
use revm::primitives::{CreateScheme, BlockEnv as RevmBlockEnv, Env as RevmEnv, ExecutionResult as RevmExecutionResult, HandlerCfg, Output, SpecId, TransactTo, TxEnv};
use revm::primitives::ExecutionResult::Success;
use revm::primitives::{
BlockEnv as RevmBlockEnv, CreateScheme, Env as RevmEnv, ExecutionResult as RevmExecutionResult,
HandlerCfg, Output, SpecId, TransactTo, TxEnv,
};
use revm::{primitives::U256, Evm, EvmContext, JournalCheckpoint as RevmCheckpoint};
use tracing::trace;

use crate::{types::{AccountInfo, BlockEnv, Env, ExecutionResult, JournalCheckpoint}, utils::{addr, pyerr}};
use crate::database::DB;
use crate::executor::call_evm;
use crate::types::{PyByteVec, PyDB};
use crate::{
types::{AccountInfo, BlockEnv, Env, ExecutionResult, JournalCheckpoint},
utils::{addr, pyerr},
};

#[derive(Debug)]
#[pyclass]
Expand Down Expand Up @@ -57,12 +63,11 @@ impl EVM {
) -> PyResult<Self> {
let spec = SpecId::from(spec_id);
let env = env.unwrap_or_default().into();
let db = fork_url.map(|url| DB::new_fork(url, fork_block_number)).unwrap_or(Ok(DB::new_memory()))?;
let db = fork_url
.map(|url| DB::new_fork(url, fork_block_number))
.unwrap_or(Ok(DB::new_memory()))?;

let Evm { context, .. } = Evm::builder()
.with_env(Box::new(env))
.with_db(db)
.build();
let Evm { context, .. } = Evm::builder().with_env(Box::new(env)).with_db(db).build();
Ok(EVM {
context: context.evm,
gas_limit: U256::from(gas_limit),
Expand All @@ -78,17 +83,23 @@ impl EVM {
log_i: self.context.journaled_state.logs.len(),
journal_i: self.context.journaled_state.journal.len(),
};
self.checkpoints.insert(checkpoint, self.context.journaled_state.checkpoint());
self.checkpoints
.insert(checkpoint, self.context.journaled_state.checkpoint());
Ok(checkpoint)
}

fn revert(&mut self, checkpoint: JournalCheckpoint) -> PyResult<()> {
if self.context.journaled_state.depth == 0 {
return Err(PyOverflowError::new_err(format!("No checkpoint to revert to: {:?}", self.context.journaled_state)));
return Err(PyOverflowError::new_err(format!(
"No checkpoint to revert to: {:?}",
self.context.journaled_state
)));
}

if let Some(revm_checkpoint) = self.checkpoints.remove(&checkpoint) {
self.context.journaled_state.checkpoint_revert(revm_checkpoint);
self.context
.journaled_state
.checkpoint_revert(revm_checkpoint);
Ok(())
} else {
Err(PyKeyError::new_err("Invalid checkpoint"))
Expand Down Expand Up @@ -129,11 +140,7 @@ impl EVM {
}

/// Inserts the provided account information in the database at the specified address.
fn insert_account_info(
&mut self,
address: &str,
info: AccountInfo,
) -> PyResult<()> {
fn insert_account_info(&mut self, address: &str, info: AccountInfo) -> PyResult<()> {
let target = addr(address)?;
match self.context.journaled_state.state.get_mut(&target) {
// account is cold, just insert into the DB, so it's retrieved next time
Expand Down Expand Up @@ -175,9 +182,15 @@ impl EVM {
is_static: bool,
py: Python<'_>,
) -> PyResult<PyObject> {
let env = self.build_test_env(addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default(), gas, gas_price);
match self.call_with_env(env, is_static)
{
let env = self.build_test_env(
addr(caller)?,
TransactTo::Call(addr(to)?),
calldata.unwrap_or_default().into(),
value.unwrap_or_default(),
gas,
gas_price,
);
match self.call_with_env(env, is_static) {
Ok(data) => Ok(PyBytes::new(py, data.as_ref()).into()),
Err(e) => Err(e),
}
Expand All @@ -195,9 +208,15 @@ impl EVM {
is_static: bool,
_abi: Option<&str>,
) -> PyResult<String> {
let env = self.build_test_env(addr(deployer)?, TransactTo::Create(CreateScheme::Create), code.into(), value.unwrap_or_default(), gas, gas_price);
match self.deploy_with_env(env, is_static)
{
let env = self.build_test_env(
addr(deployer)?,
TransactTo::Create(CreateScheme::Create),
code.into(),
value.unwrap_or_default(),
gas,
gas_price,
);
match self.deploy_with_env(env, is_static) {
Ok((_, address)) => Ok(format!("{:?}", address)),
Err(e) => Err(e),
}
Expand Down Expand Up @@ -235,16 +254,22 @@ impl EVM {

#[getter]
fn db_accounts(&self) -> PyDB {
self.context.db.get_accounts().iter().map(
|(address, db_acc)| (address.to_string(), db_acc.info.clone().into())
).collect()
self.context
.db
.get_accounts()
.iter()
.map(|(address, db_acc)| (address.to_string(), db_acc.info.clone().into()))
.collect()
}

#[getter]
fn journal_state(&self) -> PyDB {
self.context.journaled_state.state.iter().map(
|(address, acc)| (address.to_string(), acc.info.clone().into())
).collect()
self.context
.journaled_state
.state
.iter()
.map(|(address, acc)| (address.to_string(), acc.info.clone().into()))
.collect()
}

fn set_block_env(&mut self, block: BlockEnv) {
Expand Down Expand Up @@ -337,8 +362,10 @@ impl EVM {

fn run_env(&mut self, env: RevmEnv, is_static: bool) -> PyResult<RevmExecutionResult> {
self.context.env = Box::new(env);
let evm_context: EvmContext<DB> = replace(&mut self.context, EvmContext::new(DB::new_memory()));
let (result, evm_context) = call_evm(evm_context, self.handler_cfg, self.tracing, is_static)?;
let evm_context: EvmContext<DB> =
replace(&mut self.context, EvmContext::new(DB::new_memory()));
let (result, evm_context) =
call_evm(evm_context, self.handler_cfg, self.tracing, is_static)?;
self.context = evm_context;
self.result = Some(result.clone());
Ok(result)
Expand Down
Loading

0 comments on commit f6e2163

Please sign in to comment.