-
Notifications
You must be signed in to change notification settings - Fork 854
Add debug expr in EVMConstraintBuilder #1500
Conversation
Introduce the `debug_expression` method to the `EVMConstraintBuilder` which allows specifying an expression inside an ExecutionGadget to be evaluated and printed during assignment.
e77e7d7
to
ae37c38
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I tried it locally, and it works!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome! LGTM, only one nit.
// Set to true when we're assigning the next step before the current step to have | ||
// next step assignments for evaluation of the stored expressions in current step that | ||
// depend on the next step. | ||
is_next: bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will is_final
or is_final_step
be better? Or has_next
if final_step
is not accurate. I understand to use is
as prefix while it's a bool
type but in this case is_next
is not clear to know what it really means.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think is_final
or has_next
doesn't hold the real meaning here. Let me explain why I call this is_next
. Each step is assigned two times. The list of steps is iterated in a window of size 2 where we have (current_step, next_step), and we assign the next first and the current afterwards in each iteration. See
zkevm-circuits/zkevm-circuits/src/evm_circuit/execution.rs
Lines 1180 to 1206 in b6be489
// Also set the witness of the next step. | |
// These may be used in stored expressions and | |
// so their witness values need to be known to be able | |
// to correctly calculate the intermediate value. | |
if let Some((transaction_next, call_next, step_next)) = next { | |
self.assign_exec_step_int( | |
region, | |
offset + height, | |
block, | |
transaction_next, | |
call_next, | |
step_next, | |
true, | |
assign_pass, | |
)?; | |
} | |
self.assign_exec_step_int( | |
region, | |
offset, | |
block, | |
transaction, | |
call, | |
step, | |
false, | |
assign_pass, | |
) |
So if we have the steps [a, b, c] we pair them like (cur=a, next=b), (cur=b, next=c), (cur=c, next=None). And we do the following assignments:
- b (next)
- a (cur)
- b (cur)
- c (next)
- c (cur)
So here the is_next
means that we're assigning the next step before we assign the current steps for it's "side effects", but we'll go over and assign that step again later.
Do you have another suggestion instead of is_next
that conveys this meaning?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your explanation, is_next
makes sense to me now. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is nice proposed! Have try to use it and work like a charm!
Just have 2 suggestion
- can use
&'static str
type instead ofString
(as I understand it took extra heap copy) . - swap first and second parameter of
debug_expression(name, expr)
, as we used to havename
go first
Here is commit bc7a15d which apply above change. Feel free to cherry-pick it :)
Thanks for the suggestions! I've swapped the argument order so that name goes first. cb.debug_expression("tx_id", tx_id.expr());
```rust
or dynamic String cb.debug_expression(format!("limb{}", i), word.limbs[i].expr());
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for address the reviews! Into<String>
make sense to preserve more flexibility in debug purpose 👍
Description
Introduce the
debug_expression
method to theEVMConstraintBuilder
which allows specifying an expression inside an ExecutionGadget to be evaluated and printed during assignment.This can be very useful for debugging. With this we can print the value of cells, but also of arbitrary expressions. For example, it allows printing the evaluation of all the expressions used in a lookup (previous to the RLC).
Type of change
Contents
When calling
cb.debug_expression
, the expression is stored in theEVMConstraintBuilder
along with a string. Later on, at assignment, whenever a step is assigned to anExecutionState
that had some debug expressions specified, those expressions will be evaluated and printed.Example usage
In the
PushGadget::configure
method I include the following line:Then I run the a test that assigns this state (with
--nocapture
to see the stdout):And I will get the following: