Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.

Commit ad0a57b

Browse files
adria0ChihChengLiangCPerezz
authored
Integration tests for tx, copy and bytecode circuits (#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 <chihchengliang@gmail.com> * Address @ChihChengLiang comments * fix clippy lint Co-authored-by: adria0 <nowhere@> Co-authored-by: Chih Cheng Liang <chihchengliang@gmail.com> Co-authored-by: CPerezz <c.perezbaro@gmail.com>
1 parent de17e38 commit ad0a57b

File tree

11 files changed

+350
-161
lines changed

11 files changed

+350
-161
lines changed

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bus-mapping/src/circuit_input_builder.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ impl<P: JsonRpcClient> BuilderClient<P> {
245245
) -> Result<(EthBlock, Vec<eth_types::GethExecTrace>), Error> {
246246
let eth_block = self.cli.get_block_by_number(block_num.into()).await?;
247247
let geth_traces = self.cli.trace_block_by_number(block_num.into()).await?;
248+
248249
Ok((eth_block, geth_traces))
249250
}
250251

@@ -352,12 +353,21 @@ impl<P: JsonRpcClient> BuilderClient<P> {
352353
}
353354

354355
/// Perform all the steps to generate the circuit inputs
355-
pub async fn gen_inputs(&self, block_num: u64) -> Result<CircuitInputBuilder, Error> {
356+
pub async fn gen_inputs(
357+
&self,
358+
block_num: u64,
359+
) -> Result<
360+
(
361+
CircuitInputBuilder,
362+
eth_types::Block<eth_types::Transaction>,
363+
),
364+
Error,
365+
> {
356366
let (eth_block, geth_traces) = self.get_block(block_num).await?;
357367
let access_set = self.get_state_accesses(&eth_block, &geth_traces)?;
358368
let (proofs, codes) = self.get_state(block_num, access_set).await?;
359369
let (state_db, code_db) = self.build_state_code_db(proofs, codes);
360370
let builder = self.gen_inputs_from_state(state_db, code_db, &eth_block, &geth_traces)?;
361-
Ok(builder)
371+
Ok((builder, eth_block))
362372
}
363373
}

integration-tests/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,17 @@ serde_json = "1.0.66"
1313
serde = {version = "1.0.130", features = ["derive"] }
1414
bus-mapping = { path = "../bus-mapping"}
1515
eth-types = { path = "../eth-types"}
16-
zkevm-circuits = { path = "../zkevm-circuits", features = ["test"] }
16+
zkevm-circuits = { path = "../zkevm-circuits", features = ["test", "dev"] }
1717
tokio = { version = "1.13", features = ["macros", "rt-multi-thread"] }
1818
url = "2.2.2"
1919
pretty_assertions = "1.0.0"
2020
log = "0.4.14"
2121
env_logger = "0.9"
2222
halo2_proofs = { version = "0.1.0-beta.1" }
2323
ff = "0.11"
24+
rand_chacha = "0.3"
25+
group = "0.11"
26+
paste = "1.0"
2427

2528
[dev-dependencies]
2629
pretty_assertions = "1.0.0"

integration-tests/tests/circuits.rs

Lines changed: 123 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,29 @@
22

33
use bus_mapping::circuit_input_builder::BuilderClient;
44
use bus_mapping::operation::OperationContainer;
5-
use halo2_proofs::dev::MockProver;
6-
use integration_tests::{get_client, log_init, GenDataOutput};
5+
use eth_types::geth_types;
6+
use group::{Curve, Group};
7+
use halo2_proofs::arithmetic::BaseExt;
8+
use halo2_proofs::{
9+
arithmetic::{CurveAffine, Field},
10+
dev::MockProver,
11+
pairing::bn256::Fr,
12+
};
13+
use integration_tests::{get_client, log_init, GenDataOutput, CHAIN_ID};
714
use lazy_static::lazy_static;
815
use log::trace;
16+
use paste::paste;
17+
use rand_chacha::rand_core::SeedableRng;
18+
use rand_chacha::ChaCha20Rng;
19+
use std::marker::PhantomData;
20+
use zkevm_circuits::bytecode_circuit::dev::test_bytecode_circuit;
21+
use zkevm_circuits::copy_circuit::dev::test_copy_circuit;
922
use zkevm_circuits::evm_circuit::witness::RwMap;
1023
use zkevm_circuits::evm_circuit::{test::run_test_circuit, witness::block_convert};
1124
use zkevm_circuits::state_circuit::StateCircuit;
25+
use zkevm_circuits::tx_circuit::{
26+
sign_verify::SignVerifyChip, Secp256k1Affine, TxCircuit, POW_RAND_SIZE, VERIF_HEIGHT,
27+
};
1228

1329
lazy_static! {
1430
pub static ref GEN_DATA: GenDataOutput = GenDataOutput::load();
@@ -18,19 +34,17 @@ async fn test_evm_circuit_block(block_num: u64) {
1834
log::info!("test evm circuit, block number: {}", block_num);
1935
let cli = get_client();
2036
let cli = BuilderClient::new(cli).await.unwrap();
21-
let builder = cli.gen_inputs(block_num).await.unwrap();
37+
let (builder, _) = cli.gen_inputs(block_num).await.unwrap();
2238

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

2743
async fn test_state_circuit_block(block_num: u64) {
28-
use halo2_proofs::pairing::bn256::Fr;
29-
3044
log::info!("test state circuit, block number: {}", block_num);
3145
let cli = get_client();
3246
let cli = BuilderClient::new(cli).await.unwrap();
33-
let builder = cli.gen_inputs(block_num).await.unwrap();
47+
let (builder, _) = cli.gen_inputs(block_num).await.unwrap();
3448

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

75+
async fn test_tx_circuit_block(block_num: u64) {
76+
const DEGREE: u32 = 20;
77+
78+
log::info!("test tx circuit, block number: {}", block_num);
79+
let cli = get_client();
80+
let cli = BuilderClient::new(cli).await.unwrap();
81+
82+
let (_, eth_block) = cli.gen_inputs(block_num).await.unwrap();
83+
let txs: Vec<_> = eth_block
84+
.transactions
85+
.iter()
86+
.map(geth_types::Transaction::from_eth_tx)
87+
.collect();
88+
89+
let mut rng = ChaCha20Rng::seed_from_u64(2);
90+
let aux_generator = <Secp256k1Affine as CurveAffine>::CurveExt::random(&mut rng).to_affine();
91+
92+
let randomness = Fr::random(&mut rng);
93+
let mut instance: Vec<Vec<Fr>> = (1..POW_RAND_SIZE + 1)
94+
.map(|exp| vec![randomness.pow(&[exp as u64, 0, 0, 0]); txs.len() * VERIF_HEIGHT])
95+
.collect();
96+
97+
instance.push(vec![]);
98+
let circuit = TxCircuit::<Fr, 4, { 4 * (4 + 32 + 32) }> {
99+
sign_verify: SignVerifyChip {
100+
aux_generator,
101+
window_size: 2,
102+
_marker: PhantomData,
103+
},
104+
randomness,
105+
txs,
106+
chain_id: CHAIN_ID,
107+
};
108+
109+
let prover = MockProver::run(DEGREE, &circuit, instance).unwrap();
110+
111+
prover.verify().expect("tx_circuit verification failed");
112+
}
113+
114+
pub async fn test_bytecode_circuit_block(block_num: u64) {
115+
const DEGREE: u32 = 16;
116+
let randomness = Fr::from(123456);
117+
118+
log::info!("test bytecode circuit, block number: {}", block_num);
119+
let cli = get_client();
120+
let cli = BuilderClient::new(cli).await.unwrap();
121+
let (builder, _) = cli.gen_inputs(block_num).await.unwrap();
122+
let bytecodes: Vec<Vec<u8>> = builder.code_db.0.values().cloned().collect();
123+
124+
test_bytecode_circuit(DEGREE, bytecodes, randomness);
125+
}
126+
127+
pub async fn test_copy_circuit_block(block_num: u64) {
128+
const DEGREE: u32 = 16;
129+
130+
log::info!("test copy circuit, block number: {}", block_num);
131+
let cli = get_client();
132+
let cli = BuilderClient::new(cli).await.unwrap();
133+
let (builder, _) = cli.gen_inputs(block_num).await.unwrap();
134+
let block = block_convert(&builder.block, &builder.code_db);
135+
136+
assert!(test_copy_circuit(DEGREE, block).is_ok());
137+
}
138+
61139
macro_rules! declare_tests {
62-
($test_evm_name:ident, $test_state_name:ident, $block_tag:expr) => {
63-
#[tokio::test]
64-
async fn $test_evm_name() {
65-
log_init();
66-
let block_num = GEN_DATA.blocks.get($block_tag).unwrap();
67-
test_evm_circuit_block(*block_num).await;
68-
}
140+
($name:ident, $block_tag:expr) => {
141+
paste! {
142+
#[tokio::test]
143+
async fn [<serial_test_evm_ $name>]() {
144+
log_init();
145+
let block_num = GEN_DATA.blocks.get($block_tag).unwrap();
146+
test_evm_circuit_block(*block_num).await;
147+
}
148+
149+
#[tokio::test]
150+
async fn [<serial_test_state_ $name>]() {
151+
log_init();
152+
let block_num = GEN_DATA.blocks.get($block_tag).unwrap();
153+
test_state_circuit_block(*block_num).await;
154+
}
155+
156+
#[tokio::test]
157+
async fn [<serial_test_tx_ $name>]() {
158+
log_init();
159+
let block_num = GEN_DATA.blocks.get($block_tag).unwrap();
160+
test_tx_circuit_block(*block_num).await;
161+
}
162+
163+
#[tokio::test]
164+
async fn [<serial_test_bytecode_ $name>]() {
165+
log_init();
166+
let block_num = GEN_DATA.blocks.get($block_tag).unwrap();
167+
test_bytecode_circuit_block(*block_num).await;
168+
}
169+
170+
#[tokio::test]
171+
async fn [<serial_test_copy_ $name>]() {
172+
log_init();
173+
let block_num = GEN_DATA.blocks.get($block_tag).unwrap();
174+
test_copy_circuit_block(*block_num).await;
175+
}
69176

70-
#[tokio::test]
71-
async fn $test_state_name() {
72-
log_init();
73-
let block_num = GEN_DATA.blocks.get($block_tag).unwrap();
74-
test_state_circuit_block(*block_num).await;
75177
}
76178
};
77179
}
@@ -94,17 +196,14 @@ declare_tests!(
94196
);
95197
*/
96198
declare_tests!(
97-
test_evm_circuit_erc20_openzeppelin_transfer_fail,
98-
test_state_circuit_erc20_openzeppelin_transfer_fail,
199+
circuit_erc20_openzeppelin_transfer_fail,
99200
"ERC20 OpenZeppelin transfer failed"
100201
);
101202
declare_tests!(
102-
test_evm_circuit_erc20_openzeppelin_transfer_succeed,
103-
test_state_circuit_erc20_openzeppelin_transfer_succeed,
203+
circuit_erc20_openzeppelin_transfer_succeed,
104204
"ERC20 OpenZeppelin transfer successful"
105205
);
106206
declare_tests!(
107-
test_evm_circuit_multiple_erc20_openzeppelin_transfers,
108-
test_state_circuit_multiple_erc20_openzeppelin_transfers,
207+
circuit_multiple_erc20_openzeppelin_transfers,
109208
"Multiple ERC20 OpenZeppelin transfers"
110209
);

prover/src/compute_proof.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub async fn compute_proof(
3434
let url = Http::from_str(rpc_url)?;
3535
let geth_client = GethClient::new(url);
3636
let builder = BuilderClient::new(geth_client).await?;
37-
let builder = builder.gen_inputs(*block_num).await?;
37+
let (builder, _) = builder.gen_inputs(*block_num).await?;
3838

3939
// TODO: only {evm,state}_proof are implemented right now
4040
let evm_proof;

zkevm-circuits/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,5 @@ harness = false
5959

6060
[features]
6161
default = []
62-
test = []
62+
test = [ "dev" ]
63+
dev = []
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
//! The bytecode circuit implementation.
22
33
pub(crate) mod bytecode_unroller;
4+
/// Bytecode circuit tester
5+
pub mod dev;
46
pub(crate) mod param;

0 commit comments

Comments
 (0)