Skip to content

Commit

Permalink
pad evm circuit to make vk/pk universal (privacy-scaling-explorations…
Browse files Browse the repository at this point in the history
…#728)

* pad evm circuit to make vk/pk universal

* lint

* fix merge

* fix tests
  • Loading branch information
lispc authored Sep 2, 2022
1 parent 2783eba commit 882b7df
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 60 deletions.
6 changes: 6 additions & 0 deletions zkevm-circuits/src/evm_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ pub mod test {

#[cfg(test)]
mod evm_circuit_stats {

use super::test::*;
use super::*;
use crate::evm_circuit::step::ExecutionState;
Expand All @@ -378,6 +379,11 @@ mod evm_circuit_stats {
use mock::test_ctx::{helpers::*, TestContext};
use strum::IntoEnumIterator;

#[test]
pub fn empty_evm_circuit() {
run_test_circuit(Block::<Fr>::default()).unwrap();
}

/// This function prints to stdout a table with all the implemented states
/// and their responsible opcodes with the following stats:
/// - height: number of rows used by the execution state
Expand Down
76 changes: 39 additions & 37 deletions zkevm-circuits/src/evm_circuit/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,7 @@ impl<F: Field> ExecutionConfig<F> {
&self,
layouter: &mut impl Layouter<F>,
block: &Block<F>,
_exact: bool,
exact: bool,
) -> Result<(), Error> {
let power_of_randomness = (1..32)
.map(|exp| block.randomness.pow(&[exp, 0, 0, 0]))
Expand All @@ -725,45 +725,29 @@ impl<F: Field> ExecutionConfig<F> {
let mut offset = 0;

self.q_step_first.enable(&mut region, offset)?;
// handle empty block conditions
if block.txs.is_empty() {
// if enable padding to fix length in the future, just change `end_row` to
// target length
let num_rows = 2;

for i in 0..num_rows {
self.q_usable.enable(&mut region, i)?;

for column in iter::empty()
.chain([
self.q_step,
self.num_rows_until_next_step,
self.num_rows_inv,
])
.chain(self.advices)
{
region
.assign_advice(
|| "assign advice rows",
column,
i,
|| Value::known(F::zero()),
)
.unwrap();
}
}

//adjust q_step_last to 1
self.q_step_last.enable(&mut region, num_rows - 1)?;

return Ok(());
}

// handle EndBlock
let dummy_tx = Transaction {
calls: vec![Default::default()],
..Default::default()
};
let last_tx = block.txs.last().unwrap_or(&dummy_tx);
let end_block_state = &ExecStep {
rw_counter: if block.txs.is_empty() {
0
} else {
// if it is the first tx, less 1 rw lookup, refer to end_tx gadget
last_tx.steps.last().unwrap().rw_counter + 9 - (last_tx.id == 1) as usize
},
execution_state: ExecutionState::EndBlock,
..Default::default()
};
// Collect all steps
let mut steps = block
.txs
.iter()
.flat_map(|tx| tx.steps.iter().map(move |step| (tx, step)))
.chain(iter::repeat((last_tx, end_block_state)))
.peekable();

let mut last_height = 0;
Expand Down Expand Up @@ -817,7 +801,28 @@ impl<F: Field> ExecutionConfig<F> {

offset += height;
last_height = height;

if step.execution_state == ExecutionState::EndBlock {
// evm_circuit_pad_to == 0 means no extra padding
if exact || block.evm_circuit_pad_to == 0 {
// no padding
break;
} else {
// padding
if offset >= block.evm_circuit_pad_to {
if offset > block.evm_circuit_pad_to {
log::warn!(
"evm circuit offset larger than padding: {} > {}",
offset,
block.evm_circuit_pad_to
);
}
break;
}
}
}
}

// These are still referenced (but not used) in next rows
region.assign_advice(
|| "step height",
Expand All @@ -832,9 +837,6 @@ impl<F: Field> ExecutionConfig<F> {
|| Value::known(F::zero()),
)?;

// If not exact:
// TODO: Pad leftover region to the desired capacity
// TODO: Enable q_step_last
self.q_step_last.enable(&mut region, offset - last_height)?;

Ok(())
Expand Down
2 changes: 1 addition & 1 deletion zkevm-circuits/src/evm_circuit/execution/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ mod test {
// wrong `gas_left` value for the second step, to assert that
// the circuit verification fails for this scenario.
assert_eq!(block.txs.len(), 1);
assert_eq!(block.txs[0].steps.len(), 5);
assert_eq!(block.txs[0].steps.len(), 4);
block.txs[0].steps[2].gas_left -= 1;
assert!(run_test_circuit(block).is_err());
}
Expand Down
28 changes: 6 additions & 22 deletions zkevm-circuits/src/evm_circuit/witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use halo2_proofs::arithmetic::FieldExt;
use halo2_proofs::halo2curves::bn256::Fr;
use itertools::Itertools;
use sha3::{Digest, Keccak256};
use std::{collections::HashMap, iter};
use std::collections::HashMap;

#[derive(Debug, Default, Clone)]
pub struct Block<F> {
Expand All @@ -40,6 +40,8 @@ pub struct Block<F> {
pub context: BlockContext,
/// Copy events for the EVM circuit's copy table.
pub copy_events: Vec<CopyEvent>,
/// Pad evm circuit to make selectors fixed, so vk/pk can be universal.
pub evm_circuit_pad_to: usize,
/// Length to rw table rows in state circuit
pub state_circuit_pad_to: usize,
/// Inputs to the SHA3 opcode
Expand Down Expand Up @@ -1359,7 +1361,7 @@ fn step_convert(step: &circuit_input_builder::ExecStep) -> ExecStep {
}
}

fn tx_convert(tx: &circuit_input_builder::Transaction, id: usize, is_last_tx: bool) -> Transaction {
fn tx_convert(tx: &circuit_input_builder::Transaction, id: usize) -> Transaction {
Transaction {
id,
nonce: tx.nonce,
Expand Down Expand Up @@ -1398,25 +1400,7 @@ fn tx_convert(tx: &circuit_input_builder::Transaction, id: usize, is_last_tx: bo
is_static: call.is_static,
})
.collect(),
steps: tx
.steps()
.iter()
.map(step_convert)
.chain(
(if is_last_tx {
Some(iter::once(ExecStep {
// if it is the first tx, less 1 rw lookup, refer to end_tx gadget
rw_counter: tx.steps().last().unwrap().rwc.0 + 9 - (id == 1) as usize,
execution_state: ExecutionState::EndBlock,
..Default::default()
}))
} else {
None
})
.into_iter()
.flatten(),
)
.collect(),
steps: tx.steps().iter().map(step_convert).collect(),
}
}

Expand All @@ -1432,7 +1416,7 @@ pub fn block_convert(
.txs()
.iter()
.enumerate()
.map(|(idx, tx)| tx_convert(tx, idx + 1, idx + 1 == block.txs().len()))
.map(|(idx, tx)| tx_convert(tx, idx + 1))
.collect(),
bytecodes: block
.txs()
Expand Down

0 comments on commit 882b7df

Please sign in to comment.