Skip to content
This repository has been archived by the owner on Jan 9, 2025. It is now read-only.

Commit

Permalink
Move stack and static gas check to exec_opcode
Browse files Browse the repository at this point in the history
  • Loading branch information
ClementWalter committed Nov 7, 2023
1 parent 7b4569a commit 564a007
Show file tree
Hide file tree
Showing 14 changed files with 1,609 additions and 617 deletions.
1,544 changes: 1,544 additions & 0 deletions src/kakarot/constants.cairo

Large diffs are not rendered by default.

69 changes: 50 additions & 19 deletions src/kakarot/evm.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,14 @@
%lang starknet

// Starkware dependencies
from starkware.cairo.common.alloc import alloc
from starkware.cairo.common.bool import FALSE, TRUE
from starkware.cairo.common.cairo_builtins import HashBuiltin, BitwiseBuiltin
from starkware.cairo.common.invoke import invoke
from starkware.cairo.common.math import assert_nn
from starkware.cairo.common.math_cmp import is_le, is_not_zero
from starkware.cairo.common.memcpy import memcpy
from starkware.cairo.common.registers import get_ap
from starkware.cairo.common.registers import get_label_location
from starkware.cairo.common.uint256 import Uint256
from starkware.cairo.common.math_cmp import is_le
from starkware.cairo.lang.compiler.lib.registers import get_fp_and_pc

// Internal dependencies
from kakarot.account import Account
from kakarot.constants import opcodes_label, Constants
from kakarot.errors import Errors
from kakarot.execution_context import ExecutionContext
from kakarot.instructions.block_information import BlockInformation
Expand Down Expand Up @@ -56,32 +51,68 @@ namespace EVM {
// @dev The function uses an internal jump table to execute the corresponding opcode
// @param ctx The pointer to the execution context.
// @return ExecutionContext The pointer to the updated execution context.
func decode_and_execute{
func exec_opcode{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr,
bitwise_ptr: BitwiseBuiltin*,
}(ctx: model.ExecutionContext*) -> model.ExecutionContext* {
alloc_locals;

// Retrieve the current program counter.
// Get the current opcode number
let pc = ctx.program_counter;
local opcode;
local opcode: model.Opcode*;

let is_pc_ge_code_len = is_le(ctx.call_context.bytecode_len, pc);

local opcode_number;
if (is_pc_ge_code_len != FALSE) {
assert opcode = 0;
assert opcode_number = 0;
} else {
assert opcode = [ctx.call_context.bytecode + pc];
assert opcode_number = [ctx.call_context.bytecode + pc];
}

// Compute the corresponding offset in the jump table:
// count 1 for "next line" and 3 steps per opcode: call, opcode, ret
tempvar offset = 1 + 3 * opcode;
// Get the corresponding opcode data
// To cast the codeoffset opcodes_label to a model.Opcode*, we need to use it to offset
// the current pc. We get the pc from the `get_fp_and_pc` util and assign a codeoffset (pc_label) to it.
// In short, this boils down to: opcode = pc + offset - pc = offset
let (_, cairo_pc) = get_fp_and_pc();

pc_label:
assert opcode = cast(
cairo_pc + (opcodes_label - pc_label) + opcode_number * model.Opcode.SIZE, model.Opcode*
);

// Check stack over/under flow
let stack_underflow = is_le(ctx.stack.size, opcode.stack_size_min - 1);
if (stack_underflow != 0) {
let (revert_reason_len, revert_reason) = Errors.stackUnderflow();
let ctx = ExecutionContext.stop(ctx, revert_reason_len, revert_reason, TRUE);
return ctx;
}
let stack_overflow = is_le(
Constants.STACK_MAX_DEPTH, ctx.stack.size + opcode.stack_size_diff + 1
);
if (stack_overflow != 0) {
let (revert_reason_len, revert_reason) = Errors.stackOverflow();
let ctx = ExecutionContext.stop(ctx, revert_reason_len, revert_reason, TRUE);
return ctx;
}

// Check static gas
let out_of_gas = is_le(ctx.call_context.gas_limit, ctx.gas_used + opcode.gas - 1);
if (out_of_gas != 0) {
let (revert_reason_len, revert_reason) = Errors.outOfGas();
let ctx = ExecutionContext.stop(ctx, revert_reason_len, revert_reason, TRUE);
return ctx;
}

// move program counter + 1 after opcode is read
// Update ctx
let ctx = ExecutionContext.increment_program_counter(self=ctx, inc_value=1);
let ctx = ExecutionContext.increment_gas_used(ctx, opcode.gas);

// Compute the corresponding offset in the jump table:
// count 1 for "next line" and 3 steps per opcode: call, opcode, ret
tempvar offset = 1 + 3 * opcode_number;

// Prepare arguments
[ap] = syscall_ptr, ap++;
Expand Down Expand Up @@ -634,7 +665,7 @@ namespace EVM {
}
}

let ctx = decode_and_execute(ctx);
let ctx = exec_opcode(ctx);
return run(ctx);
}

Expand Down
54 changes: 2 additions & 52 deletions src/kakarot/instructions/block_information.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ from starkware.cairo.lang.compiler.lib.registers import get_fp_and_pc

// Internal dependencies
from kakarot.storages import blockhash_registry_address
from kakarot.constants import Constants
from kakarot.constants import Constants, opcodes_label
from kakarot.execution_context import ExecutionContext
from kakarot.interfaces.interfaces import IBlockhashRegistry
from kakarot.model import model
Expand All @@ -35,12 +35,6 @@ namespace BlockInformation {
local range_check: felt;
local opcode: model.Opcode*;

if (ctx.stack.size == Constants.STACK_MAX_DEPTH) {
let (revert_reason_len, revert_reason) = Errors.stackOverflow();
let ctx = ExecutionContext.stop(ctx, revert_reason_len, revert_reason, TRUE);
return ctx;
}

// See evm.cairo, pc is increased before entering the opcode
let opcode_number = [ctx.call_context.bytecode + ctx.program_counter - 1];

Expand All @@ -52,16 +46,9 @@ namespace BlockInformation {

pc_label:
assert opcode = cast(
pc + (opcodes_label - pc_label) + (opcode_number - 0x40) * model.Opcode.SIZE,
model.Opcode*,
pc + (opcodes_label - pc_label) + opcode_number * model.Opcode.SIZE, model.Opcode*
);

let out_of_gas = is_le(ctx.call_context.gas_limit, ctx.gas_used + opcode.gas - 1);
if (out_of_gas != 0) {
let (revert_reason_len, revert_reason) = Errors.outOfGas();
let ctx = ExecutionContext.stop(ctx, revert_reason_len, revert_reason, TRUE);
return ctx;
}
assert range_check = range_check_ptr;

tempvar offset = 2 * (opcode_number - 0x40) + 1;
Expand Down Expand Up @@ -172,7 +159,6 @@ namespace BlockInformation {
// Finalize opcode
let stack = Stack.push_uint256(ctx.stack, result);
let ctx = ExecutionContext.update_stack(ctx, stack);
let ctx = ExecutionContext.increment_gas_used(ctx, opcode.gas);
return ctx;
}
}
Expand All @@ -181,12 +167,6 @@ namespace Internals {
func blockhash{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
ctx: model.ExecutionContext*
) -> (model.ExecutionContext*, Uint256) {
if (ctx.stack.size == 0) {
let (revert_reason_len, revert_reason) = Errors.stackUnderflow();
let ctx = ExecutionContext.stop(ctx, revert_reason_len, revert_reason, TRUE);
return (ctx, Uint256(0, 0));
}

let (stack, block_number_uint256) = Stack.pop(ctx.stack);
let ctx = ExecutionContext.update_stack(ctx, stack);
let block_number = block_number_uint256.low;
Expand Down Expand Up @@ -217,33 +197,3 @@ namespace Internals {
return (ctx, balance);
}
}

// See model.Opcode
opcodes_label:
// BLOCKHASH
dw 20; // gas
dw 1; // stack_input
// COINBASE
dw 2; // gas
dw 0; // stack_input
// TIMESTAMP
dw 2; // gas
dw 0; // stack_input
// NUMBER
dw 2; // gas
dw 0; // stack_input
// PREVRANDAO
dw 2; // gas
dw 0; // stack_input
// GASLIMIT
dw 2; // gas
dw 0; // stack_input
// CHAINID
dw 2; // gas
dw 0; // stack_input
// SELFBALANCE
dw 5; // gas
dw 0; // stack_input
// BASEFEE
dw 2; // gas
dw 0; // stack_input
24 changes: 0 additions & 24 deletions src/kakarot/instructions/duplication_operations.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ from kakarot.constants import Constants

// @title Duplication operations opcodes.
namespace DuplicationOperations {
// Define constants.
const GAS_COST_DUP = 3;
// @notice Generic DUP operation
// @dev Duplicate the top i-th stack item to the top of the stack.
// @param ctx The pointer to the execution context.
Expand All @@ -29,35 +26,14 @@ namespace DuplicationOperations {
range_check_ptr,
bitwise_ptr: BitwiseBuiltin*,
}(ctx: model.ExecutionContext*) -> model.ExecutionContext* {
let out_of_gas = is_le(ctx.call_context.gas_limit, ctx.gas_used + GAS_COST_DUP - 1);
if (out_of_gas != 0) {
let (revert_reason_len, revert_reason) = Errors.outOfGas();
let ctx = ExecutionContext.stop(ctx, revert_reason_len, revert_reason, TRUE);
return ctx;
}

if (ctx.stack.size == Constants.STACK_MAX_DEPTH) {
let (revert_reason_len, revert_reason) = Errors.stackOverflow();
let ctx = ExecutionContext.stop(ctx, revert_reason_len, revert_reason, TRUE);
return ctx;
}

// See evm.cairo, pc is increased before entering the opcode
let opcode_number = [ctx.call_context.bytecode + ctx.program_counter - 1];
let i = opcode_number - 0x7F;

let stack_underflow = is_le(ctx.stack.size, i - 1);
if (stack_underflow != 0) {
let (revert_reason_len, revert_reason) = Errors.stackUnderflow();
let ctx = ExecutionContext.stop(ctx, revert_reason_len, revert_reason, TRUE);
return ctx;
}

let (stack, element) = Stack.peek(ctx.stack, i - 1);
let stack = Stack.push(stack, element);

let ctx = ExecutionContext.update_stack(ctx, stack);
let ctx = ExecutionContext.increment_gas_used(self=ctx, inc_value=GAS_COST_DUP);

return ctx;
}
Expand Down
Loading

0 comments on commit 564a007

Please sign in to comment.