Skip to content

Commit

Permalink
feat: A0-A4 - LOG0-4 Opcode (#322)
Browse files Browse the repository at this point in the history
* mstore tests impl

* made exec_mstore panic

* corrected test case error

* mstore opcode impl

* review correction + add 2 tests

* correction test case

* used pop_n instead

* corrected #263 succeed into succeeded

* reverted to single pop + removed tests

* first commit

* removed print and used default for array

* added readonly test & cleaned imports

* added internal get_datas

* need to merge main

* removed ',' from merge

* check load vs loadn

* switch data array from felt to u8

* cleaned code/tests

* review correction

* compare all bytes in tests + inlined app_event

* stop useless slicing

* added tests cases

* simplified expected array

* merge correction

* cleaned imports

* scarb fmt did that

* dupl app_event + setup_readonly

* change error message + setup with readonly

* correction rebase

---------

Co-authored-by: Elias Tazartes <[email protected]>
  • Loading branch information
Quentash and Eikix authored Oct 4, 2023
1 parent 3a4603c commit 9282fb2
Show file tree
Hide file tree
Showing 10 changed files with 436 additions and 45 deletions.
5 changes: 5 additions & 0 deletions crates/evm/src/context.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -315,4 +315,9 @@ impl ExecutionContextImpl of ExecutionContextTrait {
fn child_return_data(self: @ExecutionContext) -> Option<Span<u8>> {
*self.child_return_data
}

#[inline(always)]
fn append_event(ref self: ExecutionContext, event: Event) {
self.events.append(event);
}
}
9 changes: 7 additions & 2 deletions crates/evm/src/errors.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ const RETURNDATA_OUT_OF_BOUNDS_ERROR: felt252 = 'KKT: ReturnDataOutOfBounds';
// JUMP
const INVALID_DESTINATION: felt252 = 'KKT: invalid JUMP destination';

// EVM STATE
const WRITE_IN_STATIC_CONTEXT: felt252 = 'KKT: WriteInStaticContext';

#[derive(Drop, Copy, PartialEq)]
enum EVMError {
StackError: felt252,
Expand All @@ -22,7 +25,8 @@ enum EVMError {
ReturnDataError: felt252,
JumpError: felt252,
NotImplemented,
UnknownOpcode: u8
UnknownOpcode: u8,
WriteInStaticContext: felt252
}


Expand All @@ -36,7 +40,8 @@ impl EVMErrorIntoU256 of Into<EVMError, u256> {
EVMError::JumpError(error_message) => error_message.into(),
EVMError::NotImplemented => 'NotImplemented'.into(),
// TODO: refactor with dynamic strings once supported
EVMError::UnknownOpcode => 'UnknownOpcode'.into()
EVMError::UnknownOpcode => 'UnknownOpcode'.into(),
EVMError::WriteInStaticContext(error_message) => error_message.into(),
}
}
}
1 change: 1 addition & 0 deletions crates/evm/src/instructions.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use comparison_operations::ComparisonAndBitwiseOperationsTrait;
use duplication_operations::DuplicationOperationsTrait;
use environmental_information::EnvironmentInformationTrait;
use exchange_operations::ExchangeOperationsTrait;
use logging_operations::LoggingOperationsTrait;
use memory_operations::MemoryOperationTrait;
use push_operations::PushOperationsTrait;
use sha3::Sha3Trait;
Expand Down
97 changes: 63 additions & 34 deletions crates/evm/src/instructions/logging_operations.cairo
Original file line number Diff line number Diff line change
@@ -1,48 +1,77 @@
use evm::errors::EVMError;
//! Logging Operations.

// Internal imports
use evm::machine::Machine;

mod internal {
use evm::machine::Machine;
#[generate_trait]
impl LoggingOperations of LoggingOperationsTrait {
/// 0xA0 - LOG0 operation
/// Append log record with no topic.
/// # Specification: https://www.evm.codes/#a0?fork=shanghai
fn exec_log0(ref self: Machine) -> Result<(), EVMError> {
internal::exec_log_i(ref self, 0)
}

/// Generic logging operation.
/// Append log record with n topics.
fn exec_log_i(ref machine: Machine, topics_len: u8) {}
}
/// 0xA1 - LOG1
/// Append log record with one topic.
/// # Specification: https://www.evm.codes/#a1?fork=shanghai
fn exec_log1(ref self: Machine) -> Result<(), EVMError> {
internal::exec_log_i(ref self, 1)
}

/// 0xA0 - LOG0 operation
/// Append log record with no topic.
/// # Specification: https://www.evm.codes/#a0?fork=shanghai
fn exec_log0(ref machine: Machine) {
internal::exec_log_i(ref machine, 0);
}
/// 0xA2 - LOG2
/// Append log record with two topics.
/// # Specification: https://www.evm.codes/#a2?fork=shanghai
fn exec_log2(ref self: Machine) -> Result<(), EVMError> {
internal::exec_log_i(ref self, 2)
}

/// 0xA3 - LOG3
/// Append log record with three topics.
/// # Specification: https://www.evm.codes/#a3?fork=shanghai
fn exec_log3(ref self: Machine) -> Result<(), EVMError> {
internal::exec_log_i(ref self, 3)
}

/// 0xA1 - LOG1
/// Append log record with one topic.
/// # Specification: https://www.evm.codes/#a1?fork=shanghai
fn exec_log1(ref machine: Machine) {
internal::exec_log_i(ref machine, 1);
/// 0xA4 - LOG4
/// Append log record with four topics.
/// # Specification: https://www.evm.codes/#a4?fork=shanghai
fn exec_log4(ref self: Machine) -> Result<(), EVMError> {
internal::exec_log_i(ref self, 4)
}
}

/// 0xA2 - LOG2
/// Append log record with two topics.
/// # Specification: https://www.evm.codes/#a2?fork=shanghai
fn exec_log2(ref machine: Machine) {
internal::exec_log_i(ref machine, 2);
}
mod internal {
use evm::errors::{EVMError, WRITE_IN_STATIC_CONTEXT};
use evm::machine::{Machine, MachineCurrentContextTrait};
use evm::memory::MemoryTrait;
use evm::model::Event;
use evm::stack::StackTrait;

/// 0xA3 - LOG3
/// Append log record with three topics.
/// # Specification: https://www.evm.codes/#a3?fork=shanghai
fn exec_log3(ref machine: Machine) {
internal::exec_log_i(ref machine, 3);
}
/// Store a new event in the dynamic context using topics
/// popped from the stack and data from the memory.
///
/// # Arguments
///
/// * `self` - The context to which the event will be added
/// * `topics_len` - The amount of topics to pop from the stack
fn exec_log_i(ref self: Machine, topics_len: u8) -> Result<(), EVMError> {
// Revert if the transaction is in a read only context
if self.read_only() {
return Result::Err(EVMError::WriteInStaticContext(WRITE_IN_STATIC_CONTEXT));
}

let offset = self.stack.pop_usize()?;
let size = self.stack.pop_usize()?;
let topics: Array<u256> = self.stack.pop_n(topics_len.into())?;

let mut data: Array<u8> = Default::default();
self.memory.load_n(size, ref data, offset);

let event: Event = Event { keys: topics, data };
self.append_event(event);

/// 0xA4 - LOG4
/// Append log record with 4 topics.
/// # Specification: https://www.evm.codes/#a4?fork=shanghai
fn exec_log4(ref machine: Machine) {
internal::exec_log_i(ref machine, 4);
Result::Ok(())
}
}
18 changes: 10 additions & 8 deletions crates/evm/src/interpreter.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
use evm::context::{CallContextTrait,};
use evm::errors::{EVMError, PC_OUT_OF_BOUNDS};
use evm::instructions::{
ExchangeOperationsTrait, StopAndArithmeticOperationsTrait, ComparisonAndBitwiseOperationsTrait,
SystemOperationsTrait, BlockInformationTrait, DuplicationOperationsTrait,
EnvironmentInformationTrait, PushOperationsTrait, MemoryOperationTrait, logging_operations
duplication_operations, environmental_information, ExchangeOperationsTrait, logging_operations,
LoggingOperationsTrait, memory_operations, sha3, StopAndArithmeticOperationsTrait,
ComparisonAndBitwiseOperationsTrait, SystemOperationsTrait, BlockInformationTrait,
DuplicationOperationsTrait, EnvironmentInformationTrait, PushOperationsTrait,
MemoryOperationTrait
};
use evm::machine::{Machine, MachineCurrentContextTrait};
use utils::{helpers::u256_to_bytes_array};
Expand Down Expand Up @@ -586,23 +588,23 @@ impl EVMInterpreterImpl of EVMInterpreterTrait {
}
if opcode == 160 {
// LOG0
logging_operations::exec_log0(ref machine);
return machine.exec_log0();
}
if opcode == 161 {
// LOG1
logging_operations::exec_log1(ref machine);
return machine.exec_log1();
}
if opcode == 162 {
// LOG2
logging_operations::exec_log2(ref machine);
return machine.exec_log2();
}
if opcode == 163 {
// LOG3
logging_operations::exec_log3(ref machine);
return machine.exec_log3();
}
if opcode == 164 {
// LOG4
logging_operations::exec_log4(ref machine);
return machine.exec_log4();
}
if opcode == 240 {
// CREATE
Expand Down
7 changes: 7 additions & 0 deletions crates/evm/src/machine.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,13 @@ impl MachineCurrentContextImpl of MachineCurrentContextTrait {
current_call_ctx.read_only()
}

#[inline(always)]
fn append_event(ref self: Machine, event: Event) {
let mut current_execution_ctx = self.current_ctx.unbox();
current_execution_ctx.append_event(event);
self.current_ctx = BoxTrait::new(current_execution_ctx);
}

#[inline(always)]
fn gas_limit(ref self: Machine) -> u64 {
let current_call_ctx = self.call_ctx();
Expand Down
2 changes: 1 addition & 1 deletion crates/evm/src/model.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#[derive(Drop)]
struct Event {
keys: Array<u256>,
data: Array<felt252>,
data: Array<u8>,
}
1 change: 1 addition & 0 deletions crates/evm/src/tests/test_instructions.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod test_comparison_operations;
mod test_duplication_operations;
mod test_environment_information;
mod test_exchange_operations;
mod test_logging_operations;
mod test_memory_operations;
mod test_push_operations;
mod test_sha3;
Expand Down
Loading

0 comments on commit 9282fb2

Please sign in to comment.