Skip to content

Commit

Permalink
feat(blockifier): add emit_event cairo native syscall
Browse files Browse the repository at this point in the history
  • Loading branch information
PearsonWhite authored and varex83 committed Nov 13, 2024
1 parent d90688f commit 1c8e242
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 13 deletions.
28 changes: 24 additions & 4 deletions crates/blockifier/src/execution/native/syscall_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ use cairo_native::starknet::{
};
use cairo_vm::vm::runners::cairo_runner::ExecutionResources;
use starknet_api::state::StorageKey;
use starknet_api::transaction::{EventContent, EventData, EventKey};
use starknet_types_core::felt::Felt;

use crate::execution::call_info::{CallInfo, OrderedEvent, OrderedL2ToL1Message, Retdata};
use crate::execution::entry_point::{CallEntryPoint, EntryPointExecutionContext};
use crate::execution::syscalls::exceeds_event_size_limit;
use crate::execution::syscalls::hint_processor::{SyscallExecutionError, OUT_OF_GAS_ERROR};
use crate::state::state_api::State;

Expand Down Expand Up @@ -244,11 +246,29 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> {

fn emit_event(
&mut self,
_keys: &[Felt],
_data: &[Felt],
_remaining_gas: &mut u128,
keys: &[Felt],
data: &[Felt],
remaining_gas: &mut u128,
) -> SyscallResult<()> {
todo!("Implement emit_event syscall.");
self.pre_execute_syscall(remaining_gas, self.context.gas_costs().emit_event_gas_cost)?;

let order = self.context.n_emitted_events;
let event = EventContent {
keys: keys.iter().copied().map(EventKey).collect(),
data: EventData(data.to_vec()),
};

exceeds_event_size_limit(
self.context.versioned_constants(),
self.context.n_emitted_events + 1,
&event,
)
.map_err(|e| self.handle_error(remaining_gas, e.into()))?;

self.events.push(OrderedEvent { order, event });
self.context.n_emitted_events += 1;

Ok(())
}

fn send_message_to_l1(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use itertools::concat;
#[cfg(feature = "cairo_native")]
use pretty_assertions::assert_eq;
use starknet_api::felt;
use starknet_api::transaction::fields::Calldata;
Expand All @@ -25,11 +26,14 @@ const DATA: [Felt; 3] = [
];
const N_EMITTED_EVENTS: [Felt; 1] = [Felt::from_hex_unchecked("0x1")];

#[cfg_attr(
feature = "cairo_native",
test_case(FeatureContract::TestContract(CairoVersion::Native), 58930; "Native")
)]
#[test_case(FeatureContract::TestContract(CairoVersion::Cairo1), 47330; "VM")]
fn positive_flow(test_contract: FeatureContract, expected_gas: u64) {
// TODO(Ori, 1/2/2024): Write an indicative expect message explaining why the conversion
// works.
let call_info = emit_events(test_contract, &N_EMITTED_EVENTS, &KEYS, &DATA).unwrap();
let call_info = emit_events(test_contract, &N_EMITTED_EVENTS, &KEYS, &DATA)
.expect("emit_events failed with valued parameters");
let event = EventContent {
keys: KEYS.into_iter().map(EventKey).collect(),
data: EventData(DATA.to_vec()),
Expand All @@ -45,35 +49,53 @@ fn positive_flow(test_contract: FeatureContract, expected_gas: u64) {
);
}

#[cfg_attr(
feature = "cairo_native",
test_case(FeatureContract::TestContract(CairoVersion::Native); "Native")
)]
#[test_case(FeatureContract::TestContract(CairoVersion::Cairo1); "VM")]
fn data_length_exceeds_limit(test_contract: FeatureContract) {
let versioned_constants = VersionedConstants::create_for_testing();

let max_event_data_length = versioned_constants.tx_event_limits.max_data_length;
let data_too_long = vec![felt!(2_u16); max_event_data_length + 1];
let error = emit_events(test_contract, &N_EMITTED_EVENTS, &KEYS, &data_too_long).unwrap_err();

let call_result = emit_events(test_contract, &N_EMITTED_EVENTS, &KEYS, &data_too_long);

let error_message = call_result.unwrap_err().to_string();

let expected_error = EmitEventError::ExceedsMaxDataLength {
data_length: max_event_data_length + 1,
max_data_length: max_event_data_length,
};
assert!(error.to_string().contains(&expected_error.to_string()));
assert!(error_message.contains(&expected_error.to_string()));
}

#[cfg_attr(
feature = "cairo_native",
test_case(FeatureContract::TestContract(CairoVersion::Native); "Native")
)]
#[test_case(FeatureContract::TestContract(CairoVersion::Cairo1); "VM")]
fn keys_length_exceeds_limit(test_contract: FeatureContract) {
let versioned_constants = VersionedConstants::create_for_testing();

let max_event_keys_length = versioned_constants.tx_event_limits.max_keys_length;
let keys_too_long = vec![felt!(1_u16); max_event_keys_length + 1];
let error = emit_events(test_contract, &N_EMITTED_EVENTS, &keys_too_long, &DATA).unwrap_err();

let call_result = emit_events(test_contract, &N_EMITTED_EVENTS, &keys_too_long, &DATA);

let error_message = call_result.unwrap_err().to_string();

let expected_error = EmitEventError::ExceedsMaxKeysLength {
keys_length: max_event_keys_length + 1,
max_keys_length: max_event_keys_length,
};

assert!(error.to_string().contains(&expected_error.to_string()));
assert!(error_message.contains(&expected_error.to_string()));
}

#[cfg(feature = "cairo_native")]
#[test_case(FeatureContract::TestContract(CairoVersion::Native); "Native")]
#[test_case(FeatureContract::TestContract(CairoVersion::Cairo1); "VM")]
fn event_number_exceeds_limit(test_contract: FeatureContract) {
let versioned_constants = VersionedConstants::create_for_testing();
Expand All @@ -82,12 +104,15 @@ fn event_number_exceeds_limit(test_contract: FeatureContract) {
let n_emitted_events_too_big = vec![felt!(
u16::try_from(max_n_emitted_events + 1).expect("Failed to convert usize to u16.")
)];
let error = emit_events(test_contract, &n_emitted_events_too_big, &KEYS, &DATA).unwrap_err();
let call_result = emit_events(test_contract, &n_emitted_events_too_big, &KEYS, &DATA);

let error_message = call_result.unwrap_err().to_string();

let expected_error = EmitEventError::ExceedsMaxNumberOfEmittedEvents {
n_emitted_events: max_n_emitted_events + 1,
max_n_emitted_events,
};
assert!(error.to_string().contains(&expected_error.to_string()));
assert!(error_message.contains(&expected_error.to_string()));
}

fn emit_events(
Expand Down

0 comments on commit 1c8e242

Please sign in to comment.