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

Commit

Permalink
Simplify Zero and One Words construction and Address compression (#1746)
Browse files Browse the repository at this point in the history
### Description

While reviewing #1699, I noticed some room to improve the ergonomics of
the words.

### Issue Link


### Type of change

New feature (non-breaking change which adds functionality)

### Contents

- Replaced the `address_word_to_expr` function with the `compress`
method so that we can compress a word directly without finding that
function to use.
- introduced `zero_f` and `one_f` to create zero and one for `Word<F>`.

### Rationale

I noticed that it is hard to create a `one()` and `zero()` method for
both `Word<Expression<F>>` and `Word<F>`. The compiler complains about
implementing duplicated methods. Since we already use `one()` and
`zero()` in many places for `Word<Expression<F>>`, I named `zero_f` and
`one_f` for the methods for `Word<F>`.
  • Loading branch information
ChihChengLiang committed Jan 31, 2024
1 parent b303b28 commit 7f35654
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 81 deletions.
9 changes: 0 additions & 9 deletions zkevm-circuits/src/evm_circuit/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,15 +449,6 @@ pub(crate) fn is_precompiled(address: &Address) -> bool {
address.0[0..19] == [0u8; 19] && (1..=9).contains(&address.0[19])
}

const BASE_128_BYTES: [u8; 32] = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];

/// convert address (h160) to single expression.
pub fn address_word_to_expr<F: Field>(address: Word<Expression<F>>) -> Expression<F> {
address.lo() + address.hi() * Expression::Constant(F::from_repr(BASE_128_BYTES).unwrap())
}

/// Helper struct to read rw operations from a step sequentially.
pub(crate) struct StepRws<'a> {
rws: &'a RwMap,
Expand Down
19 changes: 9 additions & 10 deletions zkevm-circuits/src/evm_circuit/util/constraint_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ use halo2_proofs::{
};

use super::{
address_word_to_expr, rlc, AccountAddress, CachedRegion, CellType, MemoryAddress,
StoredExpression, U64Cell,
rlc, AccountAddress, CachedRegion, CellType, MemoryAddress, StoredExpression, U64Cell,
};

// Max degree allowed in all expressions passing through the ConstraintBuilder.
Expand Down Expand Up @@ -859,7 +858,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> {
Target::TxAccessListAccount,
RwValues::new(
tx_id,
address_word_to_expr(account_address),
account_address.compress(),
0.expr(),
Word::zero(),
Word::from_lo_unchecked(value),
Expand All @@ -882,7 +881,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> {
Target::TxAccessListAccount,
RwValues::new(
tx_id,
address_word_to_expr(account_address),
account_address.compress(),
0.expr(),
Word::zero(),
Word::from_lo_unchecked(value.clone()),
Expand All @@ -905,7 +904,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> {
Target::TxAccessListAccountStorage,
RwValues::new(
tx_id,
address_word_to_expr(account_address),
account_address.compress(),
0.expr(),
storage_key,
value,
Expand All @@ -929,7 +928,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> {
Target::TxAccessListAccountStorage,
RwValues::new(
tx_id,
address_word_to_expr(account_address),
account_address.compress(),
0.expr(),
storage_key,
value.clone(),
Expand Down Expand Up @@ -994,7 +993,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> {
Target::Account,
RwValues::new(
0.expr(),
address_word_to_expr(account_address),
account_address.compress(),
field_tag.expr(),
Word::zero(),
value.clone(),
Expand All @@ -1017,7 +1016,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> {
Target::Account,
RwValues::new(
0.expr(),
address_word_to_expr(account_address),
account_address.compress(),
field_tag.expr(),
Word::zero(),
value,
Expand All @@ -1043,7 +1042,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> {
Target::Storage,
RwValues::new(
tx_id,
address_word_to_expr(account_address),
account_address.compress(),
0.expr(),
key,
value.clone(),
Expand All @@ -1069,7 +1068,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> {
Target::Storage,
RwValues::new(
tx_id,
address_word_to_expr(account_address),
account_address.compress(),
0.expr(),
key,
value,
Expand Down
54 changes: 19 additions & 35 deletions zkevm-circuits/src/mpt_circuit/account_leaf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,10 @@ impl<F: Field> AccountLeafConfig<F> {
require!(config.main_data.is_below_account => false);

let mut key_rlc = vec![0.expr(); 2];
let mut nonce = vec![Word::<Expression<F>>::new([0.expr(), 0.expr()]); 2];
let mut balance = vec![Word::<Expression<F>>::new([0.expr(), 0.expr()]); 2];
let mut storage = vec![Word::<Expression<F>>::new([0.expr(), 0.expr()]); 2];
let mut codehash = vec![Word::<Expression<F>>::new([0.expr(), 0.expr()]); 2];
let mut nonce = vec![Word::zero(); 2];
let mut balance = vec![Word::zero(); 2];
let mut storage = vec![Word::zero(); 2];
let mut codehash = vec![Word::zero(); 2];
let mut leaf_no_key_rlc = vec![0.expr(); 2];
let mut leaf_no_key_rlc_mult = vec![0.expr(); 2];
let mut value_list_num_bytes = vec![0.expr(); 2];
Expand Down Expand Up @@ -350,8 +350,7 @@ impl<F: Field> AccountLeafConfig<F> {
[
config.main_data.proof_type.expr(),
true.expr(),
address_item.word().lo()
+ address_item.word().hi() * pow::value::<F>(256.scalar(), 16),
address_item.word().compress(),
config.main_data.new_root.lo().expr(),
config.main_data.new_root.hi().expr(),
config.main_data.old_root.lo().expr(),
Expand Down Expand Up @@ -424,18 +423,15 @@ impl<F: Field> AccountLeafConfig<F> {
require!((1.expr(), address_item.bytes_le()[1..21].rlc(&cb.keccak_r), 20.expr(), key.lo(), key.hi()) =>> @KECCAK);
}
}};
let to_hi = Expression::<F>::Constant(pow::value::<F>(256.scalar(), 16));
let lo = address_item.word().lo();
let hi = address_item.word().hi() * to_hi;
let address = lo + hi;
let address = address_item.word().compress();

ifx! {not!(config.parent_data[false.idx()].is_placeholder) => {
ctx.mpt_table.constrain(
meta,
&mut cb.base,
address.clone(),
proof_type.clone(),
Word::<Expression<F>>::new([0.expr(), 0.expr()]),
Word::zero(),
config.main_data.new_root.expr(),
config.main_data.old_root.expr(),
Word::<Expression<F>>::new([new_value_lo, new_value_hi]),
Expand All @@ -447,10 +443,10 @@ impl<F: Field> AccountLeafConfig<F> {
&mut cb.base,
address,
proof_type,
Word::<Expression<F>>::new([0.expr(), 0.expr()]),
Word::zero(),
config.main_data.new_root.expr(),
config.main_data.old_root.expr(),
Word::<Expression<F>>::new([0.expr(), 0.expr()]),
Word::zero(),
Word::<Expression<F>>::new([old_value_lo, old_value_hi]),
);
}};
Expand Down Expand Up @@ -502,10 +498,10 @@ impl<F: Field> AccountLeafConfig<F> {

// Key
let mut key_rlc = vec![0.scalar(); 2];
let mut nonce = vec![Word::<F>::new([0.scalar(), 0.scalar()]); 2];
let mut balance = vec![Word::<F>::new([0.scalar(), 0.scalar()]); 2];
let mut storage = vec![Word::<F>::new([0.scalar(), 0.scalar()]); 2];
let mut codehash = vec![Word::<F>::new([0.scalar(), 0.scalar()]); 2];
let mut nonce = vec![Word::zero_f(); 2];
let mut balance = vec![Word::zero_f(); 2];
let mut storage = vec![Word::zero_f(); 2];
let mut codehash = vec![Word::zero_f(); 2];
let mut key_data = vec![KeyDataWitness::default(); 2];
let mut parent_data = vec![ParentDataWitness::default(); 2];
for is_s in [true, false] {
Expand Down Expand Up @@ -654,16 +650,13 @@ impl<F: Field> AccountLeafConfig<F> {
)?;

// Anything following this node is below the account
let lo = address_item.word::<F>().lo();
let hi: F = address_item.word::<F>().hi() * pow::value::<F>(256.scalar(), 16);
let address = lo + hi;
MainData::witness_store(
region,
offset,
&mut memory[main_memory()],
main_data.proof_type,
true,
address,
address_item.word().compress_f(),
main_data.new_root,
main_data.old_root,
)?;
Expand All @@ -678,20 +671,11 @@ impl<F: Field> AccountLeafConfig<F> {
} else if is_codehash_mod {
(MPTProofType::CodeHashChanged, codehash)
} else if is_account_delete_mod {
(
MPTProofType::AccountDestructed,
vec![Word::<F>::new([0.scalar(), 0.scalar()]); 2],
)
(MPTProofType::AccountDestructed, vec![Word::zero_f(); 2])
} else if is_non_existing_proof {
(
MPTProofType::AccountDoesNotExist,
vec![Word::<F>::new([0.scalar(), 0.scalar()]); 2],
)
(MPTProofType::AccountDoesNotExist, vec![Word::zero_f(); 2])
} else {
(
MPTProofType::Disabled,
vec![Word::<F>::new([0.scalar(), 0.scalar()]); 2],
)
(MPTProofType::Disabled, vec![Word::zero_f(); 2])
};

if account.is_mod_extension[0] || account.is_mod_extension[1] {
Expand All @@ -705,7 +689,7 @@ impl<F: Field> AccountLeafConfig<F> {

let mut new_value = value[false.idx()];
if parent_data[false.idx()].is_placeholder {
new_value = word::Word::<F>::new([0.scalar(), 0.scalar()]);
new_value = word::Word::zero_f();
}
mpt_config.mpt_table.assign_cached(
region,
Expand All @@ -714,7 +698,7 @@ impl<F: Field> AccountLeafConfig<F> {
address: Value::known(from_bytes::value(
&account.address.iter().cloned().rev().collect::<Vec<_>>(),
)),
storage_key: word::Word::<F>::new([0.scalar(), 0.scalar()]).into_value(),
storage_key: word::Word::zero_f().into_value(),
proof_type: Value::known(proof_type.scalar()),
new_root: main_data.new_root.into_value(),
old_root: main_data.old_root.into_value(),
Expand Down
2 changes: 1 addition & 1 deletion zkevm-circuits/src/mpt_circuit/branch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ impl<F: Field> BranchGadget<F> {
let key_mult_post_branch = *key_mult * mult;

// Set the branch we'll take
let mut mod_node_hash_word = [word::Word::<F>::new([0.scalar(), 0.scalar()]); 2];
let mut mod_node_hash_word = [word::Word::zero_f(); 2];
let mut mod_node_hash_rlc = [0.scalar(); 2];
for is_s in [true, false] {
(
Expand Down
2 changes: 1 addition & 1 deletion zkevm-circuits/src/mpt_circuit/extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ impl<F: Field> ExtensionGadget<F> {
require!((FixedTableTag::ExtOddKey.expr(), first_byte, config.is_key_part_odd.expr()) =>> @FIXED);

let mut branch_rlp_rlc = vec![0.expr(); 2];
let mut branch_rlp_word = vec![Word::<Expression<F>>::new([0.expr(), 0.expr()]); 2];
let mut branch_rlp_word = vec![Word::zero(); 2];
for is_s in [true, false] {
// In C we have the key nibbles, we check below only for S.
if is_s {
Expand Down
4 changes: 2 additions & 2 deletions zkevm-circuits/src/mpt_circuit/extension_branch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ impl<F: Field> ExtensionBranchConfig<F> {
branch.mod_rlc[is_s.idx()].expr(),
false.expr(),
false.expr(),
Word::<Expression<F>>::new([0.expr(), 0.expr()])
Word::zero(),
);
} elsex {
KeyData::store(
Expand Down Expand Up @@ -287,7 +287,7 @@ impl<F: Field> ExtensionBranchConfig<F> {
mod_node_hash_rlc[is_s.idx()],
false,
false,
Word::<F>::new([0.scalar(), 0.scalar()]),
Word::zero_f(),
)?;
} else {
KeyData::witness_store(
Expand Down
7 changes: 2 additions & 5 deletions zkevm-circuits/src/mpt_circuit/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1081,11 +1081,8 @@ impl<F: Field> IsPlaceholderLeafGadget<F> {
Expression::Constant(empty_hash.hi()),
]),
);
let is_nil_in_branch_at_mod_index = IsEqualWordGadget::construct(
&mut cb.base,
&parent_word,
&Word::<Expression<F>>::new([0.expr(), 0.expr()]),
);
let is_nil_in_branch_at_mod_index =
IsEqualWordGadget::construct(&mut cb.base, &parent_word, &Word::zero());

Self {
is_empty_trie,
Expand Down
4 changes: 2 additions & 2 deletions zkevm-circuits/src/mpt_circuit/start.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ impl<F: Field> StartConfig<F> {

config.proof_type = cb.query_cell();

let mut root = vec![Word::new([0.expr(), 0.expr()]); 2];
let mut root = vec![Word::zero(); 2];
for is_s in [true, false] {
root[is_s.idx()] = root_items[is_s.idx()].word();
}
Expand Down Expand Up @@ -96,7 +96,7 @@ impl<F: Field> StartConfig<F> {
self.proof_type
.assign(region, offset, start.proof_type.scalar())?;

let mut root = vec![Word::new([0.scalar(), 0.scalar()]); 2];
let mut root = vec![Word::zero_f(); 2];
for is_s in [true, false] {
root[is_s.idx()] = rlp_values[is_s.idx()].word();
}
Expand Down
14 changes: 7 additions & 7 deletions zkevm-circuits/src/mpt_circuit/storage_leaf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl<F: Field> StorageLeafConfig<F> {
require!(config.main_data.is_below_account => true);

let mut key_rlc = vec![0.expr(); 2];
let mut value_word = vec![Word::<Expression<F>>::new([0.expr(), 0.expr()]); 2];
let mut value_word = vec![Word::zero(); 2];
let mut value_rlp_rlc = vec![0.expr(); 2];
let mut value_rlp_rlc_mult = vec![0.expr(); 2];

Expand Down Expand Up @@ -179,7 +179,7 @@ impl<F: Field> StorageLeafConfig<F> {

// Placeholder leaves default to value `0`.
ifx! {is_placeholder_leaf => {
require!(value_word[is_s.idx()] => [0.expr(), 0.expr()]);
require!(value_word[is_s.idx()] => Word::zero());
}}

// Make sure the RLP encoding is correct.
Expand Down Expand Up @@ -207,11 +207,11 @@ impl<F: Field> StorageLeafConfig<F> {
ParentData::store(
cb,
&mut ctx.memory[parent_memory(is_s)],
word::Word::<Expression<F>>::new([0.expr(), 0.expr()]),
word::Word::zero(),
0.expr(),
true.expr(),
false.expr(),
word::Word::<Expression<F>>::new([0.expr(), 0.expr()]),
word::Word::zero(),
);
}

Expand Down Expand Up @@ -332,7 +332,7 @@ impl<F: Field> StorageLeafConfig<F> {
address_item.word(),
config.main_data.new_root.expr(),
config.main_data.old_root.expr(),
Word::<Expression<F>>::new([0.expr(), 0.expr()]),
Word::zero(),
value_word[true.idx()].clone(),
);
}};
Expand Down Expand Up @@ -373,7 +373,7 @@ impl<F: Field> StorageLeafConfig<F> {
let mut key_data = vec![KeyDataWitness::default(); 2];
let mut parent_data = vec![ParentDataWitness::default(); 2];
let mut key_rlc = vec![0.scalar(); 2];
let mut value_word = vec![Word::<F>::new([0.scalar(), 0.scalar()]); 2];
let mut value_word = vec![Word::zero_f(); 2];
for is_s in [true, false] {
self.is_mod_extension[is_s.idx()].assign(
region,
Expand Down Expand Up @@ -532,7 +532,7 @@ impl<F: Field> StorageLeafConfig<F> {

let mut new_value = value_word[false.idx()];
if parent_data[false.idx()].is_placeholder {
new_value = word::Word::<F>::new([0.scalar(), 0.scalar()]);
new_value = word::Word::zero_f();
}
mpt_config.mpt_table.assign_cached(
region,
Expand Down
Loading

0 comments on commit 7f35654

Please sign in to comment.