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

ModExtensionGadget #1563

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
a9dfceb
is_mod_extension added to branch/leaf; some leaf constraints omitted …
miha-stopar Aug 14, 2023
84e6b2c
Added modified extension node values for both leaves.
miha-stopar Aug 17, 2023
37c3e84
Fix in account/storage leaf rows sequence.
miha-stopar Aug 18, 2023
5d8469c
Started on ModExtensionGadget
miha-stopar Aug 28, 2023
4719cdf
On ModExtensionGadget
miha-stopar Aug 29, 2023
84cd151
Moving to ModExtensionGadget
miha-stopar Aug 29, 2023
2266cd1
ModExtensionGadget key and first byte constraints
miha-stopar Aug 30, 2023
ac5f6ab
ModExtensionGadget refactor
miha-stopar Aug 31, 2023
fcb3187
ModExtensionGadget parent constraint
miha-stopar Aug 31, 2023
eab1d0e
Modified extension node key RLC
miha-stopar Sep 1, 2023
dffc6bc
Extension node nibbles RLC added to KeyData
miha-stopar Sep 5, 2023
eee5714
Fixing extension node key rlc
miha-stopar Sep 6, 2023
4cdeac3
Short/long nibbles RLC
miha-stopar Sep 12, 2023
934167f
Drifted index added to KeyData
miha-stopar Oct 16, 2023
fbae85d
Modified ext. node: long = middle + drifted index + short
miha-stopar Oct 18, 2023
10bcec0
ParentData into ModExtensionGadget
miha-stopar Oct 18, 2023
eef7b69
Branch lookup in the parent branch fixed
miha-stopar Oct 19, 2023
01f1306
KeyData fix
miha-stopar Oct 23, 2023
17278d6
Working on inverse operation
miha-stopar Oct 24, 2023
724c44f
is_insert fix
miha-stopar Oct 25, 2023
3eeee64
Nibbles mult fixed
miha-stopar Oct 25, 2023
87573c6
middle nibbles RLC fix
miha-stopar Oct 26, 2023
ca94593
Need to distinguish between is_long_odd and is_long_even
miha-stopar Oct 26, 2023
67cf816
Refactoring middle + short = long nibbles
miha-stopar Oct 30, 2023
1150ff5
Nibbles data fixed
miha-stopar Oct 31, 2023
fb66d34
nibbles_rlc removed from KeyData
miha-stopar Nov 6, 2023
da1f991
nibbles_mult removed
miha-stopar Nov 6, 2023
44ed300
Test added
miha-stopar Nov 6, 2023
688e611
Working on extension being split into extension and branch
miha-stopar Nov 8, 2023
2c73d0b
Short ext. node is branch case implemented
miha-stopar Nov 9, 2023
91e0fcb
ModExtensionGadget implemented
miha-stopar Nov 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions circuit-benchmarks/src/bench_params.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub(crate) const DEGREE: usize = 19;
4 changes: 3 additions & 1 deletion zkevm-circuits/src/mpt_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mod branch;
mod extension;
mod extension_branch;
mod helpers;
mod mod_extension;
mod param;
mod rlp_gadgets;
mod start;
Expand Down Expand Up @@ -811,7 +812,8 @@ mod tests {

#[test]
fn test_mpt() {
let path = "src/mpt_circuit/tests";
// let path = "src/mpt_circuit/tests";
let path = "/Users/miha/projects/2appliedzkp/zkevm-circuits/zkevm-circuits/src/mpt_circuit/tests";
let files = fs::read_dir(path).unwrap();
files
.filter_map(Result::ok)
Expand Down
218 changes: 116 additions & 102 deletions zkevm-circuits/src/mpt_circuit/account_leaf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ pub(crate) struct AccountLeafConfig<F> {
is_balance_mod: IsEqualGadget<F>,
is_storage_mod: IsEqualGadget<F>,
is_codehash_mod: IsEqualGadget<F>,
is_mod_extension: [Cell<F>; 2],
}

impl<F: Field> AccountLeafConfig<F> {
Expand Down Expand Up @@ -140,6 +141,10 @@ impl<F: Field> AccountLeafConfig<F> {
);
let key_item = ctx.rlp_item(meta, cb, AccountRowType::Key as usize, RlpItemType::Hash);

for is_s in [true, false] {
config.is_mod_extension[is_s.idx()] = cb.query_bool();
}

config.main_data =
MainData::load("main storage", cb, &ctx.memory[main_memory()], 0.expr());

Expand All @@ -155,110 +160,111 @@ impl<F: Field> AccountLeafConfig<F> {
let mut leaf_no_key_rlc_mult = vec![0.expr(); 2];
let mut value_list_num_bytes = vec![0.expr(); 2];
for is_s in [true, false] {
// Key data
let key_data = &mut config.key_data[is_s.idx()];
*key_data = KeyData::load(cb, &ctx.memory[key_memory(is_s)], 0.expr());

// Parent data
let parent_data = &mut config.parent_data[is_s.idx()];
*parent_data = ParentData::load(
"account load",
cb,
&ctx.memory[parent_memory(is_s)],
0.expr(),
);

// Placeholder leaf checks
config.is_placeholder_leaf[is_s.idx()] =
IsPlaceholderLeafGadget::construct(cb, parent_data.hash.expr());

// Calculate the key RLC
let rlp_key = &mut config.rlp_key[is_s.idx()];
*rlp_key = ListKeyGadget::construct(cb, &key_items[is_s.idx()]);

let nonce_rlp_rlc;
let balance_rlp_rlc;
let storage_rlp_rlc;
let codehash_rlp_rlc;
(nonce[is_s.idx()], nonce_rlp_rlc) = (
nonce_items[is_s.idx()].word(),
nonce_items[is_s.idx()].rlc_chain_data(),
);
(balance[is_s.idx()], balance_rlp_rlc) = (
balance_items[is_s.idx()].word(),
balance_items[is_s.idx()].rlc_chain_data(),
);
(storage[is_s.idx()], storage_rlp_rlc) = (
storage_items[is_s.idx()].word(),
storage_items[is_s.idx()].rlc_chain_data(),
);
(codehash[is_s.idx()], codehash_rlp_rlc) = (
codehash_items[is_s.idx()].word(),
codehash_items[is_s.idx()].rlc_chain_data(),
);

// Calculate the leaf RLC
let keccak_r = &cb.keccak_r;
let value_rlp_bytes = config.value_rlp_bytes[is_s.idx()].to_expr_vec();
let value_list_rlp_bytes = config.value_list_rlp_bytes[is_s.idx()].to_expr_vec();
leaf_no_key_rlc[is_s.idx()] = value_rlp_bytes
.rlc_rev(keccak_r)
.rlc_chain_rev((
value_list_rlp_bytes.rlc_rev(keccak_r),
pow::expr(keccak_r.expr(), 2),
))
.rlc_chain_rev(nonce_rlp_rlc.clone())
.rlc_chain_rev(balance_rlp_rlc.clone())
.rlc_chain_rev(storage_rlp_rlc.clone())
.rlc_chain_rev(codehash_rlp_rlc.clone());
leaf_no_key_rlc_mult[is_s.idx()] = pow::expr(keccak_r.expr(), 4)
* nonce_rlp_rlc.1
* balance_rlp_rlc.1
* storage_rlp_rlc.1
* codehash_rlp_rlc.1;
let leaf_rlc = rlp_key.rlc2(&cb.keccak_r).rlc_chain_rev((
leaf_no_key_rlc[is_s.idx()].expr(),
leaf_no_key_rlc_mult[is_s.idx()].expr(),
));

// Key
key_rlc[is_s.idx()] = key_data.rlc.expr()
+ rlp_key.key.expr(
ifx! {not!(config.is_mod_extension[is_s.idx()].expr()) => {
// Key data
let key_data = &mut config.key_data[is_s.idx()];
*key_data = KeyData::load(cb, &ctx.memory[key_memory(is_s)], 0.expr());

// Parent data
let parent_data = &mut config.parent_data[is_s.idx()];
*parent_data = ParentData::load(
"account load",
cb,
rlp_key.key_value.clone(),
key_data.mult.expr(),
key_data.is_odd.expr(),
&cb.key_r.expr(),
&ctx.memory[parent_memory(is_s)],
0.expr(),
);
// Total number of nibbles needs to be KEY_LEN_IN_NIBBLES.
let num_nibbles =
num_nibbles::expr(rlp_key.key_value.len(), key_data.is_odd.expr());
require!(key_data.num_nibbles.expr() + num_nibbles.expr() => KEY_LEN_IN_NIBBLES);

// Check if the account is in its parent.
// Check is skipped for placeholder leaves which are dummy leaves
ifx! {not!(and::expr(&[not!(parent_data.is_placeholder), config.is_placeholder_leaf[is_s.idx()].expr()])) => {
let hash = parent_data.hash.expr();
require!(vec![1.expr(), leaf_rlc, rlp_key.rlp_list.num_bytes(), hash.lo(), hash.hi()] => @KECCAK);
}}

// Check the RLP encoding consistency.
// RLP encoding: account = [key, "[nonce, balance, storage, codehash]"]
// We always store between 55 and 256 bytes of data in the values list.
require!(value_rlp_bytes[0] => RLP_LONG + 1);
// The RLP encoded list always has 2 RLP bytes.
require!(value_rlp_bytes[1] => value_list_rlp_bytes[1].expr() + 2.expr());
// The first RLP byte of the list is always RLP_LIST_LONG + 1.
require!(value_list_rlp_bytes[0] => RLP_LIST_LONG + 1);
// The length of the list is `#(nonce) + #(balance) + 2 * (1 + #(hash))`.
require!(value_list_rlp_bytes[1] => nonce_items[is_s.idx()].num_bytes() + balance_items[is_s.idx()].num_bytes() + (2 * (1 + 32)).expr());
// Now check that the the key and value list length matches the account length.
// The RLP encoded string always has 2 RLP bytes.
value_list_num_bytes[is_s.idx()] = value_rlp_bytes[1].expr() + 2.expr();

// Account length needs to equal all key bytes and all values list bytes.
require!(config.rlp_key[is_s.idx()].rlp_list.len() => config.rlp_key[is_s.idx()].key_value.num_bytes() + value_list_num_bytes[is_s.idx()].expr());
// Placeholder leaf checks
config.is_placeholder_leaf[is_s.idx()] =
IsPlaceholderLeafGadget::construct(cb, parent_data.hash.expr());

// Calculate the key RLC
let rlp_key = &mut config.rlp_key[is_s.idx()];
*rlp_key = ListKeyGadget::construct(cb, &key_items[is_s.idx()]);

let nonce_rlp_rlc;
let balance_rlp_rlc;
let storage_rlp_rlc;
let codehash_rlp_rlc;
(nonce[is_s.idx()], nonce_rlp_rlc) = (
nonce_items[is_s.idx()].word(),
nonce_items[is_s.idx()].rlc_chain_data(),
);
(balance[is_s.idx()], balance_rlp_rlc) = (
balance_items[is_s.idx()].word(),
balance_items[is_s.idx()].rlc_chain_data(),
);
(storage[is_s.idx()], storage_rlp_rlc) = (
storage_items[is_s.idx()].word(),
storage_items[is_s.idx()].rlc_chain_data(),
);
(codehash[is_s.idx()], codehash_rlp_rlc) = (
codehash_items[is_s.idx()].word(),
codehash_items[is_s.idx()].rlc_chain_data(),
);

// Calculate the leaf RLC
let keccak_r = &cb.keccak_r;
let value_rlp_bytes = config.value_rlp_bytes[is_s.idx()].to_expr_vec();
let value_list_rlp_bytes = config.value_list_rlp_bytes[is_s.idx()].to_expr_vec();
leaf_no_key_rlc[is_s.idx()] = value_rlp_bytes
.rlc_rev(keccak_r)
.rlc_chain_rev((
value_list_rlp_bytes.rlc_rev(keccak_r),
pow::expr(keccak_r.expr(), 2),
))
.rlc_chain_rev(nonce_rlp_rlc.clone())
.rlc_chain_rev(balance_rlp_rlc.clone())
.rlc_chain_rev(storage_rlp_rlc.clone())
.rlc_chain_rev(codehash_rlp_rlc.clone());
leaf_no_key_rlc_mult[is_s.idx()] = pow::expr(keccak_r.expr(), 4)
* nonce_rlp_rlc.1
* balance_rlp_rlc.1
* storage_rlp_rlc.1
* codehash_rlp_rlc.1;
let leaf_rlc = rlp_key.rlc2(&cb.keccak_r).rlc_chain_rev((
leaf_no_key_rlc[is_s.idx()].expr(),
leaf_no_key_rlc_mult[is_s.idx()].expr(),
));

// Key
key_rlc[is_s.idx()] = key_data.rlc.expr()
+ rlp_key.key.expr(
cb,
rlp_key.key_value.clone(),
key_data.mult.expr(),
key_data.is_odd.expr(),
&cb.key_r.expr(),
);
// Total number of nibbles needs to be KEY_LEN_IN_NIBBLES.
let num_nibbles =
num_nibbles::expr(rlp_key.key_value.len(), key_data.is_odd.expr());
require!(key_data.num_nibbles.expr() + num_nibbles.expr() => KEY_LEN_IN_NIBBLES);

// Check if the account is in its parent.
// Check is skipped for placeholder leaves which are dummy leaves
ifx! {not!(and::expr(&[not!(parent_data.is_placeholder), config.is_placeholder_leaf[is_s.idx()].expr()])) => {
let hash = parent_data.hash.expr();
require!(vec![1.expr(), leaf_rlc, rlp_key.rlp_list.num_bytes(), hash.lo(), hash.hi()] => @KECCAK);
}}

// Check the RLP encoding consistency.
// RLP encoding: account = [key, "[nonce, balance, storage, codehash]"]
// We always store between 55 and 256 bytes of data in the values list.
require!(value_rlp_bytes[0] => RLP_LONG + 1);
// The RLP encoded list always has 2 RLP bytes.
require!(value_rlp_bytes[1] => value_list_rlp_bytes[1].expr() + 2.expr());
// The first RLP byte of the list is always RLP_LIST_LONG + 1.
require!(value_list_rlp_bytes[0] => RLP_LIST_LONG + 1);
// The length of the list is `#(nonce) + #(balance) + 2 * (1 + #(hash))`.
require!(value_list_rlp_bytes[1] => nonce_items[is_s.idx()].num_bytes() + balance_items[is_s.idx()].num_bytes() + (2 * (1 + 32)).expr());
// Now check that the the key and value list length matches the account length.
// The RLP encoded string always has 2 RLP bytes.
value_list_num_bytes[is_s.idx()] = value_rlp_bytes[1].expr() + 2.expr();

// Account length needs to equal all key bytes and all values list bytes.
require!(config.rlp_key[is_s.idx()].rlp_list.len() => config.rlp_key[is_s.idx()].key_value.num_bytes() + value_list_num_bytes[is_s.idx()].expr());
}};
// Key done, set the starting values
KeyData::store_defaults(cb, &ctx.memory[key_memory(is_s)]);
// Store the new parent
Expand Down Expand Up @@ -302,7 +308,7 @@ impl<F: Field> AccountLeafConfig<F> {
&mut cb.base,
config.main_data.proof_type.expr(),
MPTProofType::CodeHashChanged.expr(),
);
);

// Drifted leaf handling
config.drifted = DriftedGadget::construct(
Expand All @@ -314,6 +320,7 @@ impl<F: Field> AccountLeafConfig<F> {
&leaf_no_key_rlc,
&leaf_no_key_rlc_mult,
&drifted_bytes,
&config.is_mod_extension,
&cb.key_r.expr(),
);

Expand Down Expand Up @@ -465,7 +472,7 @@ impl<F: Field> AccountLeafConfig<F> {
let drifted_item = rlp_values[AccountRowType::Drifted as usize].clone();
let expected_item = rlp_values[AccountRowType::Wrong as usize].clone();
let address_item = rlp_values[AccountRowType::Address as usize].clone();
let _key_item = rlp_values[AccountRowType::Key as usize].clone();
let _key_item = rlp_values[AccountRowType::Key as usize].clone();

let main_data =
self.main_data
Expand All @@ -480,6 +487,12 @@ impl<F: Field> AccountLeafConfig<F> {
let mut key_data = vec![KeyDataWitness::default(); 2];
let mut parent_data = vec![ParentDataWitness::default(); 2];
for is_s in [true, false] {
self.is_mod_extension[is_s.idx()].assign(
region,
offset,
account.is_mod_extension[is_s.idx()].scalar(),
)?;

for (cell, byte) in self.value_rlp_bytes[is_s.idx()]
.iter()
.zip(account.value_rlp_bytes[is_s.idx()].iter())
Expand Down Expand Up @@ -545,6 +558,7 @@ impl<F: Field> AccountLeafConfig<F> {
F::ZERO,
F::ONE,
0,
F::ZERO,
)?;
ParentData::witness_store(
region,
Expand Down
5 changes: 4 additions & 1 deletion zkevm-circuits/src/mpt_circuit/branch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub(crate) struct BranchState<F> {
pub(crate) is_key_odd: Expression<F>,
pub(crate) mod_word: [Word<Expression<F>>; 2],
pub(crate) mod_rlc: [Expression<F>; 2],
pub(crate) drifted_index: Expression<F>,
}

#[derive(Clone, Debug, Default)]
Expand Down Expand Up @@ -273,6 +274,7 @@ impl<F: Field> BranchGadget<F> {
config.mod_rlc[true.idx()].expr(),
config.mod_rlc[false.idx()].expr(),
],
drifted_index,
});
});

Expand All @@ -299,7 +301,7 @@ impl<F: Field> BranchGadget<F> {
is_key_odd: &mut bool,
node: &Node,
rlp_values: &[RLPItemWitness],
) -> Result<(F, F, F, [word::Word<F>; 2], [F; 2]), Error> {
) -> Result<(F, F, F, [word::Word<F>; 2], [F; 2], F), Error> {
let branch = &node.extension_branch.clone().unwrap().branch;

for is_s in [true, false] {
Expand Down Expand Up @@ -395,6 +397,7 @@ impl<F: Field> BranchGadget<F> {
key_mult_post_branch,
mod_node_hash_word,
mod_node_hash_rlc,
F::from(branch.drifted_index as u64)
))
}
}
Loading
Loading