From 8beba56903381ff37bfff9aa8a3b7c6fe67d1b15 Mon Sep 17 00:00:00 2001 From: Hamy Ratoanina Date: Mon, 28 Aug 2023 16:32:04 -0400 Subject: [PATCH] Constrain next row's stack length --- evm/src/cpu/cpu_stark.rs | 8 ++++---- evm/src/cpu/jumps.rs | 14 +++++++++++--- evm/src/cpu/simple_logic/eq_iszero.rs | 7 ++++++- evm/src/cpu/simple_logic/mod.rs | 6 ++++-- evm/src/cpu/stack.rs | 23 +++++++++++++++++++++-- 5 files changed, 46 insertions(+), 12 deletions(-) diff --git a/evm/src/cpu/cpu_stark.rs b/evm/src/cpu/cpu_stark.rs index 7fd0c76f..5aa64c1a 100644 --- a/evm/src/cpu/cpu_stark.rs +++ b/evm/src/cpu/cpu_stark.rs @@ -247,8 +247,8 @@ impl, const D: usize> Stark for CpuStark, const D: usize> Stark for CpuStark( 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, 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, diff --git a/evm/src/cpu/simple_logic/eq_iszero.rs b/evm/src/cpu/simple_logic/eq_iszero.rs index f16901f5..7be021ca 100644 --- a/evm/src/cpu/simple_logic/eq_iszero.rs +++ b/evm/src/cpu/simple_logic/eq_iszero.rs @@ -51,6 +51,7 @@ pub fn generate_pinv_diff(val0: U256, val1: U256, lv: &mut CpuColumnsV pub fn eval_packed( lv: &CpuColumnsView

, + nv: &CpuColumnsView

, yield_constr: &mut ConstraintConsumer

, ) { let logic = lv.general.logic(); @@ -94,9 +95,10 @@ pub fn eval_packed( 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( pub fn eval_ext_circuit, const D: usize>( builder: &mut plonky2::plonk::circuit_builder::CircuitBuilder, lv: &CpuColumnsView>, + nv: &CpuColumnsView>, yield_constr: &mut RecursiveConstraintConsumer, ) { let zero = builder.zero_extension(); @@ -173,6 +176,7 @@ pub fn eval_ext_circuit, 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, const D: usize>( stack::eval_ext_circuit_one( builder, lv, + nv, iszero_filter, IS_ZERO_STACK_BEHAVIOR.unwrap(), yield_constr, diff --git a/evm/src/cpu/simple_logic/mod.rs b/evm/src/cpu/simple_logic/mod.rs index 03d2dd15..9b4e60b0 100644 --- a/evm/src/cpu/simple_logic/mod.rs +++ b/evm/src/cpu/simple_logic/mod.rs @@ -11,17 +11,19 @@ use crate::cpu::columns::CpuColumnsView; pub fn eval_packed( lv: &CpuColumnsView

, + nv: &CpuColumnsView

, yield_constr: &mut ConstraintConsumer

, ) { 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, const D: usize>( builder: &mut plonky2::plonk::circuit_builder::CircuitBuilder, lv: &CpuColumnsView>, + nv: &CpuColumnsView>, yield_constr: &mut RecursiveConstraintConsumer, ) { 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); } diff --git a/evm/src/cpu/stack.rs b/evm/src/cpu/stack.rs index 8ffc152d..198c76db 100644 --- a/evm/src/cpu/stack.rs +++ b/evm/src/cpu/stack.rs @@ -140,6 +140,7 @@ pub(crate) const IS_ZERO_STACK_BEHAVIOR: Option = BASIC_UNARY_OP; pub(crate) fn eval_packed_one( lv: &CpuColumnsView

, + nv: &CpuColumnsView

, filter: P, stack_behavior: StackBehavior, yield_constr: &mut ConstraintConsumer

, @@ -185,15 +186,21 @@ pub(crate) fn eval_packed_one( 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( lv: &CpuColumnsView

, + nv: &CpuColumnsView

, yield_constr: &mut ConstraintConsumer

, ) { 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( pub(crate) fn eval_ext_circuit_one, const D: usize>( builder: &mut plonky2::plonk::circuit_builder::CircuitBuilder, lv: &CpuColumnsView>, + nv: &CpuColumnsView>, filter: ExtensionTarget, stack_behavior: StackBehavior, yield_constr: &mut RecursiveConstraintConsumer, @@ -298,16 +306,27 @@ pub(crate) fn eval_ext_circuit_one, 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, const D: usize>( builder: &mut plonky2::plonk::circuit_builder::CircuitBuilder, lv: &CpuColumnsView>, + nv: &CpuColumnsView>, yield_constr: &mut RecursiveConstraintConsumer, ) { 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); } } }