Constrain next row's stack length

This commit is contained in:
Hamy Ratoanina 2023-08-28 16:32:04 -04:00
parent a0b2b48992
commit 8beba56903
No known key found for this signature in database
GPG Key ID: 054683A21827F7C4
5 changed files with 46 additions and 12 deletions

View File

@ -247,8 +247,8 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for CpuStark<F, D
pc::eval_packed(local_values, yield_constr);
push0::eval_packed(local_values, yield_constr);
shift::eval_packed(local_values, yield_constr);
simple_logic::eval_packed(local_values, yield_constr);
stack::eval_packed(local_values, yield_constr);
simple_logic::eval_packed(local_values, next_values, yield_constr);
stack::eval_packed(local_values, next_values, yield_constr);
stack_bounds::eval_packed(local_values, yield_constr);
syscalls_exceptions::eval_packed(local_values, next_values, yield_constr);
}
@ -274,8 +274,8 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for CpuStark<F, D
pc::eval_ext_circuit(builder, local_values, yield_constr);
push0::eval_ext_circuit(builder, local_values, yield_constr);
shift::eval_ext_circuit(builder, local_values, yield_constr);
simple_logic::eval_ext_circuit(builder, local_values, yield_constr);
stack::eval_ext_circuit(builder, local_values, yield_constr);
simple_logic::eval_ext_circuit(builder, local_values, next_values, yield_constr);
stack::eval_ext_circuit(builder, local_values, next_values, yield_constr);
stack_bounds::eval_ext_circuit(builder, local_values, yield_constr);
syscalls_exceptions::eval_ext_circuit(builder, local_values, next_values, yield_constr);
}

View File

@ -75,8 +75,8 @@ pub fn eval_packed_jump_jumpi<P: PackedField>(
let is_jumpi = filter * lv.opcode_bits[0];
// Stack constraints.
stack::eval_packed_one(lv, is_jump, stack::JUMP_OP.unwrap(), yield_constr);
stack::eval_packed_one(lv, is_jumpi, stack::JUMPI_OP.unwrap(), yield_constr);
stack::eval_packed_one(lv, nv, is_jump, stack::JUMP_OP.unwrap(), yield_constr);
stack::eval_packed_one(lv, nv, is_jumpi, stack::JUMPI_OP.unwrap(), yield_constr);
// If `JUMP`, re-use the `JUMPI` logic, but setting the second input (the predicate) to be 1.
// In other words, we implement `JUMP(dst)` as `JUMPI(dst, cond=1)`.
@ -151,10 +151,18 @@ pub fn eval_ext_circuit_jump_jumpi<F: RichField + Extendable<D>, const D: usize>
let is_jumpi = builder.mul_extension(filter, lv.opcode_bits[0]);
// Stack constraints.
stack::eval_ext_circuit_one(builder, lv, is_jump, stack::JUMP_OP.unwrap(), yield_constr);
stack::eval_ext_circuit_one(
builder,
lv,
nv,
is_jump,
stack::JUMP_OP.unwrap(),
yield_constr,
);
stack::eval_ext_circuit_one(
builder,
lv,
nv,
is_jumpi,
stack::JUMPI_OP.unwrap(),
yield_constr,

View File

@ -51,6 +51,7 @@ pub fn generate_pinv_diff<F: Field>(val0: U256, val1: U256, lv: &mut CpuColumnsV
pub fn eval_packed<P: PackedField>(
lv: &CpuColumnsView<P>,
nv: &CpuColumnsView<P>,
yield_constr: &mut ConstraintConsumer<P>,
) {
let logic = lv.general.logic();
@ -94,9 +95,10 @@ pub fn eval_packed<P: PackedField>(
yield_constr.constraint(eq_or_iszero_filter * (dot - unequal));
// Stack constraints.
stack::eval_packed_one(lv, eq_filter, EQ_STACK_BEHAVIOR.unwrap(), yield_constr);
stack::eval_packed_one(lv, nv, eq_filter, EQ_STACK_BEHAVIOR.unwrap(), yield_constr);
stack::eval_packed_one(
lv,
nv,
iszero_filter,
IS_ZERO_STACK_BEHAVIOR.unwrap(),
yield_constr,
@ -106,6 +108,7 @@ pub fn eval_packed<P: PackedField>(
pub fn eval_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
builder: &mut plonky2::plonk::circuit_builder::CircuitBuilder<F, D>,
lv: &CpuColumnsView<ExtensionTarget<D>>,
nv: &CpuColumnsView<ExtensionTarget<D>>,
yield_constr: &mut RecursiveConstraintConsumer<F, D>,
) {
let zero = builder.zero_extension();
@ -173,6 +176,7 @@ pub fn eval_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
stack::eval_ext_circuit_one(
builder,
lv,
nv,
eq_filter,
EQ_STACK_BEHAVIOR.unwrap(),
yield_constr,
@ -180,6 +184,7 @@ pub fn eval_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
stack::eval_ext_circuit_one(
builder,
lv,
nv,
iszero_filter,
IS_ZERO_STACK_BEHAVIOR.unwrap(),
yield_constr,

View File

@ -11,17 +11,19 @@ use crate::cpu::columns::CpuColumnsView;
pub fn eval_packed<P: PackedField>(
lv: &CpuColumnsView<P>,
nv: &CpuColumnsView<P>,
yield_constr: &mut ConstraintConsumer<P>,
) {
not::eval_packed(lv, yield_constr);
eq_iszero::eval_packed(lv, yield_constr);
eq_iszero::eval_packed(lv, nv, yield_constr);
}
pub fn eval_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
builder: &mut plonky2::plonk::circuit_builder::CircuitBuilder<F, D>,
lv: &CpuColumnsView<ExtensionTarget<D>>,
nv: &CpuColumnsView<ExtensionTarget<D>>,
yield_constr: &mut RecursiveConstraintConsumer<F, D>,
) {
not::eval_ext_circuit(builder, lv, yield_constr);
eq_iszero::eval_ext_circuit(builder, lv, yield_constr);
eq_iszero::eval_ext_circuit(builder, lv, nv, yield_constr);
}

View File

@ -140,6 +140,7 @@ pub(crate) const IS_ZERO_STACK_BEHAVIOR: Option<StackBehavior> = BASIC_UNARY_OP;
pub(crate) fn eval_packed_one<P: PackedField>(
lv: &CpuColumnsView<P>,
nv: &CpuColumnsView<P>,
filter: P,
stack_behavior: StackBehavior,
yield_constr: &mut ConstraintConsumer<P>,
@ -185,15 +186,21 @@ pub(crate) fn eval_packed_one<P: PackedField>(
yield_constr.constraint(filter * channel.used);
}
}
// Constrain new stack length.
let num_pops = P::Scalar::from_canonical_usize(stack_behavior.num_pops);
let push = P::Scalar::from_canonical_usize(stack_behavior.pushes as usize);
yield_constr.constraint_transition(filter * (nv.stack_len - (lv.stack_len - num_pops + push)));
}
pub fn eval_packed<P: PackedField>(
lv: &CpuColumnsView<P>,
nv: &CpuColumnsView<P>,
yield_constr: &mut ConstraintConsumer<P>,
) {
for (op, stack_behavior) in izip!(lv.op.into_iter(), STACK_BEHAVIORS.into_iter()) {
if let Some(stack_behavior) = stack_behavior {
eval_packed_one(lv, op, stack_behavior, yield_constr);
eval_packed_one(lv, nv, op, stack_behavior, yield_constr);
}
}
}
@ -201,6 +208,7 @@ pub fn eval_packed<P: PackedField>(
pub(crate) fn eval_ext_circuit_one<F: RichField + Extendable<D>, const D: usize>(
builder: &mut plonky2::plonk::circuit_builder::CircuitBuilder<F, D>,
lv: &CpuColumnsView<ExtensionTarget<D>>,
nv: &CpuColumnsView<ExtensionTarget<D>>,
filter: ExtensionTarget<D>,
stack_behavior: StackBehavior,
yield_constr: &mut RecursiveConstraintConsumer<F, D>,
@ -298,16 +306,27 @@ pub(crate) fn eval_ext_circuit_one<F: RichField + Extendable<D>, const D: usize>
yield_constr.constraint(builder, constr);
}
}
// Constrain new stack length.
let diff = builder.constant_extension(
F::Extension::from_canonical_usize(stack_behavior.num_pops)
- F::Extension::from_canonical_usize(stack_behavior.pushes as usize),
);
let diff = builder.sub_extension(lv.stack_len, diff);
let diff = builder.sub_extension(nv.stack_len, diff);
let constr = builder.mul_extension(filter, diff);
yield_constr.constraint_transition(builder, constr);
}
pub fn eval_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
builder: &mut plonky2::plonk::circuit_builder::CircuitBuilder<F, D>,
lv: &CpuColumnsView<ExtensionTarget<D>>,
nv: &CpuColumnsView<ExtensionTarget<D>>,
yield_constr: &mut RecursiveConstraintConsumer<F, D>,
) {
for (op, stack_behavior) in izip!(lv.op.into_iter(), STACK_BEHAVIORS.into_iter()) {
if let Some(stack_behavior) = stack_behavior {
eval_ext_circuit_one(builder, lv, op, stack_behavior, yield_constr);
eval_ext_circuit_one(builder, lv, nv, op, stack_behavior, yield_constr);
}
}
}