Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ members = [
"eth-types",
"external-tracer",
"mock",
"prover"
"prover",
"mpt"
]

[patch.crates-io]
Expand Down
17 changes: 17 additions & 0 deletions mpt/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "mpt"
version = "0.1.0"
edition = "2018"

[dependencies]
halo2_proofs = { version = "0.1.0-beta.1" }
itertools = "0.10.1"
num-bigint = "0.4.2"
num-traits = "0.2.14"
plotters = { version = "0.3.0", optional = true }
eth-types = { path = "../eth-types" }
lazy_static = "1.4"
keccak256 = { path = "../keccak256"}
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

126 changes: 126 additions & 0 deletions mpt/src/branch_hash_in_parent.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
use halo2_proofs::{
plonk::{Advice, Column, ConstraintSystem, Expression, Fixed},
poly::Rotation,
};
use eth_types::Field;
use std::marker::PhantomData;

use crate::{
helpers::get_is_extension_node,
param::{KECCAK_INPUT_WIDTH, KECCAK_OUTPUT_WIDTH, IS_BRANCH_S_PLACEHOLDER_POS, IS_BRANCH_C_PLACEHOLDER_POS, RLP_NUM}, mpt::MainCols,
};

#[derive(Clone, Debug)]
pub(crate) struct BranchHashInParentConfig<F> {
_marker: PhantomData<F>,
}

impl<F: Field> BranchHashInParentConfig<F> {
pub fn configure(
meta: &mut ConstraintSystem<F>,
inter_root: Column<Advice>,
not_first_level: Column<Advice>,
q_not_first: Column<Fixed>,
is_account_leaf_in_added_branch: Column<Advice>,
is_last_branch_child: Column<Advice>,
s_main: MainCols,
mod_node_hash_rlc: Column<Advice>,
acc: Column<Advice>,
acc_mult: Column<Advice>,
keccak_table: [Column<Fixed>; KECCAK_INPUT_WIDTH + KECCAK_OUTPUT_WIDTH],
is_s: bool,
) -> Self {
let config = BranchHashInParentConfig { _marker: PhantomData, };
let one = Expression::Constant(F::from(1_u64));

meta.lookup_any(
"account first level branch hash - compared to root",
|meta| {
let mut constraints = vec![];
let q_not_first = meta.query_fixed(q_not_first, Rotation::cur());
let not_first_level = meta.query_advice(not_first_level, Rotation::cur());

let is_last_branch_child = meta.query_advice(is_last_branch_child, Rotation::cur());

// TODO: acc currently doesn't have branch ValueNode info (which 128 if nil)
let acc = meta.query_advice(acc, Rotation::cur());
let c128 = Expression::Constant(F::from(128));
let mult = meta.query_advice(acc_mult, Rotation::cur());
let branch_acc = acc + c128 * mult;

let root = meta.query_advice(inter_root, Rotation::cur());

constraints.push((
q_not_first.clone()
* is_last_branch_child.clone()
* (one.clone() - not_first_level.clone())
* branch_acc, // TODO: replace with acc once ValueNode is added
meta.query_fixed(keccak_table[0], Rotation::cur()),
));
let keccak_table_i = meta.query_fixed(keccak_table[1], Rotation::cur());
constraints.push((
q_not_first * is_last_branch_child * (one.clone() - not_first_level) * root,
keccak_table_i,
));

constraints
},
);

// Check whether hash of a branch is in parent branch.
// Check if (accumulated_s(c)_rlc, hash1, hash2, hash3, hash4) is in keccak
// table, where hash1, hash2, hash3, hash4 are stored in the previous
// branch and accumulated_s(c)_rlc presents the branch RLC.
meta.lookup_any("branch_hash_in_parent", |meta| {
let not_first_level = meta.query_advice(not_first_level, Rotation::cur());

// -17 because we are in the last branch child (-16 takes us to branch init)
let is_account_leaf_in_added_branch_prev =
meta.query_advice(is_account_leaf_in_added_branch, Rotation(-17));

// We need to do the lookup only if we are in the last branch child.
let is_last_branch_child = meta.query_advice(is_last_branch_child, Rotation::cur());

// When placeholder branch, we don't check its hash in a parent.
let mut is_branch_placeholder = meta.query_advice(s_main.bytes[IS_BRANCH_S_PLACEHOLDER_POS - RLP_NUM], Rotation(-16));
if !is_s {
is_branch_placeholder = meta.query_advice(s_main.bytes[IS_BRANCH_C_PLACEHOLDER_POS - RLP_NUM], Rotation(-16));
}

let is_extension_node = get_is_extension_node(meta, s_main.bytes, -16);

// TODO: acc currently doesn't have branch ValueNode info (which 128 if nil)
let acc = meta.query_advice(acc, Rotation::cur());
let c128 = Expression::Constant(F::from(128));
let mult = meta.query_advice(acc_mult, Rotation::cur());
let branch_acc = acc + c128 * mult;

let mut constraints = vec![(
not_first_level.clone()
* is_last_branch_child.clone()
* (one.clone() - is_account_leaf_in_added_branch_prev.clone()) // we don't check this in the first storage level
* (one.clone() - is_branch_placeholder.clone())
* (one.clone() - is_extension_node.clone())
* branch_acc, // TODO: replace with acc once ValueNode is added
meta.query_fixed(keccak_table[0], Rotation::cur()),
)];
// Any rotation that lands into branch can be used instead of -19.
let mod_node_hash_rlc_cur = meta.query_advice(mod_node_hash_rlc, Rotation(-19));
let keccak_table_i = meta.query_fixed(keccak_table[1], Rotation::cur());
constraints.push((
not_first_level
* is_last_branch_child
* (one.clone()
- is_account_leaf_in_added_branch_prev) // we don't check this in the first storage level
* (one.clone() - is_branch_placeholder)
* (one.clone() - is_extension_node)
* mod_node_hash_rlc_cur,
keccak_table_i,
));

constraints
});

config
}
}
81 changes: 81 additions & 0 deletions mpt/src/branch_rlc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use halo2_proofs::{
plonk::{Advice, Column, ConstraintSystem, Expression, VirtualCells},
poly::Rotation,
};
use eth_types::Field;
use std::marker::PhantomData;

use crate::{param::{HASH_WIDTH, R_TABLE_LEN}, mpt::MainCols};

#[derive(Clone, Debug)]
pub(crate) struct BranchRLCConfig<F> {
_marker: PhantomData<F>,
}

// BranchRLCChip verifies the random linear combination for the branch which is
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that branch_rlc_init works for S and C, but branch_rlc only works for one (S or C). Why this? I think that is going to be more clear to have a unique branch_rlc ( that are instantiated twice, one for S and other for C) that also includes init branch row.

// then used to check the hash of a branch.
impl<F: Field> BranchRLCConfig<F> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Config or Chip? IMO makes more sense if is Chip

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it suffices to have Config. Or do you think it's better to have Chips?

pub fn configure(
meta: &mut ConstraintSystem<F>,
q_enable: impl FnOnce(&mut VirtualCells<'_, F>) -> Expression<F>,
main: MainCols,
branch_acc: Column<Advice>,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is called acc_s in branch_rlc_init.rs, what about renaming it to acc? (or renaming it in branch_rlc_init.rs to branch_acc_s ?)

branch_mult: Column<Advice>,
r_table: Vec<Expression<F>>,
) -> BranchRLCConfig<F> {
let config = BranchRLCConfig { _marker: PhantomData, };

meta.create_gate("branch acc", |meta| {
let q_enable = q_enable(meta);

let mut constraints = vec![];
let rlp2 = meta.query_advice(main.rlp2, Rotation::cur());
let branch_acc_prev = meta.query_advice(branch_acc, Rotation::prev());
let branch_acc_cur = meta.query_advice(branch_acc, Rotation::cur());
let branch_mult_prev = meta.query_advice(branch_mult, Rotation::prev());
let branch_mult_cur = meta.query_advice(branch_mult, Rotation::cur());

let c128 = Expression::Constant(F::from(128_u64));
let c160 = Expression::Constant(F::from(160_u64));

// empty:
// branch_acc_curr = branch_acc_prev + 128 * branch_mult_prev
constraints.push((
"branch acc empty",
q_enable.clone()
* (c160.clone() - rlp2.clone())
* (branch_acc_cur.clone()
- branch_acc_prev.clone()
- c128 * branch_mult_prev.clone()),
));
constraints.push((
"branch acc mult empty",
q_enable.clone()
* (c160.clone() - rlp2.clone())
* (branch_mult_cur.clone() - branch_mult_prev.clone() * r_table[0].clone()),
));

// non-empty
let mut expr = c160 * branch_mult_prev.clone();
for (ind, col) in main.bytes.iter().enumerate() {
let s = meta.query_advice(*col, Rotation::cur());
expr = expr + s * branch_mult_prev.clone() * r_table[ind].clone();
}
constraints.push((
"branch acc non-empty",
q_enable.clone() * rlp2.clone() * (branch_acc_cur - branch_acc_prev - expr),
));
constraints.push((
"branch acc mult non-empty",
q_enable
* rlp2
* (branch_mult_cur
- branch_mult_prev * r_table[R_TABLE_LEN - 1].clone() * r_table[0].clone()),
));

constraints
});

config
}
}
Loading