Skip to content

Commit

Permalink
feat(levm): opcodes gas consumption (lambdaclass#584)
Browse files Browse the repository at this point in the history
**Motivation**
Implement `GAS` opcode, which requires a first global handling of gas
consumption.
<!-- Why does this pull request exist? What are its goals? -->

**Description**
- Uses `VM::gas_limit` and `VM::consumed_gas` for handling all opcodes
static and dynamic gas consumption.
- Check if gas is enough before executing each one of them.
- Save `warm_addresses` in `VM`.
- Fixes a `jump` bug and a `CALL` test.
- Adds gas checks to the tests. 
- `CALL`'s `code_execution_cost` is still to be implemented (lambdaclass#605). 
<!-- A clear and concise general description of the changes this PR
introduces -->

<!-- Link to issues: Resolves lambdaclass#111, Resolves lambdaclass#222 -->

Closes lambdaclass#493 and lambdaclass#587.

---------

Co-authored-by: Paolo Belforte <[email protected]>
Co-authored-by: iinaki <[email protected]>
  • Loading branch information
3 people authored and emirongrr committed Nov 10, 2024
1 parent 3fa62d6 commit d261b52
Show file tree
Hide file tree
Showing 8 changed files with 962 additions and 661 deletions.
2 changes: 1 addition & 1 deletion crates/levm/src/call_frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ impl CallFrame {
// Should be a halt when we implement it
panic!("Invalid jump");
}
self.pc = jump_address.as_usize() + 1;
self.pc = jump_address.as_usize();
}

fn valid_jump(&self, jump_address: U256) -> bool {
Expand Down
81 changes: 81 additions & 0 deletions crates/levm/src/constants.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,84 @@
pub const SUCCESS_FOR_CALL: i32 = 1;
pub const REVERT_FOR_CALL: i32 = 0;
pub const SUCCESS_FOR_RETURN: i32 = 1;
pub const TX_BASE_COST: u64 = 21_000;
pub const WORD_SIZE: usize = 32;

/// Contains the gas costs of the EVM instructions
pub mod gas_cost {
pub const ADD: u64 = 3;
pub const MUL: u64 = 5;
pub const SUB: u64 = 3;
pub const DIV: u64 = 5;
pub const SDIV: u64 = 5;
pub const MOD: u64 = 5;
pub const SMOD: u64 = 5;
pub const ADDMOD: u64 = 8;
pub const MULMOD: u64 = 8;
pub const EXP_STATIC: u64 = 10;
pub const EXP_DYNAMIC_BASE: u64 = 50;
pub const SIGNEXTEND: u64 = 5;
pub const LT: u64 = 3;
pub const GT: u64 = 3;
pub const SLT: u64 = 3;
pub const SGT: u64 = 3;
pub const EQ: u64 = 3;
pub const ISZERO: u64 = 3;
pub const AND: u64 = 3;
pub const OR: u64 = 3;
pub const XOR: u64 = 3;
pub const NOT: u64 = 3;
pub const BYTE: u64 = 3;
pub const SHL: u64 = 3;
pub const SHR: u64 = 3;
pub const SAR: u64 = 3;
pub const KECCAK25_STATIC: u64 = 30;
pub const KECCAK25_DYNAMIC_BASE: u64 = 6;
pub const CALLDATALOAD: u64 = 3;
pub const CALLDATASIZE: u64 = 2;
pub const CALLDATACOPY_STATIC: u64 = 3;
pub const CALLDATACOPY_DYNAMIC_BASE: u64 = 3;
pub const RETURNDATASIZE: u64 = 2;
pub const RETURNDATACOPY_STATIC: u64 = 3;
pub const RETURNDATACOPY_DYNAMIC_BASE: u64 = 3;
pub const BLOCKHASH: u64 = 20;
pub const COINBASE: u64 = 2;
pub const TIMESTAMP: u64 = 2;
pub const NUMBER: u64 = 2;
pub const PREVRANDAO: u64 = 2;
pub const GASLIMIT: u64 = 2;
pub const CHAINID: u64 = 2;
pub const SELFBALANCE: u64 = 5;
pub const BASEFEE: u64 = 2;
pub const BLOBHASH: u64 = 3;
pub const BLOBBASEFEE: u64 = 2;
pub const POP: u64 = 2;
pub const MLOAD_STATIC: u64 = 3;
pub const MSTORE_STATIC: u64 = 3;
pub const MSTORE8_STATIC: u64 = 3;
pub const JUMP: u64 = 8;
pub const JUMPI: u64 = 10;
pub const PC: u64 = 2;
pub const MSIZE: u64 = 2;
pub const GAS: u64 = 2;
pub const JUMPDEST: u64 = 1;
pub const TLOAD: u64 = 100;
pub const TSTORE: u64 = 100;
pub const MCOPY_STATIC: u64 = 3;
pub const MCOPY_DYNAMIC_BASE: u64 = 3;
pub const PUSH0: u64 = 2;
pub const PUSHN: u64 = 3;
pub const DUPN: u64 = 3;
pub const SWAPN: u64 = 3;
pub const LOGN_STATIC: u64 = 375;
pub const LOGN_DYNAMIC_BASE: u64 = 375;
pub const LOGN_DYNAMIC_BYTE_BASE: u64 = 8;
}

pub mod call_opcode {
pub const WARM_ADDRESS_ACCESS_COST: u64 = 100;
pub const COLD_ADDRESS_ACCESS_COST: u64 = 2_600;
pub const NON_ZERO_VALUE_COST: u64 = 9_000;
pub const BASIC_FALLBACK_FUNCTION_STIPEND: u64 = 2_300;
pub const VALUE_TO_EMPTY_ACCOUNT_COST: u64 = 25_000;
}
14 changes: 14 additions & 0 deletions crates/levm/src/memory.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::constants::WORD_SIZE;
use crate::primitives::U256;

#[derive(Debug, Clone, Default, PartialEq)]
Expand Down Expand Up @@ -62,4 +63,17 @@ impl Memory {

self.data[dest_offset..dest_offset + size].copy_from_slice(&temp);
}

pub fn expansion_cost(&self, memory_byte_size: usize) -> usize {
if memory_byte_size <= self.data.len() {
return 0;
}
let new_memory_size_word = (memory_byte_size + WORD_SIZE - 1) / WORD_SIZE;
let new_memory_cost =
(new_memory_size_word * new_memory_size_word) / 512 + (3 * new_memory_size_word);
let last_memory_size_word = (self.data.len() + WORD_SIZE - 1) / WORD_SIZE;
let last_memory_cost =
(last_memory_size_word * last_memory_size_word) / 512 + (3 * last_memory_size_word);
new_memory_cost - last_memory_cost
}
}
22 changes: 13 additions & 9 deletions crates/levm/src/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub enum Opcode {
// KECCAK256
KECCAK256 = 0x20,

// // Environmental Information
// Environmental Information
// ADDRESS = 0x30,
// BALANCE = 0x31,
// ORIGIN = 0x32,
Expand All @@ -51,7 +51,7 @@ pub enum Opcode {
RETURNDATACOPY = 0x3E,
// EXTCODEHASH = 0x3F,

// // Block Information
// Block Information
BLOCKHASH = 0x40,
COINBASE = 0x41,
TIMESTAMP = 0x42,
Expand All @@ -64,7 +64,7 @@ pub enum Opcode {
BLOBHASH = 0x49,
BLOBBASEFEE = 0x4A,

// // Stack, Memory, Storage, and Flow Operations
// Stack, Memory, Storage, and Flow Operations
POP = 0x50,
MLOAD = 0x51,
MSTORE = 0x52,
Expand All @@ -75,13 +75,13 @@ pub enum Opcode {
JUMPI = 0x57,
PC = 0x58,
MSIZE = 0x59,
// GAS = 0x5A,
GAS = 0x5A,
JUMPDEST = 0x5B,
TLOAD = 0x5C,
TSTORE = 0x5D,
MCOPY = 0x5E,

// // Push Operations
// Push Operations
PUSH0 = 0x5F,
PUSH1 = 0x60,
PUSH2 = 0x61,
Expand Down Expand Up @@ -115,7 +115,8 @@ pub enum Opcode {
PUSH30 = 0x7D,
PUSH31 = 0x7E,
PUSH32 = 0x7F,
// // Duplication Operations

// Duplication Operations
DUP1 = 0x80,
DUP2 = 0x81,
DUP3 = 0x82,
Expand All @@ -132,7 +133,8 @@ pub enum Opcode {
DUP14 = 0x8D,
DUP15 = 0x8E,
DUP16 = 0x8F,
// // Swap Operations

// Swap Operations
SWAP1 = 0x90,
SWAP2 = 0x91,
SWAP3 = 0x92,
Expand All @@ -149,13 +151,14 @@ pub enum Opcode {
SWAP14 = 0x9D,
SWAP15 = 0x9E,
SWAP16 = 0x9F,
// // Logging Operations
// Logging Operations
LOG0 = 0xA0,
LOG1 = 0xA1,
LOG2 = 0xA2,
LOG3 = 0xA3,
LOG4 = 0xA4,
// // System Operations

// System Operations
// CREATE = 0xF0,
CALL = 0xF1,
CALLCODE = 0xF2,
Expand Down Expand Up @@ -297,6 +300,7 @@ impl From<u8> for Opcode {
0x54 => Opcode::SLOAD,
0x55 => Opcode::SSTORE,
0x59 => Opcode::MSIZE,
0x5A => Opcode::GAS,
0x5E => Opcode::MCOPY,
x if x == Opcode::TLOAD as u8 => Opcode::TLOAD,
x if x == Opcode::TSTORE as u8 => Opcode::TSTORE,
Expand Down
4 changes: 2 additions & 2 deletions crates/levm/src/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ pub enum Operation {
Jumpi,
PC,
Msize,
// Gas,
Gas,
Jumpdest,
Tload,
Tstore,
Expand Down Expand Up @@ -177,7 +177,7 @@ impl Operation {
Operation::Jumpi => Bytes::copy_from_slice(&[Opcode::JUMPI as u8]),
Operation::PC => Bytes::copy_from_slice(&[Opcode::PC as u8]),
Operation::Msize => Bytes::copy_from_slice(&[Opcode::MSIZE as u8]),
// Operation::Gas => Bytes::copy_from_slice(&[Opcode::GAS as u8]),
Operation::Gas => Bytes::copy_from_slice(&[Opcode::GAS as u8]),
Operation::Jumpdest => Bytes::copy_from_slice(&[Opcode::JUMPDEST as u8]),
Operation::Tload => Bytes::copy_from_slice(&[Opcode::TLOAD as u8]),
Operation::Tstore => Bytes::copy_from_slice(&[Opcode::TSTORE as u8]),
Expand Down
Loading

0 comments on commit d261b52

Please sign in to comment.