Skip to content

Commit

Permalink
refactor(lang): reduce events generated code (#2662)
Browse files Browse the repository at this point in the history
* Updated functions to clear up naming with serialized

* Removed some redundecies in the code

* Removed some redundecies in the code

* updated benchmarks

* Reduced events geenrated code and updated to match model convention

* feat: add EventValue for ABI

* fix: tests

---------

Co-authored-by: glihm <[email protected]>
  • Loading branch information
bengineer42 and glihm authored Nov 8, 2024
1 parent 8ed5e72 commit cd7b3ca
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 61 deletions.
28 changes: 14 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ rpassword = "7.2.0"
rstest = "0.18.2"
rstest_reuse = "0.6.0"
salsa = "0.16.1"
scarb = { git = "https://github.com/dojoengine/scarb", rev = "a6d3b5b17b288502fe9cc63c96c0ae22fd175857" }
scarb-ui = { git = "https://github.com/dojoengine/scarb", rev = "a6d3b5b17b288502fe9cc63c96c0ae22fd175857" }
scarb = { git = "https://github.com/dojoengine/scarb", rev = "0f10b0b1d0e4afb7af278228a66196b5cb56b57b" }
scarb-ui = { git = "https://github.com/dojoengine/scarb", rev = "0f10b0b1d0e4afb7af278228a66196b5cb56b57b" }
semver = "1.0.5"
serde = { version = "1.0", features = [ "derive" ] }
serde_json = { version = "1.0", features = [ "arbitrary_precision" ] }
Expand Down
4 changes: 2 additions & 2 deletions crates/dojo/core/src/event/component.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use dojo::event::{Event, IEvent, EventDefinition};
use dojo::event::{Event, IEvent, EventDef};
use dojo::meta::{Layout, introspect::Struct};

#[starknet::embeddable]
Expand All @@ -25,7 +25,7 @@ pub impl IStoredEventImpl<

#[starknet::embeddable]
pub impl IEventImpl<TContractState, E, +Event<E>> of IEvent<TContractState> {
fn definition(self: @TContractState) -> EventDefinition {
fn definition(self: @TContractState) -> EventDef {
Event::<E>::definition()
}
}
38 changes: 35 additions & 3 deletions crates/dojo/core/src/event/event.cairo
Original file line number Diff line number Diff line change
@@ -1,20 +1,52 @@
use dojo::meta::Layout;
use dojo::meta::introspect::Struct;
use dojo::meta::{Introspect, introspect::{Struct, Ty}};
use dojo::model::model::ModelParser;

#[derive(Drop, Serde, Debug, PartialEq)]
pub struct EventDefinition {
pub struct EventDef {
pub name: ByteArray,
pub layout: Layout,
pub schema: Struct
}

pub trait EventDefinition<E> {
fn name() -> ByteArray;
}

pub trait Event<T> {
fn name() -> ByteArray;
fn definition() -> EventDefinition;
fn definition() -> EventDef;
fn layout() -> Layout;
fn schema() -> Struct;
fn serialized_keys(self: @T) -> Span<felt252>;
fn serialized_values(self: @T) -> Span<felt252>;
/// Returns the selector of the event computed for the given namespace hash.
fn selector(namespace_hash: felt252) -> felt252;
}

pub impl EventImpl<E, +ModelParser<E>, +EventDefinition<E>, +Serde<E>, +Introspect<E>> of Event<E> {
fn name() -> ByteArray {
EventDefinition::<E>::name()
}
fn definition() -> EventDef {
EventDef { name: Self::name(), layout: Self::layout(), schema: Self::schema() }
}
fn layout() -> Layout {
Introspect::<E>::layout()
}
fn schema() -> Struct {
match Introspect::<E>::ty() {
Ty::Struct(s) => s,
_ => panic!("Event: invalid schema.")
}
}
fn serialized_keys(self: @E) -> Span<felt252> {
ModelParser::<E>::serialize_keys(self)
}
fn serialized_values(self: @E) -> Span<felt252> {
ModelParser::<E>::serialize_values(self)
}
fn selector(namespace_hash: felt252) -> felt252 {
dojo::utils::selector_from_namespace_and_name(namespace_hash, @Self::name())
}
}
2 changes: 1 addition & 1 deletion crates/dojo/core/src/event/interface.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#[starknet::interface]
pub trait IEvent<T> {
fn definition(self: @T) -> super::EventDefinition;
fn definition(self: @T) -> super::EventDef;
}
2 changes: 1 addition & 1 deletion crates/dojo/core/src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub mod event {
pub mod component;

pub mod event;
pub use event::{Event, EventDefinition};
pub use event::{Event, EventDefinition, EventDef};

pub mod interface;
pub use interface::{IEvent, IEventDispatcher, IEventDispatcherTrait};
Expand Down
16 changes: 13 additions & 3 deletions crates/dojo/lang/src/attribute_macros/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,17 @@ impl DojoEvent {
});
}

let members_values = members
.iter()
.filter_map(|m| {
if m.key {
None
} else {
Some(RewriteNode::Text(format!("pub {}: {},\n", m.name, m.ty)))
}
})
.collect::<Vec<_>>();

let member_names = members
.iter()
.map(|member| RewriteNode::Text(format!("{},\n", member.name.clone())))
Expand All @@ -96,9 +107,7 @@ impl DojoEvent {
// and do not derive IntrospectPacked.
if derive_attr_names.contains(&DOJO_PACKED_DERIVE.to_string()) {
diagnostics.push(PluginDiagnostic {
message: format!(
"Event should derive {DOJO_INTROSPECT_DERIVE} instead of {DOJO_PACKED_DERIVE}."
),
message: format!("Deriving {DOJO_PACKED_DERIVE} on event is not allowed."),
stable_ptr: struct_ast.name(db).stable_ptr().untyped(),
severity: Severity::Error,
});
Expand All @@ -125,6 +134,7 @@ impl DojoEvent {
("serialized_keys".to_string(), RewriteNode::new_modified(serialized_keys)),
("serialized_values".to_string(), RewriteNode::new_modified(serialized_values)),
("unique_hash".to_string(), RewriteNode::Text(unique_hash)),
("members_values".to_string(), RewriteNode::new_modified(members_values)),
]),
);

Expand Down
59 changes: 24 additions & 35 deletions crates/dojo/lang/src/attribute_macros/patches/event.patch.cairo
Original file line number Diff line number Diff line change
@@ -1,56 +1,38 @@
pub impl $type_name$DojoEventImpl of dojo::event::Event<$type_name$> {
// EventValue on it's own does nothing since events are always emitted and
// never read from the storage. However, it's required by the ABI to
// ensure that the event definition contains both keys and values easily distinguishable.
// Only derives strictly required traits.
#[derive(Drop, Serde)]
pub struct $type_name$Value {
$members_values$
}

pub impl $type_name$Definition of dojo::event::EventDefinition<$type_name$>{
#[inline(always)]
fn name() -> ByteArray {
"$type_name$"
}
}

#[inline(always)]
fn definition() -> dojo::event::EventDefinition {
dojo::event::EventDefinition {
name: Self::name(),
layout: Self::layout(),
schema: Self::schema()
}
}

#[inline(always)]
fn layout() -> dojo::meta::Layout {
dojo::meta::introspect::Introspect::<$type_name$>::layout()
}

#[inline(always)]
fn schema() -> dojo::meta::introspect::Struct {
if let dojo::meta::introspect::Ty::Struct(s) = dojo::meta::introspect::Introspect::<$type_name$>::ty() {
s
}
else {
panic!("Event `$type_name$`: invalid schema.")
}
}

#[inline(always)]
fn serialized_keys(self: @$type_name$) -> Span<felt252> {
pub impl $type_name$ModelParser of dojo::model::model::ModelParser<$type_name$>{
fn serialize_keys(self: @$type_name$) -> Span<felt252> {
let mut serialized = core::array::ArrayTrait::new();
$serialized_keys$
core::array::ArrayTrait::span(@serialized)
}

#[inline(always)]
fn serialized_values(self: @$type_name$) -> Span<felt252> {
fn serialize_values(self: @$type_name$) -> Span<felt252> {
let mut serialized = core::array::ArrayTrait::new();
$serialized_values$
core::array::ArrayTrait::span(@serialized)
}

#[inline(always)]
fn selector(namespace_hash: felt252) -> felt252 {
dojo::utils::selector_from_namespace_and_name(namespace_hash, @Self::name())
}
}

pub impl $type_name$EventImpl = dojo::event::event::EventImpl<$type_name$>;

#[starknet::contract]
pub mod e_$type_name$ {
use super::$type_name$;
use super::$type_name$Value;

#[storage]
struct Storage {}
Expand All @@ -74,6 +56,13 @@ pub mod e_$type_name$ {
let _event = event;
}

// Outputs EventValue to allow a simple diff from the ABI compared to the
// event to retrieved the keys of an event.
#[external(v0)]
fn ensure_values(self: @ContractState, value: $type_name$Value) {
let _value = value;
}

// Ensures the generated contract has a unique classhash, using
// a hardcoded hash computed on event and member names.
#[external(v0)]
Expand Down
1 change: 1 addition & 0 deletions scripts/rebuild_test_artifacts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ cargo +nightly-2024-08-28 fmt --all -- "$@"
# CAIRO_FIX_TESTS=1 cargo test --package dojo-lang semantics

# Re-run the minimal tests, this will re-build the projects + generate the build artifacts.
./target/release/sozo build --manifest-path examples/simple/Scarb.toml
./target/release/sozo build --manifest-path examples/spawn-and-move/Scarb.toml
./target/release/sozo build --manifest-path examples/spawn-and-move/Scarb.toml -P release
./target/release/sozo build --manifest-path crates/torii/types-test/Scarb.toml
Expand Down
Binary file modified spawn-and-move-db.tar.gz
Binary file not shown.
Binary file modified types-test-db.tar.gz
Binary file not shown.

0 comments on commit cd7b3ca

Please sign in to comment.