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

Commit 2aa9875

Browse files
z2trillionz2trillion
and
z2trillion
authored
Pad StateCircuit to a fixed length (#558)
* Add failing test * Add Rw::Padding * Add padding rows to state circuit to fix test * Fix degree test and add comment * Add rw_counter to Start for padding * Ignore start test for now * Remove Rw::Padding * Fix test and cleanup * Add rw_counter constraint for Rw::Start and comment * Allow overrides in padding * Update tests * Make state circuit generic over N_ROWS and fix constraint names * Fix tests and build Co-authored-by: z2trillion <[email protected]>
1 parent 50c5194 commit 2aa9875

File tree

8 files changed

+141
-56
lines changed

8 files changed

+141
-56
lines changed

Diff for: circuit-benchmarks/src/state_circuit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ mod tests {
1717
#[cfg_attr(not(feature = "benches"), ignore)]
1818
#[test]
1919
fn bench_state_circuit_prover() {
20-
let empty_circuit = StateCircuit::<Fr>::default();
20+
let empty_circuit = StateCircuit::<Fr, { 1 << 16 }>::default();
2121

2222
// Initialize the polynomial commitment parameters
2323
let rng = XorShiftRng::from_seed([

Diff for: integration-tests/tests/circuits.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ async fn test_state_circuit_block(block_num: u64) {
5353
});
5454

5555
let randomness = Fr::rand();
56-
let circuit = StateCircuit::<Fr>::new(randomness, rw_map);
56+
let circuit = StateCircuit::<Fr, { 1 << 16 }>::new(randomness, rw_map);
5757
let power_of_randomness = circuit.instance();
5858

5959
use halo2_proofs::pairing::bn256::Fr as Fp;

Diff for: prover/src/compute_proof.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ pub async fn compute_proof(
6161

6262
{
6363
// generate state_circuit proof
64-
let circuit = StateCircuit::new(block.randomness, block.rws);
64+
const N_ROWS: usize = 1 << 16;
65+
let circuit = StateCircuit::<Fr, N_ROWS>::new(block.randomness, block.rws);
6566

6667
// TODO: same quest like in the first scope
6768
let vk = keygen_vk(params, &circuit)?;

Diff for: zkevm-circuits/src/evm_circuit/witness.rs

+13-11
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,9 @@ impl RwMap {
431431

432432
#[derive(Clone, Copy, Debug)]
433433
pub enum Rw {
434-
Start,
434+
Start {
435+
rw_counter: usize,
436+
},
435437
TxAccessListAccount {
436438
rw_counter: usize,
437439
is_write: bool,
@@ -675,8 +677,8 @@ impl Rw {
675677

676678
pub fn rw_counter(&self) -> usize {
677679
match self {
678-
Self::Start => 0,
679-
Self::Memory { rw_counter, .. }
680+
Self::Start { rw_counter }
681+
| Self::Memory { rw_counter, .. }
680682
| Self::Stack { rw_counter, .. }
681683
| Self::AccountStorage { rw_counter, .. }
682684
| Self::TxAccessListAccount { rw_counter, .. }
@@ -692,7 +694,7 @@ impl Rw {
692694

693695
pub fn is_write(&self) -> bool {
694696
match self {
695-
Self::Start => false,
697+
Self::Start { .. } => false,
696698
Self::Memory { is_write, .. }
697699
| Self::Stack { is_write, .. }
698700
| Self::AccountStorage { is_write, .. }
@@ -709,7 +711,7 @@ impl Rw {
709711

710712
pub fn tag(&self) -> RwTableTag {
711713
match self {
712-
Self::Start => RwTableTag::Start,
714+
Self::Start { .. } => RwTableTag::Start,
713715
Self::Memory { .. } => RwTableTag::Memory,
714716
Self::Stack { .. } => RwTableTag::Stack,
715717
Self::AccountStorage { .. } => RwTableTag::AccountStorage,
@@ -735,7 +737,7 @@ impl Rw {
735737
Self::CallContext { call_id, .. }
736738
| Self::Stack { call_id, .. }
737739
| Self::Memory { call_id, .. } => Some(*call_id),
738-
Self::Start | Self::Account { .. } | Self::AccountDestructed { .. } => None,
740+
Self::Start { .. } | Self::Account { .. } | Self::AccountDestructed { .. } => None,
739741
}
740742
}
741743

@@ -763,7 +765,7 @@ impl Rw {
763765
Self::TxLog { log_id, index, .. } => {
764766
Some((U256::from(*index as u64) + (U256::from(*log_id) << 8)).to_address())
765767
}
766-
Self::Start
768+
Self::Start { .. }
767769
| Self::CallContext { .. }
768770
| Self::TxRefund { .. }
769771
| Self::TxReceipt { .. } => None,
@@ -776,7 +778,7 @@ impl Rw {
776778
Self::CallContext { field_tag, .. } => Some(*field_tag as u64),
777779
Self::TxLog { field_tag, .. } => Some(*field_tag as u64),
778780
Self::TxReceipt { field_tag, .. } => Some(*field_tag as u64),
779-
Self::Start
781+
Self::Start { .. }
780782
| Self::Memory { .. }
781783
| Self::Stack { .. }
782784
| Self::AccountStorage { .. }
@@ -791,7 +793,7 @@ impl Rw {
791793
match self {
792794
Self::AccountStorage { storage_key, .. }
793795
| Self::TxAccessListAccountStorage { storage_key, .. } => Some(*storage_key),
794-
Self::Start
796+
Self::Start { .. }
795797
| Self::CallContext { .. }
796798
| Self::Stack { .. }
797799
| Self::Memory { .. }
@@ -806,7 +808,7 @@ impl Rw {
806808

807809
pub fn value_assignment<F: Field>(&self, randomness: F) -> F {
808810
match self {
809-
Self::Start => F::zero(),
811+
Self::Start { .. } => F::zero(),
810812
Self::CallContext {
811813
field_tag, value, ..
812814
} => {
@@ -861,7 +863,7 @@ impl Rw {
861863
is_destructed_prev, ..
862864
} => Some(F::from(*is_destructed_prev as u64)),
863865
Self::TxRefund { value_prev, .. } => Some(F::from(*value_prev)),
864-
Self::Start
866+
Self::Start { .. }
865867
| Self::Stack { .. }
866868
| Self::Memory { .. }
867869
| Self::CallContext { .. }

Diff for: zkevm-circuits/src/state_circuit.rs

+20-11
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,14 @@ type Lookup<F> = (&'static str, Expression<F>, Expression<F>);
6363

6464
/// State Circuit for proving RwTable is valid
6565
#[derive(Default)]
66-
pub struct StateCircuit<F: Field> {
66+
pub struct StateCircuit<F: Field, const N_ROWS: usize> {
6767
pub(crate) randomness: F,
6868
pub(crate) rows: Vec<Rw>,
6969
#[cfg(test)]
70-
overrides: HashMap<(test::AdviceColumn, usize), F>,
70+
overrides: HashMap<(test::AdviceColumn, isize), F>,
7171
}
7272

73-
impl<F: Field> StateCircuit<F> {
73+
impl<F: Field, const N_ROWS: usize> StateCircuit<F, N_ROWS> {
7474
/// make a new state circuit from an RwMap
7575
pub fn new(randomness: F, rw_map: RwMap) -> Self {
7676
let mut rows: Vec<_> = rw_map.0.into_values().flatten().collect();
@@ -95,12 +95,12 @@ impl<F: Field> StateCircuit<F> {
9595
/// powers of randomness for instance columns
9696
pub fn instance(&self) -> Vec<Vec<F>> {
9797
(1..32)
98-
.map(|exp| vec![self.randomness.pow(&[exp, 0, 0, 0]); self.rows.len() + 1])
98+
.map(|exp| vec![self.randomness.pow(&[exp, 0, 0, 0]); N_ROWS])
9999
.collect()
100100
}
101101
}
102102

103-
impl<F: Field> Circuit<F> for StateCircuit<F> {
103+
impl<F: Field, const N_ROWS: usize> Circuit<F> for StateCircuit<F, N_ROWS> {
104104
type Config = StateConfig<F>;
105105
type FloorPlanner = SimpleFloorPlanner;
106106

@@ -201,8 +201,12 @@ impl<F: Field> Circuit<F> for StateCircuit<F> {
201201
layouter.assign_region(
202202
|| "rw table",
203203
|mut region| {
204-
let rows = once(&Rw::Start).chain(&self.rows);
205-
let prev_rows = once(&Rw::Start).chain(rows.clone());
204+
let padding_length = N_ROWS - self.rows.len();
205+
let padding = (1..=padding_length).map(|rw_counter| Rw::Start { rw_counter });
206+
207+
let rows = padding.chain(self.rows.iter().cloned());
208+
let prev_rows = once(None).chain(rows.clone().map(Some));
209+
206210
for (offset, (row, prev_row)) in rows.zip(prev_rows).enumerate() {
207211
region.assign_fixed(|| "selector", config.selector, offset, || Ok(F::one()))?;
208212
config
@@ -244,8 +248,8 @@ impl<F: Field> Circuit<F> for StateCircuit<F> {
244248
|| Ok(row.value_assignment(self.randomness)),
245249
)?;
246250

247-
if offset != 0 {
248-
lexicographic_ordering_chip.assign(&mut region, offset, row, prev_row)?;
251+
if let Some(prev_row) = prev_row {
252+
lexicographic_ordering_chip.assign(&mut region, offset, &row, &prev_row)?;
249253

250254
let id_change = F::from(row.id().unwrap_or_default() as u64)
251255
- F::from(prev_row.id().unwrap_or_default() as u64);
@@ -267,9 +271,12 @@ impl<F: Field> Circuit<F> for StateCircuit<F> {
267271
}
268272

269273
#[cfg(test)]
270-
for ((column, offset), &f) in &self.overrides {
274+
for ((column, row_offset), &f) in &self.overrides {
271275
let advice_column = column.value(&config);
272-
region.assign_advice(|| "override", advice_column, *offset, || Ok(f))?;
276+
let offset =
277+
usize::try_from(isize::try_from(padding_length).unwrap() + *row_offset)
278+
.unwrap();
279+
region.assign_advice(|| "override", advice_column, offset, || Ok(f))?;
273280
}
274281

275282
Ok(())
@@ -281,6 +288,8 @@ impl<F: Field> Circuit<F> for StateCircuit<F> {
281288
fn queries<F: Field>(meta: &mut VirtualCells<'_, F>, c: &StateConfig<F>) -> Queries<F> {
282289
Queries {
283290
selector: meta.query_fixed(c.selector, Rotation::cur()),
291+
lexicographic_ordering_selector: meta
292+
.query_fixed(c.lexicographic_ordering.selector, Rotation::cur()),
284293
rw_counter: MpiQueries::new(meta, c.rw_counter),
285294
is_write: meta.query_advice(c.is_write, Rotation::cur()),
286295
tag: c.tag.value(Rotation::cur())(meta),

Diff for: zkevm-circuits/src/state_circuit/constraint_builder.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use strum::IntoEnumIterator;
1717
#[derive(Clone)]
1818
pub struct Queries<F: Field> {
1919
pub selector: Expression<F>,
20+
pub lexicographic_ordering_selector: Expression<F>,
2021
pub rw_counter: MpiQueries<F, N_LIMBS_RW_COUNTER>,
2122
pub is_write: Expression<F>,
2223
pub tag: Expression<F>,
@@ -104,7 +105,14 @@ impl<F: Field> ConstraintBuilder<F> {
104105
}
105106

106107
fn build_start_constraints(&mut self, q: &Queries<F>) {
107-
self.require_zero("rw_counter is 0 for Start", q.rw_counter.value.clone());
108+
self.require_zero("field_tag is 0 for Start", q.field_tag());
109+
self.require_zero("address is 0 for Start", q.address.value.clone());
110+
self.require_zero("id is 0 for Start", q.id());
111+
self.require_zero("storage_key is 0 for Start", q.storage_key.encoded.clone());
112+
self.require_zero(
113+
"rw_counter increases by 1 for every non-first row",
114+
q.lexicographic_ordering_selector.clone() * (q.rw_counter_change() - 1.expr()),
115+
);
108116
}
109117

110118
fn build_memory_constraints(&mut self, q: &Queries<F>) {
@@ -308,6 +316,10 @@ impl<F: Field> Queries<F> {
308316
fn address_change(&self) -> Expression<F> {
309317
self.address.value.clone() - self.address.value_prev.clone()
310318
}
319+
320+
fn rw_counter_change(&self) -> Expression<F> {
321+
self.rw_counter.value.clone() - self.rw_counter.value_prev.clone()
322+
}
311323
}
312324

313325
fn from_digits<F: Field>(digits: &[Expression<F>], base: Expression<F>) -> Expression<F> {

0 commit comments

Comments
 (0)