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
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