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

Commit

Permalink
Add missing constraints mentioned by auditors (0xPolygonZero#1499)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nashtare authored Feb 5, 2024
1 parent af0259c commit 212f29c
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 2 deletions.
9 changes: 9 additions & 0 deletions evm/src/arithmetic/arithmetic_stark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for ArithmeticSta
yield_constr.constraint(flag * (flag - P::ONES));
}

// Only a single flag must be activated at once.
let all_flags = op_flags().map(|i| lv[i]).sum::<P>();
yield_constr.constraint(all_flags * (all_flags - P::ONES));

// Check that `OPCODE_COL` holds 0 if the operation is not a range_check.
let opcode_constraint = (P::ONES - lv[columns::IS_RANGE_CHECK]) * lv[columns::OPCODE_COL];
yield_constr.constraint(opcode_constraint);
Expand Down Expand Up @@ -261,6 +265,11 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for ArithmeticSta
yield_constr.constraint(builder, constraint);
}

// Only a single flag must be activated at once.
let all_flags = builder.add_many_extension(op_flags().map(|i| lv[i]));
let constraint = builder.mul_sub_extension(all_flags, all_flags, all_flags);
yield_constr.constraint(builder, constraint);

// Check that `OPCODE_COL` holds 0 if the operation is not a range_check.
let opcode_constraint = builder.arithmetic_extension(
F::NEG_ONE,
Expand Down
22 changes: 20 additions & 2 deletions evm/src/logic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,19 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for LogicStark<F,
{
let lv = vars.get_local_values();

// IS_AND, IS_OR, and IS_XOR come from the CPU table, so we assume they're valid.
let is_and = lv[columns::IS_AND];
let is_or = lv[columns::IS_OR];
let is_xor = lv[columns::IS_XOR];

// Flags must be boolean.
for &flag in &[is_and, is_or, is_xor] {
yield_constr.constraint(flag * (flag - P::ONES));
}

// Only a single flag must be activated at once.
let all_flags = is_and + is_or + is_xor;
yield_constr.constraint(all_flags * (all_flags - P::ONES));

// The result will be `in0 OP in1 = sum_coeff * (in0 + in1) + and_coeff * (in0 AND in1)`.
// `AND => sum_coeff = 0, and_coeff = 1`
// `OR => sum_coeff = 1, and_coeff = -1`
Expand Down Expand Up @@ -276,11 +284,21 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for LogicStark<F,
) {
let lv = vars.get_local_values();

// IS_AND, IS_OR, and IS_XOR come from the CPU table, so we assume they're valid.
let is_and = lv[columns::IS_AND];
let is_or = lv[columns::IS_OR];
let is_xor = lv[columns::IS_XOR];

// Flags must be boolean.
for &flag in &[is_and, is_or, is_xor] {
let constraint = builder.mul_sub_extension(flag, flag, flag);
yield_constr.constraint(builder, constraint);
}

// Only a single flag must be activated at once.
let all_flags = builder.add_many_extension([is_and, is_or, is_xor]);
let constraint = builder.mul_sub_extension(all_flags, all_flags, all_flags);
yield_constr.constraint(builder, constraint);

// The result will be `in0 OP in1 = sum_coeff * (in0 + in1) + and_coeff * (in0 AND in1)`.
// `AND => sum_coeff = 0, and_coeff = 1`
// `OR => sum_coeff = 1, and_coeff = -1`
Expand Down

0 comments on commit 212f29c

Please sign in to comment.