Skip to content

Commit

Permalink
Update PROVER_INPUT opcode value (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nashtare authored Feb 18, 2024
1 parent f4554b7 commit de03ac3
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 47 deletions.
4 changes: 2 additions & 2 deletions docs/arithmetization/cpulogic.tex
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,15 @@ \subsection{Privileged instructions}
\item[0x21.] \texttt{KECCAK\_GENERAL}. Pops 2 elements (a Memory address, followed by a length $\ell$) and pushes the hash of the memory portion starting at the
constructed address and of length $\ell$. It is similar to KECCAK256 (0x20) instruction, but can be applied to any memory section (i.e. even privileged ones).

\item[0x49.] \texttt{PROVER\_INPUT}. Pushes a single prover input onto the stack.

\item[0xC0-0xDF.] \texttt{MSTORE\_32BYTES}. Pops 2 elements from the stack (a Memory address, and then a value), and pushes
a new address' onto the stack. The value is being decomposed into bytes and written to memory, starting from the fetched address. The new address being pushed is computed as the
initial address + the length of the byte sequence being written to memory. Note that similarly to PUSH (0x60-0x7F) instructions, there are 32 MSTORE\_32BYTES instructions, each
corresponding to a target byte length (length 0 is ignored, for the same reasons as MLOAD\_32BYTES, see below). Writing to memory an integer fitting in $n$ bytes with a length $\ell < n$ will
result in the integer being truncated. On the other hand, specifying a length $\ell$ greater than the byte size of the value being written will result in padding with zeroes. This
process is heavily used when resetting memory sections (by calling MSTORE\_32BYTES\_32 with the value 0).

\item[0xEE.] \texttt{PROVER\_INPUT}. Pushes a single prover input onto the stack.

\item[0xF6.] \texttt{GET\_CONTEXT}. Pushes the current context onto the stack. The kernel always has context 0.

\item[0xF7.] \texttt{SET\_CONTEXT}. Pops the top element of the stack and updates the current context to this value. It is usually used when calling another contract or precompile,
Expand Down
8 changes: 2 additions & 6 deletions evm_arithmetization/src/cpu/control_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub(crate) fn eval_packed_generic<P: PackedField>(
.constraint_transition(is_native_instruction * (lv.is_kernel_mode - nv.is_kernel_mode));

// Apply the same checks as before, for PROVER_INPUT.
let is_prover_input: P = lv.op.push_prover_input * (lv.opcode_bits[5] - P::ONES);
let is_prover_input: P = lv.op.push_prover_input * lv.opcode_bits[7];
yield_constr.constraint_transition(
is_prover_input * (lv.program_counter - nv.program_counter + P::ONES),
);
Expand Down Expand Up @@ -129,11 +129,7 @@ pub(crate) fn eval_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
yield_constr.constraint_transition(builder, kernel_constr);

// Same constraints as before, for PROVER_INPUT.
let is_prover_input = builder.mul_sub_extension(
lv.op.push_prover_input,
lv.opcode_bits[5],
lv.op.push_prover_input,
);
let is_prover_input = builder.mul_extension(lv.op.push_prover_input, lv.opcode_bits[7]);
let pc_constr = builder.mul_add_extension(is_prover_input, pc_diff, is_prover_input);
yield_constr.constraint_transition(builder, pc_constr);
let kernel_constr = builder.mul_extension(is_prover_input, kernel_diff);
Expand Down
13 changes: 7 additions & 6 deletions evm_arithmetization/src/cpu/cpu_stark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,7 @@ pub(crate) fn ctl_arithmetic_base_rows<F: Field>() -> TableWithColumns<F> {
// (also `ops` is used as the operation filter). The list of
// operations includes binary operations which will simply ignore
// the third input.
let col_bit = Column::linear_combination_with_constant(
vec![(COL_MAP.opcode_bits[5], F::NEG_ONE)],
F::ONE,
);
let col_bit = Column::single(COL_MAP.opcode_bits[7]);
TableWithColumns::new(
*Table::Cpu,
columns,
Expand Down Expand Up @@ -263,9 +260,13 @@ pub(crate) fn ctl_data_byte_packing_push<F: Field>() -> Vec<Column<F>> {

/// CTL filter for the `PUSH` operation.
pub(crate) fn ctl_filter_byte_packing_push<F: Field>() -> Filter<F> {
let bit_col = Column::single(COL_MAP.opcode_bits[5]);
let col_bit = Column::linear_combination_with_constant(
vec![(COL_MAP.opcode_bits[7], F::NEG_ONE)],
F::ONE,
);

Filter::new(
vec![(Column::single(COL_MAP.op.push_prover_input), bit_col)],
vec![(Column::single(COL_MAP.op.push_prover_input), col_bit)],
vec![],
)
}
Expand Down
15 changes: 5 additions & 10 deletions evm_arithmetization/src/cpu/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,11 @@ pub(crate) fn eval_packed_generic<P: PackedField>(

// Manually check PUSH and PROVER_INPUT.
// PROVER_INPUT is a kernel-only instruction, but not PUSH.
let push_prover_input_constr = (opcode - P::Scalar::from_canonical_usize(0x49_usize))
let push_prover_input_constr = (opcode - P::Scalar::from_canonical_usize(0xee_usize))
* (opcode_high_three - P::Scalar::from_canonical_usize(0x60_usize))
* lv.op.push_prover_input;
yield_constr.constraint(push_prover_input_constr);
let prover_input_constr =
lv.op.push_prover_input * (lv.opcode_bits[5] - P::ONES) * (P::ONES - kernel_mode);
let prover_input_constr = lv.op.push_prover_input * lv.opcode_bits[7] * (P::ONES - kernel_mode);
yield_constr.constraint(prover_input_constr);
}

Expand Down Expand Up @@ -389,20 +388,16 @@ pub(crate) fn eval_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
// Manually check PUSH and PROVER_INPUT.
// PROVER_INPUT is a kernel-only instruction, but not PUSH.
let prover_input_opcode =
builder.constant_extension(F::Extension::from_canonical_usize(0x49usize));
let push_opcodes = builder.constant_extension(F::Extension::from_canonical_usize(0x60usize));
builder.constant_extension(F::Extension::from_canonical_usize(0xee_usize));
let push_opcodes = builder.constant_extension(F::Extension::from_canonical_usize(0x60_usize));

let push_constr = builder.sub_extension(opcode_high_three, push_opcodes);
let prover_input_constr = builder.sub_extension(opcode, prover_input_opcode);

let push_prover_input_constr =
builder.mul_many_extension([lv.op.push_prover_input, prover_input_constr, push_constr]);
yield_constr.constraint(builder, push_prover_input_constr);
let prover_input_filter = builder.mul_sub_extension(
lv.op.push_prover_input,
lv.opcode_bits[5],
lv.op.push_prover_input,
);
let prover_input_filter = builder.mul_extension(lv.op.push_prover_input, lv.opcode_bits[7]);
let constr = builder.mul_extension(prover_input_filter, is_not_kernel_mode);
yield_constr.constraint(builder, constr);
}
16 changes: 8 additions & 8 deletions evm_arithmetization/src/cpu/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,11 @@ fn eval_packed_accumulate<P: PackedField>(
);

// For PROVER_INPUT and PUSH operations.
// PUSH operations are differentiated from PROVER_INPUT by their 6th bit set to
// PUSH operations are differentiated from PROVER_INPUT by their 8th bit set to
// 1.
let push_prover_input_gas_cost = lv.opcode_bits[5]
let push_prover_input_gas_cost = (P::ONES - lv.opcode_bits[7])
* P::Scalar::from_canonical_u32(G_VERYLOW.unwrap())
+ (P::ONES - lv.opcode_bits[5]) * P::Scalar::from_canonical_u32(KERNEL_ONLY_INSTR.unwrap());
+ lv.opcode_bits[7] * P::Scalar::from_canonical_u32(KERNEL_ONLY_INSTR.unwrap());
yield_constr
.constraint_transition(lv.op.push_prover_input * (gas_diff - push_prover_input_gas_cost));
}
Expand Down Expand Up @@ -282,13 +282,13 @@ fn eval_ext_circuit_accumulate<F: RichField + Extendable<D>, const D: usize>(
yield_constr.constraint_transition(builder, constr);

// For PROVER_INPUT and PUSH operations.
// PUSH operations are differentiated from PROVER_INPUT by their 6th bit set to
// PUSH operations are differentiated from PROVER_INPUT by their 8th bit set to
// 1.
let push_prover_input_gas_cost = builder.arithmetic_extension(
F::from_canonical_u32(G_VERYLOW.unwrap())
- F::from_canonical_u32(KERNEL_ONLY_INSTR.unwrap()),
F::from_canonical_u32(KERNEL_ONLY_INSTR.unwrap()),
lv.opcode_bits[5],
F::from_canonical_u32(KERNEL_ONLY_INSTR.unwrap())
- F::from_canonical_u32(G_VERYLOW.unwrap()),
F::from_canonical_u32(G_VERYLOW.unwrap()),
lv.opcode_bits[7],
one,
one,
);
Expand Down
24 changes: 12 additions & 12 deletions evm_arithmetization/src/cpu/kernel/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -841,7 +841,6 @@ impl<'a, F: Field> Interpreter<'a, F> {
0x46 => self.run_syscall(opcode, 0, true), // "CHAINID",
0x47 => self.run_syscall(opcode, 0, true), // SELFABALANCE,
0x48 => self.run_syscall(opcode, 0, true), // "BASEFEE",
0x49 => self.run_prover_input(), // "PROVER_INPUT",
0x4a => self.run_syscall(opcode, 0, true), // "BLOBBASEFEE",
0x50 => self.run_pop(), // "POP",
0x51 => self.run_syscall(opcode, 1, false), // "MLOAD",
Expand Down Expand Up @@ -874,19 +873,20 @@ impl<'a, F: Field> Interpreter<'a, F> {
Err(ProgramError::KernelPanic)
} // "PANIC",
x if (0xc0..0xe0).contains(&x) => self.run_mstore_32bytes(x - 0xc0 + 1), /* "MSTORE_32BYTES", */
0xf0 => self.run_syscall(opcode, 3, false), // "CREATE",
0xf1 => self.run_syscall(opcode, 7, false), // "CALL",
0xf2 => self.run_syscall(opcode, 7, false), // "CALLCODE",
0xf3 => self.run_syscall(opcode, 2, false), // "RETURN",
0xee => self.run_prover_input(), // "PROVER_INPUT",
0xf0 => self.run_syscall(opcode, 3, false), // "CREATE",
0xf1 => self.run_syscall(opcode, 7, false), // "CALL",
0xf2 => self.run_syscall(opcode, 7, false), // "CALLCODE",
0xf3 => self.run_syscall(opcode, 2, false), // "RETURN",
0xf4 => self.run_syscall(opcode, 6, false), // "DELEGATECALL",
0xf5 => self.run_syscall(opcode, 4, false), // "CREATE2",
0xf6 => self.run_get_context(), // "GET_CONTEXT",
0xf7 => self.run_set_context(), // "SET_CONTEXT",
0xf8 => self.run_mload_32bytes(), // "MLOAD_32BYTES",
0xf9 => self.run_exit_kernel(), // "EXIT_KERNEL",
0xf6 => self.run_get_context(), // "GET_CONTEXT",
0xf7 => self.run_set_context(), // "SET_CONTEXT",
0xf8 => self.run_mload_32bytes(), // "MLOAD_32BYTES",
0xf9 => self.run_exit_kernel(), // "EXIT_KERNEL",
0xfa => self.run_syscall(opcode, 6, false), // "STATICCALL",
0xfb => self.run_mload_general(), // "MLOAD_GENERAL",
0xfc => self.run_mstore_general(), // "MSTORE_GENERAL",
0xfb => self.run_mload_general(), // "MLOAD_GENERAL",
0xfc => self.run_mstore_general(), // "MSTORE_GENERAL",
0xfd => self.run_syscall(opcode, 2, false), // "REVERT",
0xfe => {
log::warn!(
Expand Down Expand Up @@ -1604,7 +1604,6 @@ fn get_mnemonic(opcode: u8) -> &'static str {
0x45 => "GASLIMIT",
0x46 => "CHAINID",
0x48 => "BASEFEE",
0x49 => "PROVER_INPUT",
0x4a => "BLOBBASEFEE",
0x50 => "POP",
0x51 => "MLOAD",
Expand Down Expand Up @@ -1722,6 +1721,7 @@ fn get_mnemonic(opcode: u8) -> &'static str {
0xdd => "MSTORE_32BYTES_30",
0xde => "MSTORE_32BYTES_31",
0xdf => "MSTORE_32BYTES_32",
0xee => "PROVER_INPUT",
0xf0 => "CREATE",
0xf1 => "CALL",
0xf2 => "CALLCODE",
Expand Down
2 changes: 1 addition & 1 deletion evm_arithmetization/src/cpu/kernel/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ pub fn get_opcode(mnemonic: &str) -> u8 {
"GASLIMIT" => 0x45,
"CHAINID" => 0x46,
"BASEFEE" => 0x48,
"PROVER_INPUT" => 0x49,
"BLOBBASEFEE" => 0x4a,
"POP" => 0x50,
"MLOAD" => 0x51,
Expand Down Expand Up @@ -148,6 +147,7 @@ pub fn get_opcode(mnemonic: &str) -> u8 {
"MSTORE_32BYTES_30" => 0xdd,
"MSTORE_32BYTES_31" => 0xde,
"MSTORE_32BYTES_32" => 0xdf,
"PROVER_INPUT" => 0xee,
"CREATE" => 0xf0,
"CALL" => 0xf1,
"CALLCODE" => 0xf2,
Expand Down
2 changes: 1 addition & 1 deletion evm_arithmetization/src/witness/operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ pub(crate) fn generate_prover_input<F: Field>(
let pc = state.registers.program_counter;
let input_fn = &KERNEL.prover_inputs[&pc];
let input = state.prover_input(input_fn)?;
let opcode = 0x49.into();
let opcode = 0xee.into();
// `ArithmeticStark` range checks `mem_channels[0]`, which contains
// the top of the stack, `mem_channels[1]`, `mem_channels[2]` and
// next_row's `mem_channels[0]` which contains the next top of the stack.
Expand Down
2 changes: 1 addition & 1 deletion evm_arithmetization/src/witness/transition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ pub(crate) fn decode(registers: RegistersState, opcode: u8) -> Result<Operation,
(0x46, _) => Ok(Operation::Syscall(opcode, 0, true)), // CHAINID
(0x47, _) => Ok(Operation::Syscall(opcode, 0, true)), // SELFBALANCE
(0x48, _) => Ok(Operation::Syscall(opcode, 0, true)), // BASEFEE
(0x49, true) => Ok(Operation::ProverInput),
(0x4a, _) => Ok(Operation::Syscall(opcode, 0, true)), // BLOBBASEFEE
(0x50, _) => Ok(Operation::Pop),
(0x51, _) => Ok(Operation::Syscall(opcode, 1, false)), // MLOAD
Expand Down Expand Up @@ -138,6 +137,7 @@ pub(crate) fn decode(registers: RegistersState, opcode: u8) -> Result<Operation,
Err(ProgramError::KernelPanic)
}
(0xc0..=0xdf, true) => Ok(Operation::Mstore32Bytes(opcode - 0xc0 + 1)),
(0xee, true) => Ok(Operation::ProverInput),
(0xf0, _) => Ok(Operation::Syscall(opcode, 3, false)), // CREATE
(0xf1, _) => Ok(Operation::Syscall(opcode, 7, false)), // CALL
(0xf2, _) => Ok(Operation::Syscall(opcode, 7, false)), // CALLCODE
Expand Down

0 comments on commit de03ac3

Please sign in to comment.