Skip to content

Commit

Permalink
fix: revm input
Browse files Browse the repository at this point in the history
  • Loading branch information
eigmax committed Dec 29, 2023
1 parent 3b15778 commit 91e9622
Show file tree
Hide file tree
Showing 3 changed files with 189 additions and 1 deletion.
10 changes: 10 additions & 0 deletions zkvm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ riscv = { git = "https://github.com/powdr-labs/powdr.git", branch = "main", pack
number = { git = "https://github.com/powdr-labs/powdr.git", branch = "main", package = "number" }
backend = { git = "https://github.com/powdr-labs/powdr.git", branch = "main", package = "backend" }

revm = { version = "3.5.0", features = ["std", "ethersdb", "serde"] }

[dev-dependencies]
env_logger = "0.10"
hex = "0.4.3"
indicatif = "*"
ethers-providers = { version = "2.0", features = ["ws"] }
ethers-core = { version = "2.0" }
tokio = { version = "1.35", features = [
"rt-multi-thread",
"macros",
] }
futures = { version = "0.3.30" }
177 changes: 176 additions & 1 deletion zkvm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,71 @@
#![allow(unused_macros)]
#![allow(dead_code)]
use std::io::BufWriter;
use std::io::Write;
use std::sync::Arc;
use std::sync::Mutex;

macro_rules! local_fill {
($left:expr, $right:expr, $fun:expr) => {
if let Some(right) = $right {
$left = $fun(right.0)
}
};
($left:expr, $right:expr) => {
if let Some(right) = $right {
$left = Address::from(right.as_fixed_bytes())
}
};
}

struct FlushWriter {
writer: Arc<Mutex<BufWriter<std::fs::File>>>,
}

impl FlushWriter {
fn new(writer: Arc<Mutex<BufWriter<std::fs::File>>>) -> Self {
Self { writer }
}
}

impl Write for FlushWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.writer.lock().unwrap().write(buf)
}

fn flush(&mut self) -> std::io::Result<()> {
self.writer.lock().unwrap().flush()
}
}

#[cfg(test)]
mod tests {
use super::*;
use backend::BackendType;
use compiler::pipeline::{Pipeline, Stage};
use ethers_core::types::BlockId;
use ethers_providers::Middleware;
use ethers_providers::{Http, Provider};
use indicatif::ProgressBar;
use mktemp::Temp;
use number::GoldilocksField;
use revm::db::{CacheDB, EmptyDB};
use revm::inspectors::TracerEip3155;
use revm::primitives::{Address, Env, TransactTo, U256};
use revm::EVM;
use riscv::{
compile_rust,
continuations::{rust_continuations, rust_continuations_dry_run},
CoProcessors,
};
use std::fs::OpenOptions;
use std::path::PathBuf;

static BYTECODE: &str = "61029a60005260206000f3";

#[test]
#[ignore = "too slow"]
fn compile_rust_riscv() {
fn test_revm_prove_single_contract() {
env_logger::try_init().unwrap_or_default();

type F = GoldilocksField;
Expand Down Expand Up @@ -59,4 +109,129 @@ mod tests {
)
.unwrap();
}

#[tokio::test]
async fn test_revm_prove_full_block() {
// Create ethers client and wrap it in Arc<M>
let client = Provider::<Http>::try_from(
"https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27",
)
.unwrap();
let client = Arc::new(client);

// Params
let chain_id: u64 = 1;
let block_number = 0x5BAD55;

// Fetch the transaction-rich block
let block = match client.get_block_with_txs(block_number).await {
Ok(Some(block)) => block,
Ok(None) => panic!("Block not found"),
Err(error) => panic!("Error: {:?}", error),
};
println!("Fetched block number: {}", block.number.unwrap().0[0]);
let previous_block_number = block_number - 1;

// Use the previous block state as the db with caching
//let _prev_id: BlockId = previous_block_number.into();
// SAFETY: This cannot fail since this is in the top-level tokio runtime
//let state_db = EthersDB::new(Arc::clone(&client), Some(prev_id)).expect("panic");
let cache_db = CacheDB::new(EmptyDB::default());
let mut evm: EVM<CacheDB<EmptyDB>> = EVM::new();
evm.database(cache_db);

let mut env = Env::default();
if let Some(number) = block.number {
let nn = number.0[0];
env.block.number = U256::from(nn);
}
local_fill!(env.block.coinbase, block.author);
local_fill!(env.block.timestamp, Some(block.timestamp), U256::from_limbs);
local_fill!(
env.block.difficulty,
Some(block.difficulty),
U256::from_limbs
);
local_fill!(env.block.gas_limit, Some(block.gas_limit), U256::from_limbs);
if let Some(base_fee) = block.base_fee_per_gas {
local_fill!(env.block.basefee, Some(base_fee), U256::from_limbs);
}

let txs = block.transactions.len();
println!("Found {txs} transactions.");

let console_bar = Arc::new(ProgressBar::new(txs as u64));
let elapsed = std::time::Duration::ZERO;

// Create the traces directory if it doesn't exist
std::fs::create_dir_all("traces").expect("Failed to create traces directory");

// Fill in CfgEnv
env.cfg.chain_id = chain_id;
for tx in block.transactions {
env.tx.caller = Address::from(tx.from.as_fixed_bytes());
env.tx.gas_limit = tx.gas.as_u64();
local_fill!(env.tx.gas_price, tx.gas_price, U256::from_limbs);
local_fill!(env.tx.value, Some(tx.value), U256::from_limbs);
env.tx.data = tx.input.0.into();
let mut gas_priority_fee = U256::ZERO;
local_fill!(
gas_priority_fee,
tx.max_priority_fee_per_gas,
U256::from_limbs
);
env.tx.gas_priority_fee = Some(gas_priority_fee);
env.tx.chain_id = Some(chain_id);
env.tx.nonce = Some(tx.nonce.as_u64());
if let Some(access_list) = tx.access_list {
env.tx.access_list = access_list
.0
.into_iter()
.map(|item| {
let new_keys: Vec<U256> = item
.storage_keys
.into_iter()
.map(|h256| U256::from_le_bytes(h256.0))
.collect();
(Address::from(item.address.as_fixed_bytes()), new_keys)
})
.collect();
} else {
env.tx.access_list = Default::default();
}

env.tx.transact_to = match tx.to {
Some(to_address) => TransactTo::Call(Address::from(to_address.as_fixed_bytes())),
None => TransactTo::create(),
};

evm.env = env.clone();

// Construct the file writer to write the trace to
let tx_number = tx.transaction_index.unwrap().0[0];
let file_name = format!("traces/{}.json", tx_number);
let write = OpenOptions::new().write(true).create(true).open(file_name);
let inner = Arc::new(Mutex::new(BufWriter::new(
write.expect("Failed to open file"),
)));
let writer = FlushWriter::new(Arc::clone(&inner));

// Inspect and commit the transaction to the EVM
let inspector = TracerEip3155::new(Box::new(writer), true, true);
if let Err(error) = evm.inspect_commit(inspector) {
println!("Got error: {:?}", error);
}

// Flush the file writer
inner.lock().unwrap().flush().expect("Failed to flush file");

console_bar.inc(1);
}

console_bar.finish_with_message("Finished all transactions.");
println!(
"Finished execution. Total CPU time: {:.6}s",
elapsed.as_secs_f64()
);
}
}
3 changes: 3 additions & 0 deletions zkvm/vm/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ fn main() {
const CONTRACT_ADDR: Address = address!("0d4a11d5EEaaC28EC3F61d100daF4d40471f1852");
const CODE_HASH: B256 =
b256!("e3c84e69bac71c159b2ff0d62b9a5c231887a809a96cb4a262a4b96ed78a1db2");

// TODO: get the block data from inputs
let mut db = CacheDB::new(EmptyDB::default());

let bytecode_len = get_data_len(0);
Expand Down Expand Up @@ -46,6 +48,7 @@ fn main() {

let result = evm.transact().unwrap();

// TODO: check the outputs
match result.result {
revm::primitives::ExecutionResult::Success {
reason: _,
Expand Down

0 comments on commit 91e9622

Please sign in to comment.