-
Notifications
You must be signed in to change notification settings - Fork 40
refactor assert_satisfied_full
#649
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
Conversation
assert_satisfied_raw in assert_satisfied_full e2e tests
assert_satisfied_raw in assert_satisfied_full e2e testsassert_satisfied_full
|
|
||
| /// Allow LK Multiplicity's key to be used with `u64` and `GoldilocksExt2`. | ||
| pub trait LkMultiplicityKey: Copy + Clone + Debug + Eq + Hash + Send { | ||
| /// If key is u64, return Some(u64), otherwise None. |
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.
The other possibility is GoldilocksExt2?
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.
LkMultiplicity's key previously was just u64. From the e2e witness we also get case where we want key as GoldilocksExt2. To enable reuse of the same code in MockProver, the trait LkMultiplicityKey helps.
matthiasgoergens
left a comment
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.
Please see #793 for most of the suggestions that are also in the comments.
ceno_zkvm/src/scheme/mock_prover.rs
Outdated
| } | ||
| ROMType::And => { | ||
| let (a, b) = AndTable::unpack(key); | ||
| format!("Element: {a} < {b}") |
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.
| format!("Element: {a} < {b}") | |
| format!("Element: {a} && {b}") |
| "constraint system" | ||
|
|
||
| let (location, element) = if let Some(key) = key.to_u64() { | ||
| let location = if *count > 0 { |
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.
That seems pretty hacky?
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.
count is recorded to print errors in the following fashion:
# when you have Uint::new in construct while Value::new_unchecked in assign
LkMultiplicityError:
2 Lookups of U16 missing in assignments
Element: 0
# when you have Uint::new_unchecked in construct while Value::new in assign
LkMultiplicityError:
2 Lookups of U16 missing in constraint system
Element: 0But I agree this could be more self explaining. Instead of count being a signed int, it could be an enum, something like-
enum LkMultiplicityErrorCount {
MissingInAssignments(u64),
MissingInConstraintSystem(u64),
}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.
Yes. Perhaps something for the next PR?
| } | ||
| ROMType::Instruction => format!("PC: {key}"), | ||
| ( | ||
| if *count > 0 { |
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.
Looks like we use count in a pretty hacky way?
| println!("Error: {} constraints not satisfied", errors.len()); | ||
| println!("======================================================"); | ||
| if panic_on_error { | ||
| panic!("(Unexpected) Constraints not satisfied"); |
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.
If panic_on_error is set, we should probably put the full error message into the panic message? (In that case, we don't need to println the error message, just put it in the panic only.)
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.
Sometimes the errors can be a lot and it can go beyond the terminal lines limit (if it's set low) and the following default rust panic stderr line would not be easily visible or lost.
thread 'main' panicked at /Users/.../mock_prover.rs:919:9:
That's why the panic message was purposefully kept short summary so that when program terminates, it can be obvious it was a panic and at which line, and dev can look at logs before to learn more details about what caused "(Unexpected) Constraints not satisfied".
But if it doesn't seem helpful, for better code we can put everything in panic.
| multiplicity.borrow_mut()[rom_type as usize].insert(key, count); | ||
| } | ||
|
|
||
| /// Clone inner, expensive operation. |
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 seems all too complicated, but let me think a bit more about it. (We can merge first.)
Suggestions for #649
|
@matthiasgoergens Thanks for review and suggestion PR! |
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 now 👍
In summary
- in
assert_satisfied_raw, each opcode we extract raw value from rlc expression and checked with expected lookup multiplicity - in
assert_satisfied_full, the lookup value was in rlc format and so as table, and do rlc to rlc comparison.
some lefted TODO after this PR
- have better naming on
assert_satisfied_rawandassert_satisfied_full. E.g.assert_satisfied_full->assert_satisfied_zkvm - retain this debug message => this break down raw value is very useful, e.g. once program table lookup failed we can quickly targeting on the opcode.
ceno/ceno_zkvm/src/scheme/mock_prover.rs
Lines 900 to 930 in 1d7818e
// log mismatch error let witness = wit_mles .get(&circuit_name) .map(|mles| { mles.iter() .map(|mle| E::from(mle.get_base_field_vec()[row as usize])) .collect_vec() }) .unwrap(); let values = input_value_exprs .iter() .map(|expr| { eval_by_expr_with_instance( &[], &witness, &[], &instance, challenges.as_slice(), expr, ) .as_bases()[0] }) .collect_vec(); tracing::error!( "{}: value {:x?} mismatch lk_multiplicity: real {:x} > remaining {:x} in {:?} table", lk_input_annotation, values, input_multiplicity, table_multiplicity, rom_type, );
assert_satisfied_fullwhich enables additional missing checks for things like assert zero expressions.