From 1cb389e5f5c7dfe8e2e130451c6299f3947d2fb4 Mon Sep 17 00:00:00 2001 From: Ho Vei Date: Wed, 11 Jan 2023 22:12:04 +0800 Subject: [PATCH 01/17] better organize of mpt table --- src/eth.rs | 74 +++++++++++++----------------------------------------- src/lib.rs | 42 ++++++++++++++++++++++++------- src/mpt.rs | 47 +++++++++++++++++++--------------- 3 files changed, 78 insertions(+), 85 deletions(-) diff --git a/src/eth.rs b/src/eth.rs index 266a86db..bebe0379 100644 --- a/src/eth.rs +++ b/src/eth.rs @@ -423,21 +423,11 @@ impl<'d, Fp: FieldExt> AccountChip<'d, Fp> { let ctrl_type = meta.query_advice(ctrl_type, Rotation::cur()); let enable_rows = Self::lagrange_polynomial_for_row::<2>(ctrl_type); let enable = enable_rows * s_enable; + let fst = meta.query_advice(acc_data_fields, Rotation::cur()); + let snd = meta.query_advice(acc_data_fields_ext, Rotation::cur()); + let hash = meta.query_advice(intermediate_1, Rotation::cur()); - vec![ - ( - enable.clone() * meta.query_advice(acc_data_fields, Rotation::cur()), - meta.query_advice(hash_table.0, Rotation::cur()), - ), - ( - enable.clone() * meta.query_advice(acc_data_fields_ext, Rotation::cur()), - meta.query_advice(hash_table.1, Rotation::cur()), - ), - ( - enable * meta.query_advice(intermediate_1, Rotation::cur()), - meta.query_advice(hash_table.2, Rotation::cur()), - ), - ] + hash_table.build_lookup(meta, enable, fst, snd, hash) }); // second hash lookup (Poseidon(hash1, Root) = hash2, Poseidon(hash3, hash2) = hash_final) @@ -448,21 +438,11 @@ impl<'d, Fp: FieldExt> AccountChip<'d, Fp> { let enable_rows = Self::lagrange_polynomial_for_row::<1>(ctrl_type.clone()) + Self::lagrange_polynomial_for_row::<2>(ctrl_type); let enable = enable_rows * s_enable; + let fst = meta.query_advice(intermediate_1, Rotation::cur()); + let snd = meta.query_advice(intermediate_2, Rotation::cur()); + let hash = meta.query_advice(intermediate_2, Rotation::prev()); - vec![ - ( - enable.clone() * meta.query_advice(intermediate_1, Rotation::cur()), - meta.query_advice(hash_table.0, Rotation::cur()), - ), - ( - enable.clone() * meta.query_advice(intermediate_2, Rotation::cur()), - meta.query_advice(hash_table.1, Rotation::cur()), - ), - ( - enable * meta.query_advice(intermediate_2, Rotation::prev()), - meta.query_advice(hash_table.2, Rotation::cur()), - ), - ] + hash_table.build_lookup(meta, enable, fst, snd, hash) }); // third hash lookup (Poseidon(nonce, balance) = hash3) @@ -473,20 +453,11 @@ impl<'d, Fp: FieldExt> AccountChip<'d, Fp> { let enable_rows = Self::lagrange_polynomial_for_row::<1>(ctrl_type); let enable = enable_rows * s_enable; - vec![ - ( - enable.clone() * meta.query_advice(acc_data_fields, Rotation::prev()), - meta.query_advice(hash_table.0, Rotation::cur()), - ), - ( - enable.clone() * meta.query_advice(acc_data_fields, Rotation::cur()), - meta.query_advice(hash_table.1, Rotation::cur()), - ), - ( - enable * meta.query_advice(intermediate_1, Rotation::cur()), - meta.query_advice(hash_table.2, Rotation::cur()), - ), - ] + let fst = meta.query_advice(acc_data_fields, Rotation::prev()); + let snd = meta.query_advice(acc_data_fields, Rotation::cur()); + let hash = meta.query_advice(intermediate_1, Rotation::cur()); + + hash_table.build_lookup(meta, enable, fst, snd, hash) }); // equality constraint: hash_final and Root @@ -602,20 +573,11 @@ impl<'d, Fp: FieldExt> StorageChip<'d, Fp> { ) -> StorageChipConfig { meta.lookup_any("value hash", |meta| { let enable = meta.query_advice(s_enable, Rotation::cur()); - vec![ - ( - enable.clone() * meta.query_advice(v_limbs[0], Rotation::cur()), - meta.query_advice(hash_table.0, Rotation::cur()), - ), - ( - enable.clone() * meta.query_advice(v_limbs[1], Rotation::cur()), - meta.query_advice(hash_table.1, Rotation::cur()), - ), - ( - enable * meta.query_advice(hash, Rotation::prev()), - meta.query_advice(hash_table.2, Rotation::cur()), - ), - ] + let fst = meta.query_advice(v_limbs[0], Rotation::cur()); + let snd = meta.query_advice(v_limbs[1], Rotation::cur()); + let hash = meta.query_advice(hash, Rotation::prev()); + + hash_table.build_lookup(meta, enable, fst, snd, hash) }); StorageChipConfig { v_limbs } diff --git a/src/lib.rs b/src/lib.rs index 5a24321d..5ee1995e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -288,10 +288,26 @@ pub struct EthTrieConfig { } impl EthTrieConfig { + /// the beginning of hash table index + pub fn hash_tbl_begin(&self) -> usize { + self.hash_tbl.commitment_index()[0] + } + + /// the beginning of mpt table index + pub fn mpt_tbl_begin(&self) -> usize { + self.mpt_tbl + .as_ref() + .expect("only call for non-lite circuit") + .mpt_table_begin_index() + } + /// configure for lite circuit (no mpt table included, for fast testing) - pub fn configure_lite(meta: &mut ConstraintSystem) -> Self { + pub fn configure_base( + meta: &mut ConstraintSystem, + hash_tbl: [Column; 4], + ) -> Self { let tables = mpt::MPTOpTables::configure_create(meta); - let hash_tbl = mpt::HashTable::configure_create(meta); + let hash_tbl = mpt::HashTable::configure_assign(&hash_tbl); let layer = LayerGadget::configure( meta, @@ -360,13 +376,20 @@ impl EthTrieConfig { } } + /// configure for lite circuit (no mpt table included, for fast testing) + pub fn configure_lite(meta: &mut ConstraintSystem) -> Self { + let hash_tbl = [0; 4].map(|_| meta.advice_column()); + Self::configure_base(meta, hash_tbl) + } + /// configure for full circuit pub fn configure_sub( meta: &mut ConstraintSystem, mpt_tbl: [Column; 7], + hash_tbl: [Column; 4], randomness: Expression, ) -> Self { - let mut lite_cfg = Self::configure_lite(meta); + let mut lite_cfg = Self::configure_base(meta, hash_tbl); let mpt_tbl = MPTTable::configure(meta, mpt_tbl, randomness); let layer = &lite_cfg.layer; let layer_exported = layer.exported_cols(0); @@ -717,17 +740,17 @@ pub struct CommitmentIndexs([usize; 3], [usize; 3], Option); impl CommitmentIndexs { /// the hash col's pos pub fn hash_pos(&self) -> (usize, usize) { - (self.0[2], self.1[0]) + (self.0[0], self.1[0]) } /// the first input col's pos pub fn left_pos(&self) -> (usize, usize) { - (self.0[0], self.1[1]) + (self.0[1], self.1[1]) } /// the second input col's pos pub fn right_pos(&self) -> (usize, usize) { - (self.0[1], self.1[2]) + (self.0[2], self.1[2]) } /// the beginning of mpt table index @@ -748,7 +771,7 @@ impl CommitmentIndexs { let hash_circuit_indexs = config.commitment_index(); Self( - trie_circuit_indexs, + trie_circuit_indexs[0..3].try_into().unwrap(), hash_circuit_indexs[0..3].try_into().unwrap(), None, ) @@ -771,7 +794,7 @@ impl CommitmentIndexs { let hash_circuit_indexs = config.commitment_index(); Self( - trie_circuit_indexs, + trie_circuit_indexs[0..3].try_into().unwrap(), hash_circuit_indexs[0..3].try_into().unwrap(), Some(mpt_table_start), ) @@ -797,8 +820,9 @@ impl Circuit for EthTrieCircuit { EthTrieConfig::configure_lite(meta) } else { let base = [0; 7].map(|_| meta.advice_column()); + let hash_tbl = [0; 4].map(|_| meta.advice_column()); let randomness = Expression::Constant(Fp::from(get_rand_base())); - EthTrieConfig::configure_sub(meta, base, randomness) + EthTrieConfig::configure_sub(meta, base, hash_tbl, randomness) } } diff --git a/src/mpt.rs b/src/mpt.rs index 051ced24..e62cb4ea 100644 --- a/src/mpt.rs +++ b/src/mpt.rs @@ -177,23 +177,19 @@ impl MPTOpTables { } #[derive(Clone, Debug)] -pub(crate) struct HashTable(pub Column, pub Column, pub Column); +pub(crate) struct HashTable(pub [Column; 4]); impl HashTable { pub fn configure_create(meta: &mut ConstraintSystem) -> Self { - Self( - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ) + Self([0; 4].map(|_| meta.advice_column())) } - fn configure_assign(cols: &[Column]) -> Self { - Self(cols[0], cols[1], cols[2]) + pub fn configure_assign(cols: &[Column]) -> Self { + Self([cols[0], cols[1], cols[2], cols[3]]) } - pub fn commitment_index(&self) -> [usize; 3] { - [self.0.index(), self.1.index(), self.2.index()] + pub fn commitment_index(&self) -> [usize; 4] { + self.0.map(|col| col.index()) } pub fn build_lookup<'d, Fp: FieldExt>( @@ -205,15 +201,19 @@ impl HashTable { hash: Expression, ) -> Vec<(Expression, Expression)> { vec![ + ( + enable.clone() * hash, + meta.query_advice(self.0[0], Rotation::cur()), + ), ( enable.clone() * fst, - meta.query_advice(self.0, Rotation::cur()), + meta.query_advice(self.0[1], Rotation::cur()), ), + (enable * snd, meta.query_advice(self.0[2], Rotation::cur())), ( - enable.clone() * snd, - meta.query_advice(self.1, Rotation::cur()), + Expression::Constant(Fp::zero()), + meta.query_advice(self.0[3], Rotation::cur()), ), - (enable * hash, meta.query_advice(self.2, Rotation::cur())), ] } @@ -247,9 +247,9 @@ impl HashTable { || "hash table", |mut table| { // default: 0, 0, 0 - table.assign_advice(|| "default", self.0, 0, || Value::known(Fp::zero()))?; - table.assign_advice(|| "default", self.1, 0, || Value::known(Fp::zero()))?; - table.assign_advice(|| "default", self.2, 0, || Value::known(Fp::zero()))?; + for col in self.0 { + table.assign_advice(|| "default", col, 0, || Value::known(Fp::zero()))?; + } hashing_records .clone() @@ -258,11 +258,18 @@ impl HashTable { let (lh, rh, h) = val; let offset = offset + 1; - table.assign_advice(|| "left", self.0, offset, || Value::known(*lh))?; + table.assign_advice(|| "result", self.0[0], offset, || Value::known(*h))?; + + table.assign_advice(|| "left", self.0[1], offset, || Value::known(*lh))?; - table.assign_advice(|| "right", self.1, offset, || Value::known(*rh))?; + table.assign_advice(|| "right", self.0[2], offset, || Value::known(*rh))?; - table.assign_advice(|| "result", self.2, offset, || Value::known(*h))?; + table.assign_advice( + || "ctrl_pad", + self.0[3], + offset, + || Value::known(Fp::zero()), + )?; Ok(()) }) From 723309fb71ef83b87aa1a908bc8e50cb14c4a64e Mon Sep 17 00:00:00 2001 From: Ho Vei Date: Wed, 11 Jan 2023 22:37:47 +0800 Subject: [PATCH 02/17] upgrade hash circuit --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b0caa78e..83162d38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -hash-circuit = { git = "https://github.com/scroll-tech/poseidon-circuit.git", branch = "scroll-dev-1230"} +hash-circuit = { package = "poseidon-circuit", git = "https://github.com/scroll-tech/poseidon-circuit.git", branch = "scroll-dev-0111"} halo2_proofs = { git = "https://github.com/scroll-tech/halo2.git", branch = "scroll-dev-1220" } rand = "0.8" lazy_static = "1.4.0" From 222cd0e73acdd0c339f686fc59e5427cbca1b1c8 Mon Sep 17 00:00:00 2001 From: Ho Vei Date: Thu, 12 Jan 2023 14:06:58 +0800 Subject: [PATCH 03/17] update hash circuit --- src/lib.rs | 83 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 31 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5ee1995e..d613dced 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -438,16 +438,37 @@ impl EthTrieConfig { mpt_tbl.load(layouter) } - /// synthesize core part (without mpt table), require a `Hashable` trait - /// on the working field - pub fn synthesize_core( + /// synthesize the hash table part, the randomness also specify + /// if the base part of mpt table should be assigned + pub fn load_hash_table<'d, Fp: Hashable>( &self, layouter: &mut impl Layouter, - ops: &[AccountOp], + hash_traces: impl Iterator + Clone, + rows: usize, + ) -> Result<(), Error> { + self.hash_tbl.fill_with_paddings( + layouter, + HashTracesSrc::from(hash_traces), + ( + Fp::zero(), + Fp::zero(), + Hashable::hash([Fp::zero(), Fp::zero()]), + ), + rows, + ) + } + + /// synthesize core part without advice tables (hash and mpt table), + /// require a `Hashable` trait on the working field + pub fn synthesize_core<'d, Fp: Hashable>( + &self, + layouter: &mut impl Layouter, + ops: impl Iterator> + Clone, rows: usize, ) -> Result<(), Error> { let start_root = ops - .first() + .clone() + .next() .map(|op| op.account_root_before()) .unwrap_or_else(Fp::zero); @@ -459,7 +480,7 @@ impl EthTrieConfig { let mut start = self.layer.assign(&mut region, rows, start_root)?; let empty_account = Default::default(); - for op in ops { + for op in ops.clone() { let block_start = start; self.layer.pace_op( &mut region, @@ -528,18 +549,6 @@ impl EthTrieConfig { }, )?; - let hash_traces_i = ops.iter().flat_map(|op| op.hash_traces()); - self.hash_tbl.fill_with_paddings( - layouter, - HashTracesSrc::from(hash_traces_i), - ( - Fp::zero(), - Fp::zero(), - Hashable::hash([Fp::zero(), Fp::zero()]), - ), - rows, - )?; - self.tables.fill_constant( layouter, MPTOpGadget::transition_rules().chain(AccountGadget::transition_rules()), @@ -659,33 +668,40 @@ impl EthTrieCircuit { } } -use hash::HashCircuit as PoseidonHashCircuit; -/// the reform hash circuit -pub struct HashCircuit(PoseidonHashCircuit); +/// hash circuit as the companion of mpt hashes +pub struct HashCircuit(hash::PoseidonHashTable, usize); impl HashCircuit { /// re-warped, all-in-one creation pub fn new(calcs: usize, input_with_check: &[&(Fp, Fp, Fp)]) -> Self { - let mut cr = PoseidonHashCircuit::::new(calcs); - cr.constant_inputs_with_check(input_with_check.iter().copied()); - Self(cr) + let mut tbl = hash::PoseidonHashTable::default(); + tbl.constant_inputs_with_check(input_with_check.iter().copied()); + Self(tbl, calcs) } } impl Circuit for HashCircuit { - type Config = as Circuit>::Config; - type FloorPlanner = as Circuit>::FloorPlanner; + type Config = hash::PoseidonHashConfig; + type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - Self(self.0.without_witnesses()) + Self(Default::default(), self.1) } fn configure(meta: &mut ConstraintSystem) -> Self::Config { - as Circuit>::configure(meta) + let hash_tbl = [0; 4].map(|_| meta.advice_column()); + hash::PoseidonHashConfig::configure_sub(meta, hash_tbl, hash_circuit::DEFAULT_STEP) } - fn synthesize(&self, config: Self::Config, layouter: impl Layouter) -> Result<(), Error> { - self.0.synthesize(config, layouter) + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = hash::PoseidonHashChip::::construct( + config, &self.0, self.1, + ); + chip.load(&mut layouter) } } @@ -831,7 +847,12 @@ impl Circuit for EthTrieCircuit { config: Self::Config, mut layouter: impl Layouter, ) -> Result<(), Error> { - config.synthesize_core(&mut layouter, self.ops.as_slice(), self.calcs)?; + config.load_hash_table( + &mut layouter, + self.ops.iter().flat_map(|op| op.hash_traces()), + self.calcs, + )?; + config.synthesize_core(&mut layouter, self.ops.iter(), self.calcs)?; if LITE { Ok(()) } else { From 9fb76766274c199007c2f86300e371f09319eff6 Mon Sep 17 00:00:00 2001 From: Ho Vei Date: Fri, 13 Jan 2023 09:48:07 +0800 Subject: [PATCH 04/17] refactor op table --- src/eth.rs | 4 +-- src/mpt.rs | 78 ++++++++++++++++++++++++++++++------------------------ 2 files changed, 45 insertions(+), 37 deletions(-) diff --git a/src/eth.rs b/src/eth.rs index bebe0379..cb0b21fe 100644 --- a/src/eth.rs +++ b/src/eth.rs @@ -242,11 +242,11 @@ impl AccountGadget { } } - pub fn transition_rules() -> impl Iterator + Clone { + pub fn transition_rules() -> impl Iterator + Clone { TRANSMAP .iter() .copied() - .map(|(a, b)| (a, b, CtrlTransitionKind::Account as u32)) + .map(|(a, b)| ([a, b, 0], CtrlTransitionKind::Account as u32)) } /// assign data and enable flag for account circuit diff --git a/src/mpt.rs b/src/mpt.rs index e62cb4ea..d4899eb3 100644 --- a/src/mpt.rs +++ b/src/mpt.rs @@ -72,7 +72,10 @@ use halo2_proofs::{ use lazy_static::lazy_static; #[derive(Clone, Debug)] -pub(crate) struct MPTOpTables(pub TableColumn, pub TableColumn, pub TableColumn); +pub(crate) struct MPTOpTables( + TableColumn, // op mark + [TableColumn; 3], // op rules +); lazy_static! { static ref OPMAP : Vec<(HashType, HashType)> = { @@ -115,11 +118,25 @@ impl MPTOpTables { pub fn configure_create(meta: &mut ConstraintSystem) -> Self { Self( meta.lookup_table_column(), - meta.lookup_table_column(), - meta.lookup_table_column(), + [0;3].map(|_|meta.lookup_table_column()), ) } + pub fn build_lookup_any( + &self, + enable: Expression, + rules: impl IntoIterator>, + mark: u64, + ) -> Vec<(Expression, TableColumn)> { + let mut ret : Vec<_> = rules + .into_iter() + .map(|exp|enable.clone() * exp) + .zip(self.1) + .collect(); + ret.push((enable * Expression::Constant(Fp::from(mark)), self.0)); + ret + } + pub fn build_lookup( &self, enable: Expression, @@ -127,47 +144,39 @@ impl MPTOpTables { new: Expression, mark: u64, ) -> Vec<(Expression, TableColumn)> { - vec![ - (enable.clone() * old, self.0), - (enable.clone() * new, self.1), - (enable * Expression::Constant(Fp::from(mark)), self.2), - ] + self.build_lookup_any(enable, [old, new], mark) } pub fn fill_constant( &self, layouter: &mut impl Layouter, - rules: impl Iterator + Clone, + rules: impl Iterator + Clone, ) -> Result<(), Error> { layouter.assign_table( || "op table", |mut table| { - // default: 0, 0, 0 - table.assign_cell(|| "default", self.0, 0, || Value::known(Fp::zero()))?; - table.assign_cell(|| "default", self.1, 0, || Value::known(Fp::zero()))?; - table.assign_cell(|| "default", self.2, 0, || Value::known(Fp::zero()))?; + // default line + table.assign_cell(|| "default mark", self.0, 0, || Value::known(Fp::zero()))?; + for i in 0..3 { + table.assign_cell(|| "default rule", self.1[i], 0, || Value::known(Fp::zero()))?; + } - for (offset, item) in rules.clone().enumerate() { + for (offset, (items, mark)) in rules.clone().enumerate() { let offset = offset + 1; - table.assign_cell( - || "cur", - self.0, - offset, - || Value::known(Fp::from(item.0 as u64)), - )?; - - table.assign_cell( - || "next", - self.1, - offset, - || Value::known(Fp::from(item.1 as u64)), - )?; + for (rule, col) in items.into_iter().zip(self.1) { + table.assign_cell( + || "rule item", + col, + offset, + || Value::known(Fp::from(rule as u64)), + )?; + } table.assign_cell( || "mark", - self.2, + self.0, offset, - || Value::known(Fp::from(item.2 as u64)), + || Value::known(Fp::from(mark as u64)), )?; } Ok(()) @@ -404,15 +413,15 @@ impl MPTOpGadget { } } - pub fn transition_rules() -> impl Iterator + Clone { + pub fn transition_rules() -> impl Iterator + Clone { let i1 = TRANSMAP .iter() .copied() - .map(|(a, b)| (a as u32, b as u32, CtrlTransitionKind::Mpt as u32)); + .map(|(a, b)| ([a as u32, b as u32, 0], CtrlTransitionKind::Mpt as u32)); let i2 = OPMAP .iter() .copied() - .map(|(a, b)| (a as u32, b as u32, CtrlTransitionKind::Operation as u32)); + .map(|(a, b)| ([a as u32, b as u32, 0], CtrlTransitionKind::Operation as u32)); i1.chain(i2) } @@ -1186,7 +1195,7 @@ mod test { &mut layouter, TRANSMAP .iter() - .map(|(a, b)| (*a as u32, *b as u32, CtrlTransitionKind::Mpt as u32)), + .map(|(a, b)| ([*a as u32, *b as u32, 0], CtrlTransitionKind::Mpt as u32)), )?; config @@ -1373,8 +1382,7 @@ mod test { &mut layouter, OPMAP .iter() - .map(|(a, b)| (*a as u32, *b as u32, CtrlTransitionKind::Operation as u32)) - .chain(Some((0, 0, CtrlTransitionKind::Operation as u32))), + .map(|(a, b)| ([*a as u32, *b as u32, 0], CtrlTransitionKind::Operation as u32)), )?; // op chip now need hash table (for key hash lookup) From 3f0d9db36270627e420e0ee6b7b8b64e44e55ff5 Mon Sep 17 00:00:00 2001 From: Ho Vei Date: Fri, 13 Jan 2023 23:18:00 +0800 Subject: [PATCH 05/17] induce ctrl_type flag --- src/eth.rs | 31 +++++++ src/layers.rs | 92 ++++++++++++++++++-- src/lib.rs | 19 +++- src/mpt.rs | 222 ++++++++++++++++++++++++++++++++--------------- src/operation.rs | 15 ++++ 5 files changed, 303 insertions(+), 76 deletions(-) diff --git a/src/eth.rs b/src/eth.rs index cb0b21fe..6019b9cf 100644 --- a/src/eth.rs +++ b/src/eth.rs @@ -60,6 +60,7 @@ pub(crate) struct AccountGadget { new_state: AccountChipConfig, s_enable: Column, ctrl_type: Column, + s_ctrl_type: [Column;4], state_change_key: Column, state_change_aux: [Column; 2], @@ -70,6 +71,10 @@ impl AccountGadget { 6 } + pub fn min_ctrl_types() -> usize { + 4 + } + /// create gadget from assigned cols, we need: /// + circuit selector * 1 /// + exported col * 8 (MUST by following sequence: layout_flag, s_enable, old_val, new_val, key_val and 3 ext field for old/new/key_val) @@ -78,6 +83,7 @@ impl AccountGadget { meta: &mut ConstraintSystem, sel: Selector, exported: &[Column], + s_ctrl_type: &[Column], free: &[Column], address_index: Option>, tables: mpt::MPTOpTables, @@ -91,6 +97,7 @@ impl AccountGadget { let data_key = exported[4]; let data_old_ext = exported[5]; let data_new_ext = exported[6]; + let s_ctrl_type = s_ctrl_type[0..4].try_into().expect("same size"); let state_change_key = data_key; let old_state = AccountChip::configure( @@ -235,6 +242,7 @@ impl AccountGadget { Self { s_enable, ctrl_type, + s_ctrl_type, old_state, new_state, state_change_key, @@ -306,6 +314,12 @@ impl AccountGadget { offset, || Value::known(Fp::from(index as u64)), )?; + region.assign_advice( + || "enable s_ctrl", + self.s_ctrl_type[index as usize], + offset, + || Value::known(Fp::one()), + )?; if index == LAST_ROW { region.assign_advice( || "padding last row", @@ -611,6 +625,7 @@ pub(crate) struct StorageGadget { key: StorageChipConfig, s_enable: Column, ctrl_type: Column, + s_ctrl_type: Column, } impl StorageGadget { @@ -618,6 +633,10 @@ impl StorageGadget { 6 } + pub fn min_ctrl_types() -> usize { + 1 + } + /// create gadget from assigned cols, we need: /// + circuit selector * 1 /// + exported col * 5 (MUST by following sequence: layout_flag, s_enable, old_val, new_val, key_val) @@ -626,6 +645,7 @@ impl StorageGadget { meta: &mut ConstraintSystem, sel: Selector, exported: &[Column], + s_ctrl_type: &[Column], _free: &[Column], hash_tbl: mpt::HashTable, ) -> Self { @@ -634,6 +654,7 @@ impl StorageGadget { let s_hash = exported[2]; let e_hash = exported[3]; let k_hash = exported[4]; + let s_ctrl_type = s_ctrl_type[0]; let s_val_limbs = [exported[2], exported[5]]; let e_val_limbs = [exported[3], exported[6]]; let k_val_limbs = [exported[4], exported[7]]; @@ -649,6 +670,7 @@ impl StorageGadget { Self { s_enable, ctrl_type, + s_ctrl_type, key, s_value, e_value, @@ -680,6 +702,13 @@ impl StorageGadget { || Value::known(Fp::zero()), )?; + region.assign_advice( + || "enable s_ctrl", + self.s_ctrl_type, + offset, + || Value::known(Fp::one()), + )?; + for (config, value) in [ (&self.s_value, &full_op.store_before), (&self.e_value, &full_op.store_after), @@ -736,6 +765,7 @@ mod test { fn configure(meta: &mut ConstraintSystem) -> Self::Config { let sel = meta.selector(); let free_cols = [(); 14].map(|_| meta.advice_column()); + let dummy_s_ctrl = [meta.advice_column();4]; let exported_cols = [ free_cols[0], free_cols[1], @@ -753,6 +783,7 @@ mod test { meta, sel, exported_cols.as_slice(), + dummy_s_ctrl.as_slice(), &free_cols[8..], None, op_tabl.clone(), diff --git a/src/layers.rs b/src/layers.rs index 2d1da433..fc6a00db 100644 --- a/src/layers.rs +++ b/src/layers.rs @@ -37,6 +37,10 @@ pub(crate) struct LayerGadget { // its flag when assigned s_stepflags: Vec>, ctrl_type: Column, + // the s_ctrl_type is supposed to be a series of integers start from 0 and each of the number + // is represented the corresponding items in s_ctrl_type array in which the number is just + // its index + s_ctrl_type: Vec>, // the 3 exported value now can be represented by 2-field and the additional // field is marked as "ext" (most value still use 1 field only) data_0: Column, @@ -74,6 +78,10 @@ impl LayerGadget { ] } + pub fn get_ctrl_type_flags(&self) -> &[Column] { + &self.s_ctrl_type + } + pub fn get_free_cols(&self) -> &[Column] { &self.free_cols } @@ -100,9 +108,13 @@ impl LayerGadget { meta: &mut ConstraintSystem, steps: usize, required_cols: usize, + minium_ctrl_types: usize, ) -> Self { - let s_stepflags: Vec> = (0..steps).map(|_| meta.advice_column()).collect(); - let free_cols = (0..required_cols).map(|_| meta.advice_column()).collect(); + assert!(steps > 0, "at least one step is required"); + assert!(minium_ctrl_types > 0, "at least one ctrl type is required"); + let s_stepflags: Vec<_> = (0..steps).map(|_| meta.advice_column()).collect(); + let free_cols: Vec<_> = (0..required_cols).map(|_| meta.advice_column()).collect(); + let s_ctrl_type: Vec<_> = (0..minium_ctrl_types).map(|_| meta.advice_column()).collect(); let sel = meta.complex_selector(); let series = meta.advice_column(); let op_type = meta.advice_column(); @@ -144,6 +156,36 @@ impl LayerGadget { ] }); + meta.create_gate("s_ctrl flags", |meta| { + let sel = meta.query_selector(sel); + // setting op flags: + // all flags is boolean + // one and at most one flag must be enabled + // the enabled flas must match with op_type + let s_ctrl : Vec<_> = s_ctrl_type.iter().copied().map(|col|meta.query_advice(col, Rotation::cur())).collect(); + + let bool_cond = s_ctrl.clone().into_iter() + .map(|col_exp|{ + sel.clone() * col_exp.clone() * (Expression::Constant(Fp::one()) - col_exp) + }); + + let one_flag_cond = s_ctrl.clone().into_iter() + .reduce(|exp, col_exp|exp + col_exp) + .map(|sum_exp|sel.clone() * (Expression::Constant(Fp::one()) - sum_exp)); + + let ctrl_type_cond = s_ctrl.into_iter().enumerate() + .map(|(idx, col_exp)|Expression::Constant(Fp::from(idx as u64))*col_exp) + .reduce(|exp, col_exp_with_idx|exp + col_exp_with_idx) + .map(|w_sum_exp|sel.clone() * (meta.query_advice(ctrl_type, Rotation::cur()) - w_sum_exp)); + + let constraints = bool_cond.chain(one_flag_cond).chain(ctrl_type_cond).collect::>(); + if constraints.is_empty() { + vec![sel * Expression::Constant(Fp::zero())] + }else { + constraints + } + }); + meta.create_gate("index identical", |meta| { // constrain all index cols so the value in identical inside a block // and gadgets can add more constraint to the indexs @@ -241,6 +283,7 @@ impl LayerGadget { sel, series, s_stepflags, + s_ctrl_type, op_type, ctrl_type, data_0, @@ -379,6 +422,17 @@ impl LayerGadget { ) .map(|_| ()) })?; + // flush all cols to avoid unassigned error + self.s_ctrl_type.iter().try_for_each(|col| { + region + .assign_advice( + || "flushing op type flag", + *col, + offset, + || Value::known(Fp::zero()), + ) + .map(|_| ()) + })?; [ self.data_0, self.data_1, @@ -656,6 +710,7 @@ impl LayerGadget { pub(crate) struct PaddingGadget { s_enable: Column, ctrl_type: Column, + s_ctrl_type: Column, } impl PaddingGadget { @@ -663,10 +718,12 @@ impl PaddingGadget { _meta: &mut ConstraintSystem, _sel: Selector, exported: &[Column], + s_ctrl_type: &[Column], ) -> Self { Self { ctrl_type: exported[0], s_enable: exported[1], + s_ctrl_type: s_ctrl_type[0], } } @@ -683,6 +740,12 @@ impl PaddingGadget { offset, || Value::known(Fp::zero()), )?; + region.assign_advice( + || "enable s_ctrl", + self.s_ctrl_type, + offset, + || Value::known(Fp::one()), + )?; region.assign_advice( || "enable padding", self.s_enable, @@ -727,9 +790,14 @@ mod test { } fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let layer = LayerGadget::configure(meta, 1, 3); + let layer = LayerGadget::configure(meta, 1, 3, 1); let padding = - PaddingGadget::configure(meta, layer.sel, layer.exported_cols(0).as_slice()); + PaddingGadget::configure( + meta, + layer.sel, + layer.exported_cols(0).as_slice(), + layer.get_ctrl_type_flags(), + ); let cst = meta.fixed_column(); meta.enable_constant(cst); @@ -822,11 +890,21 @@ mod test { } fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let layer = LayerGadget::configure(meta, 3, 2); + let layer = LayerGadget::configure(meta, 3, 2, 1); let padding0 = - PaddingGadget::configure(meta, layer.sel, layer.exported_cols(0).as_slice()); + PaddingGadget::configure( + meta, + layer.sel, + layer.exported_cols(0).as_slice(), + layer.get_ctrl_type_flags(), + ); let padding1 = - PaddingGadget::configure(meta, layer.sel, layer.exported_cols(2).as_slice()); + PaddingGadget::configure( + meta, + layer.sel, + layer.exported_cols(2).as_slice(), + layer.get_ctrl_type_flags(), + ); let cst = meta.fixed_column(); meta.enable_constant(cst); diff --git a/src/lib.rs b/src/lib.rs index d613dced..d0a8aed8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -158,16 +158,21 @@ impl Circuit for SimpleTrie { } fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let layer = LayerGadget::configure(meta, 2, MPTOpGadget::min_free_cols()); + let layer = LayerGadget::configure(meta, 2, + MPTOpGadget::min_free_cols(), + MPTOpGadget::min_ctrl_types(), + ); let padding = PaddingGadget::configure( meta, layer.public_sel(), layer.exported_cols(OP_PADDING).as_slice(), + layer.get_ctrl_type_flags(), ); let mpt = MPTOpGadget::configure_simple( meta, layer.public_sel(), layer.exported_cols(OP_MPT).as_slice(), + layer.get_ctrl_type_flags(), layer.get_free_cols(), Some(layer.get_root_indexs()), ); @@ -319,16 +324,25 @@ impl EthTrieConfig { StorageGadget::min_free_cols(), ), ), + std::cmp::max( + MPTOpGadget::min_ctrl_types(), + std::cmp::max( + AccountGadget::min_ctrl_types(), + StorageGadget::min_ctrl_types(), + ), + ), ); let padding = PaddingGadget::configure( meta, layer.public_sel(), layer.exported_cols(OP_PADDING).as_slice(), + layer.get_ctrl_type_flags(), ); let account_trie = MPTOpGadget::configure( meta, layer.public_sel(), layer.exported_cols(OP_TRIE_ACCOUNT).as_slice(), + layer.get_ctrl_type_flags(), layer.get_free_cols(), Some(layer.get_root_indexs()), tables.clone(), @@ -338,6 +352,7 @@ impl EthTrieConfig { meta, layer.public_sel(), layer.exported_cols(OP_TRIE_STATE).as_slice(), + layer.get_ctrl_type_flags(), layer.get_free_cols(), None, tables.clone(), @@ -347,6 +362,7 @@ impl EthTrieConfig { meta, layer.public_sel(), layer.exported_cols(OP_ACCOUNT).as_slice(), + layer.get_ctrl_type_flags(), layer.get_free_cols(), Some(layer.get_address_index()), tables.clone(), @@ -356,6 +372,7 @@ impl EthTrieConfig { meta, layer.public_sel(), layer.exported_cols(OP_STORAGE).as_slice(), + layer.get_ctrl_type_flags(), layer.get_free_cols(), hash_tbl.clone(), ); diff --git a/src/mpt.rs b/src/mpt.rs index d4899eb3..7dc1a163 100644 --- a/src/mpt.rs +++ b/src/mpt.rs @@ -78,20 +78,20 @@ pub(crate) struct MPTOpTables( ); lazy_static! { - static ref OPMAP : Vec<(HashType, HashType)> = { + static ref OPMAP : Vec<(HashType, HashType, HashType)> = { vec![ - (HashType::Start, HashType::Start), - (HashType::Empty, HashType::Empty), - (HashType::Empty, HashType::Leaf), - (HashType::Leaf, HashType::Empty), - (HashType::Leaf, HashType::Leaf), - (HashType::Middle, HashType::Middle), - (HashType::LeafExt, HashType::Middle), - (HashType::LeafExt, HashType::LeafExt), - (HashType::LeafExtFinal, HashType::Middle), - (HashType::LeafExtFinal, HashType::LeafExtFinal), - (HashType::Middle, HashType::LeafExt), - (HashType::Middle, HashType::LeafExtFinal), + (HashType::Start, HashType::Start, HashType::Start), + (HashType::Empty, HashType::Empty, HashType::Empty), + (HashType::Empty, HashType::Leaf, HashType::Leaf), + (HashType::Leaf, HashType::Empty, HashType::Leaf), + (HashType::Leaf, HashType::Leaf, HashType::Leaf), + (HashType::Middle, HashType::Middle, HashType::Middle), + (HashType::LeafExt, HashType::Middle, HashType::LeafExt), + (HashType::LeafExt, HashType::LeafExt, HashType::LeafExt), + (HashType::LeafExtFinal, HashType::Middle, HashType::LeafExtFinal), + (HashType::LeafExtFinal, HashType::LeafExtFinal, HashType::LeafExtFinal), + (HashType::Middle, HashType::LeafExt, HashType::LeafExt), + (HashType::Middle, HashType::LeafExtFinal, HashType::LeafExtFinal), ] }; static ref TRANSMAP : Vec<(HashType, HashType)> = { @@ -295,6 +295,8 @@ struct MPTOpConfig { s_enable: Column, s_path: Column, depth: Column, + ctrl_type: Column, + s_ctrl_type: [Column; 6], old_hash_type: Column, new_hash_type: Column, sibling: Column, @@ -324,35 +326,42 @@ impl MPTOpGadget { 8 } + pub fn min_ctrl_types() -> usize { + 6 + } + /// if the gadget would be used only once, this entry is more easy pub fn configure_simple( meta: &mut ConstraintSystem, sel: Selector, exported: &[Column], + s_ctrl_type: &[Column], free: &[Column], root_index: Option<(Column, Column)>, ) -> Self { let tables = MPTOpTables::configure_create(meta); let hash_tbls = HashTable::configure_create(meta); - Self::configure(meta, sel, exported, free, root_index, tables, hash_tbls) + Self::configure(meta, sel, exported, s_ctrl_type, free, root_index, tables, hash_tbls) } /// create gadget from assigned cols, we need: /// + circuit selector * 1 /// + exported col * 4 (MUST by following sequence: layout_flag, s_enable, old_val, new_val) + /// + s_op_flags * 6 (corresponding 6 ctrl_types) /// + free col * 8 /// notice the gadget has bi-direction exporting (on top it exporting mpt root and bottom exporting leaf) pub fn configure( meta: &mut ConstraintSystem, sel: Selector, exported: &[Column], + s_ctrl_type: &[Column], free: &[Column], root_index: Option<(Column, Column)>, tables: MPTOpTables, hash_tbl: HashTable, ) -> Self { - assert!(free.len() >= 8, "require at least 6 free cols"); + assert!(free.len() >= 8, "require at least 8 free cols"); let g_config = MPTOpConfig { tables, @@ -360,14 +369,16 @@ impl MPTOpGadget { s_path: free[0], depth: free[1], new_hash_type: free[2], - sibling: free[3], - path: free[4], - key_aux: free[5], - old_hash_type: exported[0], + old_hash_type: free[3], + sibling: free[4], + path: free[5], + key_aux: free[6], + ctrl_type: exported[0], s_enable: exported[1], old_val: exported[2], new_val: exported[3], acc_key: exported[4], + s_ctrl_type: s_ctrl_type[0..6].try_into().expect("same size"), hash_table: hash_tbl, }; @@ -421,7 +432,7 @@ impl MPTOpGadget { let i2 = OPMAP .iter() .copied() - .map(|(a, b)| ([a as u32, b as u32, 0], CtrlTransitionKind::Operation as u32)); + .map(|(a, b, c)| ([a as u32, b as u32, c as u32], CtrlTransitionKind::Operation as u32)); i1.chain(i2) } @@ -718,6 +729,8 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { #[derive(Clone, Debug)] struct OpChipConfig { + ctrl_type: Column, + s_ctrl_type: [Column;6], sibling: Column, path: Column, depth: Column, @@ -758,6 +771,8 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { let sibling = g_config.sibling; let depth_aux = g_config.depth; let key_aux = g_config.key_aux; + let ctrl_type = g_config.ctrl_type; + let s_ctrl_type = g_config.s_ctrl_type; let s_row = g_config.s_row; let s_enable = g_config.s_enable; @@ -849,6 +864,8 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { }); OpChipConfig { + ctrl_type, + s_ctrl_type, path, sibling, depth: depth_aux, @@ -899,6 +916,27 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { offset, || Value::known(Fp::zero()), )?; + let ctrl_type_head_row = self.data.ctrl_type(0); + region.assign_advice( + || "op type start", + config.ctrl_type, + offset, + || Value::known(Fp::from(ctrl_type_head_row)), + )?; + region.assign_advice( + || "enabling s_op", + config.s_ctrl_type[ctrl_type_head_row as usize], + offset, + || Value::known(Fp::one()), + )?; + + region.assign_advice( + || "sibling padding", + config.sibling, + offset, + || Value::known(Fp::zero()), + )?; + offset += 1; let mut cur_depth = Fp::one(); @@ -906,17 +944,27 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { let extend_proof = self.data.extended_proof(); - for (path, sibling) in paths.iter().zip(siblings.iter()) { + for (index, (path, sibling)) in paths.iter().zip(siblings.iter()).enumerate() { acc_key = *path * cur_depth + acc_key; - region.assign_advice(|| "path", config.path, offset, || Value::known(*path))?; + region.assign_advice( + || "path", + config.path, + offset, + || Value::known(*path) + )?; region.assign_advice( || "acckey", config.acc_key, offset, || Value::known(acc_key), )?; - region.assign_advice(|| "depth", config.depth, offset, || Value::known(cur_depth))?; + region.assign_advice( + || "depth", + config.depth, + offset, + || Value::known(cur_depth) + )?; region.assign_advice( || "sibling", config.sibling, @@ -930,12 +978,38 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { offset, || Value::known(extend_proof.map(|pf| pf.1).unwrap_or_default()), )?; + let ctrl_type = self.data.ctrl_type(index + 1); + region.assign_advice( + || "op type", + config.ctrl_type, + offset, + || Value::known(Fp::from(ctrl_type)), + )?; + region.assign_advice( + || "enabling s_op", + config.s_ctrl_type[ctrl_type as usize], + offset, + || Value::known(Fp::one()), + )?; cur_depth = cur_depth.double(); offset += 1; } // final line + let ctrl_type = self.data.ctrl_type(paths.len() + 1); + region.assign_advice( + || "op type", + config.ctrl_type, + offset, + || Value::known(Fp::from(ctrl_type)), + )?; + region.assign_advice( + || "enabling s_op", + config.s_ctrl_type[ctrl_type as usize], + offset, + || Value::known(Fp::one()), + )?; region.assign_advice( || "path", config.path, @@ -954,7 +1028,12 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { offset, || Value::known(self.data.key_immediate), )?; - region.assign_advice(|| "depth", config.depth, offset, || Value::known(cur_depth))?; + region.assign_advice( + || "depth", + config.depth, + offset, + || Value::known(cur_depth) + )?; region.assign_advice( || "sibling last (key for extended or padding)", config.sibling, @@ -987,6 +1066,8 @@ mod test { Self { s_row: meta.complex_selector(), s_enable: meta.advice_column(), + ctrl_type: meta.advice_column(), + s_ctrl_type: [meta.advice_column();6],//notice we just need one col as dummy array here s_path: meta.advice_column(), sibling: meta.advice_column(), depth: meta.advice_column(), @@ -1016,6 +1097,18 @@ mod test { offset, || Value::known(rand_fp()), )?; + region.assign_advice( + || "flushing", + self.ctrl_type, + offset, + || Value::known(rand_fp()), + )?; + region.assign_advice( + || "flushing", + self.s_ctrl_type[0], + offset, + || Value::known(rand_fp()), + )?; region.assign_advice( || "flushing", self.depth, @@ -1293,8 +1386,6 @@ mod test { #[derive(Clone)] struct TestOpCircuit { data: SingleOp, - old_hash_types: Vec, - new_hash_types: Vec, } impl Circuit for TestOpCircuit { @@ -1328,7 +1419,7 @@ mod test { |mut region| { let config = &config.global; config.flush_row(&mut region, 0)?; - let next_offset = offset + self.old_hash_types.len(); + let next_offset = offset + self.data.old.hash_types.len(); //need to fill some other cols for (index, offset) in (offset..next_offset).enumerate() { config.s_row.enable(&mut region, offset)?; @@ -1343,7 +1434,7 @@ mod test { config.s_path, offset, || { - Value::known(match self.old_hash_types[index] { + Value::known(match self.data.old.hash_types[index] { HashType::Empty | HashType::Leaf | HashType::Start => { Fp::zero() } @@ -1355,13 +1446,13 @@ mod test { || "old hash_type", config.old_hash_type, offset, - || Value::known(Fp::from(self.old_hash_types[index] as u64)), + || Value::known(Fp::from(self.data.old.hash_types[index] as u64)), )?; region.assign_advice( || "new hash_type", config.new_hash_type, offset, - || Value::known(Fp::from(self.new_hash_types[index] as u64)), + || Value::known(Fp::from(self.data.new.hash_types[index] as u64)), )?; } @@ -1382,7 +1473,7 @@ mod test { &mut layouter, OPMAP .iter() - .map(|(a, b)| ([*a as u32, *b as u32, 0], CtrlTransitionKind::Operation as u32)), + .map(|(a, b, c)| ([*a as u32, *b as u32, *c as u32], CtrlTransitionKind::Operation as u32)), )?; // op chip now need hash table (for key hash lookup) @@ -1398,13 +1489,7 @@ mod test { impl TestOpCircuit { fn from_op(op: SingleOp) -> Self { Self { - old_hash_types: op.old.hash_types, - new_hash_types: op.new.hash_types, - data: SingleOp:: { - path: op.path, - siblings: op.siblings, - ..Default::default() - }, + data: op, } } } @@ -1429,12 +1514,15 @@ mod test { key_residual: Fp::from(4u64), old: MPTPath::{ hash_traces: vec![(Fp::one(), Fp::from(4u64), Fp::zero())], + hash_types: vec![HashType::Start, HashType::Empty], + ..Default::default() + }, + new: MPTPath:: { + hash_types: vec![HashType::Start, HashType::Leaf], ..Default::default() }, ..Default::default() }, - old_hash_types: vec![HashType::Start, HashType::Empty], - new_hash_types: vec![HashType::Start, HashType::Leaf], } }; @@ -1447,12 +1535,15 @@ mod test { key_residual: Fp::from(8u64), old: MPTPath::{ hash_traces: vec![(Fp::one(), Fp::from(9u64), Fp::zero())], + hash_types: vec![HashType::Start, HashType::LeafExtFinal, HashType::Empty], ..Default::default() }, + new: MPTPath:: { + hash_types: vec![HashType::Start, HashType::Middle, HashType::Leaf], + ..Default::default() + }, ..Default::default() }, - old_hash_types: vec![HashType::Start, HashType::LeafExtFinal, HashType::Empty], - new_hash_types: vec![HashType::Start, HashType::Middle, HashType::Leaf], } }; @@ -1465,24 +1556,27 @@ mod test { key_residual: Fp::from(5u64), old: MPTPath::{ hash_traces: vec![(Fp::one(), Fp::from(45u64), Fp::zero())], + hash_types: vec![ + HashType::Start, + HashType::Middle, + HashType::LeafExt, + HashType::LeafExtFinal, + HashType::Empty, + ], ..Default::default() }, + new: MPTPath:: { + hash_types: vec![ + HashType::Start, + HashType::Middle, + HashType::Middle, + HashType::Middle, + HashType::Leaf, + ], + ..Default::default() + }, ..Default::default() }, - old_hash_types: vec![ - HashType::Start, - HashType::Middle, - HashType::LeafExt, - HashType::LeafExtFinal, - HashType::Empty, - ], - new_hash_types: vec![ - HashType::Start, - HashType::Middle, - HashType::Middle, - HashType::Middle, - HashType::Leaf, - ], } }; } @@ -1510,8 +1604,6 @@ mod test { let k = 5; let circuit = TestOpCircuit { - old_hash_types: op.old.hash_types.clone(), - new_hash_types: op.new.hash_types.clone(), data: op, }; let prover = MockProver::::run(k, &circuit, vec![]).unwrap(); @@ -1542,22 +1634,16 @@ mod test { fn configure(meta: &mut ConstraintSystem) -> Self::Config { let sel = meta.complex_selector(); let free_cols = [(); 16].map(|_| meta.advice_column()); - let exported_cols = [ - free_cols[0], - free_cols[1], - free_cols[2], - free_cols[3], - free_cols[4], - free_cols[5], - free_cols[6], - free_cols[7], - ]; + let exported_cols : [_; 8] = free_cols[0..8].try_into().unwrap(); + let op_flag_cols : Vec<_> = (0..MPTOpGadget::min_ctrl_types()) + .map(|_|meta.advice_column()).collect(); GadgetTestConfig { gadget: MPTOpGadget::configure_simple( meta, sel, &exported_cols[..], + op_flag_cols.as_slice(), &free_cols[8..], None, ), diff --git a/src/operation.rs b/src/operation.rs index 0c781cd1..14f941b1 100644 --- a/src/operation.rs +++ b/src/operation.rs @@ -242,6 +242,21 @@ impl SingleOp { self.siblings.len() + 2 } + /// calculate the ctrl_type in one row base on the two hash type of MPTPath + pub fn ctrl_type(&self, row_ind: usize) -> u64 { + let type_pair = (self.old.hash_types[row_ind], self.new.hash_types[row_ind]); + match type_pair { + (old, new) if old == new => old as u64, + (HashType::Middle, HashType::LeafExt) | + (HashType::LeafExt, HashType::Middle) => HashType::LeafExt as u64, + (HashType::Middle, HashType::LeafExtFinal) | + (HashType::LeafExtFinal, HashType::Middle) => HashType::LeafExtFinal as u64, + (HashType::Empty, HashType::Leaf) | + (HashType::Leaf, HashType::Empty) => HashType::Leaf as u64, + _ => unreachable!("invalid hash type pair: {:?}, {:?}", type_pair.0, type_pair.1), + } + } + /// the root of MPT before operation pub fn start_root(&self) -> Fp { self.old.root() From 7f73df5a5fd3bb92a366ca723b71c0e3bdf5ad13 Mon Sep 17 00:00:00 2001 From: Ho Vei Date: Fri, 13 Jan 2023 23:43:52 +0800 Subject: [PATCH 06/17] reduce degrees in eth gadget --- src/eth.rs | 55 +++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/src/eth.rs b/src/eth.rs index 6019b9cf..180f661f 100644 --- a/src/eth.rs +++ b/src/eth.rs @@ -104,7 +104,7 @@ impl AccountGadget { meta, sel, s_enable, - ctrl_type, + s_ctrl_type, data_old, data_old_ext, &free[0..2], @@ -114,7 +114,7 @@ impl AccountGadget { meta, sel, s_enable, - ctrl_type, + s_ctrl_type, data_new, data_new_ext, &free[2..4], @@ -127,9 +127,7 @@ impl AccountGadget { meta.lookup("account row trans", |meta| { let s_enable = meta.query_advice(s_enable, Rotation::cur()) * (Expression::Constant(Fp::one()) - - AccountChip::<'_, Fp>::lagrange_polynomial_for_row::<0>( - meta.query_advice(ctrl_type, Rotation::cur()), - )); + - meta.query_advice(s_ctrl_type[0], Rotation::cur())); tables.build_lookup( s_enable, @@ -143,9 +141,7 @@ impl AccountGadget { meta.create_gate("address constraint", |meta| { let s_enable = meta.query_selector(sel) * meta.query_advice(s_enable, Rotation::cur()); - let row0 = AccountChip::<'_, Fp>::lagrange_polynomial_for_row::<0>( - meta.query_advice(ctrl_type, Rotation::cur()), - ); + let row0 = meta.query_advice(s_ctrl_type[0], Rotation::cur()); let address_limb_0 = meta.query_advice(old_state.intermediate_1, Rotation::cur()); let address_limb_1 = meta.query_advice(new_state.intermediate_1, Rotation::cur()); @@ -165,9 +161,7 @@ impl AccountGadget { meta.lookup_any("address hash", |meta| { let s_enable = meta.query_advice(s_enable, Rotation::cur()) - * AccountChip::<'_, Fp>::lagrange_polynomial_for_row::<0>( - meta.query_advice(ctrl_type, Rotation::cur()), - ); + * meta.query_advice(s_ctrl_type[0], Rotation::cur()); let address_limb_0 = meta.query_advice(old_state.intermediate_1, Rotation::cur()); let address_limb_1 = meta.query_advice(new_state.intermediate_1, Rotation::cur()); @@ -230,9 +224,7 @@ impl AccountGadget { //additional row meta.create_gate("padding row", |meta| { let s_enable = meta.query_selector(sel) * meta.query_advice(s_enable, Rotation::cur()); - let row3 = AccountChip::<'_, Fp>::lagrange_polynomial_for_row::<3>( - meta.query_advice(ctrl_type, Rotation::cur()), - ); + let row3 = meta.query_advice(s_ctrl_type[3], Rotation::cur()); let old_root = meta.query_advice(data_old, Rotation::cur()); let new_root = meta.query_advice(data_new, Rotation::cur()); @@ -421,7 +413,7 @@ impl<'d, Fp: FieldExt> AccountChip<'d, Fp> { meta: &mut ConstraintSystem, sel: Selector, s_enable: Column, - ctrl_type: Column, + s_ctrl_type: [Column;4], acc_data_fields: Column, acc_data_fields_ext: Column, free_cols: &[Column], @@ -434,8 +426,7 @@ impl<'d, Fp: FieldExt> AccountChip<'d, Fp> { meta.lookup_any("account hash1 calc", |meta| { // only enable on row 2 let s_enable = meta.query_advice(s_enable, Rotation::cur()); - let ctrl_type = meta.query_advice(ctrl_type, Rotation::cur()); - let enable_rows = Self::lagrange_polynomial_for_row::<2>(ctrl_type); + let enable_rows = meta.query_advice(s_ctrl_type[2], Rotation::cur()); let enable = enable_rows * s_enable; let fst = meta.query_advice(acc_data_fields, Rotation::cur()); let snd = meta.query_advice(acc_data_fields_ext, Rotation::cur()); @@ -448,9 +439,8 @@ impl<'d, Fp: FieldExt> AccountChip<'d, Fp> { meta.lookup_any("account hash2 and hash_final calc", |meta| { // only enable on row 1 and 2 let s_enable = meta.query_advice(s_enable, Rotation::cur()); - let ctrl_type = meta.query_advice(ctrl_type, Rotation::cur()); - let enable_rows = Self::lagrange_polynomial_for_row::<1>(ctrl_type.clone()) - + Self::lagrange_polynomial_for_row::<2>(ctrl_type); + let enable_rows = meta.query_advice(s_ctrl_type[1], Rotation::cur()) + + meta.query_advice(s_ctrl_type[2], Rotation::cur()); let enable = enable_rows * s_enable; let fst = meta.query_advice(intermediate_1, Rotation::cur()); let snd = meta.query_advice(intermediate_2, Rotation::cur()); @@ -463,8 +453,7 @@ impl<'d, Fp: FieldExt> AccountChip<'d, Fp> { meta.lookup_any("account hash3 calc", |meta| { // only enable on row 1 let s_enable = meta.query_advice(s_enable, Rotation::cur()); - let ctrl_type = meta.query_advice(ctrl_type, Rotation::cur()); - let enable_rows = Self::lagrange_polynomial_for_row::<1>(ctrl_type); + let enable_rows = meta.query_advice(s_ctrl_type[1], Rotation::cur()); let enable = enable_rows * s_enable; let fst = meta.query_advice(acc_data_fields, Rotation::prev()); @@ -477,7 +466,6 @@ impl<'d, Fp: FieldExt> AccountChip<'d, Fp> { // equality constraint: hash_final and Root meta.create_gate("account calc equalities", |meta| { let s_enable = meta.query_selector(sel) * meta.query_advice(s_enable, Rotation::cur()); - let ctrl_type = meta.query_advice(ctrl_type, Rotation::cur()); let exported_equal1 = meta.query_advice(intermediate_2, Rotation::cur()) - meta.query_advice(acc_data_fields, Rotation::prev()); let exported_equal2 = meta.query_advice(intermediate_2, Rotation::cur()) @@ -486,9 +474,9 @@ impl<'d, Fp: FieldExt> AccountChip<'d, Fp> { // equalities in the circuit vec![ s_enable.clone() - * Self::lagrange_polynomial_for_row::<0>(ctrl_type.clone()) + * meta.query_advice(s_ctrl_type[0], Rotation::cur()) * exported_equal1, // equality of hash_final - s_enable * Self::lagrange_polynomial_for_row::<2>(ctrl_type) * exported_equal2, // equality of state trie root + s_enable * meta.query_advice(s_ctrl_type[2], Rotation::cur()) * exported_equal2, // equality of state trie root ] }); @@ -744,6 +732,7 @@ mod test { gadget: AccountGadget, sel: Selector, free_cols: [Column; 14], + s_ctrl_cols: [Column; 4], op_tabl: mpt::MPTOpTables, hash_tabl: mpt::HashTable, } @@ -765,7 +754,7 @@ mod test { fn configure(meta: &mut ConstraintSystem) -> Self::Config { let sel = meta.selector(); let free_cols = [(); 14].map(|_| meta.advice_column()); - let dummy_s_ctrl = [meta.advice_column();4]; + let s_ctrl_cols = [(); 4].map(|_| meta.advice_column()); let exported_cols = [ free_cols[0], free_cols[1], @@ -783,7 +772,7 @@ mod test { meta, sel, exported_cols.as_slice(), - dummy_s_ctrl.as_slice(), + s_ctrl_cols.as_slice(), &free_cols[8..], None, op_tabl.clone(), @@ -794,6 +783,7 @@ mod test { gadget, sel, free_cols, + s_ctrl_cols, op_tabl, hash_tabl, } @@ -828,6 +818,17 @@ mod test { )?; } + for offset in 1..=CIRCUIT_ROW { + for col in config.s_ctrl_cols { + region.assign_advice( + || "flush s_ctrl", + col, + offset, + || Value::known(Fp::zero()), + )?; + } + } + let till = config.gadget.assign( &mut region, 1, From f754de78877b0284b06138f2b48517012936a192 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Sat, 14 Jan 2023 16:21:30 +0800 Subject: [PATCH 07/17] wip: derive Debug for EthTrieCircuit --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index d613dced..8b0a210b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -625,7 +625,7 @@ impl EthTrie { } /// the mpt circuit type -#[derive(Clone, Default)] +#[derive(Clone, Default, Debug)] pub struct EthTrieCircuit { /// the maxium records in circuits (would affect vk) pub calcs: usize, From c9a75b0c5fa84b2cea3010eef024253a4272e625 Mon Sep 17 00:00:00 2001 From: Ho Vei Date: Mon, 16 Jan 2023 09:34:06 +0800 Subject: [PATCH 08/17] reduce degrees in mpt gadget: path chip --- src/mpt.rs | 312 +++++++++++++++++++++++++---------------------- src/operation.rs | 29 +++-- 2 files changed, 182 insertions(+), 159 deletions(-) diff --git a/src/mpt.rs b/src/mpt.rs index 7dc1a163..c3529402 100644 --- a/src/mpt.rs +++ b/src/mpt.rs @@ -296,9 +296,11 @@ struct MPTOpConfig { s_path: Column, depth: Column, ctrl_type: Column, - s_ctrl_type: [Column; 6], + s_ctrl_type: [Column; HASH_TYPE_CNT], old_hash_type: Column, new_hash_type: Column, + s_hash_match_ctrl: [Column; 2], //[old, new] + s_hash_match_ctrl_aux: [Column; 2], sibling: Column, acc_key: Column, path: Column, @@ -323,11 +325,11 @@ pub(crate) struct MPTOpGadget { impl MPTOpGadget { pub fn min_free_cols() -> usize { - 8 + 11 } pub fn min_ctrl_types() -> usize { - 6 + HASH_TYPE_CNT } /// if the gadget would be used only once, this entry is more easy @@ -373,6 +375,8 @@ impl MPTOpGadget { sibling: free[4], path: free[5], key_aux: free[6], + s_hash_match_ctrl: [free[7], free[8]], + s_hash_match_ctrl_aux: [free[9], free[10]], ctrl_type: exported[0], s_enable: exported[1], old_val: exported[2], @@ -448,8 +452,9 @@ impl MPTOpGadget { offset: usize, data: &SingleOp, ) -> Result { - let old_path_chip = PathChip::::construct(self.old_path.clone(), offset, &data.old); - let new_path_chip = PathChip::::construct(self.new_path.clone(), offset, &data.new); + let ctrl_type = data.ctrl_type(); + let old_path_chip = PathChip::::construct(self.old_path.clone(), offset, &data.old, Some(&ctrl_type)); + let new_path_chip = PathChip::::construct(self.new_path.clone(), offset, &data.new, Some(&ctrl_type)); let op_chip = OpChip::::construct(self.op.clone(), offset, data); // caution: we made double assignations on key cell so sequence is important @@ -479,10 +484,15 @@ fn lagrange_polynomial_for_hashtype( super::lagrange_polynomial::(ref_n) } +const HASH_TYPE_CNT : usize = 6; + #[derive(Clone, Debug)] struct PathChipConfig { s_path: Column, hash_type: Column, + s_hash_type: [Column;HASH_TYPE_CNT], + s_match_ctrl_type: Column, + s_match_ctrl_aux: Column, val: Column, } @@ -492,6 +502,7 @@ struct PathChip<'d, F: FieldExt> { offset: usize, config: PathChipConfig, data: &'d MPTPath, + ref_ctrl_type: Option<&'d [HashType]>, } impl Chip for PathChip<'_, Fp> { @@ -515,11 +526,22 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { ) -> >::Config { let s_path = g_config.s_path; let s_enable = g_config.s_enable; + let s_hash_type = g_config.s_ctrl_type; let hash_type = if from_old { g_config.old_hash_type } else { g_config.new_hash_type }; + let s_match_ctrl_type = if from_old { + g_config.s_hash_match_ctrl[0] + } else { + g_config.s_hash_match_ctrl[1] + }; + let s_match_ctrl_aux = if from_old { + g_config.s_hash_match_ctrl_aux[0] + } else { + g_config.s_hash_match_ctrl_aux[1] + }; let val = if from_old { g_config.old_val } else { @@ -559,10 +581,15 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { // // from table formed by (left, right, hash) meta.lookup_any("mpt node hash", |meta| { - let hash_type = meta.query_advice(hash_type, Rotation::cur()); + let s_hash_type_not_match = Expression::Constant(Fp::one()) - + meta.query_advice(s_match_ctrl_type, Rotation::cur()); let s_path = meta.query_selector(s_row) * meta.query_advice(s_enable, Rotation::cur()) - * lagrange_polynomial_for_hashtype::<_, 2>(hash_type); //Middle + * ( + meta.query_advice(s_hash_type[HashType::Middle as usize], Rotation::cur()) + + s_hash_type_not_match.clone() * meta.query_advice(s_hash_type[HashType::LeafExt as usize], Rotation::cur()) + + s_hash_type_not_match * meta.query_advice(s_hash_type[HashType::LeafExtFinal as usize], Rotation::cur()) + ); //hash type is Middle: i.e ctrl type is Middle or (Ext and ExtFinal and not match) let path_bit = meta.query_advice(path, Rotation::cur()); let val_col = meta.query_advice(val, Rotation::cur()); @@ -580,9 +607,9 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { // calculate part of the leaf hash: hash(key_immediate, val) = hash_of_key_node meta.lookup_any("mpt leaf hash", |meta| { - let hash_type = meta.query_advice(hash_type, Rotation::cur()); - let s_leaf = meta.query_advice(s_enable, Rotation::cur()) - * lagrange_polynomial_for_hashtype::<_, 5>(hash_type); //Leaf + let s_leaf = meta.query_advice(s_enable, Rotation::cur()) + * meta.query_advice(s_match_ctrl_type, Rotation::cur()) + * meta.query_advice(s_hash_type[HashType::Leaf as usize], Rotation::cur()); //(actually) Leaf let key_immediate = meta.query_advice(key_immediate, Rotation::cur()); let leaf_val = meta.query_advice(val, Rotation::cur()); @@ -593,9 +620,7 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { //transition, notice the start status is ensured outside of the gadget meta.lookup("mpt type trans", |meta| { let s_not_begin = Expression::Constant(Fp::one()) - - lagrange_polynomial_for_hashtype::<_, 0>( - meta.query_advice(hash_type, Rotation::cur()), - ); //not Start + - meta.query_advice(s_hash_type[HashType::Start as usize], Rotation::cur()); //not Start let s_block_enable = meta.query_advice(s_enable, Rotation::cur()) * s_not_begin; @@ -609,8 +634,8 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { meta.create_gate("leaf extended", |meta| { let enable = meta.query_selector(s_row) * meta.query_advice(s_enable, Rotation::cur()); - let hash_type = meta.query_advice(hash_type, Rotation::cur()); - let s_extended = lagrange_polynomial_for_hashtype::<_, 3>(hash_type); //LeafExt + let s_extended = meta.query_advice(s_match_ctrl_type, Rotation::cur()) + * meta.query_advice(s_hash_type[HashType::LeafExt as usize], Rotation::cur()); //(actually) LeafExt let sibling = meta.query_advice(sibling, Rotation::cur()); // + sibling must be 0 when hash_type is leaf extended, or malice // advisor can make arbital sibling which would halt the process of L2 @@ -626,8 +651,8 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { meta.create_gate("last leaf extended", |meta| { let enable = meta.query_selector(s_row) * meta.query_advice(s_enable, Rotation::cur()); - let hash_type = meta.query_advice(hash_type, Rotation::cur()); - let s_last_extended = lagrange_polynomial_for_hashtype::<_, 4>(hash_type); //LeafExtFinal + let s_last_extended = meta.query_advice(s_match_ctrl_type, Rotation::cur()) + * meta.query_advice(s_hash_type[HashType::LeafExtFinal as usize], Rotation::cur()); //(actually) LeafExtFinal // + sibling must be previous value of val when hash_type is leaf extended final // (notice the value for leafExtendedFinal can be omitted) @@ -678,6 +703,9 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { PathChipConfig { s_path, hash_type, + s_hash_type, + s_match_ctrl_type, + s_match_ctrl_aux, val, } } @@ -686,33 +714,40 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { config: PathChipConfig, offset: usize, data: &'d >::Loaded, + ref_ctrl_type: Option<&'d [HashType]>, ) -> Self { Self { config, offset, data, + ref_ctrl_type, } } fn assign(&self, region: &mut Region<'_, Fp>) -> Result { let config = &self.config; - let mut offset = self.offset; + let offset = self.offset; let vals = &self.data.hashes; let hash_types = &self.data.hash_types; assert_eq!(hash_types.len(), vals.len()); - for (hash_type, val) in hash_types.iter().zip(vals.iter()) { - region.assign_advice(|| "val", config.val, offset, || Value::known(*val))?; + for (index, (hash_type, val)) in hash_types.iter().copied().zip(vals.iter()).enumerate() { region.assign_advice( - || format!("hash_type {}", *hash_type as u32), - config.hash_type, - offset, - || Value::known(Fp::from(*hash_type as u64)), + || "val", + config.val, + offset + index, + || Value::known(*val), )?; + region.assign_advice( + || format!("hash_type {}", hash_type as u32), + config.hash_type, + offset + index, + || Value::known(Fp::from(hash_type as u64)), + )?; region.assign_advice( || "sel", config.s_path, - offset, + offset + index, || { Value::known(match hash_type { HashType::Start | HashType::Empty | HashType::Leaf => Fp::zero(), @@ -720,17 +755,32 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { }) }, )?; - offset += 1; } - Ok(offset) + let ref_ctrl_type = self.ref_ctrl_type.unwrap_or(&self.data.hash_types).iter().copied(); + for (index, (hash_type, ref_type)) in hash_types.iter().copied().zip(ref_ctrl_type).enumerate() { + region.assign_advice( + || "hash_type match aux", + config.s_match_ctrl_aux, + offset + index, + || Value::known(Fp::from(ref_type as u64 - hash_type as u64).invert().unwrap_or_else(Fp::zero)), + )?; + region.assign_advice( + || "hash_type match", + config.s_match_ctrl_type, + offset + index, + || Value::known(if hash_type == ref_type {Fp::one()} else {Fp::zero()}), + )?; + } + + Ok(offset + hash_types.len()) } } #[derive(Clone, Debug)] struct OpChipConfig { ctrl_type: Column, - s_ctrl_type: [Column;6], + s_ctrl_type: [Column;HASH_TYPE_CNT], sibling: Column, path: Column, depth: Column, @@ -891,6 +941,7 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { let paths = &self.data.path; let siblings = &self.data.siblings; assert_eq!(paths.len(), siblings.len()); + let ctrl_type = self.data.ctrl_type(); let mut offset = self.offset; region.assign_advice( || "path padding", @@ -916,16 +967,15 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { offset, || Value::known(Fp::zero()), )?; - let ctrl_type_head_row = self.data.ctrl_type(0); region.assign_advice( || "op type start", config.ctrl_type, offset, - || Value::known(Fp::from(ctrl_type_head_row)), + || Value::known(Fp::from(ctrl_type[0] as u64)), )?; region.assign_advice( || "enabling s_op", - config.s_ctrl_type[ctrl_type_head_row as usize], + config.s_ctrl_type[ctrl_type[0] as usize], offset, || Value::known(Fp::one()), )?; @@ -978,16 +1028,15 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { offset, || Value::known(extend_proof.map(|pf| pf.1).unwrap_or_default()), )?; - let ctrl_type = self.data.ctrl_type(index + 1); region.assign_advice( - || "op type", + || "ctrl type", config.ctrl_type, offset, - || Value::known(Fp::from(ctrl_type)), + || Value::known(Fp::from(ctrl_type[index + 1] as u64)), )?; region.assign_advice( || "enabling s_op", - config.s_ctrl_type[ctrl_type as usize], + config.s_ctrl_type[ctrl_type[index + 1] as usize], offset, || Value::known(Fp::one()), )?; @@ -997,12 +1046,12 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { } // final line - let ctrl_type = self.data.ctrl_type(paths.len() + 1); + let ctrl_type = *ctrl_type.last().expect("always has at least 2 rows"); region.assign_advice( || "op type", config.ctrl_type, offset, - || Value::known(Fp::from(ctrl_type)), + || Value::known(Fp::from(ctrl_type as u64)), )?; region.assign_advice( || "enabling s_op", @@ -1067,7 +1116,9 @@ mod test { s_row: meta.complex_selector(), s_enable: meta.advice_column(), ctrl_type: meta.advice_column(), - s_ctrl_type: [meta.advice_column();6],//notice we just need one col as dummy array here + s_ctrl_type: [();HASH_TYPE_CNT].map(|_|meta.advice_column()), + s_hash_match_ctrl: [();2].map(|_|meta.advice_column()), + s_hash_match_ctrl_aux: [();2].map(|_|meta.advice_column()), s_path: meta.advice_column(), sibling: meta.advice_column(), depth: meta.advice_column(), @@ -1085,79 +1136,42 @@ mod test { /// simply flush a row with 0 value to avoid gate poisoned / cell error in debug prover, pub fn flush_row(&self, region: &mut Region<'_, Fp>, offset: usize) -> Result<(), Error> { - region.assign_advice( - || "flushing", - self.s_enable, - offset, - || Value::known(Fp::zero()), - )?; - region.assign_advice( - || "flushing", + + for rand_flush_col in [ self.s_path, - offset, - || Value::known(rand_fp()), - )?; - region.assign_advice( - || "flushing", self.ctrl_type, - offset, - || Value::known(rand_fp()), - )?; - region.assign_advice( - || "flushing", - self.s_ctrl_type[0], - offset, - || Value::known(rand_fp()), - )?; - region.assign_advice( - || "flushing", self.depth, - offset, - || Value::known(rand_fp()), - )?; - region.assign_advice( - || "flushing", self.sibling, - offset, - || Value::known(rand_fp()), - )?; - region.assign_advice( - || "flushing", self.key_aux, - offset, - || Value::known(rand_fp()), - )?; - region.assign_advice( - || "flushing", self.acc_key, - offset, - || Value::known(rand_fp()), - )?; - region.assign_advice(|| "flushing", self.path, offset, || Value::known(rand_fp()))?; - region.assign_advice( - || "flushing", + self.path, self.old_hash_type, - offset, - || Value::known(rand_fp()), - )?; - region.assign_advice( - || "flushing", self.new_hash_type, - offset, - || Value::known(rand_fp()), - )?; - region.assign_advice( - || "flushing", self.old_val, - offset, - || Value::known(rand_fp()), - )?; - region.assign_advice( - || "flushing", self.new_val, - offset, - || Value::known(rand_fp()), - )?; + ] { + region.assign_advice( + || "rand flushing", + rand_flush_col, + offset, + || Value::known(rand_fp()), + )?; + } + + for zero_flush_col in [ + self.s_enable, + ].into_iter() + .chain(self.s_ctrl_type) + .chain(self.s_hash_match_ctrl) + .chain(self.s_hash_match_ctrl_aux) { + region.assign_advice( + || "zero flushing", + zero_flush_col, + offset, + || Value::known(Fp::zero()), + )?; + } + Ok(()) } } @@ -1203,26 +1217,35 @@ mod test { ) -> Result<(), Error> { let offset: usize = 1; let chip_cfg = config.chip.clone(); - let mpt_chip = PathChip::::construct(chip_cfg, offset, &self.data); + let mpt_chip = PathChip::::construct(chip_cfg, offset, &self.data, None); layouter.assign_region( || "main", |mut region| { let config = &config.global; config.flush_row(&mut region, 0)?; let mut working_offset = offset; - config.flush_row(&mut region, working_offset)?; // also flush the firt row of working region + //enable, flush the whole of working region and ctrl flag + for (index, hash_type) in self.data.hash_types.iter().copied().enumerate() { + config.s_row.enable(&mut region, working_offset + index)?; + config.flush_row(&mut region, working_offset + index)?; + region.assign_advice( + || "enable", + config.s_ctrl_type[hash_type as usize], + working_offset + index, + || Value::known(Fp::one()), + )?; + } region.assign_advice( || "enable", config.s_enable, working_offset, || Value::known(Fp::one()), )?; - config.s_row.enable(&mut region, working_offset)?; + working_offset += 1; let next_offset = working_offset + self.siblings.len(); //need to fill some other cols for (index, offset) in (working_offset..next_offset).enumerate() { - config.s_row.enable(&mut region, offset)?; region.assign_advice( || "enable", config.s_enable, @@ -1243,32 +1266,19 @@ mod test { )?; } - region.assign_advice( - || "enable", - config.s_enable, - next_offset, - || Value::known(Fp::one()), - )?; - region.assign_advice( - || "path", - config.path, - next_offset, - || Value::known(self.key_residue), - )?; - region.assign_advice( - || "sibling", - config.sibling, - next_offset, - || Value::known(Fp::zero()), - )?; - region.assign_advice( - || "key", - config.key_aux, - next_offset, - || Value::known(self.key_immediate), - )?; - - config.s_row.enable(&mut region, next_offset)?; + for (col, val, tip) in [ + (config.s_enable, Fp::one(), "enable"), + (config.path, self.key_residue, "path"), + (config.sibling, Fp::zero(), "sibling"), + (config.key_aux, self.key_immediate, "key"), + ]{ + region.assign_advice( + || tip, + col, + next_offset, + || Value::known(val), + )?; + } let next_offset = next_offset + 1; let chip_next_offset = mpt_chip.assign(&mut region)?; @@ -1418,8 +1428,12 @@ mod test { || "main", |mut region| { let config = &config.global; - config.flush_row(&mut region, 0)?; let next_offset = offset + self.data.old.hash_types.len(); + //flush working region and ctrl flags + for offset in 0..next_offset { + config.flush_row(&mut region, offset)?; + } + //need to fill some other cols for (index, offset) in (offset..next_offset).enumerate() { config.s_row.enable(&mut region, offset)?; @@ -1614,7 +1628,7 @@ mod test { struct GadgetTestConfig { gadget: MPTOpGadget, sel: Selector, - free_cols: [Column; 16], + free_cols: Vec>, } // express for a single path block @@ -1633,18 +1647,21 @@ mod test { fn configure(meta: &mut ConstraintSystem) -> Self::Config { let sel = meta.complex_selector(); - let free_cols = [(); 16].map(|_| meta.advice_column()); - let exported_cols : [_; 8] = free_cols[0..8].try_into().unwrap(); - let op_flag_cols : Vec<_> = (0..MPTOpGadget::min_ctrl_types()) - .map(|_|meta.advice_column()).collect(); + let free_cols : Vec<_> = (0..( + 8 + //exported + MPTOpGadget::min_ctrl_types() + + MPTOpGadget::min_free_cols() + )).map(|_| meta.advice_column()).collect(); + let exported_cols = &free_cols[0..8]; + let op_flag_cols = &free_cols[8..8+MPTOpGadget::min_ctrl_types()]; GadgetTestConfig { gadget: MPTOpGadget::configure_simple( meta, sel, - &exported_cols[..], - op_flag_cols.as_slice(), - &free_cols[8..], + exported_cols, + op_flag_cols, + &free_cols[8+MPTOpGadget::min_ctrl_types()..], None, ), free_cols, @@ -1669,12 +1686,15 @@ mod test { layouter.assign_region( || "mpt", |mut region| { - //flush first row, just avoid Cell error ... - config.free_cols.iter().try_for_each(|col| { - region - .assign_advice(|| "flushing", *col, 0, || Value::known(Fp::zero())) - .map(|_| ()) - })?; + //flush all row required by data, just avoid Cell error ... + for offset in 0..(1+self.data.use_rows()){ + config.free_cols.iter().try_for_each(|col| { + region + .assign_advice(|| "flushing", *col, offset, || Value::known(Fp::zero())) + .map(|_| ()) + })?; + } + let end = config.gadget.assign(&mut region, 1, &self.data)?; for offset in 1..end { config.sel.enable(&mut region, offset)?; diff --git a/src/operation.rs b/src/operation.rs index 14f941b1..c258681a 100644 --- a/src/operation.rs +++ b/src/operation.rs @@ -242,19 +242,22 @@ impl SingleOp { self.siblings.len() + 2 } - /// calculate the ctrl_type in one row base on the two hash type of MPTPath - pub fn ctrl_type(&self, row_ind: usize) -> u64 { - let type_pair = (self.old.hash_types[row_ind], self.new.hash_types[row_ind]); - match type_pair { - (old, new) if old == new => old as u64, - (HashType::Middle, HashType::LeafExt) | - (HashType::LeafExt, HashType::Middle) => HashType::LeafExt as u64, - (HashType::Middle, HashType::LeafExtFinal) | - (HashType::LeafExtFinal, HashType::Middle) => HashType::LeafExtFinal as u64, - (HashType::Empty, HashType::Leaf) | - (HashType::Leaf, HashType::Empty) => HashType::Leaf as u64, - _ => unreachable!("invalid hash type pair: {:?}, {:?}", type_pair.0, type_pair.1), - } + /// calculate the ctrl_type base on the two hash type of MPTPath + pub fn ctrl_type(&self) -> Vec { + self.old.hash_types.iter().copied().zip(self.new.hash_types.clone()) + .map(|type_pair|{ + match type_pair { + (old, new) if old == new => old, + (HashType::Middle, HashType::LeafExt) | + (HashType::LeafExt, HashType::Middle) => HashType::LeafExt, + (HashType::Middle, HashType::LeafExtFinal) | + (HashType::LeafExtFinal, HashType::Middle) => HashType::LeafExtFinal, + (HashType::Empty, HashType::Leaf) | + (HashType::Leaf, HashType::Empty) => HashType::Leaf, + _ => unreachable!("invalid hash type pair: {:?}, {:?}", type_pair.0, type_pair.1), + } + }).collect() + } /// the root of MPT before operation From bc3ce227a76ae592a16b537d640c645bae4c97f7 Mon Sep 17 00:00:00 2001 From: Ho Vei Date: Mon, 16 Jan 2023 10:20:42 +0800 Subject: [PATCH 09/17] complete degree reduce --- src/eth.rs | 2 +- src/layers.rs | 2 +- src/lib.rs | 4 ++-- src/mpt.rs | 40 +++++++++++++++++++--------------------- src/mpt_table.rs | 2 +- 5 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/eth.rs b/src/eth.rs index 180f661f..48edabde 100644 --- a/src/eth.rs +++ b/src/eth.rs @@ -859,7 +859,7 @@ mod test { AccountTestCircuit::configure(&mut cs); println!("account gadget degree: {}", cs.degree()); - //assert!(cs.degree() <= 9); + assert!(cs.degree() <= 9); } #[test] diff --git a/src/layers.rs b/src/layers.rs index fc6a00db..b7797c09 100644 --- a/src/layers.rs +++ b/src/layers.rs @@ -973,7 +973,7 @@ mod test { MultiOpCircuit::configure(&mut cs); println!("layer gadget degree: {}", cs.degree()); - //assert!(cs.degree() <= 9); + assert!(cs.degree() <= 9); } #[test] diff --git a/src/lib.rs b/src/lib.rs index d0a8aed8..e3ce1d2e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -897,13 +897,13 @@ mod test { EthTrieCircuit::<_, false>::configure(&mut cs); println!("mpt circuit degree: {}", cs.degree()); - //assert!(cs.degree() <= 9); + assert!(cs.degree() <= 9); let mut cs: ConstraintSystem = Default::default(); HashCircuit::configure(&mut cs); println!("hash circuit degree: {}", cs.degree()); - //assert!(cs.degree() <= 9); + assert!(cs.degree() <= 9); } #[test] diff --git a/src/mpt.rs b/src/mpt.rs index c3529402..fedab8b8 100644 --- a/src/mpt.rs +++ b/src/mpt.rs @@ -396,10 +396,9 @@ impl MPTOpGadget { if let Some((old_root_index, new_root_index)) = root_index { meta.create_gate("root index", |meta| { let s_row = meta.query_selector(g_config.s_row); - let hash_type = meta.query_advice(g_config.old_hash_type, Rotation::cur()); let s_enable = s_row * meta.query_advice(g_config.s_enable, Rotation::cur()) - * lagrange_polynomial_for_hashtype::<_, 0>(hash_type); //Start; + * meta.query_advice(g_config.s_ctrl_type[HashType::Start as usize], Rotation::cur()); // constraint root index: // the old root in heading row (START) equal to the new_root_index_prev // the old root in heading row (START) also equal to the old_root_index_cur @@ -478,11 +477,13 @@ impl MPTOpGadget { } } +/* fn lagrange_polynomial_for_hashtype( ref_n: Expression, ) -> Expression { super::lagrange_polynomial::(ref_n) } +*/ const HASH_TYPE_CNT : usize = 6; @@ -583,8 +584,7 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { meta.lookup_any("mpt node hash", |meta| { let s_hash_type_not_match = Expression::Constant(Fp::one()) - meta.query_advice(s_match_ctrl_type, Rotation::cur()); - let s_path = meta.query_selector(s_row) - * meta.query_advice(s_enable, Rotation::cur()) + let s_path = meta.query_advice(s_enable, Rotation::cur()) * ( meta.query_advice(s_hash_type[HashType::Middle as usize], Rotation::cur()) + s_hash_type_not_match.clone() * meta.query_advice(s_hash_type[HashType::LeafExt as usize], Rotation::cur()) @@ -666,10 +666,9 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { // prove the silbing is really a leaf when extended meta.lookup_any("extended sibling proof 1", |meta| { - let s_last_extended = meta.query_advice(s_enable, Rotation::cur()) - * lagrange_polynomial_for_hashtype::<_, 4>( - meta.query_advice(hash_type, Rotation::cur()), - ); //LeafExtFinal + let s_last_extended = meta.query_advice(s_enable, Rotation::cur()) * + meta.query_advice(s_match_ctrl_type, Rotation::cur()) * + meta.query_advice(s_hash_type[HashType::LeafExtFinal as usize], Rotation::cur()); //(actually) LeafExtFinal let key_proof = meta.query_advice(sibling, Rotation::next()); //key is written here let key_proof_immediate = meta.query_advice(key_immediate, Rotation::cur()); @@ -683,10 +682,9 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { }); meta.lookup_any("extended sibling proof 2", |meta| { - let s_last_extended = meta.query_advice(s_enable, Rotation::cur()) - * lagrange_polynomial_for_hashtype::<_, 4>( - meta.query_advice(hash_type, Rotation::cur()), - ); //LeafExtFinal + let s_last_extended = meta.query_advice(s_enable, Rotation::cur()) * + meta.query_advice(s_match_ctrl_type, Rotation::cur()) * + meta.query_advice(s_hash_type[HashType::LeafExtFinal as usize], Rotation::cur()); //(actually) LeafExtFinal let extended_sibling = meta.query_advice(sibling, Rotation::cur()); let key_proof_immediate = meta.query_advice(key_immediate, Rotation::cur()); let key_proof_value = meta.query_advice(ext_sibling_val, Rotation::cur()); @@ -870,9 +868,7 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { meta.create_gate("depth", |meta| { let enable = meta.query_selector(s_row) * meta.query_advice(s_enable, Rotation::cur()); - let s_begin = lagrange_polynomial_for_hashtype::<_, 0>( - meta.query_advice(old_hash_type, Rotation::cur()), - ); //Start + let s_begin = meta.query_advice(s_ctrl_type[HashType::Start as usize], Rotation::cur()); //Start let path = meta.query_advice(path, Rotation::cur()); let depth_aux_start = meta.query_advice(depth_aux, Rotation::cur()) - Expression::Constant(Fp::one().double().invert().unwrap()); @@ -898,9 +894,8 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { }); meta.lookup_any("mpt key pre calc", |meta| { - let hash_type = meta.query_advice(old_hash_type, Rotation::cur()); let s_leaf = meta.query_advice(s_enable, Rotation::cur()) - * lagrange_polynomial_for_hashtype::<_, 5>(hash_type); //Leaf + * meta.query_advice(s_ctrl_type[HashType::Leaf as usize], Rotation::cur()); //Leaf let key = meta.query_advice(acc_key, Rotation::cur()); let key_immediate = meta.query_advice(key_aux, Rotation::cur()); @@ -1364,7 +1359,7 @@ mod test { TestPathCircuit::::configure(&mut cs); println!("mpt path gadget degree: {}", cs.degree()); - //assert!(cs.degree() <= 9); + assert!(cs.degree() <= 9); } #[test] @@ -1494,7 +1489,10 @@ mod test { config .global .hash_table - .fill(&mut layouter, self.data.old.hash_traces.iter())?; + .fill(&mut layouter, + self.data.old.hash_traces.iter() + .chain([(Fp::one(), self.data.key, Fp::zero())].iter()),//dummy for key calc + )?; Ok(()) } @@ -1514,7 +1512,7 @@ mod test { TestOpCircuit::configure(&mut cs); println!("mpt op gadget degree: {}", cs.degree()); - //assert!(cs.degree() <= 9); + assert!(cs.degree() <= 9); } lazy_static! { @@ -1720,7 +1718,7 @@ mod test { MPTTestCircuit::configure(&mut cs); println!("mpt full gadget degree: {}", cs.degree()); - //assert!(cs.degree() <= 9); + assert!(cs.degree() <= 9); } #[test] diff --git a/src/mpt_table.rs b/src/mpt_table.rs index 8c75d29b..b10ae49a 100644 --- a/src/mpt_table.rs +++ b/src/mpt_table.rs @@ -683,7 +683,7 @@ mod test { TestMPTTableCircuit::configure(&mut cs); println!("mpt table circuit degree: {}", cs.degree()); - //assert!(cs.degree() <= 9); + assert!(cs.degree() <= 9); } #[test] From 7b7d1846df91ff8c8415a7a0601852f581b27a9e Mon Sep 17 00:00:00 2001 From: Ho Vei Date: Wed, 18 Jan 2023 12:24:19 +0800 Subject: [PATCH 10/17] fix the account data issue --- src/operation.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/operation.rs b/src/operation.rs index c258681a..1db2c37c 100644 --- a/src/operation.rs +++ b/src/operation.rs @@ -893,12 +893,8 @@ impl<'d, Fp: Hashable> TryFrom<&'d serde::SMTTrace> for AccountOp { None => Fp::zero(), }; - // TODO: currently we just check if it is creation (no checking for deletion) - let account_before = if let Some(account_data) = &trace.account_update[0] { - let leaf = acc_trie - .old - .leaf() - .expect("leaf should exist when there is account data"); + let account_before = if let Some(leaf) = acc_trie.old.leaf() { + let account_data = trace.account_update[0].as_ref().expect("account should exist when there is leaf"); let old_state_root = state_trie .as_ref() .map(|s| s.start_root()) @@ -912,11 +908,8 @@ impl<'d, Fp: Hashable> TryFrom<&'d serde::SMTTrace> for AccountOp { None }; - let account_after = if let Some(account_data) = &trace.account_update[1] { - let leaf = acc_trie - .new - .leaf() - .expect("leaf should exist when there is account data"); + let account_after = if let Some(leaf) = acc_trie.new.leaf() { + let account_data = trace.account_update[1].as_ref().expect("account should exist when there is leaf"); let new_state_root = state_trie .as_ref() .map(|s| s.new_root()) From 5dd32542ee48bd3f3bec8718b330b13d42aaded0 Mon Sep 17 00:00:00 2001 From: Ho Vei Date: Thu, 19 Jan 2023 21:14:19 +0800 Subject: [PATCH 11/17] temporary fix issues #14 --- src/eth.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/eth.rs b/src/eth.rs index 48edabde..e4345e39 100644 --- a/src/eth.rs +++ b/src/eth.rs @@ -94,11 +94,12 @@ impl AccountGadget { let ctrl_type = exported[0]; let data_old = exported[2]; let data_new = exported[3]; - let data_key = exported[4]; + let data_key = exported[4]; //the mpt gadget above it use the col as 'data key' + let state_change_key = data_key; //while we use it as 'state_change_key' let data_old_ext = exported[5]; let data_new_ext = exported[6]; let s_ctrl_type = s_ctrl_type[0..4].try_into().expect("same size"); - let state_change_key = data_key; + let old_state = AccountChip::configure( meta, @@ -172,7 +173,7 @@ impl AccountGadget { } // this gate constraint each gadget handle at most one change in account data - meta.create_gate("single update for account data", |meta| { +/* meta.create_gate("single update for account data", |meta| { let enable = meta.query_selector(sel) * meta.query_advice(s_enable, Rotation::cur()); let data_diff = meta.query_advice(data_old, Rotation::cur()) - meta.query_advice(data_new, Rotation::cur()); @@ -182,7 +183,7 @@ impl AccountGadget { let is_diff_boolean = data_diff.clone() * meta.query_advice(state_change_aux[0], Rotation::cur()); let is_diff_ext_boolean = - data_ext_diff.clone() * meta.query_advice(state_change_aux[0], Rotation::cur()); + data_ext_diff.clone() * meta.query_advice(state_change_aux[1], Rotation::cur()); let one = Expression::Constant(Fp::one()); // switch A || B to ! (!A ^ !B) @@ -191,17 +192,17 @@ impl AccountGadget { * (one.clone() - is_diff_ext_boolean.clone()); let diff_acc = has_diff + meta.query_advice(s_enable, Rotation::prev()) - * meta.query_advice(data_key, Rotation::prev()); - let data_key = meta.query_advice(data_key, Rotation::cur()); + * meta.query_advice(state_change_key, Rotation::prev()); + let state_change_key = meta.query_advice(state_change_key, Rotation::cur()); vec![ enable.clone() * data_diff * (one.clone() - is_diff_boolean), enable.clone() * data_ext_diff * (one.clone() - is_diff_ext_boolean), - enable.clone() * (data_key.clone() - diff_acc), - enable * data_key.clone() * (one - data_key), + enable.clone() * (state_change_key.clone() - diff_acc), + enable * state_change_key.clone() * (one - state_change_key), ] }); - +*/ //additional row // TODO: nonce now can increase more than 1, we should constraint it with lookup table (better than a compare circuit) // BUT: this constraint should also exist in state circui so do we really need it? From ec3a3afb8561ef25facbd788e4805112a0b8795a Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Fri, 20 Jan 2023 10:45:27 +0800 Subject: [PATCH 12/17] fmt --- Cargo.toml | 3 +- src/eth.rs | 69 ++++++------ src/layers.rs | 93 +++++++++------- src/mpt.rs | 279 ++++++++++++++++++++++++++--------------------- src/operation.rs | 41 ++++--- 5 files changed, 270 insertions(+), 215 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 83162d38..b5c8cb0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ serde_json = "1.0" num-bigint = "0.4" hex = "0.4" thiserror = "1.0" +log = "0.4" [features] # printout the layout of circuits for demo and some unittests @@ -32,4 +33,4 @@ path = "integration-tests/src/main.rs" [profile.test] opt-level = 3 -debug-assertions = true \ No newline at end of file +debug-assertions = true diff --git a/src/eth.rs b/src/eth.rs index e4345e39..233ede59 100644 --- a/src/eth.rs +++ b/src/eth.rs @@ -60,7 +60,7 @@ pub(crate) struct AccountGadget { new_state: AccountChipConfig, s_enable: Column, ctrl_type: Column, - s_ctrl_type: [Column;4], + s_ctrl_type: [Column; 4], state_change_key: Column, state_change_aux: [Column; 2], @@ -100,7 +100,6 @@ impl AccountGadget { let data_new_ext = exported[6]; let s_ctrl_type = s_ctrl_type[0..4].try_into().expect("same size"); - let old_state = AccountChip::configure( meta, sel, @@ -173,36 +172,36 @@ impl AccountGadget { } // this gate constraint each gadget handle at most one change in account data -/* meta.create_gate("single update for account data", |meta| { - let enable = meta.query_selector(sel) * meta.query_advice(s_enable, Rotation::cur()); - let data_diff = meta.query_advice(data_old, Rotation::cur()) - - meta.query_advice(data_new, Rotation::cur()); - let data_ext_diff = meta.query_advice(data_old_ext, Rotation::cur()) - - meta.query_advice(data_new_ext, Rotation::cur()); - - let is_diff_boolean = - data_diff.clone() * meta.query_advice(state_change_aux[0], Rotation::cur()); - let is_diff_ext_boolean = - data_ext_diff.clone() * meta.query_advice(state_change_aux[1], Rotation::cur()); - - let one = Expression::Constant(Fp::one()); - // switch A || B to ! (!A ^ !B) - let has_diff = one.clone() - - (one.clone() - is_diff_boolean.clone()) - * (one.clone() - is_diff_ext_boolean.clone()); - let diff_acc = has_diff - + meta.query_advice(s_enable, Rotation::prev()) - * meta.query_advice(state_change_key, Rotation::prev()); - let state_change_key = meta.query_advice(state_change_key, Rotation::cur()); - - vec![ - enable.clone() * data_diff * (one.clone() - is_diff_boolean), - enable.clone() * data_ext_diff * (one.clone() - is_diff_ext_boolean), - enable.clone() * (state_change_key.clone() - diff_acc), - enable * state_change_key.clone() * (one - state_change_key), - ] - }); -*/ + /* meta.create_gate("single update for account data", |meta| { + let enable = meta.query_selector(sel) * meta.query_advice(s_enable, Rotation::cur()); + let data_diff = meta.query_advice(data_old, Rotation::cur()) + - meta.query_advice(data_new, Rotation::cur()); + let data_ext_diff = meta.query_advice(data_old_ext, Rotation::cur()) + - meta.query_advice(data_new_ext, Rotation::cur()); + + let is_diff_boolean = + data_diff.clone() * meta.query_advice(state_change_aux[0], Rotation::cur()); + let is_diff_ext_boolean = + data_ext_diff.clone() * meta.query_advice(state_change_aux[1], Rotation::cur()); + + let one = Expression::Constant(Fp::one()); + // switch A || B to ! (!A ^ !B) + let has_diff = one.clone() + - (one.clone() - is_diff_boolean.clone()) + * (one.clone() - is_diff_ext_boolean.clone()); + let diff_acc = has_diff + + meta.query_advice(s_enable, Rotation::prev()) + * meta.query_advice(state_change_key, Rotation::prev()); + let state_change_key = meta.query_advice(state_change_key, Rotation::cur()); + + vec![ + enable.clone() * data_diff * (one.clone() - is_diff_boolean), + enable.clone() * data_ext_diff * (one.clone() - is_diff_ext_boolean), + enable.clone() * (state_change_key.clone() - diff_acc), + enable * state_change_key.clone() * (one - state_change_key), + ] + }); + */ //additional row // TODO: nonce now can increase more than 1, we should constraint it with lookup table (better than a compare circuit) // BUT: this constraint should also exist in state circui so do we really need it? @@ -312,7 +311,7 @@ impl AccountGadget { self.s_ctrl_type[index as usize], offset, || Value::known(Fp::one()), - )?; + )?; if index == LAST_ROW { region.assign_advice( || "padding last row", @@ -414,7 +413,7 @@ impl<'d, Fp: FieldExt> AccountChip<'d, Fp> { meta: &mut ConstraintSystem, sel: Selector, s_enable: Column, - s_ctrl_type: [Column;4], + s_ctrl_type: [Column; 4], acc_data_fields: Column, acc_data_fields_ext: Column, free_cols: &[Column], @@ -827,7 +826,7 @@ mod test { offset, || Value::known(Fp::zero()), )?; - } + } } let till = config.gadget.assign( diff --git a/src/layers.rs b/src/layers.rs index b7797c09..b743a1b7 100644 --- a/src/layers.rs +++ b/src/layers.rs @@ -40,7 +40,7 @@ pub(crate) struct LayerGadget { // the s_ctrl_type is supposed to be a series of integers start from 0 and each of the number // is represented the corresponding items in s_ctrl_type array in which the number is just // its index - s_ctrl_type: Vec>, + s_ctrl_type: Vec>, // the 3 exported value now can be represented by 2-field and the additional // field is marked as "ext" (most value still use 1 field only) data_0: Column, @@ -114,7 +114,9 @@ impl LayerGadget { assert!(minium_ctrl_types > 0, "at least one ctrl type is required"); let s_stepflags: Vec<_> = (0..steps).map(|_| meta.advice_column()).collect(); let free_cols: Vec<_> = (0..required_cols).map(|_| meta.advice_column()).collect(); - let s_ctrl_type: Vec<_> = (0..minium_ctrl_types).map(|_| meta.advice_column()).collect(); + let s_ctrl_type: Vec<_> = (0..minium_ctrl_types) + .map(|_| meta.advice_column()) + .collect(); let sel = meta.complex_selector(); let series = meta.advice_column(); let op_type = meta.advice_column(); @@ -162,26 +164,38 @@ impl LayerGadget { // all flags is boolean // one and at most one flag must be enabled // the enabled flas must match with op_type - let s_ctrl : Vec<_> = s_ctrl_type.iter().copied().map(|col|meta.query_advice(col, Rotation::cur())).collect(); - - let bool_cond = s_ctrl.clone().into_iter() - .map(|col_exp|{ - sel.clone() * col_exp.clone() * (Expression::Constant(Fp::one()) - col_exp) + let s_ctrl: Vec<_> = s_ctrl_type + .iter() + .copied() + .map(|col| meta.query_advice(col, Rotation::cur())) + .collect(); + + let bool_cond = s_ctrl.clone().into_iter().map(|col_exp| { + sel.clone() * col_exp.clone() * (Expression::Constant(Fp::one()) - col_exp) + }); + + let one_flag_cond = s_ctrl + .clone() + .into_iter() + .reduce(|exp, col_exp| exp + col_exp) + .map(|sum_exp| sel.clone() * (Expression::Constant(Fp::one()) - sum_exp)); + + let ctrl_type_cond = s_ctrl + .into_iter() + .enumerate() + .map(|(idx, col_exp)| Expression::Constant(Fp::from(idx as u64)) * col_exp) + .reduce(|exp, col_exp_with_idx| exp + col_exp_with_idx) + .map(|w_sum_exp| { + sel.clone() * (meta.query_advice(ctrl_type, Rotation::cur()) - w_sum_exp) }); - let one_flag_cond = s_ctrl.clone().into_iter() - .reduce(|exp, col_exp|exp + col_exp) - .map(|sum_exp|sel.clone() * (Expression::Constant(Fp::one()) - sum_exp)); - - let ctrl_type_cond = s_ctrl.into_iter().enumerate() - .map(|(idx, col_exp)|Expression::Constant(Fp::from(idx as u64))*col_exp) - .reduce(|exp, col_exp_with_idx|exp + col_exp_with_idx) - .map(|w_sum_exp|sel.clone() * (meta.query_advice(ctrl_type, Rotation::cur()) - w_sum_exp)); - - let constraints = bool_cond.chain(one_flag_cond).chain(ctrl_type_cond).collect::>(); + let constraints = bool_cond + .chain(one_flag_cond) + .chain(ctrl_type_cond) + .collect::>(); if constraints.is_empty() { vec![sel * Expression::Constant(Fp::zero())] - }else { + } else { constraints } }); @@ -432,7 +446,7 @@ impl LayerGadget { || Value::known(Fp::zero()), ) .map(|_| ()) - })?; + })?; [ self.data_0, self.data_1, @@ -745,7 +759,7 @@ impl PaddingGadget { self.s_ctrl_type, offset, || Value::known(Fp::one()), - )?; + )?; region.assign_advice( || "enable padding", self.s_enable, @@ -791,13 +805,12 @@ mod test { fn configure(meta: &mut ConstraintSystem) -> Self::Config { let layer = LayerGadget::configure(meta, 1, 3, 1); - let padding = - PaddingGadget::configure( - meta, - layer.sel, - layer.exported_cols(0).as_slice(), - layer.get_ctrl_type_flags(), - ); + let padding = PaddingGadget::configure( + meta, + layer.sel, + layer.exported_cols(0).as_slice(), + layer.get_ctrl_type_flags(), + ); let cst = meta.fixed_column(); meta.enable_constant(cst); @@ -891,20 +904,18 @@ mod test { fn configure(meta: &mut ConstraintSystem) -> Self::Config { let layer = LayerGadget::configure(meta, 3, 2, 1); - let padding0 = - PaddingGadget::configure( - meta, - layer.sel, - layer.exported_cols(0).as_slice(), - layer.get_ctrl_type_flags(), - ); - let padding1 = - PaddingGadget::configure( - meta, - layer.sel, - layer.exported_cols(2).as_slice(), - layer.get_ctrl_type_flags(), - ); + let padding0 = PaddingGadget::configure( + meta, + layer.sel, + layer.exported_cols(0).as_slice(), + layer.get_ctrl_type_flags(), + ); + let padding1 = PaddingGadget::configure( + meta, + layer.sel, + layer.exported_cols(2).as_slice(), + layer.get_ctrl_type_flags(), + ); let cst = meta.fixed_column(); meta.enable_constant(cst); diff --git a/src/mpt.rs b/src/mpt.rs index fedab8b8..7373ff01 100644 --- a/src/mpt.rs +++ b/src/mpt.rs @@ -73,7 +73,7 @@ use lazy_static::lazy_static; #[derive(Clone, Debug)] pub(crate) struct MPTOpTables( - TableColumn, // op mark + TableColumn, // op mark [TableColumn; 3], // op rules ); @@ -118,7 +118,7 @@ impl MPTOpTables { pub fn configure_create(meta: &mut ConstraintSystem) -> Self { Self( meta.lookup_table_column(), - [0;3].map(|_|meta.lookup_table_column()), + [0; 3].map(|_| meta.lookup_table_column()), ) } @@ -128,9 +128,9 @@ impl MPTOpTables { rules: impl IntoIterator>, mark: u64, ) -> Vec<(Expression, TableColumn)> { - let mut ret : Vec<_> = rules + let mut ret: Vec<_> = rules .into_iter() - .map(|exp|enable.clone() * exp) + .map(|exp| enable.clone() * exp) .zip(self.1) .collect(); ret.push((enable * Expression::Constant(Fp::from(mark)), self.0)); @@ -150,7 +150,7 @@ impl MPTOpTables { pub fn fill_constant( &self, layouter: &mut impl Layouter, - rules: impl Iterator + Clone, + rules: impl Iterator + Clone, ) -> Result<(), Error> { layouter.assign_table( || "op table", @@ -158,7 +158,12 @@ impl MPTOpTables { // default line table.assign_cell(|| "default mark", self.0, 0, || Value::known(Fp::zero()))?; for i in 0..3 { - table.assign_cell(|| "default rule", self.1[i], 0, || Value::known(Fp::zero()))?; + table.assign_cell( + || "default rule", + self.1[i], + 0, + || Value::known(Fp::zero()), + )?; } for (offset, (items, mark)) in rules.clone().enumerate() { @@ -169,7 +174,7 @@ impl MPTOpTables { col, offset, || Value::known(Fp::from(rule as u64)), - )?; + )?; } table.assign_cell( @@ -344,7 +349,16 @@ impl MPTOpGadget { let tables = MPTOpTables::configure_create(meta); let hash_tbls = HashTable::configure_create(meta); - Self::configure(meta, sel, exported, s_ctrl_type, free, root_index, tables, hash_tbls) + Self::configure( + meta, + sel, + exported, + s_ctrl_type, + free, + root_index, + tables, + hash_tbls, + ) } /// create gadget from assigned cols, we need: @@ -398,11 +412,14 @@ impl MPTOpGadget { let s_row = meta.query_selector(g_config.s_row); let s_enable = s_row * meta.query_advice(g_config.s_enable, Rotation::cur()) - * meta.query_advice(g_config.s_ctrl_type[HashType::Start as usize], Rotation::cur()); - // constraint root index: - // the old root in heading row (START) equal to the new_root_index_prev - // the old root in heading row (START) also equal to the old_root_index_cur - // the new root in heading row (START) equal must be equal to new_root_index_cur + * meta.query_advice( + g_config.s_ctrl_type[HashType::Start as usize], + Rotation::cur(), + ); + // constraint root index: + // the old root in heading row (START) equal to the new_root_index_prev + // the old root in heading row (START) also equal to the old_root_index_cur + // the new root in heading row (START) equal must be equal to new_root_index_cur vec![ s_enable.clone() * (meta.query_advice(g_config.old_val, Rotation::cur()) @@ -432,10 +449,12 @@ impl MPTOpGadget { .iter() .copied() .map(|(a, b)| ([a as u32, b as u32, 0], CtrlTransitionKind::Mpt as u32)); - let i2 = OPMAP - .iter() - .copied() - .map(|(a, b, c)| ([a as u32, b as u32, c as u32], CtrlTransitionKind::Operation as u32)); + let i2 = OPMAP.iter().copied().map(|(a, b, c)| { + ( + [a as u32, b as u32, c as u32], + CtrlTransitionKind::Operation as u32, + ) + }); i1.chain(i2) } @@ -452,8 +471,10 @@ impl MPTOpGadget { data: &SingleOp, ) -> Result { let ctrl_type = data.ctrl_type(); - let old_path_chip = PathChip::::construct(self.old_path.clone(), offset, &data.old, Some(&ctrl_type)); - let new_path_chip = PathChip::::construct(self.new_path.clone(), offset, &data.new, Some(&ctrl_type)); + let old_path_chip = + PathChip::::construct(self.old_path.clone(), offset, &data.old, Some(&ctrl_type)); + let new_path_chip = + PathChip::::construct(self.new_path.clone(), offset, &data.new, Some(&ctrl_type)); let op_chip = OpChip::::construct(self.op.clone(), offset, data); // caution: we made double assignations on key cell so sequence is important @@ -477,7 +498,7 @@ impl MPTOpGadget { } } -/* +/* fn lagrange_polynomial_for_hashtype( ref_n: Expression, ) -> Expression { @@ -485,13 +506,13 @@ fn lagrange_polynomial_for_hashtype( } */ -const HASH_TYPE_CNT : usize = 6; +const HASH_TYPE_CNT: usize = 6; #[derive(Clone, Debug)] struct PathChipConfig { s_path: Column, hash_type: Column, - s_hash_type: [Column;HASH_TYPE_CNT], + s_hash_type: [Column; HASH_TYPE_CNT], s_match_ctrl_type: Column, s_match_ctrl_aux: Column, val: Column, @@ -582,14 +603,20 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { // // from table formed by (left, right, hash) meta.lookup_any("mpt node hash", |meta| { - let s_hash_type_not_match = Expression::Constant(Fp::one()) - - meta.query_advice(s_match_ctrl_type, Rotation::cur()); + let s_hash_type_not_match = Expression::Constant(Fp::one()) + - meta.query_advice(s_match_ctrl_type, Rotation::cur()); let s_path = meta.query_advice(s_enable, Rotation::cur()) - * ( - meta.query_advice(s_hash_type[HashType::Middle as usize], Rotation::cur()) - + s_hash_type_not_match.clone() * meta.query_advice(s_hash_type[HashType::LeafExt as usize], Rotation::cur()) - + s_hash_type_not_match * meta.query_advice(s_hash_type[HashType::LeafExtFinal as usize], Rotation::cur()) - ); //hash type is Middle: i.e ctrl type is Middle or (Ext and ExtFinal and not match) + * (meta.query_advice(s_hash_type[HashType::Middle as usize], Rotation::cur()) + + s_hash_type_not_match.clone() + * meta.query_advice( + s_hash_type[HashType::LeafExt as usize], + Rotation::cur(), + ) + + s_hash_type_not_match + * meta.query_advice( + s_hash_type[HashType::LeafExtFinal as usize], + Rotation::cur(), + )); //hash type is Middle: i.e ctrl type is Middle or (Ext and ExtFinal and not match) let path_bit = meta.query_advice(path, Rotation::cur()); let val_col = meta.query_advice(val, Rotation::cur()); @@ -607,7 +634,7 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { // calculate part of the leaf hash: hash(key_immediate, val) = hash_of_key_node meta.lookup_any("mpt leaf hash", |meta| { - let s_leaf = meta.query_advice(s_enable, Rotation::cur()) + let s_leaf = meta.query_advice(s_enable, Rotation::cur()) * meta.query_advice(s_match_ctrl_type, Rotation::cur()) * meta.query_advice(s_hash_type[HashType::Leaf as usize], Rotation::cur()); //(actually) Leaf @@ -652,7 +679,10 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { meta.create_gate("last leaf extended", |meta| { let enable = meta.query_selector(s_row) * meta.query_advice(s_enable, Rotation::cur()); let s_last_extended = meta.query_advice(s_match_ctrl_type, Rotation::cur()) - * meta.query_advice(s_hash_type[HashType::LeafExtFinal as usize], Rotation::cur()); //(actually) LeafExtFinal + * meta.query_advice( + s_hash_type[HashType::LeafExtFinal as usize], + Rotation::cur(), + ); //(actually) LeafExtFinal // + sibling must be previous value of val when hash_type is leaf extended final // (notice the value for leafExtendedFinal can be omitted) @@ -666,9 +696,12 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { // prove the silbing is really a leaf when extended meta.lookup_any("extended sibling proof 1", |meta| { - let s_last_extended = meta.query_advice(s_enable, Rotation::cur()) * - meta.query_advice(s_match_ctrl_type, Rotation::cur()) * - meta.query_advice(s_hash_type[HashType::LeafExtFinal as usize], Rotation::cur()); //(actually) LeafExtFinal + let s_last_extended = meta.query_advice(s_enable, Rotation::cur()) + * meta.query_advice(s_match_ctrl_type, Rotation::cur()) + * meta.query_advice( + s_hash_type[HashType::LeafExtFinal as usize], + Rotation::cur(), + ); //(actually) LeafExtFinal let key_proof = meta.query_advice(sibling, Rotation::next()); //key is written here let key_proof_immediate = meta.query_advice(key_immediate, Rotation::cur()); @@ -682,9 +715,12 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { }); meta.lookup_any("extended sibling proof 2", |meta| { - let s_last_extended = meta.query_advice(s_enable, Rotation::cur()) * - meta.query_advice(s_match_ctrl_type, Rotation::cur()) * - meta.query_advice(s_hash_type[HashType::LeafExtFinal as usize], Rotation::cur()); //(actually) LeafExtFinal + let s_last_extended = meta.query_advice(s_enable, Rotation::cur()) + * meta.query_advice(s_match_ctrl_type, Rotation::cur()) + * meta.query_advice( + s_hash_type[HashType::LeafExtFinal as usize], + Rotation::cur(), + ); //(actually) LeafExtFinal let extended_sibling = meta.query_advice(sibling, Rotation::cur()); let key_proof_immediate = meta.query_advice(key_immediate, Rotation::cur()); let key_proof_value = meta.query_advice(ext_sibling_val, Rotation::cur()); @@ -730,18 +766,13 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { assert_eq!(hash_types.len(), vals.len()); for (index, (hash_type, val)) in hash_types.iter().copied().zip(vals.iter()).enumerate() { - region.assign_advice( - || "val", - config.val, - offset + index, - || Value::known(*val), - )?; + region.assign_advice(|| "val", config.val, offset + index, || Value::known(*val))?; region.assign_advice( || format!("hash_type {}", hash_type as u32), config.hash_type, offset + index, || Value::known(Fp::from(hash_type as u64)), - )?; + )?; region.assign_advice( || "sel", config.s_path, @@ -755,20 +786,38 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { )?; } - let ref_ctrl_type = self.ref_ctrl_type.unwrap_or(&self.data.hash_types).iter().copied(); - for (index, (hash_type, ref_type)) in hash_types.iter().copied().zip(ref_ctrl_type).enumerate() { + let ref_ctrl_type = self + .ref_ctrl_type + .unwrap_or(&self.data.hash_types) + .iter() + .copied(); + for (index, (hash_type, ref_type)) in + hash_types.iter().copied().zip(ref_ctrl_type).enumerate() + { region.assign_advice( - || "hash_type match aux", - config.s_match_ctrl_aux, - offset + index, - || Value::known(Fp::from(ref_type as u64 - hash_type as u64).invert().unwrap_or_else(Fp::zero)), + || "hash_type match aux", + config.s_match_ctrl_aux, + offset + index, + || { + Value::known( + Fp::from(ref_type as u64 - hash_type as u64) + .invert() + .unwrap_or_else(Fp::zero), + ) + }, )?; region.assign_advice( - || "hash_type match", - config.s_match_ctrl_type, - offset + index, - || Value::known(if hash_type == ref_type {Fp::one()} else {Fp::zero()}), - )?; + || "hash_type match", + config.s_match_ctrl_type, + offset + index, + || { + Value::known(if hash_type == ref_type { + Fp::one() + } else { + Fp::zero() + }) + }, + )?; } Ok(offset + hash_types.len()) @@ -778,7 +827,7 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { #[derive(Clone, Debug)] struct OpChipConfig { ctrl_type: Column, - s_ctrl_type: [Column;HASH_TYPE_CNT], + s_ctrl_type: [Column; HASH_TYPE_CNT], sibling: Column, path: Column, depth: Column, @@ -992,24 +1041,14 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { for (index, (path, sibling)) in paths.iter().zip(siblings.iter()).enumerate() { acc_key = *path * cur_depth + acc_key; - region.assign_advice( - || "path", - config.path, - offset, - || Value::known(*path) - )?; + region.assign_advice(|| "path", config.path, offset, || Value::known(*path))?; region.assign_advice( || "acckey", config.acc_key, offset, || Value::known(acc_key), )?; - region.assign_advice( - || "depth", - config.depth, - offset, - || Value::known(cur_depth) - )?; + region.assign_advice(|| "depth", config.depth, offset, || Value::known(cur_depth))?; region.assign_advice( || "sibling", config.sibling, @@ -1053,7 +1092,7 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { config.s_ctrl_type[ctrl_type as usize], offset, || Value::known(Fp::one()), - )?; + )?; region.assign_advice( || "path", config.path, @@ -1072,12 +1111,7 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { offset, || Value::known(self.data.key_immediate), )?; - region.assign_advice( - || "depth", - config.depth, - offset, - || Value::known(cur_depth) - )?; + region.assign_advice(|| "depth", config.depth, offset, || Value::known(cur_depth))?; region.assign_advice( || "sibling last (key for extended or padding)", config.sibling, @@ -1111,9 +1145,9 @@ mod test { s_row: meta.complex_selector(), s_enable: meta.advice_column(), ctrl_type: meta.advice_column(), - s_ctrl_type: [();HASH_TYPE_CNT].map(|_|meta.advice_column()), - s_hash_match_ctrl: [();2].map(|_|meta.advice_column()), - s_hash_match_ctrl_aux: [();2].map(|_|meta.advice_column()), + s_ctrl_type: [(); HASH_TYPE_CNT].map(|_| meta.advice_column()), + s_hash_match_ctrl: [(); 2].map(|_| meta.advice_column()), + s_hash_match_ctrl_aux: [(); 2].map(|_| meta.advice_column()), s_path: meta.advice_column(), sibling: meta.advice_column(), depth: meta.advice_column(), @@ -1131,7 +1165,6 @@ mod test { /// simply flush a row with 0 value to avoid gate poisoned / cell error in debug prover, pub fn flush_row(&self, region: &mut Region<'_, Fp>, offset: usize) -> Result<(), Error> { - for rand_flush_col in [ self.s_path, self.ctrl_type, @@ -1150,21 +1183,21 @@ mod test { rand_flush_col, offset, || Value::known(rand_fp()), - )?; + )?; } - for zero_flush_col in [ - self.s_enable, - ].into_iter() - .chain(self.s_ctrl_type) - .chain(self.s_hash_match_ctrl) - .chain(self.s_hash_match_ctrl_aux) { + for zero_flush_col in [self.s_enable] + .into_iter() + .chain(self.s_ctrl_type) + .chain(self.s_hash_match_ctrl) + .chain(self.s_hash_match_ctrl_aux) + { region.assign_advice( || "zero flushing", zero_flush_col, offset, || Value::known(Fp::zero()), - )?; + )?; } Ok(()) @@ -1228,7 +1261,7 @@ mod test { config.s_ctrl_type[hash_type as usize], working_offset + index, || Value::known(Fp::one()), - )?; + )?; } region.assign_advice( || "enable", @@ -1266,13 +1299,8 @@ mod test { (config.path, self.key_residue, "path"), (config.sibling, Fp::zero(), "sibling"), (config.key_aux, self.key_immediate, "key"), - ]{ - region.assign_advice( - || tip, - col, - next_offset, - || Value::known(val), - )?; + ] { + region.assign_advice(|| tip, col, next_offset, || Value::known(val))?; } let next_offset = next_offset + 1; @@ -1426,7 +1454,7 @@ mod test { let next_offset = offset + self.data.old.hash_types.len(); //flush working region and ctrl flags for offset in 0..next_offset { - config.flush_row(&mut region, offset)?; + config.flush_row(&mut region, offset)?; } //need to fill some other cols @@ -1480,19 +1508,23 @@ mod test { config.global.tables.fill_constant( &mut layouter, - OPMAP - .iter() - .map(|(a, b, c)| ([*a as u32, *b as u32, *c as u32], CtrlTransitionKind::Operation as u32)), + OPMAP.iter().map(|(a, b, c)| { + ( + [*a as u32, *b as u32, *c as u32], + CtrlTransitionKind::Operation as u32, + ) + }), )?; // op chip now need hash table (for key hash lookup) - config - .global - .hash_table - .fill(&mut layouter, - self.data.old.hash_traces.iter() - .chain([(Fp::one(), self.data.key, Fp::zero())].iter()),//dummy for key calc - )?; + config.global.hash_table.fill( + &mut layouter, + self.data + .old + .hash_traces + .iter() + .chain([(Fp::one(), self.data.key, Fp::zero())].iter()), //dummy for key calc + )?; Ok(()) } @@ -1500,9 +1532,7 @@ mod test { impl TestOpCircuit { fn from_op(op: SingleOp) -> Self { - Self { - data: op, - } + Self { data: op } } } @@ -1553,7 +1583,7 @@ mod test { new: MPTPath:: { hash_types: vec![HashType::Start, HashType::Middle, HashType::Leaf], ..Default::default() - }, + }, ..Default::default() }, } @@ -1586,7 +1616,7 @@ mod test { HashType::Leaf, ], ..Default::default() - }, + }, ..Default::default() }, } @@ -1615,9 +1645,7 @@ mod test { let op = SingleOp::::create_rand_op(3, None, None, mock_hash); let k = 5; - let circuit = TestOpCircuit { - data: op, - }; + let circuit = TestOpCircuit { data: op }; let prover = MockProver::::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); } @@ -1645,13 +1673,13 @@ mod test { fn configure(meta: &mut ConstraintSystem) -> Self::Config { let sel = meta.complex_selector(); - let free_cols : Vec<_> = (0..( - 8 + //exported + let free_cols: Vec<_> = (0..(8 + //exported MPTOpGadget::min_ctrl_types() + - MPTOpGadget::min_free_cols() - )).map(|_| meta.advice_column()).collect(); + MPTOpGadget::min_free_cols())) + .map(|_| meta.advice_column()) + .collect(); let exported_cols = &free_cols[0..8]; - let op_flag_cols = &free_cols[8..8+MPTOpGadget::min_ctrl_types()]; + let op_flag_cols = &free_cols[8..8 + MPTOpGadget::min_ctrl_types()]; GadgetTestConfig { gadget: MPTOpGadget::configure_simple( @@ -1659,7 +1687,7 @@ mod test { sel, exported_cols, op_flag_cols, - &free_cols[8+MPTOpGadget::min_ctrl_types()..], + &free_cols[8 + MPTOpGadget::min_ctrl_types()..], None, ), free_cols, @@ -1685,12 +1713,17 @@ mod test { || "mpt", |mut region| { //flush all row required by data, just avoid Cell error ... - for offset in 0..(1+self.data.use_rows()){ + for offset in 0..(1 + self.data.use_rows()) { config.free_cols.iter().try_for_each(|col| { region - .assign_advice(|| "flushing", *col, offset, || Value::known(Fp::zero())) + .assign_advice( + || "flushing", + *col, + offset, + || Value::known(Fp::zero()), + ) .map(|_| ()) - })?; + })?; } let end = config.gadget.assign(&mut region, 1, &self.data)?; diff --git a/src/operation.rs b/src/operation.rs index 1db2c37c..3b576ebb 100644 --- a/src/operation.rs +++ b/src/operation.rs @@ -244,20 +244,27 @@ impl SingleOp { /// calculate the ctrl_type base on the two hash type of MPTPath pub fn ctrl_type(&self) -> Vec { - self.old.hash_types.iter().copied().zip(self.new.hash_types.clone()) - .map(|type_pair|{ - match type_pair { + self.old + .hash_types + .iter() + .copied() + .zip(self.new.hash_types.clone()) + .map(|type_pair| match type_pair { (old, new) if old == new => old, - (HashType::Middle, HashType::LeafExt) | - (HashType::LeafExt, HashType::Middle) => HashType::LeafExt, - (HashType::Middle, HashType::LeafExtFinal) | - (HashType::LeafExtFinal, HashType::Middle) => HashType::LeafExtFinal, - (HashType::Empty, HashType::Leaf) | - (HashType::Leaf, HashType::Empty) => HashType::Leaf, - _ => unreachable!("invalid hash type pair: {:?}, {:?}", type_pair.0, type_pair.1), - } - }).collect() - + (HashType::Middle, HashType::LeafExt) | (HashType::LeafExt, HashType::Middle) => { + HashType::LeafExt + } + (HashType::Middle, HashType::LeafExtFinal) + | (HashType::LeafExtFinal, HashType::Middle) => HashType::LeafExtFinal, + (HashType::Empty, HashType::Leaf) | (HashType::Leaf, HashType::Empty) => { + HashType::Leaf + } + _ => unreachable!( + "invalid hash type pair: {:?}, {:?}", + type_pair.0, type_pair.1 + ), + }) + .collect() } /// the root of MPT before operation @@ -894,7 +901,9 @@ impl<'d, Fp: Hashable> TryFrom<&'d serde::SMTTrace> for AccountOp { }; let account_before = if let Some(leaf) = acc_trie.old.leaf() { - let account_data = trace.account_update[0].as_ref().expect("account should exist when there is leaf"); + let account_data = trace.account_update[0] + .as_ref() + .expect("account should exist when there is leaf"); let old_state_root = state_trie .as_ref() .map(|s| s.start_root()) @@ -909,7 +918,9 @@ impl<'d, Fp: Hashable> TryFrom<&'d serde::SMTTrace> for AccountOp { }; let account_after = if let Some(leaf) = acc_trie.new.leaf() { - let account_data = trace.account_update[1].as_ref().expect("account should exist when there is leaf"); + let account_data = trace.account_update[1] + .as_ref() + .expect("account should exist when there is leaf"); let new_state_root = state_trie .as_ref() .map(|s| s.new_root()) From cf4ab5ac23817fa9feb2622bcce2122c473f1b63 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Fri, 20 Jan 2023 10:45:50 +0800 Subject: [PATCH 13/17] fix mpt table assignment --- src/lib.rs | 15 +++++++++------ src/mpt_table.rs | 45 ++++++++++++++++++++++++--------------------- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index dd046968..e8c67fd6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -158,7 +158,9 @@ impl Circuit for SimpleTrie { } fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let layer = LayerGadget::configure(meta, 2, + let layer = LayerGadget::configure( + meta, + 2, MPTOpGadget::min_free_cols(), MPTOpGadget::min_ctrl_types(), ); @@ -440,11 +442,12 @@ impl EthTrieConfig { rows: usize, ) -> Result<(), Error> { let mpt_entries = tbl_tips.into_iter().zip(ops).map(|(proof_type, op)| { - if let Some(rand) = randomness { - MPTEntry::from_op(proof_type, op, rand) - } else { - MPTEntry::from_op_no_base(proof_type, op) - } + MPTEntry::from_op(proof_type, op, randomness.unwrap_or_default()) + //if let Some(rand) = randomness { + // MPTEntry::from_op(proof_type, op, rand) + //} else { + // MPTEntry::from_op_no_base(proof_type, op) + //} }); let mpt_tbl = MPTTable::construct( diff --git a/src/mpt_table.rs b/src/mpt_table.rs index b10ae49a..b4eeb4ce 100644 --- a/src/mpt_table.rs +++ b/src/mpt_table.rs @@ -502,7 +502,7 @@ impl MPTTable { RangeCheckChip::construct(config.range_check_u8.clone()).load(layouter)?; layouter.assign_region( - || "mpt table", + || "mpt table inside", |mut region| { for (offset, entry) in self.entries.iter().enumerate() { for (index, col) in config.proof_sel.as_slice().iter().copied().enumerate() { @@ -520,26 +520,29 @@ impl MPTTable { )?; } - if let Some(base_entries) = entry.base { - for (val, col) in base_entries.iter().zip( - [ - config.address, - config.storage_key, - config.proof_type, - config.new_root, - config.old_root, - config.new_value, - config.old_value, - ] - .as_slice(), - ) { - region.assign_advice( - || format!("assign for mpt table offset {}", offset), - *col, - offset, - || Value::known(*val), - )?; - } + let values = match entry.base { + Some(base_entries) => base_entries.map(|x| Value::known(x)), + None => [Value::unknown(); 7], + }; + + for (val, col) in values.iter().zip( + [ + config.address, + config.storage_key, + config.proof_type, + config.new_root, + config.old_root, + config.new_value, + config.old_value, + ] + .as_slice(), + ) { + region.assign_advice( + || format!("assign for mpt table offset {}", offset), + *col, + offset, + || *val, + )?; } config.storage_key_2.assign( From 1b78a0db938b627a6ee0d9d7ef5f6f1b373876c6 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Thu, 2 Feb 2023 15:36:58 +0800 Subject: [PATCH 14/17] disable non exist lookup --- src/mpt_table.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mpt_table.rs b/src/mpt_table.rs index b4eeb4ce..8e1b9c0c 100644 --- a/src/mpt_table.rs +++ b/src/mpt_table.rs @@ -178,6 +178,7 @@ impl Config { .collect() }); + if false { meta.lookup_any("mpt account not exist entry lookup", |meta| { let s_enable = meta.query_advice(self.proof_sel[3], Rotation::cur()); @@ -187,6 +188,7 @@ impl Config { .map(|(fst, snd)| (fst * s_enable.clone(), snd)) .collect() }); + } meta.lookup_any("mpt account destroy entry lookup", |meta| { let s_enable = meta.query_advice(self.proof_sel[4], Rotation::cur()); From 7c4ba231f00eb8bf4d3ed34bd27c72faee551880 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Thu, 16 Mar 2023 19:46:54 -0400 Subject: [PATCH 15/17] sync group 0.13.0 --- Cargo.toml | 25 ++++++- src/eth.rs | 68 ++++++++--------- src/layers.rs | 110 +++++++++++++-------------- src/lib.rs | 34 ++++----- src/mpt.rs | 140 +++++++++++++++++------------------ src/mpt_table.rs | 36 ++++----- src/mpt_table/byte32.rs | 10 +-- src/mpt_table/range_check.rs | 5 +- src/operation.rs | 122 +++++++++++++++--------------- src/test_utils.rs | 2 +- 10 files changed, 273 insertions(+), 279 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b5c8cb0b..865d3573 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -hash-circuit = { package = "poseidon-circuit", git = "https://github.com/scroll-tech/poseidon-circuit.git", branch = "scroll-dev-0111"} -halo2_proofs = { git = "https://github.com/scroll-tech/halo2.git", branch = "scroll-dev-1220" } +hash-circuit = { package = "poseidon-circuit", git = "https://github.com/scroll-tech/poseidon-circuit.git", branch = "halo2-ecc-snark-verifier-0220"} +halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2022_09_10" } rand = "0.8" lazy_static = "1.4.0" serde = { version = "1.0", features = ["derive"] } @@ -15,7 +15,24 @@ serde_json = "1.0" num-bigint = "0.4" hex = "0.4" thiserror = "1.0" -log = "0.4" + +[patch."https://github.com/privacy-scaling-explorations/halo2.git"] +halo2_proofs = { git = "https://github.com/scroll-tech/halo2.git", branch = "halo2-ecc-snark-verifier-0220" } + +# remove once +# https://github.com/privacy-scaling-explorations/poseidon/pull/7 +# https://github.com/privacy-scaling-explorations/halo2curves/pull/31 +# are merged +[patch."https://github.com/privacy-scaling-explorations/poseidon.git"] +poseidon = { git = "https://github.com/scroll-tech/poseidon.git", branch = "halo2-ecc-snark-verifier-0220" } + + +[patch."https://github.com/privacy-scaling-explorations/halo2curves.git"] +halo2curves = { git = "https://github.com/scroll-tech/halo2curves.git", branch = "halo2-ecc-snark-verifier-0220" } + +[patch.crates-io] +# temporary solution to funty@1.2.0 being yanked, tracking issue: https://github.com/ferrilab/funty/issues/7 +funty = { git = "https://github.com/ferrilab/funty/", rev = "7ef0d890fbcd8b3def1635ac1a877fc298488446" } [features] # printout the layout of circuits for demo and some unittests @@ -33,4 +50,4 @@ path = "integration-tests/src/main.rs" [profile.test] opt-level = 3 -debug-assertions = true +debug-assertions = true \ No newline at end of file diff --git a/src/eth.rs b/src/eth.rs index 233ede59..64178546 100644 --- a/src/eth.rs +++ b/src/eth.rs @@ -36,8 +36,8 @@ use super::mpt; use super::CtrlTransitionKind; use crate::operation::{Account, AccountOp, KeyValue}; use halo2_proofs::{ - arithmetic::FieldExt, circuit::{Chip, Region, Value}, + ff::PrimeField, plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector}, poly::Rotation, }; @@ -79,7 +79,7 @@ impl AccountGadget { /// + circuit selector * 1 /// + exported col * 8 (MUST by following sequence: layout_flag, s_enable, old_val, new_val, key_val and 3 ext field for old/new/key_val) /// + free col * 4 - pub fn configure( + pub fn configure( meta: &mut ConstraintSystem, sel: Selector, exported: &[Column], @@ -126,7 +126,7 @@ impl AccountGadget { //transition meta.lookup("account row trans", |meta| { let s_enable = meta.query_advice(s_enable, Rotation::cur()) - * (Expression::Constant(Fp::one()) + * (Expression::Constant(Fp::ONE) - meta.query_advice(s_ctrl_type[0], Rotation::cur())); tables.build_lookup( @@ -184,7 +184,7 @@ impl AccountGadget { let is_diff_ext_boolean = data_ext_diff.clone() * meta.query_advice(state_change_aux[1], Rotation::cur()); - let one = Expression::Constant(Fp::one()); + let one = Expression::Constant(Fp::ONE); // switch A || B to ! (!A ^ !B) let has_diff = one.clone() - (one.clone() - is_diff_boolean.clone()) @@ -217,7 +217,7 @@ impl AccountGadget { s_enable * row0 * (new_nonce.clone() - old_nonce.clone()) - * (new_nonce - old_nonce - Expression::Constant(Fp::one())), + * (new_nonce - old_nonce - Expression::Constant(Fp::ONE)), ] });*/ @@ -250,7 +250,7 @@ impl AccountGadget { } /// assign data and enable flag for account circuit - pub fn assign<'d, Fp: FieldExt>( + pub fn assign<'d, Fp: PrimeField>( &self, region: &mut Region<'_, Fp>, offset: usize, @@ -298,7 +298,7 @@ impl AccountGadget { || "enable account circuit", self.s_enable, offset, - || Value::known(Fp::one()), + || Value::known(Fp::ONE), )?; region.assign_advice( || "account circuit rows", @@ -310,31 +310,31 @@ impl AccountGadget { || "enable s_ctrl", self.s_ctrl_type[index as usize], offset, - || Value::known(Fp::one()), + || Value::known(Fp::ONE), )?; if index == LAST_ROW { region.assign_advice( || "padding last row", self.old_state.intermediate_2, offset, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; region.assign_advice( || "padding last row", self.new_state.intermediate_2, offset, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; } let data_delta = match index { - 0 => [data.0.nonce - data.1.nonce, Fp::zero()], - 1 => [data.0.balance - data.1.balance, Fp::zero()], + 0 => [data.0.nonce - data.1.nonce, Fp::ZERO], + 1 => [data.0.balance - data.1.balance, Fp::ZERO], 2 => [ data.0.codehash.0 - data.1.codehash.0, data.0.codehash.1 - data.1.codehash.1, ], - 3 => [data.0.state_root - data.1.state_root, Fp::zero()], + 3 => [data.0.state_root - data.1.state_root, Fp::ZERO], _ => unreachable!("no such row number"), }; @@ -350,7 +350,7 @@ impl AccountGadget { offset, || { Value::known(if bool::from(val.is_zero()) { - Fp::zero() + Fp::ZERO } else { val.invert().unwrap() }) @@ -362,13 +362,7 @@ impl AccountGadget { || "is data delta", self.state_change_key, offset, - || { - Value::known(if has_data_delta { - Fp::one() - } else { - Fp::zero() - }) - }, + || Value::known(if has_data_delta { Fp::ONE } else { Fp::ZERO }), )?; } @@ -391,7 +385,7 @@ struct AccountChip<'d, F> { data: &'d Account, } -impl Chip for AccountChip<'_, Fp> { +impl Chip for AccountChip<'_, Fp> { type Config = AccountChipConfig; type Loaded = Account; @@ -404,7 +398,7 @@ impl Chip for AccountChip<'_, Fp> { } } -impl<'d, Fp: FieldExt> AccountChip<'d, Fp> { +impl<'d, Fp: PrimeField> AccountChip<'d, Fp> { fn lagrange_polynomial_for_row(ref_n: Expression) -> Expression { super::lagrange_polynomial::(ref_n) } @@ -509,7 +503,7 @@ impl<'d, Fp: FieldExt> AccountChip<'d, Fp> { ), ( config.acc_data_fields_ext, - [Fp::zero(), Fp::zero(), data.codehash.1], + [Fp::ZERO, Fp::ZERO, data.codehash.1], "data field ext", ), ( @@ -519,7 +513,7 @@ impl<'d, Fp: FieldExt> AccountChip<'d, Fp> { ), ( config.intermediate_1, - [Fp::zero(), data.hash_traces(2), data.hash_traces(0)], + [Fp::ZERO, data.hash_traces(2), data.hash_traces(0)], "intermedia 1", ), ] { @@ -544,7 +538,7 @@ impl<'d, Fp: FieldExt> AccountChip<'d, Fp> { || "state root padding", config.acc_data_fields_ext, self.offset + LAST_ROW, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; Ok(self.offset + LAST_ROW) @@ -564,7 +558,7 @@ struct StorageChip<'d, F> { value: Option>, } -impl<'d, Fp: FieldExt> StorageChip<'d, Fp> { +impl<'d, Fp: PrimeField> StorageChip<'d, Fp> { fn configure( meta: &mut ConstraintSystem, _sel: Selector, @@ -592,14 +586,14 @@ impl<'d, Fp: FieldExt> StorageChip<'d, Fp> { || "val limb 0", config.v_limbs[0], self.offset, - || Value::known(self.value.as_ref().map_or_else(Fp::zero, |v| v.limb_0())), + || Value::known(self.value.as_ref().map_or(Fp::ZERO, |v| v.limb_0())), )?; region.assign_advice( || "val limb 1", config.v_limbs[1], self.offset, - || Value::known(self.value.as_ref().map_or_else(Fp::zero, |v| v.limb_1())), + || Value::known(self.value.as_ref().map_or(Fp::ZERO, |v| v.limb_1())), )?; Ok(self.offset + 1) @@ -629,7 +623,7 @@ impl StorageGadget { /// + circuit selector * 1 /// + exported col * 5 (MUST by following sequence: layout_flag, s_enable, old_val, new_val, key_val) /// + free col * 4 - pub fn configure( + pub fn configure( meta: &mut ConstraintSystem, sel: Selector, exported: &[Column], @@ -670,7 +664,7 @@ impl StorageGadget { [].into_iter() } - pub fn assign<'d, Fp: FieldExt>( + pub fn assign<'d, Fp: PrimeField>( &self, region: &mut Region<'_, Fp>, offset: usize, @@ -680,21 +674,21 @@ impl StorageGadget { || "enable storage leaf circuit", self.s_enable, offset, - || Value::known(Fp::one()), + || Value::known(Fp::ONE), )?; region.assign_advice( || "storage leaf circuit row", self.ctrl_type, offset, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; region.assign_advice( || "enable s_ctrl", self.s_ctrl_type, offset, - || Value::known(Fp::one()), + || Value::known(Fp::ONE), )?; for (config, value) in [ @@ -814,7 +808,7 @@ mod test { || "flush top row", col, 0, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; } @@ -824,7 +818,7 @@ mod test { || "flush s_ctrl", col, offset, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; } } @@ -844,7 +838,7 @@ mod test { || "flush last row", col, till, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; } Ok(()) diff --git a/src/layers.rs b/src/layers.rs index b743a1b7..b519386d 100644 --- a/src/layers.rs +++ b/src/layers.rs @@ -19,8 +19,8 @@ // circuit and we also call the rows for one step an "op block". use halo2_proofs::{ - arithmetic::FieldExt, circuit::{Layouter, Region, Value}, + ff::PrimeField, plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector, TableColumn}, poly::Rotation, }; @@ -104,7 +104,7 @@ impl LayerGadget { self.sel } - pub fn configure( + pub fn configure( meta: &mut ConstraintSystem, steps: usize, required_cols: usize, @@ -143,7 +143,7 @@ impl LayerGadget { let series_delta = meta.query_advice(series, Rotation::cur()) - meta.query_advice(series, Rotation::prev()); // delta ∈ {0, 1} - vec![sel * (Expression::Constant(Fp::one()) - series_delta.clone()) * series_delta] + vec![sel * (Expression::Constant(Fp::ONE) - series_delta.clone()) * series_delta] }); meta.create_gate("op transition", |meta| { @@ -152,10 +152,7 @@ impl LayerGadget { - meta.query_advice(op_type, Rotation::prev()); let op_delta_aux = meta.query_advice(op_delta_aux, Rotation::cur()); // map op_delta_aux so we can obtain 1 while delta is not zero - vec![ - sel * (Expression::Constant(Fp::one()) - op_delta_aux * op_delta.clone()) - * op_delta, - ] + vec![sel * (Expression::Constant(Fp::ONE) - op_delta_aux * op_delta.clone()) * op_delta] }); meta.create_gate("s_ctrl flags", |meta| { @@ -171,14 +168,14 @@ impl LayerGadget { .collect(); let bool_cond = s_ctrl.clone().into_iter().map(|col_exp| { - sel.clone() * col_exp.clone() * (Expression::Constant(Fp::one()) - col_exp) + sel.clone() * col_exp.clone() * (Expression::Constant(Fp::ONE) - col_exp) }); let one_flag_cond = s_ctrl .clone() .into_iter() .reduce(|exp, col_exp| exp + col_exp) - .map(|sum_exp| sel.clone() * (Expression::Constant(Fp::one()) - sum_exp)); + .map(|sum_exp| sel.clone() * (Expression::Constant(Fp::ONE) - sum_exp)); let ctrl_type_cond = s_ctrl .into_iter() @@ -194,7 +191,7 @@ impl LayerGadget { .chain(ctrl_type_cond) .collect::>(); if constraints.is_empty() { - vec![sel * Expression::Constant(Fp::zero())] + vec![sel * Expression::Constant(Fp::ZERO)] } else { constraints } @@ -210,7 +207,7 @@ impl LayerGadget { Vec::from([old_root_index, new_root_index, address_index].map(|col| { sel.clone() - * (Expression::Constant(Fp::one()) - series_delta.clone()) + * (Expression::Constant(Fp::ONE) - series_delta.clone()) * (meta.query_advice(col, Rotation::cur()) - meta.query_advice(col, Rotation::prev())) })) @@ -239,7 +236,7 @@ impl LayerGadget { // notice all flag is constrainted to boolean, and total_flag is 1, so one and at most one col must be true // and only that flag whose op_type is corresponding to its step code can be true - exps.push(sel * (Expression::Constant(Fp::one()) - total_flag)); + exps.push(sel * (Expression::Constant(Fp::ONE) - total_flag)); exps }); @@ -251,7 +248,7 @@ impl LayerGadget { // lookup from control_table meta.lookup("layer intra-block border rule", |meta| { // condition 1 (intra-block transition) is only actived when series has not change - let series_delta_zero = Expression::Constant(Fp::one()) + let series_delta_zero = Expression::Constant(Fp::ONE) - meta.query_advice(series, Rotation::cur()) + meta.query_advice(series, Rotation::prev()); let op_delta = meta.query_advice(op_type, Rotation::cur()) @@ -269,7 +266,7 @@ impl LayerGadget { (ctrl_cur, control_table[1]), (op_prev, control_table[2]), (ctrl_prev, control_table[3]), - (Expression::Constant(Fp::zero()), control_table[4]), + (Expression::Constant(Fp::ZERO), control_table[4]), ] }); @@ -289,7 +286,7 @@ impl LayerGadget { (ctrl_cur, control_table[1]), (op_prev, control_table[2]), (ctrl_prev, control_table[3]), - (Expression::Constant(Fp::one()), control_table[4]), + (Expression::Constant(Fp::ONE), control_table[4]), ] }); @@ -322,7 +319,7 @@ impl LayerGadget { } // LayerGadget must be first assigned, with other gadgets start from the offset it has returned - pub fn assign( + pub fn assign( &self, region: &mut Region<'_, Fp>, max_rows: usize, @@ -331,23 +328,23 @@ impl LayerGadget { // current we flush the first row, and start other circuits's assignation from row 1 self.free_cols.iter().try_for_each(|col| { region - .assign_advice(|| "flushing", *col, 0, || Value::known(Fp::zero())) + .assign_advice(|| "flushing", *col, 0, || Value::known(Fp::ZERO)) .map(|_| ()) })?; self.s_stepflags.iter().try_for_each(|col| { region - .assign_advice(|| "flushing", *col, 0, || Value::known(Fp::zero())) + .assign_advice(|| "flushing", *col, 0, || Value::known(Fp::ZERO)) .map(|_| ()) })?; - region.assign_advice_from_constant(|| "init series", self.series, 0, Fp::zero())?; - region.assign_advice_from_constant(|| "init series", self.series, 1, Fp::one())?; + region.assign_advice_from_constant(|| "init series", self.series, 0, Fp::ZERO)?; + region.assign_advice_from_constant(|| "init series", self.series, 1, Fp::ONE)?; region.assign_advice_from_constant( || "init op", self.op_type, 0, Fp::from(self.start_op_code() as u64), )?; - region.assign_advice_from_constant(|| "init ctrl", self.ctrl_type, 0, Fp::zero())?; + region.assign_advice_from_constant(|| "init ctrl", self.ctrl_type, 0, Fp::ZERO)?; region.assign_advice( || "start root", self.new_root_index, @@ -355,7 +352,7 @@ impl LayerGadget { || Value::known(init_root), )?; for col in [self.old_root_index, self.address_index] { - region.assign_advice(|| "index flush", col, 0, || Value::known(Fp::zero()))?; + region.assign_advice(|| "index flush", col, 0, || Value::known(Fp::ZERO))?; } for offset in 1..max_rows { @@ -369,26 +366,26 @@ impl LayerGadget { || "flushing last", *col, max_rows, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), ) .map(|_| ()) })?; // begin padding and final flush for data_rows for col in [self.data_0, self.data_1, self.data_2] { - region.assign_advice(|| "begin padding", col, 0, || Value::known(Fp::zero()))?; + region.assign_advice(|| "begin padding", col, 0, || Value::known(Fp::ZERO))?; region.assign_advice( || "last row flushing", col, max_rows, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; } region.assign_advice( || "terminalte series", self.series, max_rows, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; Ok(1) @@ -397,7 +394,7 @@ impl LayerGadget { // pace has to be called before a working gadget is assigned on the specified offset, the rows // that working gadget would occpuy, and the result of the new root which gadget has output, // must be known before - pub fn pace_op( + pub fn pace_op( &self, region: &mut Region<'_, Fp>, offset: usize, @@ -419,7 +416,7 @@ impl LayerGadget { offset, || { Value::known(if prev_op == op_type.1 { - Fp::zero() + Fp::ZERO } else { op_delta.invert().unwrap() }) @@ -428,12 +425,7 @@ impl LayerGadget { // flush all cols to avoid unassigned error self.free_cols.iter().try_for_each(|col| { region - .assign_advice( - || "flushing free", - *col, - offset, - || Value::known(Fp::zero()), - ) + .assign_advice(|| "flushing free", *col, offset, || Value::known(Fp::ZERO)) .map(|_| ()) })?; // flush all cols to avoid unassigned error @@ -443,7 +435,7 @@ impl LayerGadget { || "flushing op type flag", *col, offset, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), ) .map(|_| ()) })?; @@ -462,13 +454,13 @@ impl LayerGadget { || "flushing exported", *col, offset, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), ) .map(|_| ()) })?; self.s_stepflags.iter().try_for_each(|col| { region - .assign_advice(|| "flushing", *col, offset, || Value::known(Fp::zero())) + .assign_advice(|| "flushing", *col, offset, || Value::known(Fp::ZERO)) .map(|_| ()) })?; @@ -480,7 +472,7 @@ impl LayerGadget { // complete block is called AFTER all working gadget has been assigned on the specified offset, // this entry fill whole block with series and index value - pub fn complete_block( + pub fn complete_block( &self, region: &mut Region<'_, Fp>, offset: usize, @@ -520,7 +512,7 @@ impl LayerGadget { // set all transition rules // + end_op: is the last op code in your assignation, often just (, 0) - pub fn set_op_border( + pub fn set_op_border( &self, layouter: &mut impl Layouter, inter_op: &[OpBorder], @@ -532,7 +524,7 @@ impl LayerGadget { // set all transition rules // + start_op: all possible starting op code and ctrl code - pub fn set_op_border_ex( + pub fn set_op_border_ex( &self, layouter: &mut impl Layouter, inter_op: &[OpBorder], @@ -547,62 +539,62 @@ impl LayerGadget { || "default", self.control_table[0], 0, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; table.assign_cell( || "default", self.control_table[1], 0, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; table.assign_cell( || "default", self.control_table[2], 0, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; table.assign_cell( || "default", self.control_table[3], 0, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; table.assign_cell( || "default", self.control_table[4], 0, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; table.assign_cell( || "default op cur", self.control_table[0], 1, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; table.assign_cell( || "default ctrl cur", self.control_table[1], 1, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; table.assign_cell( || "default op prev", self.control_table[2], 1, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; table.assign_cell( || "default ctrl prev", self.control_table[3], 1, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; table.assign_cell( || "mark", self.control_table[4], 1, - || Value::known(Fp::one()), + || Value::known(Fp::ONE), )?; let mut offset = 2; @@ -631,13 +623,13 @@ impl LayerGadget { || "marking ctrl", self.control_table[3], offset, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; table.assign_cell( || "mark", self.control_table[4], offset, - || Value::known(Fp::one()), + || Value::known(Fp::ONE), )?; offset += 1; } @@ -671,7 +663,7 @@ impl LayerGadget { || "mark", self.control_table[4], offset, - || Value::known(Fp::one()), + || Value::known(Fp::ONE), )?; offset += 1; } @@ -705,7 +697,7 @@ impl LayerGadget { || "mark", self.control_table[4], offset, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; offset += 1; } @@ -728,7 +720,7 @@ pub(crate) struct PaddingGadget { } impl PaddingGadget { - pub fn configure( + pub fn configure( _meta: &mut ConstraintSystem, _sel: Selector, exported: &[Column], @@ -741,7 +733,7 @@ impl PaddingGadget { } } - pub fn padding( + pub fn padding( &self, region: &mut Region<'_, Fp>, offset: usize, @@ -752,19 +744,19 @@ impl PaddingGadget { || "ctrl type", self.ctrl_type, offset, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; region.assign_advice( || "enable s_ctrl", self.s_ctrl_type, offset, - || Value::known(Fp::one()), + || Value::known(Fp::ONE), )?; region.assign_advice( || "enable padding", self.s_enable, offset, - || Value::known(Fp::one()), + || Value::known(Fp::ONE), )?; } Ok(()) diff --git a/src/lib.rs b/src/lib.rs index e8c67fd6..7d2d6fab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -70,8 +70,8 @@ enum CtrlTransitionKind { use eth::AccountGadget; use halo2_proofs::{ - arithmetic::FieldExt, circuit::{Layouter, SimpleFloorPlanner}, + ff::PrimeField, plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Expression}, }; use hash::Hashable; @@ -80,15 +80,15 @@ use mpt::MPTOpGadget; use operation::{AccountOp, HashTracesSrc, SingleOp}; // building lagrange polynmials L for T so that L(n) = 1 when n = T else 0, n in [0, TO] -fn lagrange_polynomial( +fn lagrange_polynomial( ref_n: Expression, ) -> Expression { let mut denominators: Vec = (0..=TO) .map(|v| Fp::from(T as u64) - Fp::from(v as u64)) .collect(); denominators.swap_remove(T); - let denominator = denominators.into_iter().fold(Fp::one(), |acc, v| v * acc); - assert_ne!(denominator, Fp::zero()); + let denominator = denominators.into_iter().fold(Fp::ONE, |acc, v| v * acc); + assert_ne!(denominator, Fp::ZERO); let mut factors: Vec> = (0..(TO + 1)) .map(|v| ref_n.clone() - Expression::Constant(Fp::from(v as u64))) @@ -110,7 +110,7 @@ pub struct SimpleTrieConfig { /// The chip for op on a simple trie #[derive(Clone, Default)] -pub struct SimpleTrie { +pub struct SimpleTrie { c_size: usize, //how many rows start_root: F, final_root: F, @@ -120,7 +120,7 @@ pub struct SimpleTrie { const OP_MPT: u32 = 1; const OP_PADDING: u32 = 0; -impl SimpleTrie { +impl SimpleTrie { /// create a new, empty circuit with specified size pub fn new(c_size: usize) -> Self { Self { @@ -146,7 +146,7 @@ impl SimpleTrie { } } -impl Circuit for SimpleTrie { +impl Circuit for SimpleTrie { type Config = SimpleTrieConfig; type FloorPlanner = SimpleFloorPlanner; @@ -309,7 +309,7 @@ impl EthTrieConfig { } /// configure for lite circuit (no mpt table included, for fast testing) - pub fn configure_base( + pub fn configure_base( meta: &mut ConstraintSystem, hash_tbl: [Column; 4], ) -> Self { @@ -396,13 +396,13 @@ impl EthTrieConfig { } /// configure for lite circuit (no mpt table included, for fast testing) - pub fn configure_lite(meta: &mut ConstraintSystem) -> Self { + pub fn configure_lite(meta: &mut ConstraintSystem) -> Self { let hash_tbl = [0; 4].map(|_| meta.advice_column()); Self::configure_base(meta, hash_tbl) } /// configure for full circuit - pub fn configure_sub( + pub fn configure_sub( meta: &mut ConstraintSystem, mpt_tbl: [Column; 7], hash_tbl: [Column; 4], @@ -469,11 +469,7 @@ impl EthTrieConfig { self.hash_tbl.fill_with_paddings( layouter, HashTracesSrc::from(hash_traces), - ( - Fp::zero(), - Fp::zero(), - Hashable::hash([Fp::zero(), Fp::zero()]), - ), + (Fp::ZERO, Fp::ZERO, Hashable::hash([Fp::ZERO, Fp::ZERO])), rows, ) } @@ -490,7 +486,7 @@ impl EthTrieConfig { .clone() .next() .map(|op| op.account_root_before()) - .unwrap_or_else(Fp::zero); + .unwrap_or(Fp::ZERO); layouter.assign_region( || "main", @@ -608,7 +604,7 @@ impl EthTrieConfig { } /// The chip for op on an storage trie #[derive(Clone, Default)] -pub struct EthTrie { +pub struct EthTrie { start_root: F, final_root: F, ops: Vec>, @@ -619,7 +615,7 @@ const OP_TRIE_STATE: u32 = 2; const OP_ACCOUNT: u32 = 3; const OP_STORAGE: u32 = 4; -impl EthTrie { +impl EthTrie { /// Add an op into the circuit data pub fn add_op(&mut self, op: AccountOp) { if self.ops.is_empty() { @@ -646,7 +642,7 @@ impl EthTrie { /// the mpt circuit type #[derive(Clone, Default, Debug)] -pub struct EthTrieCircuit { +pub struct EthTrieCircuit { /// the maxium records in circuits (would affect vk) pub calcs: usize, /// the operations in circuits diff --git a/src/mpt.rs b/src/mpt.rs index 7373ff01..a8b0ed55 100644 --- a/src/mpt.rs +++ b/src/mpt.rs @@ -62,8 +62,8 @@ use super::{CtrlTransitionKind, HashType}; use crate::operation::{MPTPath, SingleOp}; use halo2_proofs::{ - arithmetic::{Field, FieldExt}, circuit::{Chip, Layouter, Region, Value}, + ff::{Field, PrimeField}, plonk::{ Advice, Column, ConstraintSystem, Error, Expression, Selector, TableColumn, VirtualCells, }, @@ -122,7 +122,7 @@ impl MPTOpTables { ) } - pub fn build_lookup_any( + pub fn build_lookup_any( &self, enable: Expression, rules: impl IntoIterator>, @@ -137,7 +137,7 @@ impl MPTOpTables { ret } - pub fn build_lookup( + pub fn build_lookup( &self, enable: Expression, old: Expression, @@ -147,7 +147,7 @@ impl MPTOpTables { self.build_lookup_any(enable, [old, new], mark) } - pub fn fill_constant( + pub fn fill_constant( &self, layouter: &mut impl Layouter, rules: impl Iterator + Clone, @@ -156,13 +156,13 @@ impl MPTOpTables { || "op table", |mut table| { // default line - table.assign_cell(|| "default mark", self.0, 0, || Value::known(Fp::zero()))?; + table.assign_cell(|| "default mark", self.0, 0, || Value::known(Fp::ZERO))?; for i in 0..3 { table.assign_cell( || "default rule", self.1[i], 0, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; } @@ -206,7 +206,7 @@ impl HashTable { self.0.map(|col| col.index()) } - pub fn build_lookup<'d, Fp: FieldExt>( + pub fn build_lookup<'d, Fp: PrimeField>( &self, meta: &mut VirtualCells<'d, Fp>, enable: Expression, @@ -225,7 +225,7 @@ impl HashTable { ), (enable * snd, meta.query_advice(self.0[2], Rotation::cur())), ( - Expression::Constant(Fp::zero()), + Expression::Constant(Fp::ZERO), meta.query_advice(self.0[3], Rotation::cur()), ), ] @@ -233,7 +233,7 @@ impl HashTable { /// a helper entry to fill hash table with specified rows, use padding record /// when hashing_records is not enough - pub fn fill_with_paddings<'d, Fp: FieldExt>( + pub fn fill_with_paddings<'d, Fp: PrimeField>( &self, layouter: &mut impl Layouter, hashing_records: impl Iterator + Clone, @@ -252,7 +252,7 @@ impl HashTable { } /// a helper entry to fill hash table - pub fn fill<'d, Fp: FieldExt>( + pub fn fill<'d, Fp: PrimeField>( &self, layouter: &mut impl Layouter, hashing_records: impl Iterator + Clone, @@ -262,7 +262,7 @@ impl HashTable { |mut table| { // default: 0, 0, 0 for col in self.0 { - table.assign_advice(|| "default", col, 0, || Value::known(Fp::zero()))?; + table.assign_advice(|| "default", col, 0, || Value::known(Fp::ZERO))?; } hashing_records @@ -282,7 +282,7 @@ impl HashTable { || "ctrl_pad", self.0[3], offset, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; Ok(()) @@ -338,7 +338,7 @@ impl MPTOpGadget { } /// if the gadget would be used only once, this entry is more easy - pub fn configure_simple( + pub fn configure_simple( meta: &mut ConstraintSystem, sel: Selector, exported: &[Column], @@ -367,7 +367,7 @@ impl MPTOpGadget { /// + s_op_flags * 6 (corresponding 6 ctrl_types) /// + free col * 8 /// notice the gadget has bi-direction exporting (on top it exporting mpt root and bottom exporting leaf) - pub fn configure( + pub fn configure( meta: &mut ConstraintSystem, sel: Selector, exported: &[Column], @@ -404,7 +404,7 @@ impl MPTOpGadget { let s_row = meta.query_selector(g_config.s_row); let s_enable = meta.query_advice(g_config.s_enable, Rotation::cur()); // s_enable ∈ {0, 1} - vec![s_row * (Expression::Constant(Fp::one()) - s_enable.clone()) * s_enable] + vec![s_row * (Expression::Constant(Fp::ONE) - s_enable.clone()) * s_enable] }); if let Some((old_root_index, new_root_index)) = root_index { @@ -458,13 +458,13 @@ impl MPTOpGadget { i1.chain(i2) } - /* pub fn init(&self, layouter: &mut impl Layouter) -> Result<(), Error> { + /* pub fn init(&self, layouter: &mut impl Layouter) -> Result<(), Error> { self.tables .fill_constant(layouter, Self::transition_rules()) }*/ /// assign data and enable flag for MPT circuit - pub fn assign( + pub fn assign( &self, region: &mut Region<'_, Fp>, offset: usize, @@ -490,7 +490,7 @@ impl MPTOpGadget { || "enable MPT circuit", self.s_enable, offset, - || Value::known(Fp::one()), + || Value::known(Fp::ONE), )?; } @@ -499,7 +499,7 @@ impl MPTOpGadget { } /* -fn lagrange_polynomial_for_hashtype( +fn lagrange_polynomial_for_hashtype( ref_n: Expression, ) -> Expression { super::lagrange_polynomial::(ref_n) @@ -520,14 +520,14 @@ struct PathChipConfig { /// chip for verify mutiple merkle path in MPT /// it do not need any auxiliary cols -struct PathChip<'d, F: FieldExt> { +struct PathChip<'d, F: PrimeField> { offset: usize, config: PathChipConfig, data: &'d MPTPath, ref_ctrl_type: Option<&'d [HashType]>, } -impl Chip for PathChip<'_, Fp> { +impl Chip for PathChip<'_, Fp> { type Config = PathChipConfig; type Loaded = MPTPath; @@ -540,7 +540,7 @@ impl Chip for PathChip<'_, Fp> { } } -impl<'d, Fp: FieldExt> PathChip<'d, Fp> { +impl<'d, Fp: PrimeField> PathChip<'d, Fp> { fn configure( meta: &mut ConstraintSystem, g_config: &MPTOpConfig, @@ -603,7 +603,7 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { // // from table formed by (left, right, hash) meta.lookup_any("mpt node hash", |meta| { - let s_hash_type_not_match = Expression::Constant(Fp::one()) + let s_hash_type_not_match = Expression::Constant(Fp::ONE) - meta.query_advice(s_match_ctrl_type, Rotation::cur()); let s_path = meta.query_advice(s_enable, Rotation::cur()) * (meta.query_advice(s_hash_type[HashType::Middle as usize], Rotation::cur()) @@ -646,7 +646,7 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { //transition, notice the start status is ensured outside of the gadget meta.lookup("mpt type trans", |meta| { - let s_not_begin = Expression::Constant(Fp::one()) + let s_not_begin = Expression::Constant(Fp::ONE) - meta.query_advice(s_hash_type[HashType::Start as usize], Rotation::cur()); //not Start let s_block_enable = meta.query_advice(s_enable, Rotation::cur()) * s_not_begin; @@ -708,7 +708,7 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { hash_table.build_lookup( meta, s_last_extended, - Expression::Constant(Fp::one()), + Expression::Constant(Fp::ONE), key_proof, key_proof_immediate, ) @@ -779,8 +779,8 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { offset + index, || { Value::known(match hash_type { - HashType::Start | HashType::Empty | HashType::Leaf => Fp::zero(), - _ => Fp::one(), + HashType::Start | HashType::Empty | HashType::Leaf => Fp::ZERO, + _ => Fp::ONE, }) }, )?; @@ -802,7 +802,7 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { Value::known( Fp::from(ref_type as u64 - hash_type as u64) .invert() - .unwrap_or_else(Fp::zero), + .unwrap_or(Fp::ZERO), ) }, )?; @@ -812,9 +812,9 @@ impl<'d, Fp: FieldExt> PathChip<'d, Fp> { offset + index, || { Value::known(if hash_type == ref_type { - Fp::one() + Fp::ONE } else { - Fp::zero() + Fp::ZERO }) }, )?; @@ -837,13 +837,13 @@ struct OpChipConfig { /// chip for verify mutiple merkle path in MPT /// it do not need any auxiliary cols -struct OpChip<'d, F: FieldExt> { +struct OpChip<'d, F: PrimeField> { offset: usize, config: OpChipConfig, data: &'d SingleOp, } -impl Chip for OpChip<'_, Fp> { +impl Chip for OpChip<'_, Fp> { type Config = OpChipConfig; type Loaded = SingleOp; @@ -856,7 +856,7 @@ impl Chip for OpChip<'_, Fp> { } } -impl<'d, Fp: FieldExt> OpChip<'d, Fp> { +impl<'d, Fp: PrimeField> OpChip<'d, Fp> { fn configure( meta: &mut ConstraintSystem, g_config: &MPTOpConfig, @@ -892,10 +892,10 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { meta.create_gate("s_path and path bit", |meta| { let enable = meta.query_selector(s_row) * meta.query_advice(s_enable, Rotation::cur()); let s_path = meta.query_advice(s_path, Rotation::cur()); - let s_path_not_opened = Expression::Constant(Fp::one()) - s_path.clone(); + let s_path_not_opened = Expression::Constant(Fp::ONE) - s_path.clone(); let path = meta.query_advice(path, Rotation::cur()); - let path_bit = (Expression::Constant(Fp::one()) - path.clone()) * path; + let path_bit = (Expression::Constant(Fp::ONE) - path.clone()) * path; let hash_type = meta.query_advice(old_hash_type, Rotation::cur()); let not_path_type = (hash_type.clone() @@ -907,9 +907,7 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { // s_path is not open when hash_type is "start" / "leaf" / "empty" // when s_path is 1, path ∈ {0, 1} vec![ - enable.clone() - * (Expression::Constant(Fp::one()) - s_path.clone()) - * s_path.clone(), + enable.clone() * (Expression::Constant(Fp::ONE) - s_path.clone()) * s_path.clone(), enable.clone() * not_path_type * s_path_not_opened, enable * s_path * path_bit, ] @@ -920,7 +918,7 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { let s_begin = meta.query_advice(s_ctrl_type[HashType::Start as usize], Rotation::cur()); //Start let path = meta.query_advice(path, Rotation::cur()); let depth_aux_start = meta.query_advice(depth_aux, Rotation::cur()) - - Expression::Constant(Fp::one().double().invert().unwrap()); + - Expression::Constant(Fp::ONE.double().invert().unwrap()); let depth_aux_common = meta.query_advice(depth_aux, Rotation::cur()) - meta.query_advice(depth_aux, Rotation::prev()) * Expression::Constant(Fp::from(2u64)); @@ -935,10 +933,10 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { vec![ enable.clone() * s_begin.clone() * depth_aux_start, enable.clone() - * (Expression::Constant(Fp::one()) - s_begin.clone()) + * (Expression::Constant(Fp::ONE) - s_begin.clone()) * depth_aux_common, enable.clone() * s_begin.clone() * meta.query_advice(acc_key, Rotation::cur()), - enable * (Expression::Constant(Fp::one()) - s_begin) * key_acc, + enable * (Expression::Constant(Fp::ONE) - s_begin) * key_acc, ] }); @@ -951,7 +949,7 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { hash_table.build_lookup( meta, s_leaf, - Expression::Constant(Fp::one()), + Expression::Constant(Fp::ONE), key, key_immediate, ) @@ -991,25 +989,25 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { || "path padding", config.path, offset, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; region.assign_advice( || "acckey padding", config.acc_key, offset, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; region.assign_advice( || "depth padding", config.depth, offset, - || Value::known(Fp::one().double().invert().unwrap()), + || Value::known(Fp::ONE.double().invert().unwrap()), )?; region.assign_advice( || "sibling padding", config.sibling, offset, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; region.assign_advice( || "op type start", @@ -1021,20 +1019,20 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { || "enabling s_op", config.s_ctrl_type[ctrl_type[0] as usize], offset, - || Value::known(Fp::one()), + || Value::known(Fp::ONE), )?; region.assign_advice( || "sibling padding", config.sibling, offset, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; offset += 1; - let mut cur_depth = Fp::one(); - let mut acc_key = Fp::zero(); + let mut cur_depth = Fp::ONE; + let mut acc_key = Fp::ZERO; let extend_proof = self.data.extended_proof(); @@ -1072,7 +1070,7 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { || "enabling s_op", config.s_ctrl_type[ctrl_type[index + 1] as usize], offset, - || Value::known(Fp::one()), + || Value::known(Fp::ONE), )?; cur_depth = cur_depth.double(); @@ -1091,7 +1089,7 @@ impl<'d, Fp: FieldExt> OpChip<'d, Fp> { || "enabling s_op", config.s_ctrl_type[ctrl_type as usize], offset, - || Value::known(Fp::one()), + || Value::known(Fp::ONE), )?; region.assign_advice( || "path", @@ -1196,7 +1194,7 @@ mod test { || "zero flushing", zero_flush_col, offset, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), )?; } @@ -1260,14 +1258,14 @@ mod test { || "enable", config.s_ctrl_type[hash_type as usize], working_offset + index, - || Value::known(Fp::one()), + || Value::known(Fp::ONE), )?; } region.assign_advice( || "enable", config.s_enable, working_offset, - || Value::known(Fp::one()), + || Value::known(Fp::ONE), )?; working_offset += 1; @@ -1278,7 +1276,7 @@ mod test { || "enable", config.s_enable, offset, - || Value::known(Fp::one()), + || Value::known(Fp::ONE), )?; region.assign_advice( || "sibling", @@ -1295,9 +1293,9 @@ mod test { } for (col, val, tip) in [ - (config.s_enable, Fp::one(), "enable"), + (config.s_enable, Fp::ONE, "enable"), (config.path, self.key_residue, "path"), - (config.sibling, Fp::zero(), "sibling"), + (config.sibling, Fp::ZERO, "sibling"), (config.key_aux, self.key_immediate, "key"), ] { region.assign_advice(|| tip, col, next_offset, || Value::known(val))?; @@ -1368,7 +1366,7 @@ mod test { ); let path: Vec = path_bits .into_iter() - .map(|not_zero| if not_zero { Fp::one() } else { Fp::zero() }) + .map(|not_zero| if not_zero { Fp::ONE } else { Fp::ZERO }) .collect(); Self { @@ -1464,7 +1462,7 @@ mod test { || "enable", config.s_enable, offset, - || Value::known(Fp::one()), + || Value::known(Fp::ONE), )?; region.assign_advice( || "s_path", @@ -1472,10 +1470,8 @@ mod test { offset, || { Value::known(match self.data.old.hash_types[index] { - HashType::Empty | HashType::Leaf | HashType::Start => { - Fp::zero() - } - _ => Fp::one(), + HashType::Empty | HashType::Leaf | HashType::Start => Fp::ZERO, + _ => Fp::ONE, }) }, )?; @@ -1523,7 +1519,7 @@ mod test { .old .hash_traces .iter() - .chain([(Fp::one(), self.data.key, Fp::zero())].iter()), //dummy for key calc + .chain([(Fp::ONE, self.data.key, Fp::ZERO)].iter()), //dummy for key calc )?; Ok(()) @@ -1555,7 +1551,7 @@ mod test { key: Fp::from(4u64), key_residual: Fp::from(4u64), old: MPTPath::{ - hash_traces: vec![(Fp::one(), Fp::from(4u64), Fp::zero())], + hash_traces: vec![(Fp::ONE, Fp::from(4u64), Fp::ZERO)], hash_types: vec![HashType::Start, HashType::Empty], ..Default::default() }, @@ -1572,11 +1568,11 @@ mod test { TestOpCircuit { data: SingleOp::{ siblings: vec![Fp::from(11u64)], - path: vec![Fp::one()], + path: vec![Fp::ONE], key: Fp::from(17u64), //0b10001u64 key_residual: Fp::from(8u64), old: MPTPath::{ - hash_traces: vec![(Fp::one(), Fp::from(9u64), Fp::zero())], + hash_traces: vec![(Fp::ONE, Fp::from(9u64), Fp::ZERO)], hash_types: vec![HashType::Start, HashType::LeafExtFinal, HashType::Empty], ..Default::default() }, @@ -1592,12 +1588,12 @@ mod test { static ref DEMOCIRCUIT3: TestOpCircuit = { TestOpCircuit { data: SingleOp::{ - siblings: vec![Fp::from(11u64), Fp::zero(), Fp::from(22u64)], - path: vec![Fp::one(), Fp::zero(), Fp::one()], + siblings: vec![Fp::from(11u64), Fp::ZERO, Fp::from(22u64)], + path: vec![Fp::ONE, Fp::ZERO, Fp::ONE], key: Fp::from(45u64), //0b101101u64 key_residual: Fp::from(5u64), old: MPTPath::{ - hash_traces: vec![(Fp::one(), Fp::from(45u64), Fp::zero())], + hash_traces: vec![(Fp::ONE, Fp::from(45u64), Fp::ZERO)], hash_types: vec![ HashType::Start, HashType::Middle, @@ -1720,7 +1716,7 @@ mod test { || "flushing", *col, offset, - || Value::known(Fp::zero()), + || Value::known(Fp::ZERO), ) .map(|_| ()) })?; diff --git a/src/mpt_table.rs b/src/mpt_table.rs index 8e1b9c0c..db577b7a 100644 --- a/src/mpt_table.rs +++ b/src/mpt_table.rs @@ -1,7 +1,7 @@ use crate::operation::{AccountOp, KeyValue}; use halo2_proofs::{ - arithmetic::{Field, FieldExt}, circuit::{Layouter, Value}, + ff::{Field, PrimeField}, plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector, VirtualCells}, poly::Rotation, }; @@ -48,7 +48,7 @@ impl Config { self.address.index() } - pub fn bind_mpt_circuit( + pub fn bind_mpt_circuit( &self, meta: &mut ConstraintSystem, gadget_id: Column, @@ -179,15 +179,15 @@ impl Config { }); if false { - meta.lookup_any("mpt account not exist entry lookup", |meta| { - let s_enable = meta.query_advice(self.proof_sel[3], Rotation::cur()); - - build_entry_lookup_common(meta, (3, 0)) - .into_iter() - .chain(build_entry_lookup_not_exist(meta)) - .map(|(fst, snd)| (fst * s_enable.clone(), snd)) - .collect() - }); + meta.lookup_any("mpt account not exist entry lookup", |meta| { + let s_enable = meta.query_advice(self.proof_sel[3], Rotation::cur()); + + build_entry_lookup_common(meta, (3, 0)) + .into_iter() + .chain(build_entry_lookup_not_exist(meta)) + .map(|(fst, snd)| (fst * s_enable.clone(), snd)) + .collect() + }); } meta.lookup_any("mpt account destroy entry lookup", |meta| { @@ -254,7 +254,7 @@ pub(crate) struct MPTEntry { old_value: KeyValue, } -impl MPTEntry { +impl MPTEntry { // detect proof type from op data itself, just mocking, // not always correct pub fn mock_from_op(op: &AccountOp, randomness: F) -> Self { @@ -388,7 +388,7 @@ pub(crate) struct MPTTable { rows: usize, } -impl MPTTable { +impl MPTTable { pub fn construct( config: Config, entries: impl IntoIterator>, @@ -775,7 +775,7 @@ mod test { proof_type: MPTProofType::BalanceChanged, base: Some([ address, - Fp::zero(), + Fp::ZERO, Fp::from(MPTProofType::BalanceChanged as u64), rand_fp(), rand_fp(), @@ -808,13 +808,13 @@ mod test { let entry3 = MPTEntry { proof_type: MPTProofType::AccountDoesNotExist, base: Some([ - address + Fp::one(), - Fp::zero(), + address + Fp::ONE, + Fp::ZERO, Fp::from(MPTProofType::AccountDoesNotExist as u64), entry2.base.unwrap()[4], entry2.base.unwrap()[4], - Fp::zero(), - Fp::zero(), + Fp::ZERO, + Fp::ZERO, ]), storage_key: Default::default(), new_value: Default::default(), diff --git a/src/mpt_table/byte32.rs b/src/mpt_table/byte32.rs index c8001cce..978a9efb 100644 --- a/src/mpt_table/byte32.rs +++ b/src/mpt_table/byte32.rs @@ -1,6 +1,6 @@ use halo2_proofs::{ - arithmetic::FieldExt, circuit::{Region, Value}, + ff::PrimeField, plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector}, poly::Rotation, }; @@ -12,7 +12,7 @@ pub(crate) struct Config { } impl Config { - pub fn configure( + pub fn configure( meta: &mut ConstraintSystem, sel: Selector, rep: &[Column; N], @@ -49,7 +49,7 @@ impl Config { Self { rep_hi, rep_lo } } - pub fn assign( + pub fn assign( &self, region: &mut Region<'_, F>, offset: usize, @@ -67,7 +67,7 @@ impl Config { Ok(true) } - pub fn flush( + pub fn flush( &self, region: &mut Region<'_, F>, offset: usize, @@ -124,7 +124,7 @@ mod test { let val = meta.query_advice(val, Rotation::cur()); vec![ meta.query_selector(sel) - * rep.bind_rlc_value(meta, val, Expression::Constant(Fp::one()), None), + * rep.bind_rlc_value(meta, val, Expression::Constant(Fp::ONE), None), ] }); diff --git a/src/mpt_table/range_check.rs b/src/mpt_table/range_check.rs index 10f52602..53701876 100644 --- a/src/mpt_table/range_check.rs +++ b/src/mpt_table/range_check.rs @@ -1,6 +1,7 @@ use halo2_proofs::{ - arithmetic::{Field, FieldExt}, + arithmetic::Field, circuit::{Layouter, Value}, + ff::PrimeField, plonk::{Advice, Column, ConstraintSystem, Error, Expression, TableColumn, VirtualCells}, poly::Rotation, }; @@ -35,7 +36,7 @@ pub(crate) struct Chip { _marker: PhantomData, } -impl Chip { +impl Chip { const RANGE: usize = 1 << N; pub fn construct(config: Config) -> Self { diff --git a/src/operation.rs b/src/operation.rs index 3b576ebb..37d6b6d4 100644 --- a/src/operation.rs +++ b/src/operation.rs @@ -4,14 +4,14 @@ use super::{eth, serde, HashType}; use crate::hash::Hashable; -use halo2_proofs::arithmetic::FieldExt; +use halo2_proofs::ff::{FromUniformBytes, PrimeField}; use num_bigint::BigUint; use std::cmp::Ordering; use std::convert::TryFrom; /// Indicate the current status of an MPTPath #[derive(Clone, Copy, Debug)] -pub enum MPTPathStatus { +pub enum MPTPathStatus { /// Path has empty leaf node Empty, /// Path has leaf node and the (key, keyImmediate) is tracked @@ -26,7 +26,7 @@ pub enum MPTPathStatus { /// according to the hash_type. It would be used for the layout of MPT /// circuit #[derive(Clone, Debug)] -pub struct MPTPath { +pub struct MPTPath { /// hash types from beginning of a path, start with HashType::Start pub hash_types: Vec, /// hashes from beginning of path, from the root of MPT to leaf node @@ -39,18 +39,18 @@ pub struct MPTPath { pub status: MPTPathStatus, } -impl Default for MPTPath { +impl Default for MPTPath { fn default() -> Self { Self { hash_types: vec![HashType::Start, HashType::Empty], - hashes: vec![Fp::zero(), Fp::zero()], + hashes: vec![Fp::ZERO, Fp::ZERO], hash_traces: Default::default(), status: MPTPathStatus::Empty, } } } -impl MPTPath { +impl MPTPath { /// the root of MPT pub fn root(&self) -> Fp { self.hashes[0] @@ -113,7 +113,7 @@ impl MPTPath { assert!(self.hash_types.len() > 1, "can not extend empty path"); let ins_pos = self.hash_types.len() - 1; // can only extend a path with leaf - let new_key_immediate = hasher(&Fp::one(), &self.key().expect("can only extend leaf")); + let new_key_immediate = hasher(&Fp::ONE, &self.key().expect("can only extend leaf")); let status = match self.status { MPTPathStatus::Leaf((fp, fp_immediate)) => MPTPathStatus::Extended(( (new_key, new_key_immediate), @@ -134,7 +134,7 @@ impl MPTPath { // move the old value at last row to upper (row LeafExtFinal) addi_hashes.push(hashes[ins_pos]); - hashes[ins_pos] = Fp::zero(); + hashes[ins_pos] = Fp::ZERO; drop(hashes.splice(ins_pos..ins_pos, addi_hashes)); Self { @@ -155,7 +155,7 @@ impl MPTPath { assert_eq!(path.len(), siblings.len()); let (status, mut hashes, mut hash_types, mut hash_traces) = if let Some(fp) = leaf { - let one = Fp::one(); + let one = Fp::ONE; let key_immediate = hasher(&one, &key); let leaf_hash = hasher(&key_immediate, &fp); @@ -168,7 +168,7 @@ impl MPTPath { } else { ( MPTPathStatus::Empty, - vec![Fp::zero(), Fp::zero()], + vec![Fp::ZERO, Fp::ZERO], vec![HashType::Empty], Vec::new(), ) @@ -219,7 +219,7 @@ impl MPTPath { /// Represent for a single operation #[derive(Clone, Debug, Default)] -pub struct SingleOp { +pub struct SingleOp { /// the key of operation pub key: Fp, /// the immediate in key hashing @@ -236,7 +236,7 @@ pub struct SingleOp { pub new: MPTPath, } -impl SingleOp { +impl SingleOp { /// indicate rows would take in circuit layout pub fn use_rows(&self) -> usize { self.siblings.len() + 2 @@ -295,7 +295,7 @@ impl SingleOp { ); let mut ret = Vec::new(); let mut tested_key = key; - let invert_2 = Fp::one().double().invert().unwrap(); + let invert_2 = Fp::ONE.double().invert().unwrap(); for _ in 0..layers { if tested_key.is_odd().unwrap_u8() == 1 { tested_key = tested_key * invert_2 - invert_2; @@ -322,7 +322,7 @@ impl SingleOp { .expect("must have immediate value for leaf node"); let path: Vec = path .into_iter() - .map(|b| if b { Fp::one() } else { Fp::zero() }) + .map(|b| if b { Fp::ONE } else { Fp::ZERO }) .collect(); Self { @@ -342,7 +342,7 @@ impl SingleOp { new_leaf: Fp, hasher: impl FnMut(&Fp, &Fp) -> Fp + Clone, ) -> Self { - let path_bool: Vec = self.path.iter().map(|v| *v != Fp::zero()).collect(); + let path_bool: Vec = self.path.iter().map(|v| *v != Fp::ZERO).collect(); let new = MPTPath::::create_with_hasher( &path_bool, &self.siblings, @@ -389,14 +389,14 @@ impl SingleOp { } } -fn bytes_to_fp(mut bt: Vec) -> std::io::Result { +fn bytes_to_fp>(mut bt: Vec) -> std::io::Result { // let expected_size = Fp::NUM_BITS as usize / 8 + if Fp::NUM_BITS % 8 == 0 { 0 } else { 1 }; bt.resize(64, 0u8); let arr: [u8; 64] = bt .as_slice() .try_into() .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; - Ok(Fp::from_bytes_wide(&arr)) + Ok(Fp::from_uniform_bytes(&arr)) } /// Represent for a eth account @@ -414,7 +414,7 @@ pub struct Account { pub hash_traces: Vec<(Fp, Fp, Fp)>, } -impl Account { +impl Account { /// calculating all traces ad-hoc with hasher function pub(crate) fn trace(mut self, mut hasher: impl FnMut(&Fp, &Fp) -> Fp) -> Self { let h1 = hasher(&self.codehash.0, &self.codehash.1); @@ -444,7 +444,7 @@ impl Account { /// there is totally 4 of them and the last one calculate the final hash pub fn hash_traces(&self, i: usize) -> Fp { if self.hash_traces.is_empty() { - Fp::zero() + Fp::ZERO } else { self.hash_traces[i].2 } @@ -453,7 +453,7 @@ impl Account { /// the hash of account, which act as leaf value in account trie pub fn account_hash(&self) -> Fp { if self.hash_traces.is_empty() { - Fp::zero() + Fp::ZERO } else { assert_eq!(self.hash_traces.len(), 4); self.hash_traces[3].2 @@ -481,12 +481,12 @@ pub struct KeyValue { data: (Fp, Fp, Fp), // (the first 16 bytes, the second 16 bytes, hash value) } -impl KeyValue { +impl> KeyValue { /// create object and omit the hash pub fn create_base(bytes32: (Fp, Fp)) -> Self { let (fst, snd) = bytes32; Self { - data: (fst, snd, Fp::zero()), + data: (fst, snd, Fp::ZERO), } } @@ -507,8 +507,8 @@ impl KeyValue { /// the u256 is represented by le bytes and combined with randomness 1, o, o^2 ... o^31 on each /// and we calculate it from be represent pub fn u8_rlc(&self, randomness: Fp) -> Fp { - let u128_hi = self.data.0.get_lower_128(); - let u128_lo = self.data.1.get_lower_128(); + let u128_hi = u128::from_le_bytes(self.data.0.to_repr()[0..16].try_into().unwrap()); + let u128_lo = u128::from_le_bytes(self.data.1.to_repr()[0..16].try_into().unwrap()); u128_hi .to_be_bytes() .into_iter() @@ -546,7 +546,7 @@ impl KeyValue { /// Represent an operation in eth MPT, which update 2 layer of tries (state and account) #[derive(Clone, Debug, Default)] -pub struct AccountOp { +pub struct AccountOp { /// the operation on the account trie (first layer) pub acc_trie: SingleOp, /// the operation on the state trie (second layer) @@ -567,7 +567,7 @@ pub struct AccountOp { pub store_key: Option>, } -impl AccountOp { +impl AccountOp { /// indicate rows would take for whole operation pub fn use_rows(&self) -> usize { self.use_rows_account() @@ -622,11 +622,7 @@ impl AccountOp { impl AccountOp { /// providing the padding record for hash table pub fn padding_hash() -> (Fp, Fp, Fp) { - ( - Fp::zero(), - Fp::zero(), - Hashable::hash([Fp::zero(), Fp::zero()]), - ) + (Fp::ZERO, Fp::ZERO, Hashable::hash([Fp::ZERO, Fp::ZERO])) } /// iter all the hash traces inside an operation (may contain duplications) @@ -657,14 +653,14 @@ pub enum TraceError { } // parse Trace data into MPTPath and additional data (siblings and path) -struct SMTPathParse(MPTPath, Vec, Vec); +struct SMTPathParse(MPTPath, Vec, Vec); impl<'d, Fp: Hashable> TryFrom<&'d serde::SMTPath> for SMTPathParse { type Error = TraceError; fn try_from(path_trace: &'d serde::SMTPath) -> Result { let mut siblings: Vec = Vec::new(); for n in &path_trace.path { - let s = Fp::from_bytes_wide(&n.sibling.cast()); + let s = Fp::from_uniform_bytes(&n.sibling.cast()); siblings.push(s); } @@ -674,20 +670,20 @@ impl<'d, Fp: Hashable> TryFrom<&'d serde::SMTPath> for SMTPathParse { for i in 0..siblings.len() { let bit = (BigUint::from(1u64) << i) & &path_trace.path_part != BigUint::from(0u64); path_bits.push(bit); - path.push(if bit { Fp::one() } else { Fp::zero() }); + path.push(if bit { Fp::ONE } else { Fp::ZERO }); } - let mut key = Fp::zero(); + let mut key = Fp::ZERO; let mut leaf = None; // notice when there is no leaf node, providing 0 key if let Some(leaf_node) = &path_trace.leaf { - key = Fp::from_bytes_wide(&leaf_node.sibling.cast()); - leaf = Some(Fp::from_bytes_wide(&leaf_node.value.cast())); + key = Fp::from_uniform_bytes(&leaf_node.sibling.cast()); + leaf = Some(Fp::from_uniform_bytes(&leaf_node.value.cast())); } let mpt_path = MPTPath::create(&path_bits, &siblings, key, leaf); // sanity check - let root = Fp::from_bytes_wide(&path_trace.root.cast()); + let root = Fp::from_uniform_bytes(&path_trace.root.cast()); assert_eq!(root, mpt_path.root()); Ok(SMTPathParse(mpt_path, siblings, path)) @@ -703,7 +699,7 @@ impl<'d, Fp: Hashable> TryFrom<(&'d serde::SMTPath, &'d serde::SMTPath, serde::H ) -> Result { let (before, after, ref_key) = traces; - let key = Fp::from_bytes_wide(&ref_key.cast()); + let key = Fp::from_uniform_bytes(&ref_key.cast()); let before_parsed: SMTPathParse = before.try_into()?; let after_parsed: SMTPathParse = after.try_into()?; let mut old = before_parsed.0; @@ -747,7 +743,7 @@ impl<'d, Fp: Hashable> TryFrom<(&'d serde::SMTPath, &'d serde::SMTPath, serde::H if let Some(another_key) = old.key() { // we need to make full path extension for both side, manually - let invert_2 = Fp::one().double().invert().unwrap(); + let invert_2 = Fp::ONE.double().invert().unwrap(); let mut k1 = another_key; let mut k2 = key; let mut common_prefix_depth: usize = 0; @@ -765,7 +761,7 @@ impl<'d, Fp: Hashable> TryFrom<(&'d serde::SMTPath, &'d serde::SMTPath, serde::H common_prefix_depth += 1; if common_prefix_depth > path.len() { path.push(Fp::from(k2_bit as u64)); - siblings.push(Fp::zero()); + siblings.push(Fp::ZERO); } assert_ne!(k1, k2); k2_bit = k2.is_odd().unwrap_u8(); @@ -782,8 +778,8 @@ impl<'d, Fp: Hashable> TryFrom<(&'d serde::SMTPath, &'d serde::SMTPath, serde::H } // and also insert the required key hash trace - let key_immediate = ::hash([Fp::one(), key]); - old.hash_traces.push((Fp::one(), key, key_immediate)); + let key_immediate = ::hash([Fp::ONE, key]); + old.hash_traces.push((Fp::ONE, key, key_immediate)); (siblings, path, key_immediate) } else if old.key() == Some(key) { @@ -825,7 +821,7 @@ impl<'d, Fp: Hashable> TryFrom<(&'d serde::AccountData, Fp)> for Account { let balance = bytes_to_fp(acc.balance.to_bytes_le()).map_err(TraceError::DeErr)?; let buf = acc.code_hash.to_bytes_le(); let codehash = if buf.len() < 16 { - (bytes_to_fp(buf).map_err(TraceError::DeErr)?, Fp::zero()) + (bytes_to_fp(buf).map_err(TraceError::DeErr)?, Fp::ZERO) } else { ( bytes_to_fp(Vec::from(&buf[16..])).map_err(TraceError::DeErr)?, @@ -896,8 +892,8 @@ impl<'d, Fp: Hashable> TryFrom<&'d serde::SMTTrace> for AccountOp { }; let comm_state_root = match trace.common_state_root { - Some(h) => Fp::from_bytes_wide(&h.cast()), - None => Fp::zero(), + Some(h) => Fp::from_uniform_bytes(&h.cast()), + None => Fp::ZERO, }; let account_before = if let Some(leaf) = acc_trie.old.leaf() { @@ -975,30 +971,32 @@ impl<'d, Fp: Hashable> TryFrom<&'d serde::SMTTrace> for AccountOp { } #[derive(Clone, Debug, PartialEq, Eq)] -struct HashableField(Fp); +struct HashableField(Fp); -impl std::hash::Hash for HashableField { +impl std::hash::Hash for HashableField { fn hash(&self, state: &mut H) where H: std::hash::Hasher, { - state.write_u128(self.0.get_lower_128()); + state.write_u128(u128::from_le_bytes( + self.0.to_repr()[0..16].try_into().unwrap(), + )); } } -impl From for HashableField { +impl From for HashableField { fn from(v: Fp) -> Self { Self(v) } } #[derive(Clone)] -pub(crate) struct HashTracesSrc { +pub(crate) struct HashTracesSrc { source: T, deduplicator: std::collections::HashSet>, } -impl From for HashTracesSrc { +impl From for HashTracesSrc { fn from(source: T) -> Self { Self { source, @@ -1010,7 +1008,7 @@ impl From for HashTracesSrc { impl<'d, T, Fp> Iterator for HashTracesSrc where T: Iterator, - Fp: FieldExt, + Fp: PrimeField, { type Item = &'d (Fp, Fp, Fp); @@ -1032,7 +1030,7 @@ mod tests { use crate::test_utils::{rand_bytes_array, rand_gen, Fp}; use halo2_proofs::halo2curves::group::ff::{Field, PrimeField}; - impl SingleOp { + impl SingleOp { /// create an fully random update operation with leafs customable pub fn create_rand_op( layers: usize, @@ -1054,7 +1052,7 @@ mod tests { } } - impl KeyValue { + impl KeyValue { /// create an fully random k/v pub fn create_rand(mut hasher: impl FnMut(&Fp, &Fp) -> Fp + Clone) -> Self { let a = Fp::from_u128(u128::from_be_bytes(rand_bytes_array::<16>())); @@ -1065,10 +1063,10 @@ mod tests { } } - fn decompose(inp: Fp, l: usize) -> (Vec, Fp) { + fn decompose(inp: Fp, l: usize) -> (Vec, Fp) { let mut ret = Vec::new(); let mut tested_key = inp; - let invert_2 = Fp::one().double().invert().unwrap(); + let invert_2 = Fp::ONE.double().invert().unwrap(); for _ in 0..l { if tested_key.is_odd().unwrap_u8() == 1 { tested_key = tested_key * invert_2 - invert_2; @@ -1081,12 +1079,12 @@ mod tests { (ret, tested_key) } - fn recover(path: &[bool], res: Fp) -> Fp { - let mut mask = Fp::one(); - let mut ret = Fp::zero(); + fn recover(path: &[bool], res: Fp) -> Fp { + let mut mask = Fp::ONE; + let mut ret = Fp::ZERO; for b in path { - ret += if *b { mask } else { Fp::zero() }; + ret += if *b { mask } else { Fp::ZERO }; mask = mask.double(); } @@ -1193,7 +1191,7 @@ mod tests { let data: Account = Account { balance: Fp::from(0u64), nonce: Fp::from(1u64), - codehash: (Fp::zero(), Fp::zero()), + codehash: (Fp::ZERO, Fp::ZERO), //0x20b24ebee7712fbbe84a15027eba4f1208e2e2df9f925de51b3382b86433e6a5 state_root: Fp::from_str_vartime( "14789053415173694845992038966920525110567435779704439275440571405364058384037", diff --git a/src/test_utils.rs b/src/test_utils.rs index 26e542ae..c782715a 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -1,4 +1,4 @@ -pub use halo2_proofs::arithmetic::{Field, FieldExt}; +pub use halo2_proofs::arithmetic::{Field, PrimeField}; pub use halo2_proofs::halo2curves::bn256::Fr as Fp; use lazy_static::lazy_static; use rand::{random, SeedableRng}; From 6c89af8225f5beff7cd57b58960c68f471a76217 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Thu, 16 Mar 2023 20:12:03 -0400 Subject: [PATCH 16/17] fix comipling bugs --- src/eth.rs | 8 ++++---- src/lib.rs | 24 ++++++++++++++---------- src/mpt_table.rs | 16 ++++++++-------- src/mpt_table/byte32.rs | 2 +- src/mpt_table/value_rep.rs | 4 ++-- src/operation.rs | 12 ++++++------ 6 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/eth.rs b/src/eth.rs index 64178546..5b587ae7 100644 --- a/src/eth.rs +++ b/src/eth.rs @@ -250,7 +250,7 @@ impl AccountGadget { } /// assign data and enable flag for account circuit - pub fn assign<'d, Fp: PrimeField>( + pub fn assign<'d, Fp: PrimeField>( &self, region: &mut Region<'_, Fp>, offset: usize, @@ -558,7 +558,7 @@ struct StorageChip<'d, F> { value: Option>, } -impl<'d, Fp: PrimeField> StorageChip<'d, Fp> { +impl<'d, Fp: PrimeField> StorageChip<'d, Fp> { fn configure( meta: &mut ConstraintSystem, _sel: Selector, @@ -623,7 +623,7 @@ impl StorageGadget { /// + circuit selector * 1 /// + exported col * 5 (MUST by following sequence: layout_flag, s_enable, old_val, new_val, key_val) /// + free col * 4 - pub fn configure( + pub fn configure>( meta: &mut ConstraintSystem, sel: Selector, exported: &[Column], @@ -664,7 +664,7 @@ impl StorageGadget { [].into_iter() } - pub fn assign<'d, Fp: PrimeField>( + pub fn assign<'d, Fp: PrimeField>( &self, region: &mut Region<'_, Fp>, offset: usize, diff --git a/src/lib.rs b/src/lib.rs index 7d2d6fab..5e8c0ac1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -309,7 +309,7 @@ impl EthTrieConfig { } /// configure for lite circuit (no mpt table included, for fast testing) - pub fn configure_base( + pub fn configure_base>( meta: &mut ConstraintSystem, hash_tbl: [Column; 4], ) -> Self { @@ -396,13 +396,15 @@ impl EthTrieConfig { } /// configure for lite circuit (no mpt table included, for fast testing) - pub fn configure_lite(meta: &mut ConstraintSystem) -> Self { + pub fn configure_lite>( + meta: &mut ConstraintSystem, + ) -> Self { let hash_tbl = [0; 4].map(|_| meta.advice_column()); Self::configure_base(meta, hash_tbl) } /// configure for full circuit - pub fn configure_sub( + pub fn configure_sub>( meta: &mut ConstraintSystem, mpt_tbl: [Column; 7], hash_tbl: [Column; 4], @@ -433,7 +435,7 @@ impl EthTrieConfig { /// synthesize the mpt table part, the randomness also specify /// if the base part of mpt table should be assigned - pub fn load_mpt_table<'d, Fp: Hashable>( + pub fn load_mpt_table<'d, Fp: Hashable + PrimeField>( &self, layouter: &mut impl Layouter, randomness: Option, @@ -460,7 +462,7 @@ impl EthTrieConfig { /// synthesize the hash table part, the randomness also specify /// if the base part of mpt table should be assigned - pub fn load_hash_table<'d, Fp: Hashable>( + pub fn load_hash_table<'d, Fp: Hashable + PrimeField>( &self, layouter: &mut impl Layouter, hash_traces: impl Iterator + Clone, @@ -476,7 +478,7 @@ impl EthTrieConfig { /// synthesize core part without advice tables (hash and mpt table), /// require a `Hashable` trait on the working field - pub fn synthesize_core<'d, Fp: Hashable>( + pub fn synthesize_core<'d, Fp: Hashable + PrimeField>( &self, layouter: &mut impl Layouter, ops: impl Iterator> + Clone, @@ -721,7 +723,7 @@ impl Circuit for HashCircuit { } } -impl EthTrie { +impl> EthTrie { /// Obtain the total required rows for mpt and hash circuits (include the top and bottom padding) pub fn use_rows(&self) -> (usize, usize) { // calc rows for mpt circuit, we need to compare the rows used by adviced region and table region @@ -791,7 +793,7 @@ impl CommitmentIndexs { } /// get commitment for lite circuit (no mpt) - pub fn new() -> Self { + pub fn new>() -> Self { let mut cs: ConstraintSystem = Default::default(); let config = EthTrieCircuit::<_, true>::configure(&mut cs); @@ -810,7 +812,7 @@ impl CommitmentIndexs { } /// get commitment for full circuit - pub fn new_full_circuit() -> Self { + pub fn new_full_circuit>() -> Self { let mut cs: ConstraintSystem = Default::default(); let config = EthTrieCircuit::<_, false>::configure(&mut cs); @@ -835,7 +837,9 @@ impl CommitmentIndexs { const TEMP_RANDOMNESS: u64 = 1; -impl Circuit for EthTrieCircuit { +impl, const LITE: bool> Circuit + for EthTrieCircuit +{ type Config = EthTrieConfig; type FloorPlanner = SimpleFloorPlanner; diff --git a/src/mpt_table.rs b/src/mpt_table.rs index db577b7a..62c02ea8 100644 --- a/src/mpt_table.rs +++ b/src/mpt_table.rs @@ -254,7 +254,7 @@ pub(crate) struct MPTEntry { old_value: KeyValue, } -impl MPTEntry { +impl> MPTEntry { // detect proof type from op data itself, just mocking, // not always correct pub fn mock_from_op(op: &AccountOp, randomness: F) -> Self { @@ -341,7 +341,7 @@ impl MPTEntry { ret.old_value.u8_rlc(randomness), ret.new_value.u8_rlc(randomness), ), - _ => (F::zero(), F::zero()), + _ => (F::ZERO, F::ZERO), }; ret.base.replace([ @@ -388,7 +388,7 @@ pub(crate) struct MPTTable { rows: usize, } -impl MPTTable { +impl> MPTTable { pub fn construct( config: Config, entries: impl IntoIterator>, @@ -458,7 +458,7 @@ impl MPTTable { // each col is boolean // when enabled, it must equal to proof_type vec![ - sel.clone() * col.clone() * (Expression::Constant(F::one()) - col.clone()), + sel.clone() * col.clone() * (Expression::Constant(F::ONE) - col.clone()), sel * col * (Expression::Constant(F::from(index as u64 + 1)) - proof_type), ] }); @@ -474,7 +474,7 @@ impl MPTTable { .reduce(|acc, col_exp| acc + col_exp) .expect("not null"); - vec![sel * total_enalbed.clone() * (Expression::Constant(F::one()) - total_enalbed)] + vec![sel * total_enalbed.clone() * (Expression::Constant(F::ONE) - total_enalbed)] }); Config { @@ -514,9 +514,9 @@ impl MPTTable { offset, || { Value::known(if index + 1 == entry.proof_type as usize { - F::one() + F::ONE } else { - F::zero() + F::ZERO }) }, )?; @@ -617,7 +617,7 @@ impl MPTTable { || "flush rows", col, row, - || Value::known(F::zero()), + || Value::known(F::ZERO), )?; } diff --git a/src/mpt_table/byte32.rs b/src/mpt_table/byte32.rs index 978a9efb..4a76e2fe 100644 --- a/src/mpt_table/byte32.rs +++ b/src/mpt_table/byte32.rs @@ -72,7 +72,7 @@ impl Config { region: &mut Region<'_, F>, offset: usize, ) -> Result { - self.assign(region, offset, &(F::zero(), F::zero())) + self.assign(region, offset, &(F::ZERO, F::ZERO)) } } diff --git a/src/mpt_table/value_rep.rs b/src/mpt_table/value_rep.rs index 8797fd0a..da896660 100644 --- a/src/mpt_table/value_rep.rs +++ b/src/mpt_table/value_rep.rs @@ -71,7 +71,7 @@ impl Config { let le_bytes = val.to_repr(); let limb_bytes = EXP / 8; - let mut out = [F::zero(); N]; + let mut out = [F::ZERO; N]; for i in 0..N { out[N - i - 1] = F::from( @@ -109,7 +109,7 @@ impl Config { region: &mut Region<'_, F>, offset: usize, ) -> Result { - self.assign(region, offset, [F::zero(); N].as_slice()) + self.assign(region, offset, [F::ZERO; N].as_slice()) } } diff --git a/src/operation.rs b/src/operation.rs index 37d6b6d4..f1c8afe0 100644 --- a/src/operation.rs +++ b/src/operation.rs @@ -971,9 +971,9 @@ impl<'d, Fp: Hashable> TryFrom<&'d serde::SMTTrace> for AccountOp { } #[derive(Clone, Debug, PartialEq, Eq)] -struct HashableField(Fp); +struct HashableField>(Fp); -impl std::hash::Hash for HashableField { +impl> std::hash::Hash for HashableField { fn hash(&self, state: &mut H) where H: std::hash::Hasher, @@ -984,19 +984,19 @@ impl std::hash::Hash for HashableField { } } -impl From for HashableField { +impl> From for HashableField { fn from(v: Fp) -> Self { Self(v) } } #[derive(Clone)] -pub(crate) struct HashTracesSrc { +pub(crate) struct HashTracesSrc> { source: T, deduplicator: std::collections::HashSet>, } -impl From for HashTracesSrc { +impl> From for HashTracesSrc { fn from(source: T) -> Self { Self { source, @@ -1008,7 +1008,7 @@ impl From for HashTracesSrc { impl<'d, T, Fp> Iterator for HashTracesSrc where T: Iterator, - Fp: PrimeField, + Fp: PrimeField, { type Item = &'d (Fp, Fp, Fp); From 121dd82320f2adfaff5b0bfa6a9e571158a58792 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Thu, 16 Mar 2023 20:17:18 -0400 Subject: [PATCH 17/17] fix bugs in tests --- src/test_utils.rs | 2 +- tests/trace_proving.rs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/test_utils.rs b/src/test_utils.rs index c782715a..ea7b80e9 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -1,4 +1,4 @@ -pub use halo2_proofs::arithmetic::{Field, PrimeField}; +pub use halo2_proofs::ff::{Field, PrimeField}; pub use halo2_proofs::halo2curves::bn256::Fr as Fp; use lazy_static::lazy_static; use rand::{random, SeedableRng}; diff --git a/tests/trace_proving.rs b/tests/trace_proving.rs index 547f01a1..cc337135 100644 --- a/tests/trace_proving.rs +++ b/tests/trace_proving.rs @@ -1,4 +1,5 @@ use halo2_mpt_circuits::{operation::AccountOp, serde, EthTrie}; +use halo2_proofs::SerdeFormat; use halo2_proofs::dev::MockProver; use halo2_proofs::halo2curves::bn256::{Bn256, Fr as Fp, G1Affine}; use halo2_proofs::plonk::{create_proof, keygen_pk, keygen_vk, verify_proof}; @@ -94,14 +95,14 @@ fn vk_validity() { let vk1 = keygen_vk(¶ms, &circuit).unwrap(); let mut vk1_buf: Vec = Vec::new(); - vk1.write(&mut vk1_buf).unwrap(); + vk1.write(&mut vk1_buf, SerdeFormat::RawBytes).unwrap(); let data: EthTrie = Default::default(); let (circuit, _) = data.circuits(200); let vk2 = keygen_vk(¶ms, &circuit).unwrap(); let mut vk2_buf: Vec = Vec::new(); - vk2.write(&mut vk2_buf).unwrap(); + vk2.write(&mut vk2_buf, SerdeFormat::RawBytes).unwrap(); assert_eq!(vk1_buf, vk2_buf); }