mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-03 22:33:06 +00:00
Combine PUSH0 and PC flags. (#1256)
This commit is contained in:
parent
0d97b93af5
commit
6332900d86
@ -28,12 +28,8 @@ pub struct OpsColumnsView<T: Copy> {
|
||||
pub prover_input: T,
|
||||
/// Combines JUMP and JUMPI flags.
|
||||
pub jumps: T,
|
||||
/// Flag for PC.
|
||||
pub pc: T,
|
||||
/// Flag for JUMPDEST.
|
||||
pub jumpdest: T,
|
||||
/// Flag for PUSH0.
|
||||
pub push0: T,
|
||||
/// Flag for PUSH.
|
||||
pub push: T,
|
||||
/// Combines DUP and SWAP flags.
|
||||
@ -48,6 +44,8 @@ pub struct OpsColumnsView<T: Copy> {
|
||||
pub exit_kernel: T,
|
||||
/// Combines MSTORE_GENERAL and MLOAD_GENERAL flags.
|
||||
pub m_op_general: T,
|
||||
/// Combines PC and PUSH0
|
||||
pub pc_push0: T,
|
||||
|
||||
/// Flag for syscalls.
|
||||
pub syscall: T,
|
||||
|
||||
@ -8,7 +8,7 @@ use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer
|
||||
use crate::cpu::columns::{CpuColumnsView, COL_MAP};
|
||||
use crate::cpu::kernel::aggregator::KERNEL;
|
||||
|
||||
const NATIVE_INSTRUCTIONS: [usize; 15] = [
|
||||
const NATIVE_INSTRUCTIONS: [usize; 14] = [
|
||||
COL_MAP.op.binary_op,
|
||||
COL_MAP.op.ternary_op,
|
||||
COL_MAP.op.fp254_op,
|
||||
@ -19,9 +19,8 @@ const NATIVE_INSTRUCTIONS: [usize; 15] = [
|
||||
COL_MAP.op.keccak_general,
|
||||
COL_MAP.op.prover_input,
|
||||
// not JUMPS (possible need to jump)
|
||||
COL_MAP.op.pc,
|
||||
COL_MAP.op.pc_push0,
|
||||
COL_MAP.op.jumpdest,
|
||||
COL_MAP.op.push0,
|
||||
// not PUSH (need to increment by more than 1)
|
||||
COL_MAP.op.dup_swap,
|
||||
COL_MAP.op.context_op,
|
||||
|
||||
@ -23,7 +23,7 @@ use crate::cpu::columns::{CpuColumnsView, COL_MAP};
|
||||
/// behavior.
|
||||
/// Note: invalid opcodes are not represented here. _Any_ opcode is permitted to decode to
|
||||
/// `is_invalid`. The kernel then verifies that the opcode was _actually_ invalid.
|
||||
const OPCODES: [(u8, usize, bool, usize); 13] = [
|
||||
const OPCODES: [(u8, usize, bool, usize); 11] = [
|
||||
// (start index of block, number of top bits to check (log2), kernel-only, flag column)
|
||||
// ADD, MUL, SUB, DIV, MOD, LT, GT and BYTE flags are handled partly manually here, and partly through the Arithmetic table CTL.
|
||||
// ADDMOD, MULMOD and SUBMOD flags are handled partly manually here, and partly through the Arithmetic table CTL.
|
||||
@ -35,9 +35,7 @@ const OPCODES: [(u8, usize, bool, usize); 13] = [
|
||||
(0x21, 0, true, COL_MAP.op.keccak_general),
|
||||
(0x49, 0, true, COL_MAP.op.prover_input),
|
||||
(0x56, 1, false, COL_MAP.op.jumps), // 0x56-0x57
|
||||
(0x58, 0, false, COL_MAP.op.pc),
|
||||
(0x5b, 0, false, COL_MAP.op.jumpdest),
|
||||
(0x5f, 0, false, COL_MAP.op.push0),
|
||||
(0x60, 5, false, COL_MAP.op.push), // 0x60-0x7f
|
||||
(0x80, 5, false, COL_MAP.op.dup_swap), // 0x80-0x9f
|
||||
(0xee, 0, true, COL_MAP.op.mstore_32bytes),
|
||||
@ -50,7 +48,7 @@ const OPCODES: [(u8, usize, bool, usize); 13] = [
|
||||
/// List of combined opcodes requiring a special handling.
|
||||
/// Each index in the list corresponds to an arbitrary combination
|
||||
/// of opcodes defined in evm/src/cpu/columns/ops.rs.
|
||||
const COMBINED_OPCODES: [usize; 7] = [
|
||||
const COMBINED_OPCODES: [usize; 8] = [
|
||||
COL_MAP.op.logic_op,
|
||||
COL_MAP.op.fp254_op,
|
||||
COL_MAP.op.binary_op,
|
||||
@ -58,6 +56,7 @@ const COMBINED_OPCODES: [usize; 7] = [
|
||||
COL_MAP.op.shift,
|
||||
COL_MAP.op.m_op_general,
|
||||
COL_MAP.op.not_pop,
|
||||
COL_MAP.op.pc_push0,
|
||||
];
|
||||
|
||||
/// Break up an opcode (which is 8 bits long) into its eight bits.
|
||||
@ -148,6 +147,14 @@ pub fn eval_packed_generic<P: PackedField>(
|
||||
* lv.op.m_op_general;
|
||||
yield_constr.constraint(m_op_constr);
|
||||
|
||||
// Manually check lv.op.pc_push0.
|
||||
// Both PC and PUSH0 can be called outside of the kernel mode:
|
||||
// there is no need to constrain them in that regard.
|
||||
let pc_push0_constr = (opcode - P::Scalar::from_canonical_usize(0x58_usize))
|
||||
* (opcode - P::Scalar::from_canonical_usize(0x5f_usize))
|
||||
* lv.op.pc_push0;
|
||||
yield_constr.constraint(pc_push0_constr);
|
||||
|
||||
// Manually check lv.op.not_pop.
|
||||
// Both NOT and POP can be called outside of the kernel mode:
|
||||
// there is no need to constrain them in that regard.
|
||||
@ -260,6 +267,17 @@ pub fn eval_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
|
||||
|
||||
yield_constr.constraint(builder, m_op_constr);
|
||||
|
||||
// Manually check lv.op.pc_push0.
|
||||
// Both PC and PUSH0 can be called outside of the kernel mode:
|
||||
// there is no need to constrain them in that regard.
|
||||
let pc_opcode = builder.constant_extension(F::Extension::from_canonical_usize(0x58_usize));
|
||||
let push0_opcode = builder.constant_extension(F::Extension::from_canonical_usize(0x5f_usize));
|
||||
let pc_constr = builder.sub_extension(opcode, pc_opcode);
|
||||
let push0_constr = builder.sub_extension(opcode, push0_opcode);
|
||||
let mut pc_push0_constr = builder.mul_extension(pc_constr, push0_constr);
|
||||
pc_push0_constr = builder.mul_extension(pc_push0_constr, lv.op.pc_push0);
|
||||
yield_constr.constraint(builder, pc_push0_constr);
|
||||
|
||||
// Manually check lv.op.not_pop.
|
||||
// Both NOT and POP can be called outside of the kernel mode:
|
||||
// there is no need to constrain them in that regard.
|
||||
|
||||
@ -29,9 +29,8 @@ const SIMPLE_OPCODES: OpsColumnsView<Option<u32>> = OpsColumnsView {
|
||||
keccak_general: KERNEL_ONLY_INSTR,
|
||||
prover_input: KERNEL_ONLY_INSTR,
|
||||
jumps: None, // Combined flag handled separately.
|
||||
pc: G_BASE,
|
||||
pc_push0: G_BASE,
|
||||
jumpdest: G_JUMPDEST,
|
||||
push0: G_BASE,
|
||||
push: G_VERYLOW,
|
||||
dup_swap: G_VERYLOW,
|
||||
context_op: KERNEL_ONLY_INSTR,
|
||||
|
||||
@ -12,7 +12,8 @@ pub fn eval_packed<P: PackedField>(
|
||||
nv: &CpuColumnsView<P>,
|
||||
yield_constr: &mut ConstraintConsumer<P>,
|
||||
) {
|
||||
let filter = lv.op.pc;
|
||||
// `PUSH0`'s opcode is odd, while `PC`'s opcode is even.
|
||||
let filter = lv.op.pc_push0 * (P::ONES - lv.opcode_bits[0]);
|
||||
let new_stack_top = nv.mem_channels[0].value;
|
||||
yield_constr.constraint(filter * (new_stack_top[0] - lv.program_counter));
|
||||
for &limb in &new_stack_top[1..] {
|
||||
@ -28,7 +29,10 @@ pub fn eval_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
|
||||
nv: &CpuColumnsView<ExtensionTarget<D>>,
|
||||
yield_constr: &mut RecursiveConstraintConsumer<F, D>,
|
||||
) {
|
||||
let filter = lv.op.pc;
|
||||
// `PUSH0`'s opcode is odd, while `PC`'s opcode is even.
|
||||
let one = builder.one_extension();
|
||||
let mut filter = builder.sub_extension(one, lv.opcode_bits[0]);
|
||||
filter = builder.mul_extension(lv.op.pc_push0, filter);
|
||||
let new_stack_top = nv.mem_channels[0].value;
|
||||
{
|
||||
let diff = builder.sub_extension(new_stack_top[0], lv.program_counter);
|
||||
|
||||
@ -12,7 +12,8 @@ pub fn eval_packed<P: PackedField>(
|
||||
nv: &CpuColumnsView<P>,
|
||||
yield_constr: &mut ConstraintConsumer<P>,
|
||||
) {
|
||||
let filter = lv.op.push0;
|
||||
// `PUSH0`'s opcode is odd, while `PC`'s opcode is even.
|
||||
let filter = lv.op.pc_push0 * lv.opcode_bits[0];
|
||||
for limb in nv.mem_channels[0].value {
|
||||
yield_constr.constraint(filter * limb);
|
||||
}
|
||||
@ -26,7 +27,8 @@ pub fn eval_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
|
||||
nv: &CpuColumnsView<ExtensionTarget<D>>,
|
||||
yield_constr: &mut RecursiveConstraintConsumer<F, D>,
|
||||
) {
|
||||
let filter = lv.op.push0;
|
||||
// `PUSH0`'s opcode is odd, while `PC`'s opcode is even.
|
||||
let filter = builder.mul_extension(lv.op.pc_push0, lv.opcode_bits[0]);
|
||||
for limb in nv.mem_channels[0].value {
|
||||
let constr = builder.mul_extension(filter, limb);
|
||||
yield_constr.constraint(builder, constr);
|
||||
|
||||
@ -85,7 +85,7 @@ pub(crate) const STACK_BEHAVIORS: OpsColumnsView<Option<StackBehavior>> = OpsCol
|
||||
}),
|
||||
prover_input: None, // TODO
|
||||
jumps: None, // Depends on whether it's a JUMP or a JUMPI.
|
||||
pc: Some(StackBehavior {
|
||||
pc_push0: Some(StackBehavior {
|
||||
num_pops: 0,
|
||||
pushes: true,
|
||||
disable_other_channels: true,
|
||||
@ -95,11 +95,6 @@ pub(crate) const STACK_BEHAVIORS: OpsColumnsView<Option<StackBehavior>> = OpsCol
|
||||
pushes: false,
|
||||
disable_other_channels: true,
|
||||
}),
|
||||
push0: Some(StackBehavior {
|
||||
num_pops: 0,
|
||||
pushes: true,
|
||||
disable_other_channels: true,
|
||||
}),
|
||||
push: None, // TODO
|
||||
dup_swap: None,
|
||||
context_op: None,
|
||||
|
||||
@ -160,7 +160,6 @@ fn decode(registers: RegistersState, opcode: u8) -> Result<Operation, ProgramErr
|
||||
fn fill_op_flag<F: Field>(op: Operation, row: &mut CpuColumnsView<F>) {
|
||||
let flags = &mut row.op;
|
||||
*match op {
|
||||
Operation::Push(0) => &mut flags.push0,
|
||||
Operation::Push(1..) => &mut flags.push,
|
||||
Operation::Dup(_) | Operation::Swap(_) => &mut flags.dup_swap,
|
||||
Operation::Iszero | Operation::Eq => &mut flags.eq_iszero,
|
||||
@ -177,7 +176,7 @@ fn fill_op_flag<F: Field>(op: Operation, row: &mut CpuColumnsView<F>) {
|
||||
Operation::KeccakGeneral => &mut flags.keccak_general,
|
||||
Operation::ProverInput => &mut flags.prover_input,
|
||||
Operation::Jump | Operation::Jumpi => &mut flags.jumps,
|
||||
Operation::Pc => &mut flags.pc,
|
||||
Operation::Pc | Operation::Push(0) => &mut flags.pc_push0,
|
||||
Operation::Jumpdest => &mut flags.jumpdest,
|
||||
Operation::GetContext | Operation::SetContext => &mut flags.context_op,
|
||||
Operation::Mload32Bytes => &mut flags.mload_32bytes,
|
||||
@ -190,7 +189,7 @@ fn fill_op_flag<F: Field>(op: Operation, row: &mut CpuColumnsView<F>) {
|
||||
// Equal to the number of pops if an operation pops without pushing, and `None` otherwise.
|
||||
fn get_op_special_length(op: Operation) -> Option<usize> {
|
||||
let behavior_opt = match op {
|
||||
Operation::Push(0) => STACK_BEHAVIORS.push0,
|
||||
Operation::Push(0) | Operation::Pc => STACK_BEHAVIORS.pc_push0,
|
||||
Operation::Push(1..) => STACK_BEHAVIORS.push,
|
||||
Operation::Dup(_) | Operation::Swap(_) => STACK_BEHAVIORS.dup_swap,
|
||||
Operation::Iszero => IS_ZERO_STACK_BEHAVIOR,
|
||||
@ -211,7 +210,6 @@ fn get_op_special_length(op: Operation) -> Option<usize> {
|
||||
Operation::ProverInput => STACK_BEHAVIORS.prover_input,
|
||||
Operation::Jump => JUMP_OP,
|
||||
Operation::Jumpi => JUMPI_OP,
|
||||
Operation::Pc => STACK_BEHAVIORS.pc,
|
||||
Operation::Jumpdest => STACK_BEHAVIORS.jumpdest,
|
||||
Operation::GetContext | Operation::SetContext => None,
|
||||
Operation::Mload32Bytes => STACK_BEHAVIORS.mload_32bytes,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user