Skip to content

Commit

Permalink
Integration tests for tx, copy and bytecode circuits (privacy-scaling…
Browse files Browse the repository at this point in the history
…-explorations#654)

* Add tx circuit integation test

* use paste in macro function generation

* added bytecode integration test

* refactor

* fix merge

* Fix @pinkiebell comments

* make clippy happy

* Fix merge

* Prefix integration tests with serial_

* Update integration-tests/tests/circuits.rs

Co-authored-by: Chih Cheng Liang <[email protected]>

* Address @ChihChengLiang comments

* fix clippy lint

Co-authored-by: adria0 <nowhere@>
Co-authored-by: Chih Cheng Liang <[email protected]>
Co-authored-by: CPerezz <[email protected]>
  • Loading branch information
3 people authored Aug 16, 2022
1 parent de17e38 commit ad0a57b
Show file tree
Hide file tree
Showing 11 changed files with 350 additions and 161 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 12 additions & 2 deletions bus-mapping/src/circuit_input_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ impl<P: JsonRpcClient> BuilderClient<P> {
) -> Result<(EthBlock, Vec<eth_types::GethExecTrace>), Error> {
let eth_block = self.cli.get_block_by_number(block_num.into()).await?;
let geth_traces = self.cli.trace_block_by_number(block_num.into()).await?;

Ok((eth_block, geth_traces))
}

Expand Down Expand Up @@ -352,12 +353,21 @@ impl<P: JsonRpcClient> BuilderClient<P> {
}

/// Perform all the steps to generate the circuit inputs
pub async fn gen_inputs(&self, block_num: u64) -> Result<CircuitInputBuilder, Error> {
pub async fn gen_inputs(
&self,
block_num: u64,
) -> Result<
(
CircuitInputBuilder,
eth_types::Block<eth_types::Transaction>,
),
Error,
> {
let (eth_block, geth_traces) = self.get_block(block_num).await?;
let access_set = self.get_state_accesses(&eth_block, &geth_traces)?;
let (proofs, codes) = self.get_state(block_num, access_set).await?;
let (state_db, code_db) = self.build_state_code_db(proofs, codes);
let builder = self.gen_inputs_from_state(state_db, code_db, &eth_block, &geth_traces)?;
Ok(builder)
Ok((builder, eth_block))
}
}
5 changes: 4 additions & 1 deletion integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@ serde_json = "1.0.66"
serde = {version = "1.0.130", features = ["derive"] }
bus-mapping = { path = "../bus-mapping"}
eth-types = { path = "../eth-types"}
zkevm-circuits = { path = "../zkevm-circuits", features = ["test"] }
zkevm-circuits = { path = "../zkevm-circuits", features = ["test", "dev"] }
tokio = { version = "1.13", features = ["macros", "rt-multi-thread"] }
url = "2.2.2"
pretty_assertions = "1.0.0"
log = "0.4.14"
env_logger = "0.9"
halo2_proofs = { version = "0.1.0-beta.1" }
ff = "0.11"
rand_chacha = "0.3"
group = "0.11"
paste = "1.0"

[dev-dependencies]
pretty_assertions = "1.0.0"
Expand Down
147 changes: 123 additions & 24 deletions integration-tests/tests/circuits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,29 @@

use bus_mapping::circuit_input_builder::BuilderClient;
use bus_mapping::operation::OperationContainer;
use halo2_proofs::dev::MockProver;
use integration_tests::{get_client, log_init, GenDataOutput};
use eth_types::geth_types;
use group::{Curve, Group};
use halo2_proofs::arithmetic::BaseExt;
use halo2_proofs::{
arithmetic::{CurveAffine, Field},
dev::MockProver,
pairing::bn256::Fr,
};
use integration_tests::{get_client, log_init, GenDataOutput, CHAIN_ID};
use lazy_static::lazy_static;
use log::trace;
use paste::paste;
use rand_chacha::rand_core::SeedableRng;
use rand_chacha::ChaCha20Rng;
use std::marker::PhantomData;
use zkevm_circuits::bytecode_circuit::dev::test_bytecode_circuit;
use zkevm_circuits::copy_circuit::dev::test_copy_circuit;
use zkevm_circuits::evm_circuit::witness::RwMap;
use zkevm_circuits::evm_circuit::{test::run_test_circuit, witness::block_convert};
use zkevm_circuits::state_circuit::StateCircuit;
use zkevm_circuits::tx_circuit::{
sign_verify::SignVerifyChip, Secp256k1Affine, TxCircuit, POW_RAND_SIZE, VERIF_HEIGHT,
};

lazy_static! {
pub static ref GEN_DATA: GenDataOutput = GenDataOutput::load();
Expand All @@ -18,19 +34,17 @@ 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();
let (builder, _) = cli.gen_inputs(block_num).await.unwrap();

let block = block_convert(&builder.block, &builder.code_db);
run_test_circuit(block).expect("evm_circuit verification failed");
}

async fn test_state_circuit_block(block_num: u64) {
use halo2_proofs::pairing::bn256::Fr;

log::info!("test state 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();
let (builder, _) = cli.gen_inputs(block_num).await.unwrap();

// Generate state proof
let stack_ops = builder.block.container.sorted_stack();
Expand Down Expand Up @@ -58,20 +72,108 @@ async fn test_state_circuit_block(block_num: u64) {
prover.verify().expect("state_circuit verification failed");
}

async fn test_tx_circuit_block(block_num: u64) {
const DEGREE: u32 = 20;

log::info!("test tx circuit, block number: {}", block_num);
let cli = get_client();
let cli = BuilderClient::new(cli).await.unwrap();

let (_, eth_block) = cli.gen_inputs(block_num).await.unwrap();
let txs: Vec<_> = eth_block
.transactions
.iter()
.map(geth_types::Transaction::from_eth_tx)
.collect();

let mut rng = ChaCha20Rng::seed_from_u64(2);
let aux_generator = <Secp256k1Affine as CurveAffine>::CurveExt::random(&mut rng).to_affine();

let randomness = Fr::random(&mut rng);
let mut instance: Vec<Vec<Fr>> = (1..POW_RAND_SIZE + 1)
.map(|exp| vec![randomness.pow(&[exp as u64, 0, 0, 0]); txs.len() * VERIF_HEIGHT])
.collect();

instance.push(vec![]);
let circuit = TxCircuit::<Fr, 4, { 4 * (4 + 32 + 32) }> {
sign_verify: SignVerifyChip {
aux_generator,
window_size: 2,
_marker: PhantomData,
},
randomness,
txs,
chain_id: CHAIN_ID,
};

let prover = MockProver::run(DEGREE, &circuit, instance).unwrap();

prover.verify().expect("tx_circuit verification failed");
}

pub async fn test_bytecode_circuit_block(block_num: u64) {
const DEGREE: u32 = 16;
let randomness = Fr::from(123456);

log::info!("test bytecode 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();
let bytecodes: Vec<Vec<u8>> = builder.code_db.0.values().cloned().collect();

test_bytecode_circuit(DEGREE, bytecodes, randomness);
}

pub async fn test_copy_circuit_block(block_num: u64) {
const DEGREE: u32 = 16;

log::info!("test copy 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();
let block = block_convert(&builder.block, &builder.code_db);

assert!(test_copy_circuit(DEGREE, block).is_ok());
}

macro_rules! declare_tests {
($test_evm_name:ident, $test_state_name:ident, $block_tag:expr) => {
#[tokio::test]
async fn $test_evm_name() {
log_init();
let block_num = GEN_DATA.blocks.get($block_tag).unwrap();
test_evm_circuit_block(*block_num).await;
}
($name:ident, $block_tag:expr) => {
paste! {
#[tokio::test]
async fn [<serial_test_evm_ $name>]() {
log_init();
let block_num = GEN_DATA.blocks.get($block_tag).unwrap();
test_evm_circuit_block(*block_num).await;
}

#[tokio::test]
async fn [<serial_test_state_ $name>]() {
log_init();
let block_num = GEN_DATA.blocks.get($block_tag).unwrap();
test_state_circuit_block(*block_num).await;
}

#[tokio::test]
async fn [<serial_test_tx_ $name>]() {
log_init();
let block_num = GEN_DATA.blocks.get($block_tag).unwrap();
test_tx_circuit_block(*block_num).await;
}

#[tokio::test]
async fn [<serial_test_bytecode_ $name>]() {
log_init();
let block_num = GEN_DATA.blocks.get($block_tag).unwrap();
test_bytecode_circuit_block(*block_num).await;
}

#[tokio::test]
async fn [<serial_test_copy_ $name>]() {
log_init();
let block_num = GEN_DATA.blocks.get($block_tag).unwrap();
test_copy_circuit_block(*block_num).await;
}

#[tokio::test]
async fn $test_state_name() {
log_init();
let block_num = GEN_DATA.blocks.get($block_tag).unwrap();
test_state_circuit_block(*block_num).await;
}
};
}
Expand All @@ -94,17 +196,14 @@ declare_tests!(
);
*/
declare_tests!(
test_evm_circuit_erc20_openzeppelin_transfer_fail,
test_state_circuit_erc20_openzeppelin_transfer_fail,
circuit_erc20_openzeppelin_transfer_fail,
"ERC20 OpenZeppelin transfer failed"
);
declare_tests!(
test_evm_circuit_erc20_openzeppelin_transfer_succeed,
test_state_circuit_erc20_openzeppelin_transfer_succeed,
circuit_erc20_openzeppelin_transfer_succeed,
"ERC20 OpenZeppelin transfer successful"
);
declare_tests!(
test_evm_circuit_multiple_erc20_openzeppelin_transfers,
test_state_circuit_multiple_erc20_openzeppelin_transfers,
circuit_multiple_erc20_openzeppelin_transfers,
"Multiple ERC20 OpenZeppelin transfers"
);
2 changes: 1 addition & 1 deletion prover/src/compute_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub async fn compute_proof(
let url = Http::from_str(rpc_url)?;
let geth_client = GethClient::new(url);
let builder = BuilderClient::new(geth_client).await?;
let builder = builder.gen_inputs(*block_num).await?;
let (builder, _) = builder.gen_inputs(*block_num).await?;

// TODO: only {evm,state}_proof are implemented right now
let evm_proof;
Expand Down
3 changes: 2 additions & 1 deletion zkevm-circuits/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,5 @@ harness = false

[features]
default = []
test = []
test = [ "dev" ]
dev = []
2 changes: 2 additions & 0 deletions zkevm-circuits/src/bytecode_circuit.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
//! The bytecode circuit implementation.
pub(crate) mod bytecode_unroller;
/// Bytecode circuit tester
pub mod dev;
pub(crate) mod param;
Loading

0 comments on commit ad0a57b

Please sign in to comment.