Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MPT review #9

Open
wants to merge 21 commits into
base: mpt-refactor
Choose a base branch
from
Open

Conversation

CeciliaZ030
Copy link

Copy link
Owner

@Brechtpd Brechtpd left a comment

Choose a reason for hiding this comment

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

Generally looks good! Just some suggestions and a missing is_long in the lookup table that needs some explanation/implementation to make it work.

Comment on lines +877 to +878
// Rlp prefixes table [rlp_tag, byte, is_string, is_short, is_verylong]
for ind in 0..=127 {
Copy link
Owner

Choose a reason for hiding this comment

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

Could you do this a bit more like in the witness generation with a match statement for example. Will be quite a bit shorter, less duplicated code (like setting the tag to the same value for each case) and that also uses the RLP constants like RLP_SHORT etc... so fewer magic values.

Comment on lines +52 to +54
is_string.expr(),
is_short.expr(),
is_very_long.expr()] => @"fixed"
Copy link
Owner

Choose a reason for hiding this comment

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

is_long seems to be missing? I think that's actually smart to only do 2 out of 3 in the lookup table because it saves a cell and you can deduce one of the three values e.g. is_long is 1 - is_short - is_very_long, but I don't see that being done so not sure what's up? :)

Copy link
Owner

@Brechtpd Brechtpd left a comment

Choose a reason for hiding this comment

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

I think you got the correct idea for the state machine selectors, but seems like the implementation is more complex than needed.

A table so it's easier to talk about:

row is_start is_branch is_account is_storage
0 1 0 0 0
1 0 0 0 0
2 0 1 0 0
3 0 0 0 0
4-23 0 0 0 0
24 0 0 1 0
... ... ... ... ....

So this is the current state of the circuit. The selectors for each node are enabled on each row correctly by the witness, but the circuit doesn't have any checks that enforces this.

So I think the only thing that really needs to be checked is that for e.g. the first row with a start node (which has StartRowType::Count rows) has zero's for all the state selectors on the next row, but on the 2nd row there is exactly one selector enabled again (can be any type, doesn't matter).

And because on each row we do check that the selectors are boolean, we can pretty much just brute-force this check

  • For all state selectors in the following rows up to RowType::Count, basically just sum all those selectors togethers and force the sum to be 0.
  • On the ``RowType::Countth, sum the selectors just on that row and check that it's 1`.

Easy solution, and pretty efficient.

The EVM circuit instead of doing the brute force method does do something similar you're trying to do here with counting down, so e.g.

row is_start is_branch is_account is_storage num_data_rows_left
0 1 0 0 0 0
1 0 0 0 0 StartRowType::Count - 1
2 0 1 0 0 0
3 0 0 0 0 BranchRowType::Count - 1

Where the number of data only rows are written into num_data_rows_left and then there's 2 cases:

  • num_data_rows_left == 0 -> A state selector needs to be enabled on the current row
  • num_data_rows_left != 0 -> All state selectors need to be disabled on the current row, and num_data_rows_left.cur() - 1 => num_data_rows_left.next().

@CeciliaZ030 CeciliaZ030 changed the title constrain ext_is_key_part_odd with fixed lookup MPT review Mar 18, 2023
@CeciliaZ030
Copy link
Author

I removed the unnecessary lookups as we discussed 😊 and added checks according to your table.
One thing is that I decided to leave Start -> Branch* -> Account -> Branch* -> Storage with q_row and q_node constraints because the current is_below_branch only make sure no account is beneath account. I feel like is better to have a set of holistic state machine constraints.

@Brechtpd
Copy link
Owner

One thing is that I decided to leave Start -> Branch* -> Account -> Branch* -> Storage with q_row and q_node constraints because the current is_below_branch only make sure no account is beneath account. I feel like is better to have a set of holistic state machine constraints.

We'll see. ;) I also think that generally you do indeed want to add these, but in this case it's a bit tricky to get right. Like Account -> Branch -> Storage is not the only option I believe, it's also possible to go directly Account -> Storage when there's only a single storage leaf. Same with the accounts I think.

These are all the valid transitions I think:

- Start -> Branch
- Start -> Account
- Start -> Start (for padding purposes)

- Branch -> Branch
- Branch -> Account
- Branch -> Storage
- Branch -> Start (doesn't make much sense, but because Start resets everything we can allow it)
- 
- Account -> Storage
- Account -> Start
- Account -> Branch

- Storage -> Start
- Storage -> X (could be made valid if we reset the necessary state as well)

So most transitions are actually allowed by the state machine itself, but we need checks elsewhere where we have more context what's going on to actually check if the transition make sense.

Copy link
Owner

@Brechtpd Brechtpd left a comment

Choose a reason for hiding this comment

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

Went over things pretty quickly but generally looking good!

Not sure why you kept the non-CachedRegion assign functions for now, but you can remove if you're done converting everything to the CachedRegion ones.

cells: Vec<Cell<F>>,
columns: Vec<CellColumn<F>>,
// branch ctxs
branch_ctxs: HashMap<String, CmContext<F>>,
Copy link
Owner

Choose a reason for hiding this comment

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

Isn't some kind of stack more convenient? So you can just push and pop contexts as needed without having to worry about parents and stuff.

@@ -180,9 +181,14 @@ impl<F: Field> MPTConfig<F> {
memory.allocate(meta, parent_memory(true));
memory.allocate(meta, main_memory());

let ctx = MPTContext {
let mut cb = MPTConstraintBuilder::new(33 + 10, None, power_of_randomness.clone());
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
let mut cb = MPTConstraintBuilder::new(33 + 10, None, power_of_randomness.clone());
let mut cb = MPTConstraintBuilder::new(9, None, power_of_randomness.clone());

This should be a good test so see if the expression splitting (and CachedRegion) is working correctly! (you may need to allocate some extra columns to the cell manager because this may need quite a few extra cells to store intermediate results).

Comment on lines +39 to +44
// Max degree allowed in all expressions passing through the ConstraintBuilder.
// It aims to cap `extended_k` to 2, which allows constraint degree to 2^2+1,
// but each ExecutionGadget has implicit selector degree 3, so here it only
// allows 2^2+1-3 = 2.
const MAX_DEGREE: usize = 5;
const IMPLICIT_DEGREE: usize = 3;
Copy link
Owner

Choose a reason for hiding this comment

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

This is EVM circuit specific so to generalize things don't use these anymore. Instead of MAX_DEGREE use max_degree as stored in the ConstraintBuilder. IMPLICIT_DEGREE you can drop completely, we shouldn't need it anymore.

@CeciliaZ030
Copy link
Author

Not sure why you kept the non-CachedRegion assign functions for now, but you can remove if you're done converting everything to the CachedRegion ones.

I tried to code in a way that if I break something I can use old things :) And I changed some of the names (like _CellManager with the dash) so I can change all occurance easily.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants