Skip to content
This repository was archived by the owner on Apr 18, 2025. It is now read-only.

scroll-dev-0521 #158

Closed
wants to merge 14 commits into from
Closed
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
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
push:
branches:
- main
- scroll-dev-0521

## `actions-rs/toolchain@v1` overwrite set to false so that
## `rust-toolchain` is always used and the only source of truth.
Expand Down
23 changes: 21 additions & 2 deletions bus-mapping/src/circuit_input_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ pub use access::{Access, AccessSet, AccessValue, CodeSource};
pub use block::{Block, BlockContext};
pub use call::{Call, CallContext, CallKind};
use core::fmt::Debug;
use eth_types::{self, Address, GethExecStep, GethExecTrace, Word};
use eth_types::evm_types::GasCost;
use eth_types::{self, Address, GethExecStep, GethExecTrace, ToWord, Word};
use ethers_providers::JsonRpcClient;
pub use execution::{CopyDetails, ExecState, ExecStep, StepAuxiliaryData};
pub use input_state_ref::CircuitInputStateRef;
Expand Down Expand Up @@ -141,6 +142,14 @@ impl<'a> CircuitInputBuilder {
let mut cumulative_gas_used = HashMap::new();
for (tx_index, tx) in eth_block.transactions.iter().enumerate() {
let geth_trace = &geth_traces[tx_index];
if geth_trace.struct_logs.is_empty() {
log::warn!("Native transfer transaction is left unimplemented");
continue;
}
if tx.to.is_none() {
log::warn!("Creation transaction is left unimplemented");
continue;
}
self.handle_tx(
tx,
geth_trace,
Expand All @@ -167,11 +176,21 @@ impl<'a> CircuitInputBuilder {
let mut tx = self.new_tx(eth_tx, !geth_trace.failed)?;
let mut tx_ctx = TransactionContext::new(eth_tx, geth_trace, is_last_tx)?;

if let Some(al) = &eth_tx.access_list {
for item in &al.0 {
self.sdb.add_account_to_access_list(item.address);
for k in &item.storage_keys {
self.sdb
.add_account_storage_to_access_list((item.address, (*k).to_word()));
}
}
}
// TODO: Move into gen_associated_steps with
// - execution_state: BeginTx
// - op: None
// Generate BeginTx step
let begin_tx_step = gen_begin_tx_ops(&mut self.state_ref(&mut tx, &mut tx_ctx))?;
let mut begin_tx_step = gen_begin_tx_ops(&mut self.state_ref(&mut tx, &mut tx_ctx))?;
begin_tx_step.gas_cost = GasCost(tx.gas - geth_trace.struct_logs[0].gas.0);
tx.steps_mut().push(begin_tx_step);

for (index, geth_step) in geth_trace.struct_logs.iter().enumerate() {
Expand Down
5 changes: 3 additions & 2 deletions bus-mapping/src/evm/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ fn fn_gen_associated_ops(opcode_id: &OpcodeId) -> FnGenAssociatedOps {
OpcodeId::SHL => StackOnlyOpcode::<2, 1>::gen_associated_ops,
OpcodeId::SHR => StackOnlyOpcode::<2, 1>::gen_associated_ops,
OpcodeId::SAR => StackOnlyOpcode::<2, 1>::gen_associated_ops,
// OpcodeId::SHA3 => {},
OpcodeId::SHA3 => StackOnlyOpcode::<2, 1>::gen_associated_ops,
// OpcodeId::ADDRESS => {},
// OpcodeId::BALANCE => {},
OpcodeId::ORIGIN => Origin::gen_associated_ops,
Expand Down Expand Up @@ -191,7 +191,7 @@ fn fn_gen_associated_ops(opcode_id: &OpcodeId) -> FnGenAssociatedOps {
// OpcodeId::LOG0 => {},
// OpcodeId::LOG1 => {},
// OpcodeId::LOG2 => {},
// OpcodeId::LOG3 => {},
OpcodeId::LOG3 => StackOnlyOpcode::<5, 0>::gen_associated_ops,
// OpcodeId::LOG4 => {},
// OpcodeId::CREATE => {},
OpcodeId::CALL => Call::gen_associated_ops,
Expand All @@ -203,6 +203,7 @@ fn fn_gen_associated_ops(opcode_id: &OpcodeId) -> FnGenAssociatedOps {
// OpcodeId::STATICCALL => {},
// TODO: Handle REVERT by its own gen_associated_ops.
OpcodeId::REVERT => Stop::gen_associated_ops,
OpcodeId::INVALID(_) => Stop::gen_associated_ops,
OpcodeId::SELFDESTRUCT => {
warn!("Using dummy gen_selfdestruct_ops for opcode SELFDESTRUCT");
dummy_gen_selfdestruct_ops
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ ff = "0.11"
pretty_assertions = "1.0.0"

[features]
default = []
default = ["circuits"]
rpc = []
circuit_input_builder = []
circuits = []
13 changes: 10 additions & 3 deletions integration-tests/src/bin/gen_blockchain_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use ethers::{
},
core::utils::WEI_IN_ETHER,
middleware::SignerMiddleware,
prelude::NonceManagerMiddleware,
providers::{Middleware, PendingTransaction},
signers::Signer,
solc::Solc,
Expand Down Expand Up @@ -169,7 +170,10 @@ async fn main() {
//

let mut deployments = HashMap::new();
let prov_wallet0 = Arc::new(SignerMiddleware::new(get_provider(), wallet0));
let prov_wallet0 = Arc::new(NonceManagerMiddleware::new(
SignerMiddleware::new(get_provider(), wallet0.clone()),
wallet0.address(),
));

// Greeter
let contract = deploy(
Expand All @@ -191,7 +195,7 @@ async fn main() {
contracts
.get("OpenZeppelinERC20TestToken")
.expect("contract not found"),
prov_wallet0.address(),
wallet0.address(),
)
.await;
let block_num = prov.get_block_number().await.expect("cannot get block_num");
Expand Down Expand Up @@ -322,14 +326,17 @@ async fn main() {
for (i, (from_i, to_i)) in [(0, 1), (2, 3), (1, 0), (3, 2)].iter().enumerate() {
let amount = U256::from(0x800000000000000 / (i + 1));
let prov_wallet = &wallets[*from_i];
let tx = erc20_transfer(
let mut tx = erc20_transfer(
prov_wallet.clone(),
contract_address,
contract_abi,
wallets[*to_i].address(),
amount,
);

prov_wallet.fill_transaction(&mut tx, None).await.unwrap();
tx.set_gas(100_000u64);

let pending_tx = prov_wallet
.send_transaction(tx, None)
.await
Expand Down
12 changes: 12 additions & 0 deletions integration-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ lazy_static! {
Err(VarError::NotPresent) => GETH0_URL_DEFAULT.to_string(),
Err(e) => panic!("Error in GETH0_URL env var: {:?}", e),
};
/// ..
pub static ref START_BLOCK: usize = match env::var("START_BLOCK") {
Ok(val) => str::parse::<usize>(&val).unwrap(),
Err(VarError::NotPresent) => 1,
Err(e) => panic!("Error in START_BLOCK env var: {:?}", e),
};
/// ..
pub static ref END_BLOCK: usize = match env::var("END_BLOCK") {
Ok(val) => str::parse::<usize>(&val).unwrap(),
Err(VarError::NotPresent) => 8,
Err(e) => panic!("Error in END_BLOCK env var: {:?}", e),
};
}

static LOG_INIT: Once = Once::new();
Expand Down
42 changes: 37 additions & 5 deletions integration-tests/tests/circuits.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,60 @@
#![cfg(feature = "circuits")]

use bus_mapping::circuit_input_builder::BuilderClient;
use bus_mapping::circuit_input_builder::{BuilderClient, ExecState};
use bus_mapping::evm::OpcodeId;
use bus_mapping::operation::OperationContainer;
use halo2_proofs::dev::MockProver;
use integration_tests::{get_client, log_init, GenDataOutput};
use integration_tests::{get_client, log_init, GenDataOutput, END_BLOCK, START_BLOCK};
use lazy_static::lazy_static;
use log::trace;
use zkevm_circuits::evm_circuit::witness::RwMap;
use zkevm_circuits::evm_circuit::{
test::run_test_circuit_complete_fixed_table, witness::block_convert,
test::run_test_circuit_complete_fixed_table, test::run_test_circuit_incomplete_fixed_table,
witness::block_convert,
};
use zkevm_circuits::state_circuit::StateCircuit;

lazy_static! {
pub static ref GEN_DATA: GenDataOutput = GenDataOutput::load();
}

#[tokio::test]
async fn test_evm_circuit_all_block() {
log_init();
let start: usize = *START_BLOCK;
let end: usize = *END_BLOCK;
for blk in start..=end {
test_evm_circuit_block(blk as u64).await;
}
}

async fn test_evm_circuit_block(block_num: u64) {
log::info!("test evm circuit, block number: {}", block_num);
let cli = get_client();
let cli = BuilderClient::new(cli).await.unwrap();
let builder = cli.gen_inputs(block_num).await.unwrap();

if builder.block.txs.is_empty() {
log::info!("skip empty block");
return;
}

let block = block_convert(&builder.block, &builder.code_db);
run_test_circuit_complete_fixed_table(block).expect("evm_circuit verification failed");
let need_bitwise_lookup = builder.block.txs.iter().any(|tx| {
tx.steps().iter().any(|step| {
matches!(
step.exec_state,
ExecState::Op(OpcodeId::ADD)
| ExecState::Op(OpcodeId::OR)
| ExecState::Op(OpcodeId::XOR)
)
})
});
if need_bitwise_lookup {
run_test_circuit_complete_fixed_table(block).expect("evm_circuit verification failed");
} else {
run_test_circuit_incomplete_fixed_table(block).expect("evm_circuit verification failed");
}
}

async fn test_state_circuit_block(block_num: u64) {
Expand All @@ -46,7 +78,7 @@ async fn test_state_circuit_block(block_num: u64) {
let rw_map = RwMap::from(&OperationContainer {
memory: memory_ops,
stack: stack_ops,
storage: storage_ops,
//storage: storage_ops,
..Default::default()
});

Expand Down
36 changes: 24 additions & 12 deletions prover/src/bin/prover_cmd.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use env_logger::Env;
use halo2_proofs::pairing::bn256::G1Affine;
use halo2_proofs::pairing::bn256::{Bn256, G1Affine};
use halo2_proofs::poly::commitment::Params;
use std::env::var;
use std::fs::File;
use std::io::BufReader;
use std::{env::var, fs::File, io::BufReader};

use prover::compute_proof::compute_proof;

Expand All @@ -24,15 +22,29 @@ async fn main() {
.expect("RPC_URL env var")
.parse()
.expect("Cannot parse RPC_URL env var");
let params_path: String = var("PARAMS_PATH")
.expect("PARAMS_PATH env var")
.parse()
.expect("Cannot parse PARAMS_PATH env var");

// load polynomial commitment parameters
let params_fs = File::open(&params_path).expect("couldn't open params");
let params: Params<G1Affine> =
Params::read::<_>(&mut BufReader::new(params_fs)).expect("Failed to read params");
let params_path: String = match var("PARAMS_PATH") {
Ok(path) => path,
Err(e) => {
log::warn!(
"PARAMS_PATH env var is invalid: {:?}. Params will be setup locally.",
e
);
"".to_string()
}
};

let params: Params<G1Affine> = if params_path.is_empty() {
let degree = 18;
log::debug!("setup with degree {}", degree);
let params: Params<G1Affine> = Params::<G1Affine>::unsafe_setup::<Bn256>(degree);
log::debug!("setup done");
params
} else {
// load polynomial commitment parameters from file
let params_fs = File::open(&params_path).expect("couldn't open params");
Params::read::<_>(&mut BufReader::new(params_fs)).expect("Failed to read params")
};

let result = compute_proof(&params, &block_num, &rpc_url)
.await
Expand Down
46 changes: 21 additions & 25 deletions zkevm-circuits/src/evm_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,21 +141,23 @@ impl<F: Field> EvmCircuit<F> {

#[cfg(any(feature = "test", test))]
pub mod test {

use std::convert::TryInto;

use crate::{
evm_circuit::{
table::FixedTableTag,
witness::{Block, BlockContext, Bytecode, RwMap, Transaction},
EvmCircuit,
},
rw_table::RwTable,
util::Expr,
util::DEFAULT_RAND,
};
use eth_types::{Field, Word};
use halo2_proofs::{
circuit::{Layouter, SimpleFloorPlanner},
dev::{MockProver, VerifyFailure},
plonk::{Advice, Circuit, Column, ConstraintSystem, Error},
poly::Rotation,
plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Expression},
};
use itertools::Itertools;
use rand::{
Expand Down Expand Up @@ -375,20 +377,11 @@ pub mod test {
let bytecode_table = [(); 5].map(|_| meta.advice_column());
let block_table = [(); 3].map(|_| meta.advice_column());

let power_of_randomness = {
let columns = [(); 31].map(|_| meta.instance_column());
let mut power_of_randomness = None;

meta.create_gate("", |meta| {
power_of_randomness =
Some(columns.map(|column| meta.query_instance(column, Rotation::cur())));

[0.expr()]
});

power_of_randomness.unwrap()
};

let power_of_randomness: [Expression<F>; 31] = (1..32)
.map(|exp| Expression::Constant(F::from_u128(DEFAULT_RAND).pow(&[exp, 0, 0, 0])))
.collect::<Vec<_>>()
.try_into()
.unwrap();
Self::Config {
tx_table,
rw_table,
Expand Down Expand Up @@ -418,9 +411,14 @@ pub mod test {
config.load_rws(&mut layouter, &self.block.rws, self.block.randomness)?;
config.load_bytecodes(&mut layouter, &self.block.bytecodes, self.block.randomness)?;
config.load_block(&mut layouter, &self.block.context, self.block.randomness)?;
config
.evm_circuit
.assign_block_exact(&mut layouter, &self.block)
if self.block.pad_to != 0 {
config.evm_circuit.assign_block(&mut layouter, &self.block)
} else {
config
.evm_circuit
.assign_block_exact(&mut layouter, &self.block)
}?;
Ok(())
}
}

Expand Down Expand Up @@ -461,13 +459,11 @@ pub mod test {
));
let k = k.max(log2_ceil(64 + num_rows_required_for_steps));
log::debug!("evm circuit uses k = {}", k);

let power_of_randomness = (1..32)
.map(|exp| vec![block.randomness.pow(&[exp, 0, 0, 0]); (1 << k) - 64])
.collect();
let (active_gate_rows, active_lookup_rows) = TestCircuit::get_active_rows(&block);
let block = block;
//block.pad_to = (1 << k) - 64;
let circuit = TestCircuit::<F>::new(block, fixed_table_tags);
let prover = MockProver::<F>::run(k, &circuit, power_of_randomness).unwrap();
let prover = MockProver::<F>::run(k, &circuit, vec![]).unwrap();
prover.verify_at_rows(active_gate_rows.into_iter(), active_lookup_rows.into_iter())
}

Expand Down
Loading