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

feat(l2): prover comparison benchmarks #1221

Merged
merged 24 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from 13 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
9 changes: 8 additions & 1 deletion cmd/ethrex_l2/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
commands::{autocomplete, config, stack, test, utils, wallet},
commands::{autocomplete, config, prove, stack, test, utils, wallet},
config::load_selected_config,
};
use clap::{Parser, Subcommand};
Expand Down Expand Up @@ -35,13 +35,19 @@ enum EthrexL2Command {
Test(test::Command),
#[clap(subcommand, about = "Generate shell completion scripts.")]
Autocomplete(autocomplete::Command),
#[clap(about = "Read a test chain from disk and prove a block.")]
Prove(prove::Command),
}

pub async fn start() -> eyre::Result<()> {
let EthrexL2CLI { command } = EthrexL2CLI::parse();
if let EthrexL2Command::Config(cmd) = command {
return cmd.run().await;
}
if let EthrexL2Command::Prove(cmd) = command {
return cmd.run();
}

let cfg = load_selected_config().await?;
match command {
EthrexL2Command::Stack(cmd) => cmd.run(cfg).await?,
Expand All @@ -50,6 +56,7 @@ pub async fn start() -> eyre::Result<()> {
EthrexL2Command::Autocomplete(cmd) => cmd.run()?,
EthrexL2Command::Config(_) => unreachable!(),
EthrexL2Command::Test(cmd) => cmd.run(cfg).await?,
EthrexL2Command::Prove(_) => unreachable!(),
};
Ok(())
}
1 change: 1 addition & 0 deletions cmd/ethrex_l2/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub(crate) mod autocomplete;
pub(crate) mod config;
pub(crate) mod prove;
pub(crate) mod stack;
pub(crate) mod test;
pub(crate) mod utils;
Expand Down
43 changes: 43 additions & 0 deletions cmd/ethrex_l2/src/commands/prove.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use clap::Args;
use ethrex_l2::utils::test_data_io::{generate_program_input, read_chain_file, read_genesis_file};
use ethrex_prover_lib::prover::Prover;

#[derive(Args)]
pub(crate) struct Command {
#[clap(
short = 'g',
long = "genesis",
help = "Path to the file containing the genesis block."
)]
genesis: String,
#[clap(
short = 'c',
long = "chain",
help = "Path to the file containing the test chain."
)]
chain: String,
#[clap(
short = 'n',
long = "block-number",
help = "Number of the block in the test chain to prove."
)]
block_number: usize,
}

impl Command {
pub fn run(self) -> eyre::Result<()> {
let genesis = read_genesis_file(&self.genesis);
let chain = read_chain_file(&self.chain);
let program_input = generate_program_input(genesis, chain, self.block_number)?;

let mut prover = Prover::new();
prover.prove(program_input).expect("proving failed");
println!(
"Total gas consumption: {}",
prover
.get_gas()
.expect("failed to deserialize gas consumption")
);
Ok(())
}
}
1 change: 1 addition & 0 deletions crates/l2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ secp256k1.workspace = true
keccak-hash = "0.10.0"
envy = "0.4.2"
thiserror.workspace = true
zkvm_interface = { path = "./prover/zkvm/interface/", default-features = false }

# risc0
risc0-zkvm = { version = "1.1.2" }
Expand Down
2 changes: 2 additions & 0 deletions crates/l2/prover/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
rsp/
target/
38 changes: 36 additions & 2 deletions crates/l2/prover/Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,44 @@
.PHONY: perf_test_proving perf_gpu rsp_comparison

ROOT_DIRECTORY := ../../..

RISC0_DEV_MODE?=1
RUST_LOG?="info"
perf_test_proving:
@echo "Using RISC0_DEV_MODE: ${RISC0_DEV_MODE}"
RISC0_DEV_MODE=${RISC0_DEV_MODE} RUST_LOG=${RUST_LOG} cargo test --release --test perf_zkvm --features build_zkvm -- --show-output
.PHONY: perf_test_proving

perf_gpu:
RUSTFLAGS="-C target-cpu=native" RISC0_DEV_MODE=0 RUST_LOG="debug" cargo test --release --test perf_zkvm --features "build_zkvm,gpu" -- --show-output
.PHONY: perf_gpu

# L2 Prover comparison with rsp. Uses GPU by default.

ETHREX_L2_BIN := ./target/release/ethrex_l2
RSP_BIN := ./target/release/rsp

GENESIS_FILE := $(ROOT_DIRECTORY)/test_data/genesis-l2-old.json
CHAIN_FILE := $(ROOT_DIRECTORY)/test_data/l2-loadtest.rlp
RSP_CACHE := $(ROOT_DIRECTORY)/test_data/rsp

rsp_comparison: $(ETHREX_L2_BIN) $(RSP_BIN)
@echo "rsp times (L1 Mainnet block, 24 MGas):"
@time $(RSP_BIN) --prove \
--chain-id 1 \
--block-number 21272632 \
--cache-dir $(RSP_CACHE) \
> /dev/null 2>&1
@echo ""
@echo "ethrex_l2 times (L2 block, 25 MGas):"
@RISC0_DEV_MODE=1 time $(ETHREX_L2_BIN) prove \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be RISC0_DEV_MODE=0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! good catch, thanks!!

--genesis $(GENESIS_FILE) \
--chain $(CHAIN_FILE) \
--block-number 2 \
> /dev/null 2>&1

$(ETHREX_L2_BIN):
CARGO_TARGET_DIR=target cargo build -r --manifest-path $(ROOT_DIRECTORY)/Cargo.toml --bin ethrex_l2 --features "build_zkvm,gpu"

$(RSP_BIN):
git clone https://github.com/succinctlabs/rsp.git
cd rsp; \
CARGO_TARGET_DIR=../target cargo build -r --bin rsp --features cuda
6 changes: 6 additions & 0 deletions crates/l2/prover/src/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ impl<'a> Prover<'a> {
Ok(())
}

pub fn get_gas(&self) -> Result<u64, Box<dyn std::error::Error>> {
Ok(risc0_zkvm::serde::from_slice(
&self.stdout[..8], // first 8 bytes
)?)
}

pub fn get_commitment(
receipt: &risc0_zkvm::Receipt,
) -> Result<ProgramOutput, Box<dyn std::error::Error>> {
Expand Down
7 changes: 7 additions & 0 deletions crates/l2/prover/zkvm/interface/guest/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ fn main() {
let receipts = execute_block(&block, &mut state).expect("failed to execute block");
validate_gas_used(&receipts, &block.header).expect("invalid gas used");

env::write(
&receipts
.last()
.expect("no receipts found")
.cumulative_gas_used,
);

let account_updates = get_state_transitions(&mut state);

// Update tries and calculate final state root hash
Expand Down
18 changes: 18 additions & 0 deletions crates/l2/utils/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use ethrex_blockchain::error::ChainError;
use ethrex_storage::error::StoreError;
use ethrex_vm::errors::ExecutionDBError;
use keccak_hash::H256;

#[derive(Debug, thiserror::Error)]
pub enum ProverInputError {
#[error("Invalid block number: {0}")]
InvalidBlockNumber(usize),
#[error("Invalid parent block: {0}")]
InvalidParentBlock(H256),
#[error("Store error: {0}")]
StoreError(#[from] StoreError),
#[error("Chain error: {0}")]
ChainError(#[from] ChainError),
#[error("ExecutionDB error: {0}")]
ExecutionDBError(#[from] ExecutionDBError),
}
1 change: 1 addition & 0 deletions crates/l2/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use secp256k1::SecretKey;
use serde::{Deserialize, Deserializer, Serialize, Serializer};

pub mod config;
pub mod error;
pub mod eth_client;
pub mod merkle_tree;
pub mod test_data_io;
Expand Down
38 changes: 37 additions & 1 deletion crates/l2/utils/test_data_io.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
use ethrex_blockchain::add_block;
use ethrex_core::types::{Block, Genesis};
use ethrex_rlp::{decode::RLPDecode, encode::RLPEncode};
use ethrex_storage::Store;
use ethrex_storage::{EngineType, Store};
use ethrex_vm::execution_db::ExecutionDB;
use tracing::info;
use zkvm_interface::io::ProgramInput;

use std::{
fs::File,
io::{BufReader, Read as _, Write},
path::PathBuf,
};

use super::error::ProverInputError;

// From cmd/ethrex
pub fn read_chain_file(chain_rlp_path: &str) -> Vec<Block> {
let chain_file = File::open(chain_rlp_path).expect("Failed to open chain rlp file");
Expand Down Expand Up @@ -51,6 +56,37 @@ pub fn generate_rlp(
Ok(())
}

pub fn generate_program_input(
genesis: Genesis,
chain: Vec<Block>,
block_number: usize,
) -> Result<ProgramInput, ProverInputError> {
let block = chain
.get(block_number)
.ok_or(ProverInputError::InvalidBlockNumber(block_number))?
.clone();

// create store
let store = Store::new("memory", EngineType::InMemory)?;
store.add_initial_state(genesis)?;
for block in chain {
add_block(&block, &store)?;
}

let parent_block_header = store
.get_block_header_by_hash(block.header.parent_hash)?
.ok_or(ProverInputError::InvalidParentBlock(
block.header.parent_hash,
))?;
let db = ExecutionDB::from_exec(&block, &store)?;

Ok(ProgramInput {
db,
block,
parent_block_header,
})
}

// From cmd/ethrex/decode.rs
fn _chain_file(file: File) -> Result<Vec<Block>, Box<dyn std::error::Error>> {
let mut chain_rlp_reader = BufReader::new(file);
Expand Down
2 changes: 1 addition & 1 deletion crates/vm/vm.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub mod db;
mod errors;
pub mod errors;
pub mod execution_db;
mod execution_result;
#[cfg(feature = "l2")]
Expand Down
Binary file added test_data/rsp/input/1/21272632.bin
Binary file not shown.