From d39fff68c25104a6a0f17aa5e3b55f1e5ac4705e Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 18 Oct 2023 14:05:16 +0200 Subject: [PATCH 01/40] feat(log_data_indexes): Added SerializableFelt252Dict --- src/event/event_utils.cairo | 5 +- src/lib.cairo | 1 + src/utils/serializable_felt_dict.cairo | 125 +++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 src/utils/serializable_felt_dict.cairo diff --git a/src/event/event_utils.cairo b/src/event/event_utils.cairo index a4c839bd..3c0c61a1 100644 --- a/src/event/event_utils.cairo +++ b/src/event/event_utils.cairo @@ -3,6 +3,7 @@ use array::ArrayTrait; use satoru::utils::i128::{I128Serde, I128Default}; use traits::Default; use satoru::utils::traits::ContractAddressDefault; +use satoru::utils::serializable_felt_dict::{SerializableFelt252Dict, SerializableFelt252DictTrait}; //TODO Switch the append with a set in the functions when its available #[derive(Drop, Serde)] @@ -83,7 +84,7 @@ struct IntArrayKeyValue { //bool #[derive(Default, Serde, Drop)] struct BoolItems { - items: Array, + items: SerializableFelt252Dict, array_items: Array, } @@ -218,7 +219,7 @@ fn set_item_array_int_items( fn set_item_bool_items(mut items: BoolItems, index: u32, key: felt252, value: bool) -> BoolItems { let bool_key_value: BoolKeyValue = BoolKeyValue { key, value }; let mut address: BoolItems = items; - address.items.append(bool_key_value); + address.items.add(key, bool_key_value); return address; } diff --git a/src/lib.cairo b/src/lib.cairo index 2e3cdd5d..2357ec99 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -153,6 +153,7 @@ mod utils { mod starknet_utils; mod traits; mod default; + mod serializable_felt_dict; } // `liquidation` function to help with liquidations. diff --git a/src/utils/serializable_felt_dict.cairo b/src/utils/serializable_felt_dict.cairo new file mode 100644 index 00000000..287d8608 --- /dev/null +++ b/src/utils/serializable_felt_dict.cairo @@ -0,0 +1,125 @@ +use core::array::SpanTrait; +use core::array::ArrayTrait; +use core::traits::Into; +use starknet::{get_caller_address, ContractAddress, contract_address_const}; +use traits::Default; +use dict::Felt252DictTrait; +use nullable::{nullable_from_box, match_nullable, FromNullableResult}; + +/// TODO docs. +#[derive(Default, Drop)] +struct SerializableFelt252Dict { + keys: Array, + values: Felt252Dict>, +} + +impl Felt252DictDrop> of Drop>; +impl Felt252DictCopy> of Copy>; + +trait SerializableFelt252DictTrait { + /// Creates a new SerializableFelt252Dict object. + fn new() -> SerializableFelt252Dict; + /// Adds an element. + fn add(ref self: SerializableFelt252Dict, key: felt252, value: T); + /// Gets an element. + fn get>(ref self: SerializableFelt252Dict, key: felt252) -> T; + /// Checks if a key is in the dictionnary. + fn contains_key(self: @SerializableFelt252Dict, key: felt252) -> bool; + /// Length of the dictionnary. + fn len(self: @SerializableFelt252Dict) -> usize; + /// Checks if a dictionnary is empty. + fn is_empty(self: @SerializableFelt252Dict) -> bool; +} + +impl SerializableFelt252DictImpl< + T, impl TDefault: Felt252DictValue, impl TDrop: Drop, impl TCopy: Copy +> of SerializableFelt252DictTrait { + fn new() -> SerializableFelt252Dict { + SerializableFelt252Dict { keys: array![], values: Default::default() } + } + + fn add(ref self: SerializableFelt252Dict, key: felt252, value: T) { + self.values.insert(0, nullable_from_box(BoxTrait::new(value))); + } + + fn get>(ref self: SerializableFelt252Dict, key: felt252) -> T { + match match_nullable(self.values.get(key)) { + FromNullableResult::Null(()) => panic_with_felt252('No value found'), + FromNullableResult::NotNull(val) => val.unbox(), + } + } + + fn contains_key(self: @SerializableFelt252Dict, key: felt252) -> bool { + let mut keys: Span = self.keys.span(); + let mut contains_key: bool = false; + loop { + match keys.pop_front() { + Option::Some(value) => { + if *value == key { + contains_key = true; + break; + } + }, + Option::None => { + break; + }, + }; + }; + return contains_key; + } + + fn len(self: @SerializableFelt252Dict) -> usize { + self.keys.len() + } + + fn is_empty(self: @SerializableFelt252Dict) -> bool { + self.keys.is_empty() + } +} + +/// TODO: Currently only the value is serizalized & we loose the key information. +impl SerializableFelt252DictSerde< + T, impl TDrop: Drop, impl TCopy: Copy, impl TSerde: Serde, impl TInto: Into +> of Serde> { + fn serialize(self: @SerializableFelt252Dict, ref output: Array) { + let mut keys: Span = self.keys.span(); + loop { + match keys.pop_front() { + Option::Some(key) => { + let mut values: Felt252Dict> = *self.values; + let value = match match_nullable(values.get(*key)) { + FromNullableResult::Null(()) => panic_with_felt252('Serialize key error'), + FromNullableResult::NotNull(boxed_value) => boxed_value.unbox(), + }; + value.serialize(ref output); + }, + Option::None => { + break; + }, + }; + } + } + + fn deserialize(ref serialized: Span) -> Option> { + let mut initial_key: felt252 = '0'; + let mut d: SerializableFelt252Dict = SerializableFelt252Dict { + keys: array![], values: Default::default() + }; + loop { + match serialized.pop_front() { + Option::Some(value) => { + let value: T = (*value).into(); + let value = nullable_from_box(BoxTrait::new(value)); + d.values.insert(initial_key, value); + d.keys.append(initial_key); + initial_key += 1; + }, + Option::None => { + break; + }, + }; + }; + Option::Some(d) + } +} + From 9130137f5d0aeb1d24c7fe976b1c7651f584e2fc Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 18 Oct 2023 14:24:58 +0200 Subject: [PATCH 02/40] feat(log_data_indexes): Added docstring for SerializableFelt252Dict --- src/utils/serializable_felt_dict.cairo | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/utils/serializable_felt_dict.cairo b/src/utils/serializable_felt_dict.cairo index 287d8608..5967286e 100644 --- a/src/utils/serializable_felt_dict.cairo +++ b/src/utils/serializable_felt_dict.cairo @@ -6,7 +6,18 @@ use traits::Default; use dict::Felt252DictTrait; use nullable::{nullable_from_box, match_nullable, FromNullableResult}; -/// TODO docs. +/// +/// SerializableFelt252Dict +/// +/// Wrapper around the Felt252Dict. +/// It behaves the same as a regular dict but has also a keys parameter +/// that keeps track of the keys registered. +/// This allows us to serialize & deserialize the struct, which is not +/// possible with a regular Felt252Dict. +/// +/// * keys: Array => the keys currently stored in the dictionnary +/// * values: Felt252Dict> => dictionnary containing the values of type T +/// #[derive(Default, Drop)] struct SerializableFelt252Dict { keys: Array, From 9e462e198a4ee82610105e132296b96aadfd81ae Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 18 Oct 2023 15:23:15 +0200 Subject: [PATCH 03/40] feat(log_data_indexes): Draft --- src/event/event_utils.cairo | 4 +++- src/utils/serializable_felt_dict.cairo | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/event/event_utils.cairo b/src/event/event_utils.cairo index 3c0c61a1..00556156 100644 --- a/src/event/event_utils.cairo +++ b/src/event/event_utils.cairo @@ -3,7 +3,9 @@ use array::ArrayTrait; use satoru::utils::i128::{I128Serde, I128Default}; use traits::Default; use satoru::utils::traits::ContractAddressDefault; -use satoru::utils::serializable_felt_dict::{SerializableFelt252Dict, SerializableFelt252DictTrait}; +use satoru::utils::serializable_felt_dict::{ + SerializableFelt252Dict, SerializableFelt252DictTrait, SerializableFelt252DictSerde +}; //TODO Switch the append with a set in the functions when its available #[derive(Drop, Serde)] diff --git a/src/utils/serializable_felt_dict.cairo b/src/utils/serializable_felt_dict.cairo index 5967286e..ae110d7f 100644 --- a/src/utils/serializable_felt_dict.cairo +++ b/src/utils/serializable_felt_dict.cairo @@ -112,7 +112,7 @@ impl SerializableFelt252DictSerde< } fn deserialize(ref serialized: Span) -> Option> { - let mut initial_key: felt252 = '0'; + let mut current_key: felt252 = 0; let mut d: SerializableFelt252Dict = SerializableFelt252Dict { keys: array![], values: Default::default() }; @@ -121,9 +121,9 @@ impl SerializableFelt252DictSerde< Option::Some(value) => { let value: T = (*value).into(); let value = nullable_from_box(BoxTrait::new(value)); - d.values.insert(initial_key, value); - d.keys.append(initial_key); - initial_key += 1; + d.values.insert(current_key, value); + d.keys.append(current_key); + current_key += 1; }, Option::None => { break; From 9b1597d6fca8c97e61b494accf21ad859de99e2c Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 18 Oct 2023 15:27:18 +0200 Subject: [PATCH 04/40] feat(log_data_indexes): Added TODO --- src/event/event_utils.cairo | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/event/event_utils.cairo b/src/event/event_utils.cairo index 00556156..ca2989be 100644 --- a/src/event/event_utils.cairo +++ b/src/event/event_utils.cairo @@ -221,7 +221,8 @@ fn set_item_array_int_items( fn set_item_bool_items(mut items: BoolItems, index: u32, key: felt252, value: bool) -> BoolItems { let bool_key_value: BoolKeyValue = BoolKeyValue { key, value }; let mut address: BoolItems = items; - address.items.add(key, bool_key_value); + let dict: SerializableFelt252Dict = address.items; + dict.add(key, bool_key_value); return address; } From 2764875f3f09e59f8e560480b8e33d473d474584 Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 18 Oct 2023 15:38:37 +0200 Subject: [PATCH 05/40] feat(log_data_indexes): get->Option instead of get->T --- src/utils/serializable_felt_dict.cairo | 29 ++++---------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/src/utils/serializable_felt_dict.cairo b/src/utils/serializable_felt_dict.cairo index ae110d7f..64997e9a 100644 --- a/src/utils/serializable_felt_dict.cairo +++ b/src/utils/serializable_felt_dict.cairo @@ -33,9 +33,7 @@ trait SerializableFelt252DictTrait { /// Adds an element. fn add(ref self: SerializableFelt252Dict, key: felt252, value: T); /// Gets an element. - fn get>(ref self: SerializableFelt252Dict, key: felt252) -> T; - /// Checks if a key is in the dictionnary. - fn contains_key(self: @SerializableFelt252Dict, key: felt252) -> bool; + fn get>(ref self: SerializableFelt252Dict, key: felt252) -> Option; /// Length of the dictionnary. fn len(self: @SerializableFelt252Dict) -> usize; /// Checks if a dictionnary is empty. @@ -53,32 +51,13 @@ impl SerializableFelt252DictImpl< self.values.insert(0, nullable_from_box(BoxTrait::new(value))); } - fn get>(ref self: SerializableFelt252Dict, key: felt252) -> T { + fn get>(ref self: SerializableFelt252Dict, key: felt252) -> Option { match match_nullable(self.values.get(key)) { - FromNullableResult::Null(()) => panic_with_felt252('No value found'), - FromNullableResult::NotNull(val) => val.unbox(), + FromNullableResult::Null(()) => Option::None, + FromNullableResult::NotNull(val) => Option::Some(val.unbox()), } } - fn contains_key(self: @SerializableFelt252Dict, key: felt252) -> bool { - let mut keys: Span = self.keys.span(); - let mut contains_key: bool = false; - loop { - match keys.pop_front() { - Option::Some(value) => { - if *value == key { - contains_key = true; - break; - } - }, - Option::None => { - break; - }, - }; - }; - return contains_key; - } - fn len(self: @SerializableFelt252Dict) -> usize { self.keys.len() } From a393b8b3cbb419bf440a907153d88ab2c8d0a05a Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 18 Oct 2023 16:04:49 +0200 Subject: [PATCH 06/40] feat(log_data_indexes): Test almost working --- src/event/event_utils.cairo | 5 ++--- src/utils/serializable_felt_dict.cairo | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/event/event_utils.cairo b/src/event/event_utils.cairo index ca2989be..92d3b465 100644 --- a/src/event/event_utils.cairo +++ b/src/event/event_utils.cairo @@ -90,7 +90,7 @@ struct BoolItems { array_items: Array, } -#[derive(Default, Serde, Drop)] +#[derive(Default, Serde, Drop, Copy, Into)] struct BoolKeyValue { key: felt252, value: bool, @@ -221,8 +221,7 @@ fn set_item_array_int_items( fn set_item_bool_items(mut items: BoolItems, index: u32, key: felt252, value: bool) -> BoolItems { let bool_key_value: BoolKeyValue = BoolKeyValue { key, value }; let mut address: BoolItems = items; - let dict: SerializableFelt252Dict = address.items; - dict.add(key, bool_key_value); + address.items.add(key, bool_key_value); return address; } diff --git a/src/utils/serializable_felt_dict.cairo b/src/utils/serializable_felt_dict.cairo index 64997e9a..543a09e6 100644 --- a/src/utils/serializable_felt_dict.cairo +++ b/src/utils/serializable_felt_dict.cairo @@ -41,7 +41,7 @@ trait SerializableFelt252DictTrait { } impl SerializableFelt252DictImpl< - T, impl TDefault: Felt252DictValue, impl TDrop: Drop, impl TCopy: Copy + T, impl TDefault: Default, impl TDrop: Drop, impl TCopy: Copy > of SerializableFelt252DictTrait { fn new() -> SerializableFelt252Dict { SerializableFelt252Dict { keys: array![], values: Default::default() } From 3754f745283778610709df6ea12a5a25697b55ca Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 18 Oct 2023 16:41:53 +0200 Subject: [PATCH 07/40] feat(log_data_indexes): Serializing OK but still errs --- src/event/event_utils.cairo | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/event/event_utils.cairo b/src/event/event_utils.cairo index 92d3b465..d3c5fb59 100644 --- a/src/event/event_utils.cairo +++ b/src/event/event_utils.cairo @@ -83,26 +83,37 @@ struct IntArrayKeyValue { value: Array, } -//bool -#[derive(Default, Serde, Drop)] + +/// Bool + +#[derive(Default, Serde, Drop, Copy, Into)] struct BoolItems { items: SerializableFelt252Dict, array_items: Array, } +impl Felt252IntoBoolKeyValue of Into { + fn into(self: felt252) -> BoolKeyValue { + BoolKeyValue { key: 'TODO_placeholder', // TODO: actual implementation + value: true } + } +} + #[derive(Default, Serde, Drop, Copy, Into)] struct BoolKeyValue { key: felt252, value: bool, } -#[derive(Default, Serde, Drop)] +#[derive(Default, Serde, Drop, Copy, Into)] struct BoolArrayKeyValue { key: felt252, value: Array, } -//Felt252 + +/// Felt252 + #[derive(Default, Serde, Drop)] struct Felt252Items { items: Array, From 20e10cf7dfb3394b08db430a51904190d4a86e5f Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 18 Oct 2023 18:36:50 +0200 Subject: [PATCH 08/40] feat(log_data_indexes): Revert event_utils & trying different things in SerializableFeltDict --- src/event/event_utils.cairo | 28 ++++++---------------- src/utils/serializable_felt_dict.cairo | 33 ++++++++++---------------- 2 files changed, 20 insertions(+), 41 deletions(-) diff --git a/src/event/event_utils.cairo b/src/event/event_utils.cairo index d3c5fb59..a4c839bd 100644 --- a/src/event/event_utils.cairo +++ b/src/event/event_utils.cairo @@ -3,9 +3,6 @@ use array::ArrayTrait; use satoru::utils::i128::{I128Serde, I128Default}; use traits::Default; use satoru::utils::traits::ContractAddressDefault; -use satoru::utils::serializable_felt_dict::{ - SerializableFelt252Dict, SerializableFelt252DictTrait, SerializableFelt252DictSerde -}; //TODO Switch the append with a set in the functions when its available #[derive(Drop, Serde)] @@ -83,37 +80,26 @@ struct IntArrayKeyValue { value: Array, } - -/// Bool - -#[derive(Default, Serde, Drop, Copy, Into)] +//bool +#[derive(Default, Serde, Drop)] struct BoolItems { - items: SerializableFelt252Dict, + items: Array, array_items: Array, } -impl Felt252IntoBoolKeyValue of Into { - fn into(self: felt252) -> BoolKeyValue { - BoolKeyValue { key: 'TODO_placeholder', // TODO: actual implementation - value: true } - } -} - -#[derive(Default, Serde, Drop, Copy, Into)] +#[derive(Default, Serde, Drop)] struct BoolKeyValue { key: felt252, value: bool, } -#[derive(Default, Serde, Drop, Copy, Into)] +#[derive(Default, Serde, Drop)] struct BoolArrayKeyValue { key: felt252, value: Array, } - -/// Felt252 - +//Felt252 #[derive(Default, Serde, Drop)] struct Felt252Items { items: Array, @@ -232,7 +218,7 @@ fn set_item_array_int_items( fn set_item_bool_items(mut items: BoolItems, index: u32, key: felt252, value: bool) -> BoolItems { let bool_key_value: BoolKeyValue = BoolKeyValue { key, value }; let mut address: BoolItems = items; - address.items.add(key, bool_key_value); + address.items.append(bool_key_value); return address; } diff --git a/src/utils/serializable_felt_dict.cairo b/src/utils/serializable_felt_dict.cairo index 543a09e6..7f48a0b2 100644 --- a/src/utils/serializable_felt_dict.cairo +++ b/src/utils/serializable_felt_dict.cairo @@ -18,30 +18,23 @@ use nullable::{nullable_from_box, match_nullable, FromNullableResult}; /// * keys: Array => the keys currently stored in the dictionnary /// * values: Felt252Dict> => dictionnary containing the values of type T /// -#[derive(Default, Drop)] +#[derive(Default, Destruct)] struct SerializableFelt252Dict { keys: Array, values: Felt252Dict>, } -impl Felt252DictDrop> of Drop>; -impl Felt252DictCopy> of Copy>; - -trait SerializableFelt252DictTrait { - /// Creates a new SerializableFelt252Dict object. - fn new() -> SerializableFelt252Dict; - /// Adds an element. - fn add(ref self: SerializableFelt252Dict, key: felt252, value: T); - /// Gets an element. - fn get>(ref self: SerializableFelt252Dict, key: felt252) -> Option; - /// Length of the dictionnary. - fn len(self: @SerializableFelt252Dict) -> usize; - /// Checks if a dictionnary is empty. - fn is_empty(self: @SerializableFelt252Dict) -> bool; +impl DestructSerializableFelt252Dict< + T, impl TDrop: Drop +> of Destruct> { + fn destruct(self: SerializableFelt252Dict) nopanic { + self.values.squash(); + } } +#[generate_trait] impl SerializableFelt252DictImpl< - T, impl TDefault: Default, impl TDrop: Drop, impl TCopy: Copy + T, impl TDefault: Default, impl TDrop: Drop > of SerializableFelt252DictTrait { fn new() -> SerializableFelt252Dict { SerializableFelt252Dict { keys: array![], values: Default::default() } @@ -69,19 +62,19 @@ impl SerializableFelt252DictImpl< /// TODO: Currently only the value is serizalized & we loose the key information. impl SerializableFelt252DictSerde< - T, impl TDrop: Drop, impl TCopy: Copy, impl TSerde: Serde, impl TInto: Into + T, impl TDrop: Drop, impl TSerde: Serde, impl TInto: Into > of Serde> { fn serialize(self: @SerializableFelt252Dict, ref output: Array) { let mut keys: Span = self.keys.span(); loop { match keys.pop_front() { Option::Some(key) => { - let mut values: Felt252Dict> = *self.values; - let value = match match_nullable(values.get(*key)) { + let values: Felt252Dict> = *(self.values); + let (entry, value) = values.entry(*key); + let value = match match_nullable(value) { FromNullableResult::Null(()) => panic_with_felt252('Serialize key error'), FromNullableResult::NotNull(boxed_value) => boxed_value.unbox(), }; - value.serialize(ref output); }, Option::None => { break; From bd37409f9a00de4a9cb6f96804d9e618ae269b04 Mon Sep 17 00:00:00 2001 From: akhercha Date: Tue, 24 Oct 2023 22:19:47 +0200 Subject: [PATCH 09/40] feat(log_data_indexes): OrderedDict tries --- src/event/event_utils_sandbox.cairo | 34 ++++ src/lib.cairo | 3 +- src/utils/ordered_dict.cairo | 271 +++++++++++++++++++++++++ src/utils/serializable_felt_dict.cairo | 108 ---------- 4 files changed, 307 insertions(+), 109 deletions(-) create mode 100644 src/event/event_utils_sandbox.cairo create mode 100644 src/utils/ordered_dict.cairo delete mode 100644 src/utils/serializable_felt_dict.cairo diff --git a/src/event/event_utils_sandbox.cairo b/src/event/event_utils_sandbox.cairo new file mode 100644 index 00000000..af99c424 --- /dev/null +++ b/src/event/event_utils_sandbox.cairo @@ -0,0 +1,34 @@ +use starknet::{get_caller_address, ContractAddress, contract_address_const}; +use array::ArrayTrait; +use satoru::utils::i128::{I128Serde, I128Default}; +use traits::Default; +use satoru::utils::traits::ContractAddressDefault; + +use satoru::utils::ordered_dict::{OrderedDict, OrderedDictTraitImpl, OrderedDictSerde, Value}; + +//TODO Switch the append with a set in the functions when its available +#[derive(Serde, Destruct)] +struct EventLogData { + cant_be_empty: u128, // remove +// TODO +} + +#[derive(Default, Destruct, Serde)] +struct LogData { + bool_items: OrderedDict, +} + +// bool +fn set_item_bool_items( + mut dict: OrderedDict, index: u32, key: felt252, value: bool +) -> OrderedDict { + OrderedDictTraitImpl::add_single(ref dict, key, value); + dict +} + +fn set_item_array_bool_items( + mut dict: OrderedDict, index: u32, key: felt252, value: Array +) -> OrderedDict { + OrderedDictTraitImpl::add_multiple(ref dict, key, value); + dict +} diff --git a/src/lib.cairo b/src/lib.cairo index 2357ec99..b9342d04 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -44,6 +44,7 @@ mod config { // `event` is a module event management functions. mod event { mod event_utils; + mod event_utils_sandbox; mod event_emitter; } @@ -153,7 +154,7 @@ mod utils { mod starknet_utils; mod traits; mod default; - mod serializable_felt_dict; + mod ordered_dict; } // `liquidation` function to help with liquidations. diff --git a/src/utils/ordered_dict.cairo b/src/utils/ordered_dict.cairo new file mode 100644 index 00000000..70512d1f --- /dev/null +++ b/src/utils/ordered_dict.cairo @@ -0,0 +1,271 @@ +use core::serde::Serde; +use core::array::SpanTrait; +use core::array::ArrayTrait; +use core::traits::Into; +use starknet::{get_caller_address, ContractAddress, contract_address_const}; +use traits::Default; +use dict::{Felt252DictTrait, Felt252Dict}; +use nullable::{nullable_from_box, match_nullable, FromNullableResult, Nullable}; + +use alexandria_data_structures::array_ext::ArrayTraitExt; + +#[derive(Drop, Copy)] +enum Value { + Single: T, + Multiple: Array +} + +#[derive(Default, Copy)] +struct OrderedDict { + keys: Array, + values: Felt252Dict>> +} + +impl OrderedDictDestruct< + T, impl TDrop: Drop, impl TDefault: Felt252DictValue +> of Destruct> { + fn destruct(self: OrderedDict) nopanic { + self.values.squash(); + self.keys.destruct(); + } +} + +impl ArrayTCopy of Copy>; +impl Felt252DictValueTCopy of Copy>>>; + +impl TArraySerialize< + T, + impl TDrop: Drop, + impl TCopy: Copy, + impl TIntoT: Into, + impl TIntoFelt: Into +> of Serde> { + fn serialize(self: @Array, ref output: Array) { + let mut span_arr = self.span(); + loop { + match span_arr.pop_front() { + Option::Some(v) => { + let as_felt: felt252 = (*v).into(); + output.append(as_felt); + }, + Option::None => { + break; + } + }; + } + } + + fn deserialize(ref serialized: Span) -> Option> { + let mut arr: Array = array![]; + loop { + match serialized.pop_front() { + Option::Some(v) => { + arr.append((*v).into()); + }, + Option::None => { + break; + } + }; + }; + Option::Some(arr) + } +} + +trait OrderedDictTrait { + /// Creates a new OrderedDict object. + fn new() -> OrderedDict; + /// Adds an element. + fn add_single(ref self: OrderedDict, key: felt252, value: T); + /// Adds an array of elements. + fn add_multiple(ref self: OrderedDict, key: felt252, values: Array); + /// Gets an element. + fn get>(ref self: OrderedDict, key: felt252) -> Value; + /// Checks if a key is in the dictionnary. + fn contains_key(self: @OrderedDict, key: felt252) -> bool; + /// Checks if a dictionnary is empty. + fn is_empty(self: @OrderedDict) -> bool; +} + +impl OrderedDictTraitImpl< + T, impl TDefault: Felt252DictValue, impl TDrop: Drop, impl TCopy: Copy +> of OrderedDictTrait { + fn new() -> OrderedDict { + OrderedDict { keys: array![], values: Default::default() } + } + + fn add_single(ref self: OrderedDict, key: felt252, value: T) { + let value = Value::Single(value); + self.values.insert(0, nullable_from_box(BoxTrait::new(value))); + } + + fn add_multiple(ref self: OrderedDict, key: felt252, values: Array) { + let values = Value::Multiple(values); + self.values.insert(0, nullable_from_box(BoxTrait::new(values))); + } + + fn get>(ref self: OrderedDict, key: felt252) -> Value { + match match_nullable(self.values.get(key)) { + FromNullableResult::Null(()) => panic_with_felt252('No value found'), + FromNullableResult::NotNull(val) => val.unbox(), + } + } + + fn contains_key(self: @OrderedDict, key: felt252) -> bool { + let mut keys: Span = self.keys.span(); + let mut contains_key: bool = false; + loop { + match keys.pop_front() { + Option::Some(value) => { + if *value == key { + contains_key = true; + break; + } + }, + Option::None => { + break; + }, + }; + }; + return contains_key; + } + + fn is_empty(self: @OrderedDict) -> bool { + self.keys.is_empty() + } +} + + +impl OrderedDictSerde< + T, + impl TCopy: Copy, + impl TDrop: Drop, + impl TIntoT: Into, + impl TIntoFelt: Into, + impl TPartialOrd: PartialOrd +> of Serde> { + // + // Serialization of an OrderedDict + // + // An OrderedDict is serialized as follow: + // [ KEY | NB_ELEMENTS | X | Y | ... | KEY | NB_ELEMENTS | X | ...] + // + // + // e.g. if we try to serialize this Dict: + // keys: [0, 1] + // values: { + // 0: 1, + // 1: [1, 2, 3] + // } + // + // will give: + // + // key: 0 key: 1 + // | ------ | ----------- | + // [0, 1, 1, 1, 3, 1, 2, 3] (Array) + // + fn serialize(self: @OrderedDict, ref output: Array) { + let mut keys: Span = self.keys.span(); + let mut included_keys: Array = array![]; + loop { + match keys.pop_back() { + Option::Some(key) => { + if (!included_keys.contains(*key)) { + continue; + } + let mut ordered_dict = (*self); + let nullable_value: Nullable> = ordered_dict.values.get(*key); + let value: Value = match match_nullable(nullable_value) { + FromNullableResult::Null(()) => panic_with_felt252( + 'key not found (serialize)' + ), + FromNullableResult::NotNull(boxed_value) => boxed_value.unbox(), + }; + match value { + Value::Single(v) => { + output.append(*key); // key + output.append(1_felt252); // len + output.append(v.into()); // value + }, + Value::Multiple(arr) => { + output.append(*key); // key + output.append(arr.len().into()); // len + let mut arr_as_span: Span = arr.span(); + loop { + match arr_as_span.pop_front() { + Option::Some(v) => { + output.append((*v).into()); + }, + Option::None => { + break; + } + }; + } + } + }; + included_keys.append(*key); + }, + Option::None => { + break; + }, + }; + } + } + + // + // Deserialization of an OrderedDict + // + // An OrderedDict is serialized as follow: + // [ KEY | NB_ELEMENTS | X | Y | ... | KEY | NB_ELEMENTS | X | ...] + // + fn deserialize(ref serialized: Span) -> Option> { + let mut d: OrderedDict = OrderedDict { keys: array![], values: Default::default() }; + loop { + // Try to retrive the next key + match serialized.pop_front() { + Option::Some(key) => { + // Key found; try to retrieved the size of elements + match serialized.pop_front() { + Option::Some(size) => { + // If only one element, insert it & quit + if ((*size) == 1) { + let value: T = get_next_value_from(serialized); + let value: Value = Value::Single(value); + d.values.insert(*key, nullable_from_box(BoxTrait::new(value))); + continue; + } + // Else append all elements into an array ... + let mut arr_size: felt252 = *size; + let mut arr_values: Array = array![]; + loop { + if (arr_size) == 0 { + break; + }; + let value: T = get_next_value_from(serialized); + arr_values.append(value); + arr_size -= 1; + }; + // ... & insert it + let values: Value = Value::Multiple(arr_values); + d.values.insert(*key, nullable_from_box(BoxTrait::new(values))); + }, + Option::None => panic_with_felt252('err getting size') + } + }, + Option::None => { + break; + }, + }; + }; + Option::Some(d) + } +} + + +fn get_next_value_from>(mut serialized: Span) -> T { + let value = match serialized.pop_front() { + Option::Some(value) => value, + Option::None => panic_with_felt252('err getting value') + }; + let value: T = (*value).into(); + value +} diff --git a/src/utils/serializable_felt_dict.cairo b/src/utils/serializable_felt_dict.cairo deleted file mode 100644 index 7f48a0b2..00000000 --- a/src/utils/serializable_felt_dict.cairo +++ /dev/null @@ -1,108 +0,0 @@ -use core::array::SpanTrait; -use core::array::ArrayTrait; -use core::traits::Into; -use starknet::{get_caller_address, ContractAddress, contract_address_const}; -use traits::Default; -use dict::Felt252DictTrait; -use nullable::{nullable_from_box, match_nullable, FromNullableResult}; - -/// -/// SerializableFelt252Dict -/// -/// Wrapper around the Felt252Dict. -/// It behaves the same as a regular dict but has also a keys parameter -/// that keeps track of the keys registered. -/// This allows us to serialize & deserialize the struct, which is not -/// possible with a regular Felt252Dict. -/// -/// * keys: Array => the keys currently stored in the dictionnary -/// * values: Felt252Dict> => dictionnary containing the values of type T -/// -#[derive(Default, Destruct)] -struct SerializableFelt252Dict { - keys: Array, - values: Felt252Dict>, -} - -impl DestructSerializableFelt252Dict< - T, impl TDrop: Drop -> of Destruct> { - fn destruct(self: SerializableFelt252Dict) nopanic { - self.values.squash(); - } -} - -#[generate_trait] -impl SerializableFelt252DictImpl< - T, impl TDefault: Default, impl TDrop: Drop -> of SerializableFelt252DictTrait { - fn new() -> SerializableFelt252Dict { - SerializableFelt252Dict { keys: array![], values: Default::default() } - } - - fn add(ref self: SerializableFelt252Dict, key: felt252, value: T) { - self.values.insert(0, nullable_from_box(BoxTrait::new(value))); - } - - fn get>(ref self: SerializableFelt252Dict, key: felt252) -> Option { - match match_nullable(self.values.get(key)) { - FromNullableResult::Null(()) => Option::None, - FromNullableResult::NotNull(val) => Option::Some(val.unbox()), - } - } - - fn len(self: @SerializableFelt252Dict) -> usize { - self.keys.len() - } - - fn is_empty(self: @SerializableFelt252Dict) -> bool { - self.keys.is_empty() - } -} - -/// TODO: Currently only the value is serizalized & we loose the key information. -impl SerializableFelt252DictSerde< - T, impl TDrop: Drop, impl TSerde: Serde, impl TInto: Into -> of Serde> { - fn serialize(self: @SerializableFelt252Dict, ref output: Array) { - let mut keys: Span = self.keys.span(); - loop { - match keys.pop_front() { - Option::Some(key) => { - let values: Felt252Dict> = *(self.values); - let (entry, value) = values.entry(*key); - let value = match match_nullable(value) { - FromNullableResult::Null(()) => panic_with_felt252('Serialize key error'), - FromNullableResult::NotNull(boxed_value) => boxed_value.unbox(), - }; - }, - Option::None => { - break; - }, - }; - } - } - - fn deserialize(ref serialized: Span) -> Option> { - let mut current_key: felt252 = 0; - let mut d: SerializableFelt252Dict = SerializableFelt252Dict { - keys: array![], values: Default::default() - }; - loop { - match serialized.pop_front() { - Option::Some(value) => { - let value: T = (*value).into(); - let value = nullable_from_box(BoxTrait::new(value)); - d.values.insert(current_key, value); - d.keys.append(current_key); - current_key += 1; - }, - Option::None => { - break; - }, - }; - }; - Option::Some(d) - } -} - From 63595efffef8b0cb40889b3bdb4b33c654a11e19 Mon Sep 17 00:00:00 2001 From: akhercha Date: Tue, 24 Oct 2023 22:52:18 +0200 Subject: [PATCH 10/40] feat(log_data_indexes): Compiles --- src/event/event_utils_sandbox.cairo | 48 ++++++++++++++++++++++++++--- src/utils/ordered_dict.cairo | 11 +++---- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/event/event_utils_sandbox.cairo b/src/event/event_utils_sandbox.cairo index af99c424..f8953f41 100644 --- a/src/event/event_utils_sandbox.cairo +++ b/src/event/event_utils_sandbox.cairo @@ -4,10 +4,33 @@ use satoru::utils::i128::{I128Serde, I128Default}; use traits::Default; use satoru::utils::traits::ContractAddressDefault; -use satoru::utils::ordered_dict::{OrderedDict, OrderedDictTraitImpl, OrderedDictSerde, Value}; +use satoru::utils::ordered_dict::{OrderedDict, OrderedDictTraitImpl, OrderedDictSerde}; + +// +// NEEDED IMPLEMENTATIONS... +// + +impl Felt252IntoBool of Into { + #[inline(always)] + fn into(self: felt252) -> bool { + let as_u8: u8 = self.try_into().unwrap(); + as_u8 > 0 + } +} + +impl Felt252IntoU128 of Into { + #[inline(always)] + fn into(self: felt252) -> u128 { + self.try_into().unwrap() + } +} + +// +// LOG DATA +// //TODO Switch the append with a set in the functions when its available -#[derive(Serde, Destruct)] +#[derive(Default, Serde, Destruct)] struct EventLogData { cant_be_empty: u128, // remove // TODO @@ -15,9 +38,26 @@ struct EventLogData { #[derive(Default, Destruct, Serde)] struct LogData { + uint_items: OrderedDict, bool_items: OrderedDict, } +// uint +fn set_item_uint_items( + mut dict: OrderedDict, index: u32, key: felt252, value: u128 +) -> OrderedDict { + OrderedDictTraitImpl::add_single(ref dict, key, value); + dict +} + +fn set_item_array_uint_items( + mut dict: OrderedDict, index: u32, key: felt252, values: Array +) -> OrderedDict { + OrderedDictTraitImpl::add_multiple(ref dict, key, values); + dict +} + + // bool fn set_item_bool_items( mut dict: OrderedDict, index: u32, key: felt252, value: bool @@ -27,8 +67,8 @@ fn set_item_bool_items( } fn set_item_array_bool_items( - mut dict: OrderedDict, index: u32, key: felt252, value: Array + mut dict: OrderedDict, index: u32, key: felt252, values: Array ) -> OrderedDict { - OrderedDictTraitImpl::add_multiple(ref dict, key, value); + OrderedDictTraitImpl::add_multiple(ref dict, key, values); dict } diff --git a/src/utils/ordered_dict.cairo b/src/utils/ordered_dict.cairo index 70512d1f..119d0da9 100644 --- a/src/utils/ordered_dict.cairo +++ b/src/utils/ordered_dict.cairo @@ -79,7 +79,7 @@ trait OrderedDictTrait { /// Adds an array of elements. fn add_multiple(ref self: OrderedDict, key: felt252, values: Array); /// Gets an element. - fn get>(ref self: OrderedDict, key: felt252) -> Value; + fn get>(ref self: OrderedDict, key: felt252) -> Option>; /// Checks if a key is in the dictionnary. fn contains_key(self: @OrderedDict, key: felt252) -> bool; /// Checks if a dictionnary is empty. @@ -103,10 +103,10 @@ impl OrderedDictTraitImpl< self.values.insert(0, nullable_from_box(BoxTrait::new(values))); } - fn get>(ref self: OrderedDict, key: felt252) -> Value { + fn get>(ref self: OrderedDict, key: felt252) -> Option> { match match_nullable(self.values.get(key)) { - FromNullableResult::Null(()) => panic_with_felt252('No value found'), - FromNullableResult::NotNull(val) => val.unbox(), + FromNullableResult::Null(()) => Option::None, + FromNullableResult::NotNull(val) => Option::Some(val.unbox()), } } @@ -139,9 +139,8 @@ impl OrderedDictSerde< T, impl TCopy: Copy, impl TDrop: Drop, - impl TIntoT: Into, + impl FeltIntoT: Into, impl TIntoFelt: Into, - impl TPartialOrd: PartialOrd > of Serde> { // // Serialization of an OrderedDict From 199d9c93947857b4edc71e4e61211c7d97bff17f Mon Sep 17 00:00:00 2001 From: akhercha Date: Tue, 24 Oct 2023 23:05:22 +0200 Subject: [PATCH 11/40] feat(log_data_indexes): Added i128 --- src/event/event_utils_sandbox.cairo | 36 ++++++++++++++++++++++++++--- src/utils/i128.cairo | 1 + 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/event/event_utils_sandbox.cairo b/src/event/event_utils_sandbox.cairo index f8953f41..7148c185 100644 --- a/src/event/event_utils_sandbox.cairo +++ b/src/event/event_utils_sandbox.cairo @@ -13,15 +13,28 @@ use satoru::utils::ordered_dict::{OrderedDict, OrderedDictTraitImpl, OrderedDict impl Felt252IntoBool of Into { #[inline(always)] fn into(self: felt252) -> bool { - let as_u8: u8 = self.try_into().unwrap(); - as_u8 > 0 + let as_u128: u128 = self.try_into().expect('u128 Overflow'); + as_u128 > 0 } } impl Felt252IntoU128 of Into { #[inline(always)] fn into(self: felt252) -> u128 { - self.try_into().unwrap() + self.try_into().expect('u128 Overflow') + } +} + +impl Felt252IntoI128 of Into { + #[inline(always)] + fn into(self: felt252) -> i128 { + self.try_into().expect('i128 Overflow') + } +} +impl I128252DictValue of Felt252DictValue { + #[inline(always)] + fn zero_default() -> i128 nopanic { + 0 } } @@ -39,6 +52,7 @@ struct EventLogData { #[derive(Default, Destruct, Serde)] struct LogData { uint_items: OrderedDict, + int_items: OrderedDict, bool_items: OrderedDict, } @@ -58,6 +72,22 @@ fn set_item_array_uint_items( } +// int +fn set_item_int_items( + mut dict: OrderedDict, index: u32, key: felt252, value: i128 +) -> OrderedDict { + OrderedDictTraitImpl::add_single(ref dict, key, value); + dict +} + +fn set_item_array_int_items( + mut dict: OrderedDict, index: u32, key: felt252, values: Array +) -> OrderedDict { + OrderedDictTraitImpl::add_multiple(ref dict, key, values); + dict +} + + // bool fn set_item_bool_items( mut dict: OrderedDict, index: u32, key: felt252, value: bool diff --git a/src/utils/i128.cairo b/src/utils/i128.cairo index 45217d30..8b9348c3 100644 --- a/src/utils/i128.cairo +++ b/src/utils/i128.cairo @@ -95,3 +95,4 @@ impl I128Serde of Serde { Option::Some(i128_val) } } + From 7c5d19c137f0e9f2b197d51c261172c420e803f1 Mon Sep 17 00:00:00 2001 From: akhercha Date: Tue, 24 Oct 2023 23:06:47 +0200 Subject: [PATCH 12/40] feat(log_data_indexes): Added felt252 --- src/event/event_utils_sandbox.cairo | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/event/event_utils_sandbox.cairo b/src/event/event_utils_sandbox.cairo index 7148c185..a0aadeda 100644 --- a/src/event/event_utils_sandbox.cairo +++ b/src/event/event_utils_sandbox.cairo @@ -54,6 +54,7 @@ struct LogData { uint_items: OrderedDict, int_items: OrderedDict, bool_items: OrderedDict, + felt252_items: OrderedDict } // uint @@ -102,3 +103,19 @@ fn set_item_array_bool_items( OrderedDictTraitImpl::add_multiple(ref dict, key, values); dict } + + +// felt252 +fn set_item_Felt252_items( + mut dict: OrderedDict, index: u32, key: felt252, value: felt252 +) -> OrderedDict { + OrderedDictTraitImpl::add_single(ref dict, key, value); + dict +} + +fn set_item_array_Felt252_items( + mut dict: OrderedDict, index: u32, key: felt252, values: Array +) -> OrderedDict { + OrderedDictTraitImpl::add_multiple(ref dict, key, values); + dict +} From 936ebdd65187f68d81317b57289584a93dedd16e Mon Sep 17 00:00:00 2001 From: akhercha Date: Tue, 24 Oct 2023 23:18:15 +0200 Subject: [PATCH 13/40] feat(log_data_indexes): Added TODOs --- src/event/event_utils_sandbox.cairo | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/event/event_utils_sandbox.cairo b/src/event/event_utils_sandbox.cairo index a0aadeda..4f0d4295 100644 --- a/src/event/event_utils_sandbox.cairo +++ b/src/event/event_utils_sandbox.cairo @@ -51,10 +51,13 @@ struct EventLogData { #[derive(Default, Destruct, Serde)] struct LogData { + // TODO address_items: OrderedDict uint_items: OrderedDict, int_items: OrderedDict, bool_items: OrderedDict, - felt252_items: OrderedDict + felt252_items: OrderedDict, + // TODO? Possible? array_of_felt_items: OrderedDict>, + string_items: OrderedDict } // uint @@ -119,3 +122,19 @@ fn set_item_array_Felt252_items( OrderedDictTraitImpl::add_multiple(ref dict, key, values); dict } + + +// string +fn set_item_string_items( + mut dict: OrderedDict, index: u32, key: felt252, value: felt252 +) -> OrderedDict { + OrderedDictTraitImpl::add_single(ref dict, key, value); + dict +} + +fn set_item_array_string_items( + mut dict: OrderedDict, index: u32, key: felt252, values: Array +) -> OrderedDict { + OrderedDictTraitImpl::add_multiple(ref dict, key, values); + dict +} From b09d65b0672ded2615414d2765d61a07d16c29b4 Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 25 Oct 2023 09:02:57 +0200 Subject: [PATCH 14/40] feat(log_data_indexes): Renamed structs + address_items impl --- src/event/event_utils_sandbox.cairo | 31 ++++++++++++++++++++++------- src/utils/ordered_dict.cairo | 30 ++++++++++++++-------------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/src/event/event_utils_sandbox.cairo b/src/event/event_utils_sandbox.cairo index 4f0d4295..bdf03282 100644 --- a/src/event/event_utils_sandbox.cairo +++ b/src/event/event_utils_sandbox.cairo @@ -1,4 +1,7 @@ -use starknet::{get_caller_address, ContractAddress, contract_address_const}; +use starknet::{ + get_caller_address, ContractAddress, Felt252TryIntoContractAddress, ContractAddressIntoFelt252, + contract_address_const +}; use array::ArrayTrait; use satoru::utils::i128::{I128Serde, I128Default}; use traits::Default; @@ -31,12 +34,26 @@ impl Felt252IntoI128 of Into { self.try_into().expect('i128 Overflow') } } + +impl Felt252IntoContractAddress of Into { + #[inline(always)] + fn into(self: felt252) -> ContractAddress { + Felt252TryIntoContractAddress::try_into(self).expect('felt252 overflow') + } +} + impl I128252DictValue of Felt252DictValue { #[inline(always)] fn zero_default() -> i128 nopanic { 0 } } +impl ContractAddressDictValue of Felt252DictValue { + #[inline(always)] + fn zero_default() -> ContractAddress nopanic { + contract_address_const::<0>() + } +} // // LOG DATA @@ -51,7 +68,7 @@ struct EventLogData { #[derive(Default, Destruct, Serde)] struct LogData { - // TODO address_items: OrderedDict + address_items: OrderedDict, uint_items: OrderedDict, int_items: OrderedDict, bool_items: OrderedDict, @@ -71,7 +88,7 @@ fn set_item_uint_items( fn set_item_array_uint_items( mut dict: OrderedDict, index: u32, key: felt252, values: Array ) -> OrderedDict { - OrderedDictTraitImpl::add_multiple(ref dict, key, values); + OrderedDictTraitImpl::add_array(ref dict, key, values); dict } @@ -87,7 +104,7 @@ fn set_item_int_items( fn set_item_array_int_items( mut dict: OrderedDict, index: u32, key: felt252, values: Array ) -> OrderedDict { - OrderedDictTraitImpl::add_multiple(ref dict, key, values); + OrderedDictTraitImpl::add_array(ref dict, key, values); dict } @@ -103,7 +120,7 @@ fn set_item_bool_items( fn set_item_array_bool_items( mut dict: OrderedDict, index: u32, key: felt252, values: Array ) -> OrderedDict { - OrderedDictTraitImpl::add_multiple(ref dict, key, values); + OrderedDictTraitImpl::add_array(ref dict, key, values); dict } @@ -119,7 +136,7 @@ fn set_item_Felt252_items( fn set_item_array_Felt252_items( mut dict: OrderedDict, index: u32, key: felt252, values: Array ) -> OrderedDict { - OrderedDictTraitImpl::add_multiple(ref dict, key, values); + OrderedDictTraitImpl::add_array(ref dict, key, values); dict } @@ -135,6 +152,6 @@ fn set_item_string_items( fn set_item_array_string_items( mut dict: OrderedDict, index: u32, key: felt252, values: Array ) -> OrderedDict { - OrderedDictTraitImpl::add_multiple(ref dict, key, values); + OrderedDictTraitImpl::add_array(ref dict, key, values); dict } diff --git a/src/utils/ordered_dict.cairo b/src/utils/ordered_dict.cairo index 119d0da9..e1da6f35 100644 --- a/src/utils/ordered_dict.cairo +++ b/src/utils/ordered_dict.cairo @@ -10,7 +10,7 @@ use nullable::{nullable_from_box, match_nullable, FromNullableResult, Nullable}; use alexandria_data_structures::array_ext::ArrayTraitExt; #[derive(Drop, Copy)] -enum Value { +enum Item { Single: T, Multiple: Array } @@ -18,7 +18,7 @@ enum Value { #[derive(Default, Copy)] struct OrderedDict { keys: Array, - values: Felt252Dict>> + values: Felt252Dict>> } impl OrderedDictDestruct< @@ -31,7 +31,7 @@ impl OrderedDictDestruct< } impl ArrayTCopy of Copy>; -impl Felt252DictValueTCopy of Copy>>>; +impl Felt252DictValueTCopy of Copy>>>; impl TArraySerialize< T, @@ -77,9 +77,9 @@ trait OrderedDictTrait { /// Adds an element. fn add_single(ref self: OrderedDict, key: felt252, value: T); /// Adds an array of elements. - fn add_multiple(ref self: OrderedDict, key: felt252, values: Array); + fn add_array(ref self: OrderedDict, key: felt252, values: Array); /// Gets an element. - fn get>(ref self: OrderedDict, key: felt252) -> Option>; + fn get>(ref self: OrderedDict, key: felt252) -> Option>; /// Checks if a key is in the dictionnary. fn contains_key(self: @OrderedDict, key: felt252) -> bool; /// Checks if a dictionnary is empty. @@ -94,16 +94,16 @@ impl OrderedDictTraitImpl< } fn add_single(ref self: OrderedDict, key: felt252, value: T) { - let value = Value::Single(value); + let value = Item::Single(value); self.values.insert(0, nullable_from_box(BoxTrait::new(value))); } - fn add_multiple(ref self: OrderedDict, key: felt252, values: Array) { - let values = Value::Multiple(values); + fn add_array(ref self: OrderedDict, key: felt252, values: Array) { + let values = Item::Multiple(values); self.values.insert(0, nullable_from_box(BoxTrait::new(values))); } - fn get>(ref self: OrderedDict, key: felt252) -> Option> { + fn get>(ref self: OrderedDict, key: felt252) -> Option> { match match_nullable(self.values.get(key)) { FromNullableResult::Null(()) => Option::None, FromNullableResult::NotNull(val) => Option::Some(val.unbox()), @@ -172,20 +172,20 @@ impl OrderedDictSerde< continue; } let mut ordered_dict = (*self); - let nullable_value: Nullable> = ordered_dict.values.get(*key); - let value: Value = match match_nullable(nullable_value) { + let nullable_value: Nullable> = ordered_dict.values.get(*key); + let value: Item = match match_nullable(nullable_value) { FromNullableResult::Null(()) => panic_with_felt252( 'key not found (serialize)' ), FromNullableResult::NotNull(boxed_value) => boxed_value.unbox(), }; match value { - Value::Single(v) => { + Item::Single(v) => { output.append(*key); // key output.append(1_felt252); // len output.append(v.into()); // value }, - Value::Multiple(arr) => { + Item::Multiple(arr) => { output.append(*key); // key output.append(arr.len().into()); // len let mut arr_as_span: Span = arr.span(); @@ -228,7 +228,7 @@ impl OrderedDictSerde< // If only one element, insert it & quit if ((*size) == 1) { let value: T = get_next_value_from(serialized); - let value: Value = Value::Single(value); + let value: Item = Item::Single(value); d.values.insert(*key, nullable_from_box(BoxTrait::new(value))); continue; } @@ -244,7 +244,7 @@ impl OrderedDictSerde< arr_size -= 1; }; // ... & insert it - let values: Value = Value::Multiple(arr_values); + let values: Item = Item::Multiple(arr_values); d.values.insert(*key, nullable_from_box(BoxTrait::new(values))); }, Option::None => panic_with_felt252('err getting size') From 9999822a5fbd37fd78a3549795c88d7c1ec37f7e Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 25 Oct 2023 09:16:32 +0200 Subject: [PATCH 15/40] feat(log_data_indexes): Generic impl --- src/event/event_utils_sandbox.cairo | 37 ++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/src/event/event_utils_sandbox.cairo b/src/event/event_utils_sandbox.cairo index bdf03282..4405e77e 100644 --- a/src/event/event_utils_sandbox.cairo +++ b/src/event/event_utils_sandbox.cairo @@ -38,7 +38,7 @@ impl Felt252IntoI128 of Into { impl Felt252IntoContractAddress of Into { #[inline(always)] fn into(self: felt252) -> ContractAddress { - Felt252TryIntoContractAddress::try_into(self).expect('felt252 overflow') + Felt252TryIntoContractAddress::try_into(self).expect('contractaddress overflow') } } @@ -77,16 +77,31 @@ struct LogData { string_items: OrderedDict } +// generic ... +fn set_item< + T, T, impl TDefault: Felt252DictValue, impl TDrop: Drop, impl TCopy: Copy +>(mut dict: OrderedDict, key: felt252, value: T) -> OrderedDict { + OrderedDictTraitImpl::add_single(ref dict, key, value); + dict +} + +fn set_array_item< + T, T, impl TDefault: Felt252DictValue, impl TDrop: Drop, impl TCopy: Copy +>(mut dict: OrderedDict, key: felt252, values: Array) -> OrderedDict { + OrderedDictTraitImpl::add_array(ref dict, key, values); + dict +} + // uint fn set_item_uint_items( - mut dict: OrderedDict, index: u32, key: felt252, value: u128 + mut dict: OrderedDict, key: felt252, value: u128 ) -> OrderedDict { OrderedDictTraitImpl::add_single(ref dict, key, value); dict } fn set_item_array_uint_items( - mut dict: OrderedDict, index: u32, key: felt252, values: Array + mut dict: OrderedDict, key: felt252, values: Array ) -> OrderedDict { OrderedDictTraitImpl::add_array(ref dict, key, values); dict @@ -95,14 +110,14 @@ fn set_item_array_uint_items( // int fn set_item_int_items( - mut dict: OrderedDict, index: u32, key: felt252, value: i128 + mut dict: OrderedDict, key: felt252, value: i128 ) -> OrderedDict { OrderedDictTraitImpl::add_single(ref dict, key, value); dict } fn set_item_array_int_items( - mut dict: OrderedDict, index: u32, key: felt252, values: Array + mut dict: OrderedDict, key: felt252, values: Array ) -> OrderedDict { OrderedDictTraitImpl::add_array(ref dict, key, values); dict @@ -111,14 +126,14 @@ fn set_item_array_int_items( // bool fn set_item_bool_items( - mut dict: OrderedDict, index: u32, key: felt252, value: bool + mut dict: OrderedDict, key: felt252, value: bool ) -> OrderedDict { OrderedDictTraitImpl::add_single(ref dict, key, value); dict } fn set_item_array_bool_items( - mut dict: OrderedDict, index: u32, key: felt252, values: Array + mut dict: OrderedDict, key: felt252, values: Array ) -> OrderedDict { OrderedDictTraitImpl::add_array(ref dict, key, values); dict @@ -127,14 +142,14 @@ fn set_item_array_bool_items( // felt252 fn set_item_Felt252_items( - mut dict: OrderedDict, index: u32, key: felt252, value: felt252 + mut dict: OrderedDict, key: felt252, value: felt252 ) -> OrderedDict { OrderedDictTraitImpl::add_single(ref dict, key, value); dict } fn set_item_array_Felt252_items( - mut dict: OrderedDict, index: u32, key: felt252, values: Array + mut dict: OrderedDict, key: felt252, values: Array ) -> OrderedDict { OrderedDictTraitImpl::add_array(ref dict, key, values); dict @@ -143,14 +158,14 @@ fn set_item_array_Felt252_items( // string fn set_item_string_items( - mut dict: OrderedDict, index: u32, key: felt252, value: felt252 + mut dict: OrderedDict, key: felt252, value: felt252 ) -> OrderedDict { OrderedDictTraitImpl::add_single(ref dict, key, value); dict } fn set_item_array_string_items( - mut dict: OrderedDict, index: u32, key: felt252, values: Array + mut dict: OrderedDict, key: felt252, values: Array ) -> OrderedDict { OrderedDictTraitImpl::add_array(ref dict, key, values); dict From 61185c22c2ccdcea9982184230cbd45cd3891332 Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 25 Oct 2023 09:21:39 +0200 Subject: [PATCH 16/40] feat(log_data_indexes): fmt --- src/event/event_utils_sandbox.cairo | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/event/event_utils_sandbox.cairo b/src/event/event_utils_sandbox.cairo index 4405e77e..f79e4c33 100644 --- a/src/event/event_utils_sandbox.cairo +++ b/src/event/event_utils_sandbox.cairo @@ -78,16 +78,18 @@ struct LogData { } // generic ... -fn set_item< - T, T, impl TDefault: Felt252DictValue, impl TDrop: Drop, impl TCopy: Copy ->(mut dict: OrderedDict, key: felt252, value: T) -> OrderedDict { +fn set_item, impl TDrop: Drop, impl TCopy: Copy>( + mut dict: OrderedDict, key: felt252, value: T +) -> OrderedDict { OrderedDictTraitImpl::add_single(ref dict, key, value); dict } fn set_array_item< T, T, impl TDefault: Felt252DictValue, impl TDrop: Drop, impl TCopy: Copy ->(mut dict: OrderedDict, key: felt252, values: Array) -> OrderedDict { +>( + mut dict: OrderedDict, key: felt252, values: Array +) -> OrderedDict { OrderedDictTraitImpl::add_array(ref dict, key, values); dict } @@ -109,9 +111,7 @@ fn set_item_array_uint_items( // int -fn set_item_int_items( - mut dict: OrderedDict, key: felt252, value: i128 -) -> OrderedDict { +fn set_item_int_items(mut dict: OrderedDict, key: felt252, value: i128) -> OrderedDict { OrderedDictTraitImpl::add_single(ref dict, key, value); dict } From cd89257fa7e83fd42a1ae365e1b208bb383bbb7f Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 25 Oct 2023 09:30:56 +0200 Subject: [PATCH 17/40] feat(log_data_indexes): Trigger CI to check semgrep --- src/event/event_utils_sandbox.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/event/event_utils_sandbox.cairo b/src/event/event_utils_sandbox.cairo index f79e4c33..372f4bb9 100644 --- a/src/event/event_utils_sandbox.cairo +++ b/src/event/event_utils_sandbox.cairo @@ -160,7 +160,7 @@ fn set_item_array_Felt252_items( fn set_item_string_items( mut dict: OrderedDict, key: felt252, value: felt252 ) -> OrderedDict { - OrderedDictTraitImpl::add_single(ref dict, key, value); + OrderedDictTraitImpl::add_single(ref dict, key, value); // trigger CI dict } From 728c5dc7404883b378bd97d543294330a94e87e1 Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 25 Oct 2023 15:13:57 +0200 Subject: [PATCH 18/40] feat(log_data_indexes): Renaming + Started unit tests --- src/event/event_utils_sandbox.cairo | 90 +++++++++-------- src/lib.cairo | 2 +- ...red_dict.cairo => serializable_dict.cairo} | 99 ++++++++++++------- tests/lib.cairo | 1 + tests/utils/test_serializable_dict.cairo | 50 ++++++++++ 5 files changed, 164 insertions(+), 78 deletions(-) rename src/utils/{ordered_dict.cairo => serializable_dict.cairo} (73%) create mode 100644 tests/utils/test_serializable_dict.cairo diff --git a/src/event/event_utils_sandbox.cairo b/src/event/event_utils_sandbox.cairo index 372f4bb9..238186f0 100644 --- a/src/event/event_utils_sandbox.cairo +++ b/src/event/event_utils_sandbox.cairo @@ -7,7 +7,9 @@ use satoru::utils::i128::{I128Serde, I128Default}; use traits::Default; use satoru::utils::traits::ContractAddressDefault; -use satoru::utils::ordered_dict::{OrderedDict, OrderedDictTraitImpl, OrderedDictSerde}; +use satoru::utils::serializable_dict::{ + SerializableFelt252Dict, SerializableFelt252DictTrait, SerializableFelt252DictSerde +}; // // NEEDED IMPLEMENTATIONS... @@ -68,105 +70,107 @@ struct EventLogData { #[derive(Default, Destruct, Serde)] struct LogData { - address_items: OrderedDict, - uint_items: OrderedDict, - int_items: OrderedDict, - bool_items: OrderedDict, - felt252_items: OrderedDict, - // TODO? Possible? array_of_felt_items: OrderedDict>, - string_items: OrderedDict + address_items: SerializableFelt252Dict, + uint_items: SerializableFelt252Dict, + int_items: SerializableFelt252Dict, + bool_items: SerializableFelt252Dict, + felt252_items: SerializableFelt252Dict, + // TODO? Possible? array_of_felt_items: SerializableFelt252Dict>, + string_items: SerializableFelt252Dict } // generic ... fn set_item, impl TDrop: Drop, impl TCopy: Copy>( - mut dict: OrderedDict, key: felt252, value: T -) -> OrderedDict { - OrderedDictTraitImpl::add_single(ref dict, key, value); + mut dict: SerializableFelt252Dict, key: felt252, value: T +) -> SerializableFelt252Dict { + dict.add_single(key, value); dict } fn set_array_item< T, T, impl TDefault: Felt252DictValue, impl TDrop: Drop, impl TCopy: Copy >( - mut dict: OrderedDict, key: felt252, values: Array -) -> OrderedDict { - OrderedDictTraitImpl::add_array(ref dict, key, values); + mut dict: SerializableFelt252Dict, key: felt252, values: Array +) -> SerializableFelt252Dict { + dict.add_array(key, values); dict } // uint fn set_item_uint_items( - mut dict: OrderedDict, key: felt252, value: u128 -) -> OrderedDict { - OrderedDictTraitImpl::add_single(ref dict, key, value); + mut dict: SerializableFelt252Dict, key: felt252, value: u128 +) -> SerializableFelt252Dict { + dict.add_single(key, value); dict } fn set_item_array_uint_items( - mut dict: OrderedDict, key: felt252, values: Array -) -> OrderedDict { - OrderedDictTraitImpl::add_array(ref dict, key, values); + mut dict: SerializableFelt252Dict, key: felt252, values: Array +) -> SerializableFelt252Dict { + dict.add_array(key, values); dict } // int -fn set_item_int_items(mut dict: OrderedDict, key: felt252, value: i128) -> OrderedDict { - OrderedDictTraitImpl::add_single(ref dict, key, value); +fn set_item_int_items( + mut dict: SerializableFelt252Dict, key: felt252, value: i128 +) -> SerializableFelt252Dict { + dict.add_single(key, value); dict } fn set_item_array_int_items( - mut dict: OrderedDict, key: felt252, values: Array -) -> OrderedDict { - OrderedDictTraitImpl::add_array(ref dict, key, values); + mut dict: SerializableFelt252Dict, key: felt252, values: Array +) -> SerializableFelt252Dict { + dict.add_array(key, values); dict } // bool fn set_item_bool_items( - mut dict: OrderedDict, key: felt252, value: bool -) -> OrderedDict { - OrderedDictTraitImpl::add_single(ref dict, key, value); + mut dict: SerializableFelt252Dict, key: felt252, value: bool +) -> SerializableFelt252Dict { + dict.add_single(key, value); dict } fn set_item_array_bool_items( - mut dict: OrderedDict, key: felt252, values: Array -) -> OrderedDict { - OrderedDictTraitImpl::add_array(ref dict, key, values); + mut dict: SerializableFelt252Dict, key: felt252, values: Array +) -> SerializableFelt252Dict { + dict.add_array(key, values); dict } // felt252 fn set_item_Felt252_items( - mut dict: OrderedDict, key: felt252, value: felt252 -) -> OrderedDict { - OrderedDictTraitImpl::add_single(ref dict, key, value); + mut dict: SerializableFelt252Dict, key: felt252, value: felt252 +) -> SerializableFelt252Dict { + dict.add_single(key, value); dict } fn set_item_array_Felt252_items( - mut dict: OrderedDict, key: felt252, values: Array -) -> OrderedDict { - OrderedDictTraitImpl::add_array(ref dict, key, values); + mut dict: SerializableFelt252Dict, key: felt252, values: Array +) -> SerializableFelt252Dict { + dict.add_array(key, values); dict } // string fn set_item_string_items( - mut dict: OrderedDict, key: felt252, value: felt252 -) -> OrderedDict { - OrderedDictTraitImpl::add_single(ref dict, key, value); // trigger CI + mut dict: SerializableFelt252Dict, key: felt252, value: felt252 +) -> SerializableFelt252Dict { + dict.add_single(key, value); // trigger CI dict } fn set_item_array_string_items( - mut dict: OrderedDict, key: felt252, values: Array -) -> OrderedDict { - OrderedDictTraitImpl::add_array(ref dict, key, values); + mut dict: SerializableFelt252Dict, key: felt252, values: Array +) -> SerializableFelt252Dict { + dict.add_array(key, values); dict } diff --git a/src/lib.cairo b/src/lib.cairo index b9342d04..8d29acc0 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -154,7 +154,7 @@ mod utils { mod starknet_utils; mod traits; mod default; - mod ordered_dict; + mod serializable_dict; } // `liquidation` function to help with liquidations. diff --git a/src/utils/ordered_dict.cairo b/src/utils/serializable_dict.cairo similarity index 73% rename from src/utils/ordered_dict.cairo rename to src/utils/serializable_dict.cairo index e1da6f35..43729ec0 100644 --- a/src/utils/ordered_dict.cairo +++ b/src/utils/serializable_dict.cairo @@ -12,19 +12,43 @@ use alexandria_data_structures::array_ext::ArrayTraitExt; #[derive(Drop, Copy)] enum Item { Single: T, - Multiple: Array + Array: Array +} + +#[generate_trait] +impl ItemImpl of ItemTrait { + fn is_single(self: @Item) -> bool { + match self { + Item::Single(v) => true, + Item::Array(arr) => false + } + } + + fn is_array(self: @Item) -> bool { + match self { + Item::Single(v) => false, + Item::Array(arr) => true + } + } + + fn len(self: @Item) -> usize { + match self { + Item::Single(v) => 1, + Item::Array(arr) => arr.len() + } + } } #[derive(Default, Copy)] -struct OrderedDict { +struct SerializableFelt252Dict { keys: Array, values: Felt252Dict>> } -impl OrderedDictDestruct< +impl SerializableFelt252DictDestruct< T, impl TDrop: Drop, impl TDefault: Felt252DictValue -> of Destruct> { - fn destruct(self: OrderedDict) nopanic { +> of Destruct> { + fn destruct(self: SerializableFelt252Dict) nopanic { self.values.squash(); self.keys.destruct(); } @@ -71,46 +95,51 @@ impl TArraySerialize< } } -trait OrderedDictTrait { - /// Creates a new OrderedDict object. - fn new() -> OrderedDict; +trait SerializableFelt252DictTrait { + /// Creates a new SerializableFelt252Dict object. + fn new() -> SerializableFelt252Dict; /// Adds an element. - fn add_single(ref self: OrderedDict, key: felt252, value: T); + fn add_single(ref self: SerializableFelt252Dict, key: felt252, value: T); /// Adds an array of elements. - fn add_array(ref self: OrderedDict, key: felt252, values: Array); + fn add_array(ref self: SerializableFelt252Dict, key: felt252, values: Array); /// Gets an element. - fn get>(ref self: OrderedDict, key: felt252) -> Option>; + fn get>( + ref self: SerializableFelt252Dict, key: felt252 + ) -> Option>; /// Checks if a key is in the dictionnary. - fn contains_key(self: @OrderedDict, key: felt252) -> bool; + fn contains_key(self: @SerializableFelt252Dict, key: felt252) -> bool; /// Checks if a dictionnary is empty. - fn is_empty(self: @OrderedDict) -> bool; + fn is_empty(self: @SerializableFelt252Dict) -> bool; +/// TODO: When Cairo is updated we can use unique() from Alexandria & have fn len() } -impl OrderedDictTraitImpl< +impl SerializableFelt252DictTraitImpl< T, impl TDefault: Felt252DictValue, impl TDrop: Drop, impl TCopy: Copy -> of OrderedDictTrait { - fn new() -> OrderedDict { - OrderedDict { keys: array![], values: Default::default() } +> of SerializableFelt252DictTrait { + fn new() -> SerializableFelt252Dict { + SerializableFelt252Dict { keys: array![], values: Default::default() } } - fn add_single(ref self: OrderedDict, key: felt252, value: T) { + fn add_single(ref self: SerializableFelt252Dict, key: felt252, value: T) { let value = Item::Single(value); self.values.insert(0, nullable_from_box(BoxTrait::new(value))); } - fn add_array(ref self: OrderedDict, key: felt252, values: Array) { - let values = Item::Multiple(values); + fn add_array(ref self: SerializableFelt252Dict, key: felt252, values: Array) { + let values = Item::Array(values); self.values.insert(0, nullable_from_box(BoxTrait::new(values))); } - fn get>(ref self: OrderedDict, key: felt252) -> Option> { + fn get>( + ref self: SerializableFelt252Dict, key: felt252 + ) -> Option> { match match_nullable(self.values.get(key)) { FromNullableResult::Null(()) => Option::None, FromNullableResult::NotNull(val) => Option::Some(val.unbox()), } } - fn contains_key(self: @OrderedDict, key: felt252) -> bool { + fn contains_key(self: @SerializableFelt252Dict, key: felt252) -> bool { let mut keys: Span = self.keys.span(); let mut contains_key: bool = false; loop { @@ -129,23 +158,23 @@ impl OrderedDictTraitImpl< return contains_key; } - fn is_empty(self: @OrderedDict) -> bool { + fn is_empty(self: @SerializableFelt252Dict) -> bool { self.keys.is_empty() } } -impl OrderedDictSerde< +impl SerializableFelt252DictSerde< T, impl TCopy: Copy, impl TDrop: Drop, impl FeltIntoT: Into, impl TIntoFelt: Into, -> of Serde> { +> of Serde> { // - // Serialization of an OrderedDict + // Serialization of an SerializableFelt252Dict // - // An OrderedDict is serialized as follow: + // An SerializableFelt252Dict is serialized as follow: // [ KEY | NB_ELEMENTS | X | Y | ... | KEY | NB_ELEMENTS | X | ...] // // @@ -162,7 +191,7 @@ impl OrderedDictSerde< // | ------ | ----------- | // [0, 1, 1, 1, 3, 1, 2, 3] (Array) // - fn serialize(self: @OrderedDict, ref output: Array) { + fn serialize(self: @SerializableFelt252Dict, ref output: Array) { let mut keys: Span = self.keys.span(); let mut included_keys: Array = array![]; loop { @@ -185,7 +214,7 @@ impl OrderedDictSerde< output.append(1_felt252); // len output.append(v.into()); // value }, - Item::Multiple(arr) => { + Item::Array(arr) => { output.append(*key); // key output.append(arr.len().into()); // len let mut arr_as_span: Span = arr.span(); @@ -211,13 +240,15 @@ impl OrderedDictSerde< } // - // Deserialization of an OrderedDict + // Deserialization of an SerializableFelt252Dict // - // An OrderedDict is serialized as follow: + // An SerializableFelt252Dict is serialized as follow: // [ KEY | NB_ELEMENTS | X | Y | ... | KEY | NB_ELEMENTS | X | ...] // - fn deserialize(ref serialized: Span) -> Option> { - let mut d: OrderedDict = OrderedDict { keys: array![], values: Default::default() }; + fn deserialize(ref serialized: Span) -> Option> { + let mut d: SerializableFelt252Dict = SerializableFelt252Dict { + keys: array![], values: Default::default() + }; loop { // Try to retrive the next key match serialized.pop_front() { @@ -244,7 +275,7 @@ impl OrderedDictSerde< arr_size -= 1; }; // ... & insert it - let values: Item = Item::Multiple(arr_values); + let values: Item = Item::Array(arr_values); d.values.insert(*key, nullable_from_box(BoxTrait::new(values))); }, Option::None => panic_with_felt252('err getting size') diff --git a/tests/lib.cairo b/tests/lib.cairo index 1d2da98c..c79acf3f 100644 --- a/tests/lib.cairo +++ b/tests/lib.cairo @@ -105,6 +105,7 @@ mod utils { mod test_starknet_utils; mod test_u128_mask; mod test_i128; + mod test_serializable_dict; } mod mock { mod test_governable; diff --git a/tests/utils/test_serializable_dict.cairo b/tests/utils/test_serializable_dict.cairo new file mode 100644 index 00000000..60f1cba5 --- /dev/null +++ b/tests/utils/test_serializable_dict.cairo @@ -0,0 +1,50 @@ +//! Test file for `src/utils/serializable_dict.cairo`. + +// ************************************************************************* +// IMPORTS +// ************************************************************************* +// Core lib imports. +use starknet::{ + get_caller_address, ContractAddress, Felt252TryIntoContractAddress, ContractAddressIntoFelt252, + contract_address_const +}; +use array::ArrayTrait; +use traits::Default; + +// Local imports. +use satoru::utils::i128::{I128Serde, I128Default}; +use satoru::utils::traits::ContractAddressDefault; +use satoru::utils::serializable_dict::{ + Item, ItemTrait, SerializableFelt252Dict, SerializableFelt252DictTrait, + SerializableFelt252DictSerde +}; + +// ********************************************************************************************* +// * TEST LOGIC * +// ********************************************************************************************* + +/// Item tests + +#[test] +fn test_item_single() { + let item: Item = Item::Single(8); + + assert(item.is_single() == true, 'item should be single'); + assert(item.is_array() == false, 'item shouldnt be array'); + assert(item.len() == 1, 'item len not 1'); +} + +#[test] +fn test_item_multiple() { + let arr: Array = array![1, 2, 3, 4, 5]; + let expected_len: usize = arr.len(); + + let item: Item = Item::Array(arr); + + assert(item.is_array() == true, 'item should be array'); + assert(item.is_single() == false, 'item shouldnt be single'); + assert(item.len() == expected_len, 'incorrect len'); +} +// SerializableDict tests + + From 38d5c81b794bd71e15a7ac1d58c0f4d0919620a7 Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 25 Oct 2023 15:14:34 +0200 Subject: [PATCH 19/40] feat(log_data_indexes): Merge --- src/utils/i128.cairo | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils/i128.cairo b/src/utils/i128.cairo index e28e3ad7..256f8e72 100644 --- a/src/utils/i128.cairo +++ b/src/utils/i128.cairo @@ -738,3 +738,4 @@ fn ensure_non_negative_zero(mag: u128, sign: bool) -> i128 { // Option::Some(i128_val) // } // } + From 15daea3f276c10957547c061bc9b3fce04fb6cb1 Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 25 Oct 2023 15:24:11 +0200 Subject: [PATCH 20/40] feat(log_data_indexes): Update SerializableDict with custom i128 --- src/event/event_utils_sandbox.cairo | 5 +++-- src/utils/i128.cairo | 1 + src/utils/serializable_dict.cairo | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/event/event_utils_sandbox.cairo b/src/event/event_utils_sandbox.cairo index 238186f0..05c9711f 100644 --- a/src/event/event_utils_sandbox.cairo +++ b/src/event/event_utils_sandbox.cairo @@ -3,7 +3,7 @@ use starknet::{ contract_address_const }; use array::ArrayTrait; -use satoru::utils::i128::{I128Serde, I128Default}; +use satoru::utils::i128::i128; use traits::Default; use satoru::utils::traits::ContractAddressDefault; @@ -47,9 +47,10 @@ impl Felt252IntoContractAddress of Into { impl I128252DictValue of Felt252DictValue { #[inline(always)] fn zero_default() -> i128 nopanic { - 0 + i128 { mag: 0, sign: false } } } + impl ContractAddressDictValue of Felt252DictValue { #[inline(always)] fn zero_default() -> ContractAddress nopanic { diff --git a/src/utils/i128.cairo b/src/utils/i128.cairo index 256f8e72..5e63680e 100644 --- a/src/utils/i128.cairo +++ b/src/utils/i128.cairo @@ -739,3 +739,4 @@ fn ensure_non_negative_zero(mag: u128, sign: bool) -> i128 { // } // } + diff --git a/src/utils/serializable_dict.cairo b/src/utils/serializable_dict.cairo index 43729ec0..43f03f03 100644 --- a/src/utils/serializable_dict.cairo +++ b/src/utils/serializable_dict.cairo @@ -110,7 +110,7 @@ trait SerializableFelt252DictTrait { fn contains_key(self: @SerializableFelt252Dict, key: felt252) -> bool; /// Checks if a dictionnary is empty. fn is_empty(self: @SerializableFelt252Dict) -> bool; -/// TODO: When Cairo is updated we can use unique() from Alexandria & have fn len() +/// TODO: When Scarb is updated we can use unique() from Alexandria & have fn len() } impl SerializableFelt252DictTraitImpl< From 5e72d6c584c7a7a36f3faad498ab299a683b2a04 Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 25 Oct 2023 16:19:01 +0200 Subject: [PATCH 21/40] feat(log_data_indexes): Checkpoint; units break --- src/event/event_utils_sandbox.cairo | 24 +++------------------- tests/utils/test_serializable_dict.cairo | 26 ++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/event/event_utils_sandbox.cairo b/src/event/event_utils_sandbox.cairo index 05c9711f..f538e40f 100644 --- a/src/event/event_utils_sandbox.cairo +++ b/src/event/event_utils_sandbox.cairo @@ -7,13 +7,12 @@ use satoru::utils::i128::i128; use traits::Default; use satoru::utils::traits::ContractAddressDefault; -use satoru::utils::serializable_dict::{ - SerializableFelt252Dict, SerializableFelt252DictTrait, SerializableFelt252DictSerde -}; +use satoru::utils::serializable_dict::{SerializableFelt252Dict, SerializableFelt252DictTrait}; // // NEEDED IMPLEMENTATIONS... // +/// TODO: move those somewhere else? impl Felt252IntoBool of Into { #[inline(always)] @@ -80,23 +79,6 @@ struct LogData { string_items: SerializableFelt252Dict } -// generic ... -fn set_item, impl TDrop: Drop, impl TCopy: Copy>( - mut dict: SerializableFelt252Dict, key: felt252, value: T -) -> SerializableFelt252Dict { - dict.add_single(key, value); - dict -} - -fn set_array_item< - T, T, impl TDefault: Felt252DictValue, impl TDrop: Drop, impl TCopy: Copy ->( - mut dict: SerializableFelt252Dict, key: felt252, values: Array -) -> SerializableFelt252Dict { - dict.add_array(key, values); - dict -} - // uint fn set_item_uint_items( mut dict: SerializableFelt252Dict, key: felt252, value: u128 @@ -165,7 +147,7 @@ fn set_item_array_Felt252_items( fn set_item_string_items( mut dict: SerializableFelt252Dict, key: felt252, value: felt252 ) -> SerializableFelt252Dict { - dict.add_single(key, value); // trigger CI + dict.add_single(key, value); dict } diff --git a/tests/utils/test_serializable_dict.cairo b/tests/utils/test_serializable_dict.cairo index 60f1cba5..aaa9dc04 100644 --- a/tests/utils/test_serializable_dict.cairo +++ b/tests/utils/test_serializable_dict.cairo @@ -12,11 +12,10 @@ use array::ArrayTrait; use traits::Default; // Local imports. -use satoru::utils::i128::{I128Serde, I128Default}; use satoru::utils::traits::ContractAddressDefault; use satoru::utils::serializable_dict::{ Item, ItemTrait, SerializableFelt252Dict, SerializableFelt252DictTrait, - SerializableFelt252DictSerde + SerializableFelt252DictTraitImpl }; // ********************************************************************************************* @@ -45,6 +44,29 @@ fn test_item_multiple() { assert(item.is_single() == false, 'item shouldnt be single'); assert(item.len() == expected_len, 'incorrect len'); } + // SerializableDict tests +#[test] +fn test_serializable_dict_add_single() { + let mut dict: SerializableFelt252Dict = SerializableFelt252Dict { + keys: array![], values: Default::default() + }; + + let key: felt252 = 'starknet'; + let expected_value: felt252 = 'cairo'; + + dict.add_single(key, expected_value); + let retrieved_item: Item = match dict.get(key) { + Option::Some(i) => i, + Option::None => panic_with_felt252('err while searching key') + }; + + let out_value: felt252 = match retrieved_item { + Item::Single(v) => v, + Item::Array(_) => panic_with_felt252('should not be array') + }; + + assert(out_value == expected_value, 'wrong value'); +} From a81153cf93caeb9200fc07549ff2fe2b90489a7c Mon Sep 17 00:00:00 2001 From: akhercha Date: Fri, 27 Oct 2023 11:19:04 +0200 Subject: [PATCH 22/40] feat(log_data_indexes): Replaced SerializableDict's Array by Span --- src/event/event_utils_sandbox.cairo | 10 +++--- src/utils/serializable_dict.cairo | 44 +++++++++++------------ tests/utils/test_serializable_dict.cairo | 45 ++++++++++++++++++------ 3 files changed, 62 insertions(+), 37 deletions(-) diff --git a/src/event/event_utils_sandbox.cairo b/src/event/event_utils_sandbox.cairo index f538e40f..bd676203 100644 --- a/src/event/event_utils_sandbox.cairo +++ b/src/event/event_utils_sandbox.cairo @@ -90,7 +90,7 @@ fn set_item_uint_items( fn set_item_array_uint_items( mut dict: SerializableFelt252Dict, key: felt252, values: Array ) -> SerializableFelt252Dict { - dict.add_array(key, values); + dict.add_span(key, values.span()); dict } @@ -106,7 +106,7 @@ fn set_item_int_items( fn set_item_array_int_items( mut dict: SerializableFelt252Dict, key: felt252, values: Array ) -> SerializableFelt252Dict { - dict.add_array(key, values); + dict.add_span(key, values.span()); dict } @@ -122,7 +122,7 @@ fn set_item_bool_items( fn set_item_array_bool_items( mut dict: SerializableFelt252Dict, key: felt252, values: Array ) -> SerializableFelt252Dict { - dict.add_array(key, values); + dict.add_span(key, values.span()); dict } @@ -138,7 +138,7 @@ fn set_item_Felt252_items( fn set_item_array_Felt252_items( mut dict: SerializableFelt252Dict, key: felt252, values: Array ) -> SerializableFelt252Dict { - dict.add_array(key, values); + dict.add_span(key, values.span()); dict } @@ -154,6 +154,6 @@ fn set_item_string_items( fn set_item_array_string_items( mut dict: SerializableFelt252Dict, key: felt252, values: Array ) -> SerializableFelt252Dict { - dict.add_array(key, values); + dict.add_span(key, values.span()); dict } diff --git a/src/utils/serializable_dict.cairo b/src/utils/serializable_dict.cairo index 43f03f03..d04df993 100644 --- a/src/utils/serializable_dict.cairo +++ b/src/utils/serializable_dict.cairo @@ -12,7 +12,7 @@ use alexandria_data_structures::array_ext::ArrayTraitExt; #[derive(Drop, Copy)] enum Item { Single: T, - Array: Array + Span: Span } #[generate_trait] @@ -20,21 +20,21 @@ impl ItemImpl of ItemTrait { fn is_single(self: @Item) -> bool { match self { Item::Single(v) => true, - Item::Array(arr) => false + Item::Span(arr) => false } } - fn is_array(self: @Item) -> bool { + fn is_span(self: @Item) -> bool { match self { Item::Single(v) => false, - Item::Array(arr) => true + Item::Span(arr) => true } } fn len(self: @Item) -> usize { match self { Item::Single(v) => 1, - Item::Array(arr) => arr.len() + Item::Span(s) => (*s).len() } } } @@ -101,7 +101,7 @@ trait SerializableFelt252DictTrait { /// Adds an element. fn add_single(ref self: SerializableFelt252Dict, key: felt252, value: T); /// Adds an array of elements. - fn add_array(ref self: SerializableFelt252Dict, key: felt252, values: Array); + fn add_span(ref self: SerializableFelt252Dict, key: felt252, values: Span); /// Gets an element. fn get>( ref self: SerializableFelt252Dict, key: felt252 @@ -122,12 +122,18 @@ impl SerializableFelt252DictTraitImpl< fn add_single(ref self: SerializableFelt252Dict, key: felt252, value: T) { let value = Item::Single(value); - self.values.insert(0, nullable_from_box(BoxTrait::new(value))); + if !self.keys.contains(key) { + self.keys.append(key); + } + self.values.insert(key, nullable_from_box(BoxTrait::new(value))); } - fn add_array(ref self: SerializableFelt252Dict, key: felt252, values: Array) { - let values = Item::Array(values); - self.values.insert(0, nullable_from_box(BoxTrait::new(values))); + fn add_span(ref self: SerializableFelt252Dict, key: felt252, values: Span) { + let values = Item::Span(values); + if !self.keys.contains(key) { + self.keys.append(key); + } + self.values.insert(key, nullable_from_box(BoxTrait::new(values))); } fn get>( @@ -193,13 +199,9 @@ impl SerializableFelt252DictSerde< // fn serialize(self: @SerializableFelt252Dict, ref output: Array) { let mut keys: Span = self.keys.span(); - let mut included_keys: Array = array![]; loop { match keys.pop_back() { Option::Some(key) => { - if (!included_keys.contains(*key)) { - continue; - } let mut ordered_dict = (*self); let nullable_value: Nullable> = ordered_dict.values.get(*key); let value: Item = match match_nullable(nullable_value) { @@ -214,12 +216,11 @@ impl SerializableFelt252DictSerde< output.append(1_felt252); // len output.append(v.into()); // value }, - Item::Array(arr) => { + Item::Span(mut arr) => { output.append(*key); // key output.append(arr.len().into()); // len - let mut arr_as_span: Span = arr.span(); loop { - match arr_as_span.pop_front() { + match arr.pop_front() { Option::Some(v) => { output.append((*v).into()); }, @@ -230,7 +231,6 @@ impl SerializableFelt252DictSerde< } } }; - included_keys.append(*key); }, Option::None => { break; @@ -258,7 +258,7 @@ impl SerializableFelt252DictSerde< Option::Some(size) => { // If only one element, insert it & quit if ((*size) == 1) { - let value: T = get_next_value_from(serialized); + let value: T = pop_front_next(serialized); let value: Item = Item::Single(value); d.values.insert(*key, nullable_from_box(BoxTrait::new(value))); continue; @@ -270,12 +270,12 @@ impl SerializableFelt252DictSerde< if (arr_size) == 0 { break; }; - let value: T = get_next_value_from(serialized); + let value: T = pop_front_next(serialized); arr_values.append(value); arr_size -= 1; }; // ... & insert it - let values: Item = Item::Array(arr_values); + let values: Item = Item::Span(arr_values.span()); d.values.insert(*key, nullable_from_box(BoxTrait::new(values))); }, Option::None => panic_with_felt252('err getting size') @@ -291,7 +291,7 @@ impl SerializableFelt252DictSerde< } -fn get_next_value_from>(mut serialized: Span) -> T { +fn pop_front_next>(mut serialized: Span) -> T { let value = match serialized.pop_front() { Option::Some(value) => value, Option::None => panic_with_felt252('err getting value') diff --git a/tests/utils/test_serializable_dict.cairo b/tests/utils/test_serializable_dict.cairo index aaa9dc04..9b731c1c 100644 --- a/tests/utils/test_serializable_dict.cairo +++ b/tests/utils/test_serializable_dict.cairo @@ -10,6 +10,7 @@ use starknet::{ }; use array::ArrayTrait; use traits::Default; +use alexandria_data_structures::array_ext::ArrayTraitExt; // Local imports. use satoru::utils::traits::ContractAddressDefault; @@ -29,18 +30,18 @@ fn test_item_single() { let item: Item = Item::Single(8); assert(item.is_single() == true, 'item should be single'); - assert(item.is_array() == false, 'item shouldnt be array'); + assert(item.is_span() == false, 'item shouldnt be a span'); assert(item.len() == 1, 'item len not 1'); } #[test] -fn test_item_multiple() { +fn test_item_span() { let arr: Array = array![1, 2, 3, 4, 5]; let expected_len: usize = arr.len(); - let item: Item = Item::Array(arr); + let item: Item = Item::Span(arr.span()); - assert(item.is_array() == true, 'item should be array'); + assert(item.is_span() == true, 'item should be a span'); assert(item.is_single() == false, 'item shouldnt be single'); assert(item.len() == expected_len, 'incorrect len'); } @@ -49,24 +50,48 @@ fn test_item_multiple() { #[test] fn test_serializable_dict_add_single() { - let mut dict: SerializableFelt252Dict = SerializableFelt252Dict { - keys: array![], values: Default::default() - }; + let mut dict: SerializableFelt252Dict = SerializableFelt252DictTrait::new(); let key: felt252 = 'starknet'; let expected_value: felt252 = 'cairo'; dict.add_single(key, expected_value); - let retrieved_item: Item = match dict.get(key) { + let retrieved_item = match dict.get(key) { Option::Some(i) => i, - Option::None => panic_with_felt252('err while searching key') + Option::None => panic_with_felt252('key should be in dict') }; let out_value: felt252 = match retrieved_item { Item::Single(v) => v, - Item::Array(_) => panic_with_felt252('should not be array') + Item::Span(_) => panic_with_felt252('item should not be a span') }; + assert(dict.keys.contains(key), 'key should be in dict'); assert(out_value == expected_value, 'wrong value'); } + +#[test] +fn test_serializable_dict_add_span() { + let mut dict: SerializableFelt252Dict = SerializableFelt252DictTrait::new(); + + let key: felt252 = 'starknet'; + let expected_array: Array = array![1, 2, 3]; + + dict.add_span(key, expected_array.span()); + + let retrieved_item = match dict.get(key) { + Option::Some(i) => i, + Option::None => panic_with_felt252('key should be in dict') + }; + + let out_span: Span = match retrieved_item { + Item::Single(_) => panic_with_felt252('item should not single'), + Item::Span(s) => s + }; + + assert(dict.keys.contains(key), 'key should be in dict'); + assert(out_span.at(0) == expected_array.at(0), 'wrong at idx 0'); + assert(out_span.at(1) == expected_array.at(1), 'wrong at idx 0'); + assert(out_span.at(2) == expected_array.at(2), 'wrong at idx 0'); +} From 4af231ed70c15508f5aff6bbe86fb6297b708b9e Mon Sep 17 00:00:00 2001 From: akhercha Date: Fri, 27 Oct 2023 11:38:13 +0200 Subject: [PATCH 23/40] feat(log_data_indexes): Utilities fn --- src/utils/serializable_dict.cairo | 64 ++++++++---------------- tests/utils/test_serializable_dict.cairo | 27 +++------- 2 files changed, 27 insertions(+), 64 deletions(-) diff --git a/src/utils/serializable_dict.cairo b/src/utils/serializable_dict.cairo index d04df993..3d7879b4 100644 --- a/src/utils/serializable_dict.cairo +++ b/src/utils/serializable_dict.cairo @@ -25,10 +25,7 @@ impl ItemImpl of ItemTrait { } fn is_span(self: @Item) -> bool { - match self { - Item::Single(v) => false, - Item::Span(arr) => true - } + !self.is_single() } fn len(self: @Item) -> usize { @@ -37,6 +34,20 @@ impl ItemImpl of ItemTrait { Item::Span(s) => (*s).len() } } + + fn unwrap_single>(self: @Item) -> T { + match self { + Item::Single(v) => (*v), + Item::Span(arr) => panic_with_felt252('should not be a span') + } + } + + fn unwrap_span(self: @Item) -> Span { + match self { + Item::Single(v) => panic_with_felt252('should not be single'), + Item::Span(arr) => *arr + } + } } #[derive(Default, Copy)] @@ -57,44 +68,6 @@ impl SerializableFelt252DictDestruct< impl ArrayTCopy of Copy>; impl Felt252DictValueTCopy of Copy>>>; -impl TArraySerialize< - T, - impl TDrop: Drop, - impl TCopy: Copy, - impl TIntoT: Into, - impl TIntoFelt: Into -> of Serde> { - fn serialize(self: @Array, ref output: Array) { - let mut span_arr = self.span(); - loop { - match span_arr.pop_front() { - Option::Some(v) => { - let as_felt: felt252 = (*v).into(); - output.append(as_felt); - }, - Option::None => { - break; - } - }; - } - } - - fn deserialize(ref serialized: Span) -> Option> { - let mut arr: Array = array![]; - loop { - match serialized.pop_front() { - Option::Some(v) => { - arr.append((*v).into()); - }, - Option::None => { - break; - } - }; - }; - Option::Some(arr) - } -} - trait SerializableFelt252DictTrait { /// Creates a new SerializableFelt252Dict object. fn new() -> SerializableFelt252Dict; @@ -110,7 +83,8 @@ trait SerializableFelt252DictTrait { fn contains_key(self: @SerializableFelt252Dict, key: felt252) -> bool; /// Checks if a dictionnary is empty. fn is_empty(self: @SerializableFelt252Dict) -> bool; -/// TODO: When Scarb is updated we can use unique() from Alexandria & have fn len() + /// Number of keys in the dictionnary. + fn len(self: @SerializableFelt252Dict) -> usize; } impl SerializableFelt252DictTraitImpl< @@ -167,6 +141,10 @@ impl SerializableFelt252DictTraitImpl< fn is_empty(self: @SerializableFelt252Dict) -> bool { self.keys.is_empty() } + + fn len(self: @SerializableFelt252Dict) -> usize { + self.keys.len() + } } diff --git a/tests/utils/test_serializable_dict.cairo b/tests/utils/test_serializable_dict.cairo index 9b731c1c..6acb7e1e 100644 --- a/tests/utils/test_serializable_dict.cairo +++ b/tests/utils/test_serializable_dict.cairo @@ -50,24 +50,16 @@ fn test_item_span() { #[test] fn test_serializable_dict_add_single() { - let mut dict: SerializableFelt252Dict = SerializableFelt252DictTrait::new(); + let mut dict: SerializableFelt252Dict = SerializableFelt252DictTrait::new(); let key: felt252 = 'starknet'; - let expected_value: felt252 = 'cairo'; + let expected_value: u8 = 42; dict.add_single(key, expected_value); - let retrieved_item = match dict.get(key) { - Option::Some(i) => i, - Option::None => panic_with_felt252('key should be in dict') - }; - - let out_value: felt252 = match retrieved_item { - Item::Single(v) => v, - Item::Span(_) => panic_with_felt252('item should not be a span') - }; + let retrieved_item: Item = dict.get(key).expect('key should be in dict'); + let out_value: u8 = retrieved_item.unwrap_single(); - assert(dict.keys.contains(key), 'key should be in dict'); assert(out_value == expected_value, 'wrong value'); } @@ -80,15 +72,8 @@ fn test_serializable_dict_add_span() { dict.add_span(key, expected_array.span()); - let retrieved_item = match dict.get(key) { - Option::Some(i) => i, - Option::None => panic_with_felt252('key should be in dict') - }; - - let out_span: Span = match retrieved_item { - Item::Single(_) => panic_with_felt252('item should not single'), - Item::Span(s) => s - }; + let retrieved_item: Item = dict.get(key).expect('key should be in dict'); + let out_span: Span = retrieved_item.unwrap_span(); assert(dict.keys.contains(key), 'key should be in dict'); assert(out_span.at(0) == expected_array.at(0), 'wrong at idx 0'); From 74850d10a47cff44070627fca3bf474f3c6f4b05 Mon Sep 17 00:00:00 2001 From: akhercha Date: Sat, 28 Oct 2023 10:14:36 +0200 Subject: [PATCH 24/40] feat(log_data_indexes): Adding unit tests for debug --- src/utils/serializable_dict.cairo | 2 +- tests/event/test_event_utils.cairo | 104 +++++++++++++++++++++++ tests/lib.cairo | 1 + tests/utils/test_serializable_dict.cairo | 9 +- 4 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 tests/event/test_event_utils.cairo diff --git a/src/utils/serializable_dict.cairo b/src/utils/serializable_dict.cairo index 3d7879b4..1b79a65e 100644 --- a/src/utils/serializable_dict.cairo +++ b/src/utils/serializable_dict.cairo @@ -191,7 +191,7 @@ impl SerializableFelt252DictSerde< match value { Item::Single(v) => { output.append(*key); // key - output.append(1_felt252); // len + output.append(1); // len output.append(v.into()); // value }, Item::Span(mut arr) => { diff --git a/tests/event/test_event_utils.cairo b/tests/event/test_event_utils.cairo new file mode 100644 index 00000000..b01e3e9f --- /dev/null +++ b/tests/event/test_event_utils.cairo @@ -0,0 +1,104 @@ +use starknet::{ + get_caller_address, ContractAddress, Felt252TryIntoContractAddress, ContractAddressIntoFelt252, + contract_address_const +}; +use satoru::event::event_utils_sandbox::{ + Felt252IntoBool, Felt252IntoU128, Felt252IntoI128, Felt252IntoContractAddress, I128252DictValue, + ContractAddressDictValue, LogData +}; +use satoru::utils::traits::{ContractAddressDefault}; +use traits::Default; +use satoru::utils::serializable_dict::{ + Item, ItemTrait, SerializableFelt252Dict, SerializableFelt252DictTrait, + SerializableFelt252DictTraitImpl +}; + +#[test] +fn test_log_data_default() { + let mut log_data: LogData = Default::default(); + + // try to add things + log_data.address_items.add_single('test', contract_address_const::<0>()); + log_data.uint_items.add_single('test', 12_u128); + + // assert results OK + let addr_item = log_data.address_items.get('test').expect('key not found'); + let addr_value = addr_item.unwrap_single(); + assert(addr_value == contract_address_const::<0>(), 'addr value wrong'); + + let uint_item = log_data.uint_items.get('test').expect('key not found'); + let uint_value = uint_item.unwrap_single(); + assert(uint_value == 12_u128, 'uint value wrong'); +} + +#[test] +fn test_log_data_default_each() { + let mut log_data: LogData = LogData { + address_items: Default::default(), + uint_items: Default::default(), + int_items: Default::default(), + bool_items: Default::default(), + felt252_items: Default::default(), + string_items: Default::default() + }; + + // try to add things + log_data.address_items.add_single('test', contract_address_const::<0>()); + log_data.uint_items.add_single('test', 12_u128); + + // assert results OK + let addr_item = log_data.address_items.get('test').expect('key not found'); + let addr_value = addr_item.unwrap_single(); + assert(addr_value == contract_address_const::<0>(), 'addr value wrong'); + + let uint_item = log_data.uint_items.get('test').expect('key not found'); + let uint_value = uint_item.unwrap_single(); + assert(uint_value == 12_u128, 'uint value wrong'); +} + +#[test] +fn test_log_data_multiple_types() { + let mut log_data: LogData = Default::default(); + + let arr_to_add: Array = array![ + contract_address_const::<'cairo'>(), + contract_address_const::<'starknet'>(), + contract_address_const::<'rust'>() + ]; + + // try to add unique + log_data.address_items.add_single('test', contract_address_const::<0>()); + log_data.address_items.add_span('test_arr', arr_to_add.span()); + + // assert results OK + let addr_item = log_data.address_items.get('test').expect('key not found'); + let addr_value = addr_item.unwrap_single(); + assert(addr_value == contract_address_const::<0>(), 'addr value wrong'); + + let addr_span_item: Item = log_data + .address_items + .get('test_arr') + .expect('key should be in dict'); + let out_span: Span = addr_span_item.unwrap_span(); + assert(out_span.at(0) == arr_to_add.at(0), 'wrong at idx 0'); + assert(out_span.at(1) == arr_to_add.at(1), 'wrong at idx 1'); + assert(out_span.at(2) == arr_to_add.at(2), 'wrong at idx 2'); +} + +#[test] +fn test_log_data_serialization() { + let mut log_data: LogData = Default::default(); + + let arr_to_add: Array = array![ + contract_address_const::<'cairo'>(), + contract_address_const::<'starknet'>(), + contract_address_const::<'rust'>() + ]; + + // try to add unique + log_data.address_items.add_single('test', contract_address_const::<0>()); + log_data.address_items.add_span('test_arr', arr_to_add.span()); + + let mut output = array![]; +// log_data.serialize(ref output); FAIL +} diff --git a/tests/lib.cairo b/tests/lib.cairo index f0990d60..27c244a2 100644 --- a/tests/lib.cairo +++ b/tests/lib.cairo @@ -39,6 +39,7 @@ mod event { mod test_swap_events_emitted; mod test_timelock_events_emitted; mod test_withdrawal_events_emitted; + mod test_event_utils; } mod exchange { mod test_liquidation_handler; diff --git a/tests/utils/test_serializable_dict.cairo b/tests/utils/test_serializable_dict.cairo index 6acb7e1e..5725f940 100644 --- a/tests/utils/test_serializable_dict.cairo +++ b/tests/utils/test_serializable_dict.cairo @@ -4,6 +4,7 @@ // IMPORTS // ************************************************************************* // Core lib imports. +use serde::Serde; use starknet::{ get_caller_address, ContractAddress, Felt252TryIntoContractAddress, ContractAddressIntoFelt252, contract_address_const @@ -14,6 +15,10 @@ use alexandria_data_structures::array_ext::ArrayTraitExt; // Local imports. use satoru::utils::traits::ContractAddressDefault; +use satoru::event::event_utils_sandbox::{ + Felt252IntoBool, Felt252IntoU128, Felt252IntoI128, Felt252IntoContractAddress, I128252DictValue, + ContractAddressDictValue +}; use satoru::utils::serializable_dict::{ Item, ItemTrait, SerializableFelt252Dict, SerializableFelt252DictTrait, SerializableFelt252DictTraitImpl @@ -77,6 +82,6 @@ fn test_serializable_dict_add_span() { assert(dict.keys.contains(key), 'key should be in dict'); assert(out_span.at(0) == expected_array.at(0), 'wrong at idx 0'); - assert(out_span.at(1) == expected_array.at(1), 'wrong at idx 0'); - assert(out_span.at(2) == expected_array.at(2), 'wrong at idx 0'); + assert(out_span.at(1) == expected_array.at(1), 'wrong at idx 1'); + assert(out_span.at(2) == expected_array.at(2), 'wrong at idx 2'); } From b3b71cd732199b4271478384b622f7119c804c19 Mon Sep 17 00:00:00 2001 From: akhercha Date: Sat, 28 Oct 2023 10:37:38 +0200 Subject: [PATCH 25/40] feat(log_data_indexes): TODO: investigate serialization fail --- tests/event/test_event_utils.cairo | 3 --- tests/utils/test_serializable_dict.cairo | 15 ++++++++++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/event/test_event_utils.cairo b/tests/event/test_event_utils.cairo index b01e3e9f..8c96b869 100644 --- a/tests/event/test_event_utils.cairo +++ b/tests/event/test_event_utils.cairo @@ -98,7 +98,4 @@ fn test_log_data_serialization() { // try to add unique log_data.address_items.add_single('test', contract_address_const::<0>()); log_data.address_items.add_span('test_arr', arr_to_add.span()); - - let mut output = array![]; -// log_data.serialize(ref output); FAIL } diff --git a/tests/utils/test_serializable_dict.cairo b/tests/utils/test_serializable_dict.cairo index 5725f940..af98d954 100644 --- a/tests/utils/test_serializable_dict.cairo +++ b/tests/utils/test_serializable_dict.cairo @@ -10,6 +10,7 @@ use starknet::{ contract_address_const }; use array::ArrayTrait; +use array::SpanTrait; use traits::Default; use alexandria_data_structures::array_ext::ArrayTraitExt; @@ -21,7 +22,7 @@ use satoru::event::event_utils_sandbox::{ }; use satoru::utils::serializable_dict::{ Item, ItemTrait, SerializableFelt252Dict, SerializableFelt252DictTrait, - SerializableFelt252DictTraitImpl + SerializableFelt252DictTraitImpl, SerializableFelt252DictSerde }; // ********************************************************************************************* @@ -85,3 +86,15 @@ fn test_serializable_dict_add_span() { assert(out_span.at(1) == expected_array.at(1), 'wrong at idx 1'); assert(out_span.at(2) == expected_array.at(2), 'wrong at idx 2'); } + +#[test] +fn test_serializable_dict_serialize() { + let mut dict: SerializableFelt252Dict = SerializableFelt252DictTrait::new(); + + dict.add_single('test', 42_u128); + dict.add_span('test_arr', array![1, 2, 3].span()); + + let mut output: Array = array![]; +// TODO: this fail +// SerializableFelt252DictSerde::serialize(@dict, ref output); +} From ffd003d2198b9069a2987858a35f90dbf3866851 Mon Sep 17 00:00:00 2001 From: akhercha Date: Sat, 28 Oct 2023 13:41:17 +0200 Subject: [PATCH 26/40] feat(log_data_indexes): update --- src/event/event_utils_sandbox.cairo | 20 +++---- src/utils/serializable_dict.cairo | 66 +++++++++++------------- tests/event/test_event_utils.cairo | 16 +++--- tests/utils/test_serializable_dict.cairo | 12 ++--- 4 files changed, 54 insertions(+), 60 deletions(-) diff --git a/src/event/event_utils_sandbox.cairo b/src/event/event_utils_sandbox.cairo index bd676203..0a20f32f 100644 --- a/src/event/event_utils_sandbox.cairo +++ b/src/event/event_utils_sandbox.cairo @@ -83,14 +83,14 @@ struct LogData { fn set_item_uint_items( mut dict: SerializableFelt252Dict, key: felt252, value: u128 ) -> SerializableFelt252Dict { - dict.add_single(key, value); + dict.insert_single(key, value); dict } fn set_item_array_uint_items( mut dict: SerializableFelt252Dict, key: felt252, values: Array ) -> SerializableFelt252Dict { - dict.add_span(key, values.span()); + dict.insert_span(key, values.span()); dict } @@ -99,14 +99,14 @@ fn set_item_array_uint_items( fn set_item_int_items( mut dict: SerializableFelt252Dict, key: felt252, value: i128 ) -> SerializableFelt252Dict { - dict.add_single(key, value); + dict.insert_single(key, value); dict } fn set_item_array_int_items( mut dict: SerializableFelt252Dict, key: felt252, values: Array ) -> SerializableFelt252Dict { - dict.add_span(key, values.span()); + dict.insert_span(key, values.span()); dict } @@ -115,14 +115,14 @@ fn set_item_array_int_items( fn set_item_bool_items( mut dict: SerializableFelt252Dict, key: felt252, value: bool ) -> SerializableFelt252Dict { - dict.add_single(key, value); + dict.insert_single(key, value); dict } fn set_item_array_bool_items( mut dict: SerializableFelt252Dict, key: felt252, values: Array ) -> SerializableFelt252Dict { - dict.add_span(key, values.span()); + dict.insert_span(key, values.span()); dict } @@ -131,14 +131,14 @@ fn set_item_array_bool_items( fn set_item_Felt252_items( mut dict: SerializableFelt252Dict, key: felt252, value: felt252 ) -> SerializableFelt252Dict { - dict.add_single(key, value); + dict.insert_single(key, value); dict } fn set_item_array_Felt252_items( mut dict: SerializableFelt252Dict, key: felt252, values: Array ) -> SerializableFelt252Dict { - dict.add_span(key, values.span()); + dict.insert_span(key, values.span()); dict } @@ -147,13 +147,13 @@ fn set_item_array_Felt252_items( fn set_item_string_items( mut dict: SerializableFelt252Dict, key: felt252, value: felt252 ) -> SerializableFelt252Dict { - dict.add_single(key, value); + dict.insert_single(key, value); dict } fn set_item_array_string_items( mut dict: SerializableFelt252Dict, key: felt252, values: Array ) -> SerializableFelt252Dict { - dict.add_span(key, values.span()); + dict.insert_span(key, values.span()); dict } diff --git a/src/utils/serializable_dict.cairo b/src/utils/serializable_dict.cairo index 1b79a65e..1cc635ce 100644 --- a/src/utils/serializable_dict.cairo +++ b/src/utils/serializable_dict.cairo @@ -66,25 +66,25 @@ impl SerializableFelt252DictDestruct< } impl ArrayTCopy of Copy>; -impl Felt252DictValueTCopy of Copy>>>; +impl Felt252DictItemCopy of Copy>; trait SerializableFelt252DictTrait { /// Creates a new SerializableFelt252Dict object. fn new() -> SerializableFelt252Dict; /// Adds an element. - fn add_single(ref self: SerializableFelt252Dict, key: felt252, value: T); + fn insert_single(ref self: SerializableFelt252Dict, key: felt252, value: T); /// Adds an array of elements. - fn add_span(ref self: SerializableFelt252Dict, key: felt252, values: Span); + fn insert_span(ref self: SerializableFelt252Dict, key: felt252, values: Span); /// Gets an element. fn get>( ref self: SerializableFelt252Dict, key: felt252 ) -> Option>; /// Checks if a key is in the dictionnary. - fn contains_key(self: @SerializableFelt252Dict, key: felt252) -> bool; - /// Checks if a dictionnary is empty. - fn is_empty(self: @SerializableFelt252Dict) -> bool; + fn contains(self: @SerializableFelt252Dict, key: felt252) -> bool; /// Number of keys in the dictionnary. fn len(self: @SerializableFelt252Dict) -> usize; + /// Checks if a dictionnary is empty. + fn is_empty(self: @SerializableFelt252Dict) -> bool; } impl SerializableFelt252DictTraitImpl< @@ -94,7 +94,7 @@ impl SerializableFelt252DictTraitImpl< SerializableFelt252Dict { keys: array![], values: Default::default() } } - fn add_single(ref self: SerializableFelt252Dict, key: felt252, value: T) { + fn insert_single(ref self: SerializableFelt252Dict, key: felt252, value: T) { let value = Item::Single(value); if !self.keys.contains(key) { self.keys.append(key); @@ -102,7 +102,7 @@ impl SerializableFelt252DictTraitImpl< self.values.insert(key, nullable_from_box(BoxTrait::new(value))); } - fn add_span(ref self: SerializableFelt252Dict, key: felt252, values: Span) { + fn insert_span(ref self: SerializableFelt252Dict, key: felt252, values: Span) { let values = Item::Span(values); if !self.keys.contains(key) { self.keys.append(key); @@ -119,7 +119,7 @@ impl SerializableFelt252DictTraitImpl< } } - fn contains_key(self: @SerializableFelt252Dict, key: felt252) -> bool { + fn contains(self: @SerializableFelt252Dict, key: felt252) -> bool { let mut keys: Span = self.keys.span(); let mut contains_key: bool = false; loop { @@ -138,13 +138,13 @@ impl SerializableFelt252DictTraitImpl< return contains_key; } - fn is_empty(self: @SerializableFelt252Dict) -> bool { - self.keys.is_empty() - } - fn len(self: @SerializableFelt252Dict) -> usize { self.keys.len() } + + fn is_empty(self: @SerializableFelt252Dict) -> bool { + self.len() == 0 + } } @@ -178,14 +178,12 @@ impl SerializableFelt252DictSerde< fn serialize(self: @SerializableFelt252Dict, ref output: Array) { let mut keys: Span = self.keys.span(); loop { - match keys.pop_back() { + match keys.pop_front() { Option::Some(key) => { - let mut ordered_dict = (*self); - let nullable_value: Nullable> = ordered_dict.values.get(*key); + let mut d = *self.values; + let nullable_value: Nullable> = d.get(*key); let value: Item = match match_nullable(nullable_value) { - FromNullableResult::Null(()) => panic_with_felt252( - 'key not found (serialize)' - ), + FromNullableResult::Null(()) => panic_with_felt252('err getting key'), FromNullableResult::NotNull(boxed_value) => boxed_value.unbox(), }; match value { @@ -197,7 +195,7 @@ impl SerializableFelt252DictSerde< Item::Span(mut arr) => { output.append(*key); // key output.append(arr.len().into()); // len - loop { + loop { // append each values match arr.pop_front() { Option::Some(v) => { output.append((*v).into()); @@ -206,15 +204,15 @@ impl SerializableFelt252DictSerde< break; } }; - } - } + }; + }, }; }, Option::None => { break; }, }; - } + }; } // @@ -236,11 +234,14 @@ impl SerializableFelt252DictSerde< Option::Some(size) => { // If only one element, insert it & quit if ((*size) == 1) { - let value: T = pop_front_next(serialized); + let value: T = match serialized.pop_front() { + Option::Some(value) => (*value).into(), + Option::None => panic_with_felt252('err getting value') + }; let value: Item = Item::Single(value); d.values.insert(*key, nullable_from_box(BoxTrait::new(value))); continue; - } + }; // Else append all elements into an array ... let mut arr_size: felt252 = *size; let mut arr_values: Array = array![]; @@ -248,7 +249,10 @@ impl SerializableFelt252DictSerde< if (arr_size) == 0 { break; }; - let value: T = pop_front_next(serialized); + let value: T = match serialized.pop_front() { + Option::Some(value) => (*value).into(), + Option::None => panic_with_felt252('err getting value') + }; arr_values.append(value); arr_size -= 1; }; @@ -267,13 +271,3 @@ impl SerializableFelt252DictSerde< Option::Some(d) } } - - -fn pop_front_next>(mut serialized: Span) -> T { - let value = match serialized.pop_front() { - Option::Some(value) => value, - Option::None => panic_with_felt252('err getting value') - }; - let value: T = (*value).into(); - value -} diff --git a/tests/event/test_event_utils.cairo b/tests/event/test_event_utils.cairo index 8c96b869..ecf6061c 100644 --- a/tests/event/test_event_utils.cairo +++ b/tests/event/test_event_utils.cairo @@ -18,8 +18,8 @@ fn test_log_data_default() { let mut log_data: LogData = Default::default(); // try to add things - log_data.address_items.add_single('test', contract_address_const::<0>()); - log_data.uint_items.add_single('test', 12_u128); + log_data.address_items.insert_single('test', contract_address_const::<0>()); + log_data.uint_items.insert_single('test', 12_u128); // assert results OK let addr_item = log_data.address_items.get('test').expect('key not found'); @@ -43,8 +43,8 @@ fn test_log_data_default_each() { }; // try to add things - log_data.address_items.add_single('test', contract_address_const::<0>()); - log_data.uint_items.add_single('test', 12_u128); + log_data.address_items.insert_single('test', contract_address_const::<0>()); + log_data.uint_items.insert_single('test', 12_u128); // assert results OK let addr_item = log_data.address_items.get('test').expect('key not found'); @@ -67,8 +67,8 @@ fn test_log_data_multiple_types() { ]; // try to add unique - log_data.address_items.add_single('test', contract_address_const::<0>()); - log_data.address_items.add_span('test_arr', arr_to_add.span()); + log_data.address_items.insert_single('test', contract_address_const::<0>()); + log_data.address_items.insert_span('test_arr', arr_to_add.span()); // assert results OK let addr_item = log_data.address_items.get('test').expect('key not found'); @@ -96,6 +96,6 @@ fn test_log_data_serialization() { ]; // try to add unique - log_data.address_items.add_single('test', contract_address_const::<0>()); - log_data.address_items.add_span('test_arr', arr_to_add.span()); + log_data.address_items.insert_single('test', contract_address_const::<0>()); + log_data.address_items.insert_span('test_arr', arr_to_add.span()); } diff --git a/tests/utils/test_serializable_dict.cairo b/tests/utils/test_serializable_dict.cairo index af98d954..42d58f18 100644 --- a/tests/utils/test_serializable_dict.cairo +++ b/tests/utils/test_serializable_dict.cairo @@ -55,13 +55,13 @@ fn test_item_span() { // SerializableDict tests #[test] -fn test_serializable_dict_add_single() { +fn test_serializable_dict_insert_single() { let mut dict: SerializableFelt252Dict = SerializableFelt252DictTrait::new(); let key: felt252 = 'starknet'; let expected_value: u8 = 42; - dict.add_single(key, expected_value); + dict.insert_single(key, expected_value); let retrieved_item: Item = dict.get(key).expect('key should be in dict'); let out_value: u8 = retrieved_item.unwrap_single(); @@ -70,13 +70,13 @@ fn test_serializable_dict_add_single() { } #[test] -fn test_serializable_dict_add_span() { +fn test_serializable_dict_insert_span() { let mut dict: SerializableFelt252Dict = SerializableFelt252DictTrait::new(); let key: felt252 = 'starknet'; let expected_array: Array = array![1, 2, 3]; - dict.add_span(key, expected_array.span()); + dict.insert_span(key, expected_array.span()); let retrieved_item: Item = dict.get(key).expect('key should be in dict'); let out_span: Span = retrieved_item.unwrap_span(); @@ -91,8 +91,8 @@ fn test_serializable_dict_add_span() { fn test_serializable_dict_serialize() { let mut dict: SerializableFelt252Dict = SerializableFelt252DictTrait::new(); - dict.add_single('test', 42_u128); - dict.add_span('test_arr', array![1, 2, 3].span()); + dict.insert_single('test', 42_u128); + dict.insert_span('test_arr', array![1, 2, 3].span()); let mut output: Array = array![]; // TODO: this fail From 1c86f273704e88d06f97b86d3da3193cd0f4f5ed Mon Sep 17 00:00:00 2001 From: akhercha Date: Mon, 30 Oct 2023 16:40:42 +0100 Subject: [PATCH 27/40] feat(log_data_indexes): Using a custom (de)serialization --- src/event/event_utils_sandbox.cairo | 10 +++- src/utils/serializable_dict.cairo | 63 +++++------------------- tests/event/test_event_utils.cairo | 15 ------ tests/utils/test_serializable_dict.cairo | 52 +++++++++++++------ 4 files changed, 59 insertions(+), 81 deletions(-) diff --git a/src/event/event_utils_sandbox.cairo b/src/event/event_utils_sandbox.cairo index 0a20f32f..58accce3 100644 --- a/src/event/event_utils_sandbox.cairo +++ b/src/event/event_utils_sandbox.cairo @@ -68,7 +68,7 @@ struct EventLogData { // TODO } -#[derive(Default, Destruct, Serde)] +#[derive(Default, Destruct)] struct LogData { address_items: SerializableFelt252Dict, uint_items: SerializableFelt252Dict, @@ -79,6 +79,14 @@ struct LogData { string_items: SerializableFelt252Dict } +#[generate_trait] +impl LogDataImpl of LogDataTrait { + fn custom_serialize(ref self: LogData, ref output: Array) {} + fn custom_deserialize(ref serialized: Span) -> Option { + Option::Some(Default::default()) + } +} + // uint fn set_item_uint_items( mut dict: SerializableFelt252Dict, key: felt252, value: u128 diff --git a/src/utils/serializable_dict.cairo b/src/utils/serializable_dict.cairo index 1cc635ce..f2fd7f63 100644 --- a/src/utils/serializable_dict.cairo +++ b/src/utils/serializable_dict.cairo @@ -76,19 +76,24 @@ trait SerializableFelt252DictTrait { /// Adds an array of elements. fn insert_span(ref self: SerializableFelt252Dict, key: felt252, values: Span); /// Gets an element. - fn get>( - ref self: SerializableFelt252Dict, key: felt252 - ) -> Option>; + fn get(ref self: SerializableFelt252Dict, key: felt252) -> Option>; /// Checks if a key is in the dictionnary. fn contains(self: @SerializableFelt252Dict, key: felt252) -> bool; /// Number of keys in the dictionnary. fn len(self: @SerializableFelt252Dict) -> usize; /// Checks if a dictionnary is empty. fn is_empty(self: @SerializableFelt252Dict) -> bool; + fn custom_serialize(ref self: SerializableFelt252Dict, ref output: Array); + fn custom_deserialize(ref serialized: Span) -> Option>; } impl SerializableFelt252DictTraitImpl< - T, impl TDefault: Felt252DictValue, impl TDrop: Drop, impl TCopy: Copy + T, + impl TDefault: Felt252DictValue, + impl TDrop: Drop, + impl TCopy: Copy, + impl FeltIntoT: Into, + impl TIntoFelt: Into, > of SerializableFelt252DictTrait { fn new() -> SerializableFelt252Dict { SerializableFelt252Dict { keys: array![], values: Default::default() } @@ -110,9 +115,7 @@ impl SerializableFelt252DictTraitImpl< self.values.insert(key, nullable_from_box(BoxTrait::new(values))); } - fn get>( - ref self: SerializableFelt252Dict, key: felt252 - ) -> Option> { + fn get(ref self: SerializableFelt252Dict, key: felt252) -> Option> { match match_nullable(self.values.get(key)) { FromNullableResult::Null(()) => Option::None, FromNullableResult::NotNull(val) => Option::Some(val.unbox()), @@ -145,47 +148,13 @@ impl SerializableFelt252DictTraitImpl< fn is_empty(self: @SerializableFelt252Dict) -> bool { self.len() == 0 } -} - -impl SerializableFelt252DictSerde< - T, - impl TCopy: Copy, - impl TDrop: Drop, - impl FeltIntoT: Into, - impl TIntoFelt: Into, -> of Serde> { - // - // Serialization of an SerializableFelt252Dict - // - // An SerializableFelt252Dict is serialized as follow: - // [ KEY | NB_ELEMENTS | X | Y | ... | KEY | NB_ELEMENTS | X | ...] - // - // - // e.g. if we try to serialize this Dict: - // keys: [0, 1] - // values: { - // 0: 1, - // 1: [1, 2, 3] - // } - // - // will give: - // - // key: 0 key: 1 - // | ------ | ----------- | - // [0, 1, 1, 1, 3, 1, 2, 3] (Array) - // - fn serialize(self: @SerializableFelt252Dict, ref output: Array) { + fn custom_serialize(ref self: SerializableFelt252Dict, ref output: Array) { let mut keys: Span = self.keys.span(); loop { match keys.pop_front() { Option::Some(key) => { - let mut d = *self.values; - let nullable_value: Nullable> = d.get(*key); - let value: Item = match match_nullable(nullable_value) { - FromNullableResult::Null(()) => panic_with_felt252('err getting key'), - FromNullableResult::NotNull(boxed_value) => boxed_value.unbox(), - }; + let value: Item = self.get(*key).expect('key should exist'); match value { Item::Single(v) => { output.append(*key); // key @@ -215,13 +184,7 @@ impl SerializableFelt252DictSerde< }; } - // - // Deserialization of an SerializableFelt252Dict - // - // An SerializableFelt252Dict is serialized as follow: - // [ KEY | NB_ELEMENTS | X | Y | ... | KEY | NB_ELEMENTS | X | ...] - // - fn deserialize(ref serialized: Span) -> Option> { + fn custom_deserialize(ref serialized: Span) -> Option> { let mut d: SerializableFelt252Dict = SerializableFelt252Dict { keys: array![], values: Default::default() }; diff --git a/tests/event/test_event_utils.cairo b/tests/event/test_event_utils.cairo index ecf6061c..eacd77ea 100644 --- a/tests/event/test_event_utils.cairo +++ b/tests/event/test_event_utils.cairo @@ -84,18 +84,3 @@ fn test_log_data_multiple_types() { assert(out_span.at(1) == arr_to_add.at(1), 'wrong at idx 1'); assert(out_span.at(2) == arr_to_add.at(2), 'wrong at idx 2'); } - -#[test] -fn test_log_data_serialization() { - let mut log_data: LogData = Default::default(); - - let arr_to_add: Array = array![ - contract_address_const::<'cairo'>(), - contract_address_const::<'starknet'>(), - contract_address_const::<'rust'>() - ]; - - // try to add unique - log_data.address_items.insert_single('test', contract_address_const::<0>()); - log_data.address_items.insert_span('test_arr', arr_to_add.span()); -} diff --git a/tests/utils/test_serializable_dict.cairo b/tests/utils/test_serializable_dict.cairo index 42d58f18..66e4b6b3 100644 --- a/tests/utils/test_serializable_dict.cairo +++ b/tests/utils/test_serializable_dict.cairo @@ -22,7 +22,7 @@ use satoru::event::event_utils_sandbox::{ }; use satoru::utils::serializable_dict::{ Item, ItemTrait, SerializableFelt252Dict, SerializableFelt252DictTrait, - SerializableFelt252DictTraitImpl, SerializableFelt252DictSerde + SerializableFelt252DictTraitImpl }; // ********************************************************************************************* @@ -33,7 +33,7 @@ use satoru::utils::serializable_dict::{ #[test] fn test_item_single() { - let item: Item = Item::Single(8); + let item: Item = Item::Single(8); assert(item.is_single() == true, 'item should be single'); assert(item.is_span() == false, 'item shouldnt be a span'); @@ -42,10 +42,10 @@ fn test_item_single() { #[test] fn test_item_span() { - let arr: Array = array![1, 2, 3, 4, 5]; + let arr: Array = array![1, 2, 3, 4, 5]; let expected_len: usize = arr.len(); - let item: Item = Item::Span(arr.span()); + let item: Item = Item::Span(arr.span()); assert(item.is_span() == true, 'item should be a span'); assert(item.is_single() == false, 'item shouldnt be single'); @@ -56,30 +56,30 @@ fn test_item_span() { #[test] fn test_serializable_dict_insert_single() { - let mut dict: SerializableFelt252Dict = SerializableFelt252DictTrait::new(); + let mut dict: SerializableFelt252Dict = SerializableFelt252DictTrait::new(); let key: felt252 = 'starknet'; - let expected_value: u8 = 42; + let expected_value: u128 = 42; dict.insert_single(key, expected_value); let retrieved_item: Item = dict.get(key).expect('key should be in dict'); - let out_value: u8 = retrieved_item.unwrap_single(); + let out_value: u128 = retrieved_item.unwrap_single(); assert(out_value == expected_value, 'wrong value'); } #[test] fn test_serializable_dict_insert_span() { - let mut dict: SerializableFelt252Dict = SerializableFelt252DictTrait::new(); + let mut dict: SerializableFelt252Dict = SerializableFelt252DictTrait::new(); let key: felt252 = 'starknet'; - let expected_array: Array = array![1, 2, 3]; + let expected_array: Array = array![1, 2, 3]; dict.insert_span(key, expected_array.span()); let retrieved_item: Item = dict.get(key).expect('key should be in dict'); - let out_span: Span = retrieved_item.unwrap_span(); + let out_span: Span = retrieved_item.unwrap_span(); assert(dict.keys.contains(key), 'key should be in dict'); assert(out_span.at(0) == expected_array.at(0), 'wrong at idx 0'); @@ -91,10 +91,32 @@ fn test_serializable_dict_insert_span() { fn test_serializable_dict_serialize() { let mut dict: SerializableFelt252Dict = SerializableFelt252DictTrait::new(); - dict.insert_single('test', 42_u128); - dict.insert_span('test_arr', array![1, 2, 3].span()); + let expected_value: u128 = 42; + let expected_array: Array = array![1, 2, 3]; + + dict.insert_single('test', expected_value); + dict.insert_span('test_span', expected_array.span()); + + let mut serialized: Array = array![]; + dict.custom_serialize(ref serialized); + + let mut span_serialized: Span = serialized.span(); + let mut deserialized_dict: SerializableFelt252Dict = + match SerializableFelt252DictTrait::::custom_deserialize(ref span_serialized) { + Option::Some(d) => d, + Option::None => panic_with_felt252('err while recreating d') + }; - let mut output: Array = array![]; -// TODO: this fail -// SerializableFelt252DictSerde::serialize(@dict, ref output); + assert(dict.keys.contains('test'), 'key should be in dict'); + let retrieved_item: Item = dict.get('test').expect('key should be in dict'); + let out_value: u128 = retrieved_item.unwrap_single(); + + assert(dict.keys.contains('test_span'), 'key should be in dict'); + let retrieved_item: Item = deserialized_dict + .get('test_span') + .expect('key should be in dict'); + let out_span: Span = retrieved_item.unwrap_span(); + assert(out_span.at(0) == expected_array.at(0), 'wrong at idx 0'); + assert(out_span.at(1) == expected_array.at(1), 'wrong at idx 1'); + assert(out_span.at(2) == expected_array.at(2), 'wrong at idx 2'); } From 4663984f28be4c80ef88f6c4cf96eaccccf7b0a8 Mon Sep 17 00:00:00 2001 From: akhercha Date: Mon, 30 Oct 2023 16:44:31 +0100 Subject: [PATCH 28/40] feat(log_data_indexes): TODO: implement custom_(de)serialize for LogData --- src/event/event_utils_sandbox.cairo | 82 ++--------------------------- 1 file changed, 3 insertions(+), 79 deletions(-) diff --git a/src/event/event_utils_sandbox.cairo b/src/event/event_utils_sandbox.cairo index 58accce3..8c6516b9 100644 --- a/src/event/event_utils_sandbox.cairo +++ b/src/event/event_utils_sandbox.cairo @@ -81,87 +81,11 @@ struct LogData { #[generate_trait] impl LogDataImpl of LogDataTrait { + /// Serializes all the sub-dicts of LogData & append all the felt252 array together fn custom_serialize(ref self: LogData, ref output: Array) {} + /// Deserialize all the sub-dicts serialized into a LogData fn custom_deserialize(ref serialized: Span) -> Option { + // TODO + needed? Option::Some(Default::default()) } } - -// uint -fn set_item_uint_items( - mut dict: SerializableFelt252Dict, key: felt252, value: u128 -) -> SerializableFelt252Dict { - dict.insert_single(key, value); - dict -} - -fn set_item_array_uint_items( - mut dict: SerializableFelt252Dict, key: felt252, values: Array -) -> SerializableFelt252Dict { - dict.insert_span(key, values.span()); - dict -} - - -// int -fn set_item_int_items( - mut dict: SerializableFelt252Dict, key: felt252, value: i128 -) -> SerializableFelt252Dict { - dict.insert_single(key, value); - dict -} - -fn set_item_array_int_items( - mut dict: SerializableFelt252Dict, key: felt252, values: Array -) -> SerializableFelt252Dict { - dict.insert_span(key, values.span()); - dict -} - - -// bool -fn set_item_bool_items( - mut dict: SerializableFelt252Dict, key: felt252, value: bool -) -> SerializableFelt252Dict { - dict.insert_single(key, value); - dict -} - -fn set_item_array_bool_items( - mut dict: SerializableFelt252Dict, key: felt252, values: Array -) -> SerializableFelt252Dict { - dict.insert_span(key, values.span()); - dict -} - - -// felt252 -fn set_item_Felt252_items( - mut dict: SerializableFelt252Dict, key: felt252, value: felt252 -) -> SerializableFelt252Dict { - dict.insert_single(key, value); - dict -} - -fn set_item_array_Felt252_items( - mut dict: SerializableFelt252Dict, key: felt252, values: Array -) -> SerializableFelt252Dict { - dict.insert_span(key, values.span()); - dict -} - - -// string -fn set_item_string_items( - mut dict: SerializableFelt252Dict, key: felt252, value: felt252 -) -> SerializableFelt252Dict { - dict.insert_single(key, value); - dict -} - -fn set_item_array_string_items( - mut dict: SerializableFelt252Dict, key: felt252, values: Array -) -> SerializableFelt252Dict { - dict.insert_span(key, values.span()); - dict -} From 8beccb59be7c10d26932046a9c92ac9dab6a9138 Mon Sep 17 00:00:00 2001 From: akhercha Date: Mon, 30 Oct 2023 17:01:23 +0100 Subject: [PATCH 29/40] feat(log_data_indexes): Added serialization for LogData --- src/event/event_utils_sandbox.cairo | 81 +++++++++++++++++++++++++---- tests/event/test_event_utils.cairo | 36 ++++++------- 2 files changed, 89 insertions(+), 28 deletions(-) diff --git a/src/event/event_utils_sandbox.cairo b/src/event/event_utils_sandbox.cairo index 8c6516b9..7ecec78f 100644 --- a/src/event/event_utils_sandbox.cairo +++ b/src/event/event_utils_sandbox.cairo @@ -10,9 +10,8 @@ use satoru::utils::traits::ContractAddressDefault; use satoru::utils::serializable_dict::{SerializableFelt252Dict, SerializableFelt252DictTrait}; // -// NEEDED IMPLEMENTATIONS... +// NEEDED IMPLEMENTATIONS FOR LOGDATA TYPES // -/// TODO: move those somewhere else? impl Felt252IntoBool of Into { #[inline(always)] @@ -70,22 +69,84 @@ struct EventLogData { #[derive(Default, Destruct)] struct LogData { - address_items: SerializableFelt252Dict, - uint_items: SerializableFelt252Dict, - int_items: SerializableFelt252Dict, - bool_items: SerializableFelt252Dict, - felt252_items: SerializableFelt252Dict, - // TODO? Possible? array_of_felt_items: SerializableFelt252Dict>, - string_items: SerializableFelt252Dict + address_dict: SerializableFelt252Dict, + uint_dict: SerializableFelt252Dict, + int_dict: SerializableFelt252Dict, + bool_dict: SerializableFelt252Dict, + felt252_dict: SerializableFelt252Dict, + // TODO? Possible? array_of_felt_dict: SerializableFelt252Dict>, + string_dict: SerializableFelt252Dict } #[generate_trait] impl LogDataImpl of LogDataTrait { /// Serializes all the sub-dicts of LogData & append all the felt252 array together - fn custom_serialize(ref self: LogData, ref output: Array) {} + fn custom_serialize(ref self: LogData, ref output: Array) { + let mut serialized_dicts: Array> = array![]; + + let mut address_dict_serialized: Array = array![]; + self.address_dict.custom_serialize(ref address_dict_serialized); + serialized_dicts.append(address_dict_serialized); + + let mut uint_dict_serialized: Array = array![]; + self.uint_dict.custom_serialize(ref uint_dict_serialized); + serialized_dicts.append(uint_dict_serialized); + + let mut int_dict_serialized: Array = array![]; + self.int_dict.custom_serialize(ref int_dict_serialized); + serialized_dicts.append(int_dict_serialized); + + let mut bool_dict_serialized: Array = array![]; + self.bool_dict.custom_serialize(ref bool_dict_serialized); + serialized_dicts.append(bool_dict_serialized); + + let mut felt252_dict_serialized: Array = array![]; + self.felt252_dict.custom_serialize(ref felt252_dict_serialized); + serialized_dicts.append(felt252_dict_serialized); + + let mut string_dict_serialized: Array = array![]; + self.string_dict.custom_serialize(ref string_dict_serialized); + serialized_dicts.append(string_dict_serialized); + + append_all_arrays_to_output(serialized_dicts, ref output); + } /// Deserialize all the sub-dicts serialized into a LogData fn custom_deserialize(ref serialized: Span) -> Option { // TODO + needed? Option::Some(Default::default()) } } + +// +// UTILITIES +// + +// When serializing dicts into a unique Array, this is the value that will +// be used to recognized a separation between two dicts. +const DICT_SEPARATION: felt252 = '______'; + +fn append_all_arrays_to_output(array_of_arrays: Array>, ref output: Array) { + let mut span_arrays = array_of_arrays.span(); + + loop { + match span_arrays.pop_front() { + Option::Some(arr) => { + let mut sub_array_span = arr.span(); + loop { + match sub_array_span.pop_front() { + Option::Some(v) => { + output.append(*v); + }, + Option::None => { + break; + } + }; + }; + output.append(DICT_SEPARATION); + }, + Option::None => { + break; + } + }; + } +} diff --git a/tests/event/test_event_utils.cairo b/tests/event/test_event_utils.cairo index eacd77ea..c1d72617 100644 --- a/tests/event/test_event_utils.cairo +++ b/tests/event/test_event_utils.cairo @@ -18,15 +18,15 @@ fn test_log_data_default() { let mut log_data: LogData = Default::default(); // try to add things - log_data.address_items.insert_single('test', contract_address_const::<0>()); - log_data.uint_items.insert_single('test', 12_u128); + log_data.address_dict.insert_single('test', contract_address_const::<0>()); + log_data.uint_dict.insert_single('test', 12_u128); // assert results OK - let addr_item = log_data.address_items.get('test').expect('key not found'); + let addr_item = log_data.address_dict.get('test').expect('key not found'); let addr_value = addr_item.unwrap_single(); assert(addr_value == contract_address_const::<0>(), 'addr value wrong'); - let uint_item = log_data.uint_items.get('test').expect('key not found'); + let uint_item = log_data.uint_dict.get('test').expect('key not found'); let uint_value = uint_item.unwrap_single(); assert(uint_value == 12_u128, 'uint value wrong'); } @@ -34,24 +34,24 @@ fn test_log_data_default() { #[test] fn test_log_data_default_each() { let mut log_data: LogData = LogData { - address_items: Default::default(), - uint_items: Default::default(), - int_items: Default::default(), - bool_items: Default::default(), - felt252_items: Default::default(), - string_items: Default::default() + address_dict: Default::default(), + uint_dict: Default::default(), + int_dict: Default::default(), + bool_dict: Default::default(), + felt252_dict: Default::default(), + string_dict: Default::default() }; // try to add things - log_data.address_items.insert_single('test', contract_address_const::<0>()); - log_data.uint_items.insert_single('test', 12_u128); + log_data.address_dict.insert_single('test', contract_address_const::<0>()); + log_data.uint_dict.insert_single('test', 12_u128); // assert results OK - let addr_item = log_data.address_items.get('test').expect('key not found'); + let addr_item = log_data.address_dict.get('test').expect('key not found'); let addr_value = addr_item.unwrap_single(); assert(addr_value == contract_address_const::<0>(), 'addr value wrong'); - let uint_item = log_data.uint_items.get('test').expect('key not found'); + let uint_item = log_data.uint_dict.get('test').expect('key not found'); let uint_value = uint_item.unwrap_single(); assert(uint_value == 12_u128, 'uint value wrong'); } @@ -67,16 +67,16 @@ fn test_log_data_multiple_types() { ]; // try to add unique - log_data.address_items.insert_single('test', contract_address_const::<0>()); - log_data.address_items.insert_span('test_arr', arr_to_add.span()); + log_data.address_dict.insert_single('test', contract_address_const::<0>()); + log_data.address_dict.insert_span('test_arr', arr_to_add.span()); // assert results OK - let addr_item = log_data.address_items.get('test').expect('key not found'); + let addr_item = log_data.address_dict.get('test').expect('key not found'); let addr_value = addr_item.unwrap_single(); assert(addr_value == contract_address_const::<0>(), 'addr value wrong'); let addr_span_item: Item = log_data - .address_items + .address_dict .get('test_arr') .expect('key should be in dict'); let out_span: Span = addr_span_item.unwrap_span(); From f5984d3b5f18fdd571ee3186201cef3ba27c1afd Mon Sep 17 00:00:00 2001 From: akhercha Date: Mon, 30 Oct 2023 17:29:05 +0100 Subject: [PATCH 30/40] feat(log_data_indexes): Dict working --- src/callback/callback_utils.cairo | 46 +- .../deposit_callback_receiver/interface.cairo | 4 +- src/callback/mocks.cairo | 4 +- .../order_callback_receiver/interface.cairo | 8 +- .../interface.cairo | 4 +- src/deposit/deposit_utils.cairo | 3 +- src/deposit/execute_deposit_utils.cairo | 14 +- src/event/event_utils.cairo | 400 ++++++------------ src/order/decrease_order_utils.cairo | 41 +- src/order/order_utils.cairo | 12 +- src/order/swap_order_utils.cairo | 27 +- tests/callback/test_callback_utils.cairo | 2 +- 12 files changed, 209 insertions(+), 356 deletions(-) diff --git a/src/callback/callback_utils.cairo b/src/callback/callback_utils.cairo index 21f46091..61500413 100644 --- a/src/callback/callback_utils.cairo +++ b/src/callback/callback_utils.cairo @@ -91,99 +91,103 @@ fn get_saved_callback_contract( /// # Arguments /// * `key` - They key of the deposit. /// * `deposit` - The deposit that was executed. -/// * `log_data` - The log data. -fn after_deposit_execution(key: felt252, deposit: Deposit, log_data: LogData) { +/// * `serialized_log_data` - The log data. +fn after_deposit_execution(key: felt252, deposit: Deposit, serialized_log_data: Array) { if !is_valid_callback_contract(deposit.callback_contract) { return; } let dispatcher = IDepositCallbackReceiverDispatcher { contract_address: deposit.callback_contract }; - dispatcher.after_deposit_execution(key, deposit, log_data) + dispatcher.after_deposit_execution(key, deposit, serialized_log_data) } /// Called after a deposit cancellation. /// # Arguments /// * `key` - They key of the deposit. /// * `deposit` - The deposit that was cancelled. -/// * `log_data` - The log data. -fn after_deposit_cancellation(key: felt252, deposit: Deposit, log_data: LogData) { +/// * `serialized_log_data` - The log data. +fn after_deposit_cancellation(key: felt252, deposit: Deposit, serialized_log_data: Array) { if !is_valid_callback_contract(deposit.callback_contract) { return; } let dispatcher = IDepositCallbackReceiverDispatcher { contract_address: deposit.callback_contract }; - dispatcher.after_deposit_cancellation(key, deposit, log_data) + dispatcher.after_deposit_cancellation(key, deposit, serialized_log_data) } /// Called after a withdrawal execution. /// # Arguments /// * `key` - They key of the withdrawal. /// * `withdrawal` - The withdrawal that was executed. -/// * `log_data` - The log data. -fn after_withdrawal_execution(key: felt252, withdrawal: Withdrawal, log_data: LogData) { +/// * `serialized_log_data` - The log data. +fn after_withdrawal_execution( + key: felt252, withdrawal: Withdrawal, serialized_log_data: Array +) { if !is_valid_callback_contract(withdrawal.callback_contract) { return; } let dispatcher = IWithdrawalCallbackReceiverDispatcher { contract_address: withdrawal.callback_contract }; - dispatcher.after_withdrawal_execution(key, withdrawal, log_data) + dispatcher.after_withdrawal_execution(key, withdrawal, serialized_log_data) } /// Called after an withdrawal cancellation. /// # Arguments /// * `key` - They key of the withdrawal. /// * `withdrawal` - The withdrawal that was cancelled. -/// * `log_data` - The log data. -fn after_withdrawal_cancellation(key: felt252, withdrawal: Withdrawal, log_data: LogData) { +/// * `serialized_log_data` - The log data. +fn after_withdrawal_cancellation( + key: felt252, withdrawal: Withdrawal, serialized_log_data: Array +) { if !is_valid_callback_contract(withdrawal.callback_contract) { return; } let dispatcher = IWithdrawalCallbackReceiverDispatcher { contract_address: withdrawal.callback_contract }; - dispatcher.after_withdrawal_cancellation(key, withdrawal, log_data) + dispatcher.after_withdrawal_cancellation(key, withdrawal, serialized_log_data) } /// Called after an order execution. /// # Arguments /// * `key` - They key of the order. /// * `order` - The order that was executed. -/// * `log_data` - The log data. -fn after_order_execution(key: felt252, order: Order, log_data: LogData) { +/// * `serialized_log_data` - The log data. +fn after_order_execution(key: felt252, order: Order, serialized_log_data: Array) { if !is_valid_callback_contract(order.callback_contract) { return; } let dispatcher = IOrderCallbackReceiverDispatcher { contract_address: order.callback_contract }; - dispatcher.after_order_execution(key, order, log_data) + dispatcher.after_order_execution(key, order, serialized_log_data) } /// Called after an order cancellation. /// # Arguments /// * `key` - They key of the order. /// * `order` - The order that was cancelled. -/// * `log_data` - The log data. -fn after_order_cancellation(key: felt252, order: Order, log_data: LogData) { +/// * `serialized_log_data` - The log data. +fn after_order_cancellation(key: felt252, order: Order, serialized_log_data: Array) { if !is_valid_callback_contract(order.callback_contract) { return; } let dispatcher = IOrderCallbackReceiverDispatcher { contract_address: order.callback_contract }; - dispatcher.after_order_cancellation(key, order, log_data) + dispatcher.after_order_cancellation(key, order, serialized_log_data) } /// Called after an order cancellation. /// # Arguments /// * `key` - They key of the order. /// * `order` - The order that was frozen. -/// * `log_data` - The log data. -fn after_order_frozen(key: felt252, order: Order, log_data: LogData) { +/// * `serialized_log_data` - The log data. +fn after_order_frozen(key: felt252, order: Order, serialized_log_data: Array) { if !is_valid_callback_contract(order.callback_contract) { return; } let dispatcher = IOrderCallbackReceiverDispatcher { contract_address: order.callback_contract }; - dispatcher.after_order_frozen(key, order, log_data) + dispatcher.after_order_frozen(key, order, serialized_log_data) } /// Validates that the given address is a contract. diff --git a/src/callback/deposit_callback_receiver/interface.cairo b/src/callback/deposit_callback_receiver/interface.cairo index de3d21f6..e45b7b33 100644 --- a/src/callback/deposit_callback_receiver/interface.cairo +++ b/src/callback/deposit_callback_receiver/interface.cairo @@ -13,7 +13,7 @@ trait IDepositCallbackReceiver { /// * `event_data` - The event log data. /// * `deposit` - The deposit that was executed. fn after_deposit_execution( - ref self: TContractState, key: felt252, deposit: Deposit, log_data: LogData, + ref self: TContractState, key: felt252, deposit: Deposit, log_data: Array, ); /// Called after a deposit cancellation. @@ -22,6 +22,6 @@ trait IDepositCallbackReceiver { /// * `event_data` - The event log data. /// * `deposit` - The deposit that was cancelled. fn after_deposit_cancellation( - ref self: TContractState, key: felt252, deposit: Deposit, log_data: LogData, + ref self: TContractState, key: felt252, deposit: Deposit, log_data: Array, ); } diff --git a/src/callback/mocks.cairo b/src/callback/mocks.cairo index e34d0438..f4f66d4b 100644 --- a/src/callback/mocks.cairo +++ b/src/callback/mocks.cairo @@ -35,13 +35,13 @@ mod CallbackMock { #[external(v0)] impl IDepositCallbackReceiverImpl of IDepositCallbackReceiver { fn after_deposit_execution( - ref self: ContractState, key: felt252, deposit: Deposit, log_data: LogData, + ref self: ContractState, key: felt252, deposit: Deposit, log_data: Array, ) { self.counter.write(self.get_counter() + 1); } fn after_deposit_cancellation( - ref self: ContractState, key: felt252, deposit: Deposit, log_data: LogData, + ref self: ContractState, key: felt252, deposit: Deposit, log_data: Array, ) { self.counter.write(self.get_counter() + 1); } diff --git a/src/callback/order_callback_receiver/interface.cairo b/src/callback/order_callback_receiver/interface.cairo index f1cc1944..8d1c8912 100644 --- a/src/callback/order_callback_receiver/interface.cairo +++ b/src/callback/order_callback_receiver/interface.cairo @@ -13,7 +13,7 @@ trait IOrderCallbackReceiver { /// * `order` - The order that was executed. /// * `log_data` - The log data. fn after_order_execution( - ref self: TContractState, key: felt252, order: Order, log_data: LogData + ref self: TContractState, key: felt252, order: Order, log_data: Array ); /// Called after an order cancellation. @@ -22,7 +22,7 @@ trait IOrderCallbackReceiver { /// * `order` - The order that was cancelled. /// * `log_data` - The log data. fn after_order_cancellation( - ref self: TContractState, key: felt252, order: Order, log_data: LogData + ref self: TContractState, key: felt252, order: Order, log_data: Array ); /// Called after an order cancellation. @@ -30,5 +30,7 @@ trait IOrderCallbackReceiver { /// * `key` - They key of the order. /// * `order` - The order that was frozen. /// * `log_data` - The log data. - fn after_order_frozen(ref self: TContractState, key: felt252, order: Order, log_data: LogData); + fn after_order_frozen( + ref self: TContractState, key: felt252, order: Order, log_data: Array + ); } diff --git a/src/callback/withdrawal_callback_receiver/interface.cairo b/src/callback/withdrawal_callback_receiver/interface.cairo index 9f73f468..1c43a31f 100644 --- a/src/callback/withdrawal_callback_receiver/interface.cairo +++ b/src/callback/withdrawal_callback_receiver/interface.cairo @@ -14,7 +14,7 @@ trait IWithdrawalCallbackReceiver { /// * `log_data` - The log data. // TODO uncomment withdrawal when available fn after_withdrawal_execution( - ref self: TContractState, key: felt252, withdrawal: Withdrawal, log_data: LogData, + ref self: TContractState, key: felt252, withdrawal: Withdrawal, log_data: Array, ); /// Called after an withdrawal cancellation. @@ -23,6 +23,6 @@ trait IWithdrawalCallbackReceiver { /// * `withdrawal` - The withdrawal that was cancelled. /// * `log_data` - The log data. fn after_withdrawal_cancellation( - ref self: TContractState, key: felt252, withdrawal: Withdrawal, log_data: LogData, + ref self: TContractState, key: felt252, withdrawal: Withdrawal, log_data: Array, ); } diff --git a/src/deposit/deposit_utils.cairo b/src/deposit/deposit_utils.cairo index e5d3719a..9b9aa81a 100644 --- a/src/deposit/deposit_utils.cairo +++ b/src/deposit/deposit_utils.cairo @@ -184,8 +184,7 @@ fn cancel_deposit( event_emitter.emit_deposit_cancelled(key, reason, reason_bytes.span()); - let log_data: LogData = Default::default(); - after_deposit_cancellation(key, deposit, log_data); + after_deposit_cancellation(key, deposit, array![]); gas_utils::pay_execution_fee_deposit( data_store, diff --git a/src/deposit/execute_deposit_utils.cairo b/src/deposit/execute_deposit_utils.cairo index a44d0112..6311ace2 100644 --- a/src/deposit/execute_deposit_utils.cairo +++ b/src/deposit/execute_deposit_utils.cairo @@ -20,7 +20,10 @@ use satoru::deposit::{ deposit_vault::{IDepositVaultDispatcher, IDepositVaultDispatcherTrait}, error::DepositError }; use satoru::event::event_emitter::{IEventEmitterDispatcher, IEventEmitterDispatcherTrait}; -use satoru::event::event_utils::{LogData, set_item_uint_items, UintItems}; +use satoru::event::event_utils::{ + LogData, LogDataTrait, Felt252IntoU128, ContractAddressDictValue, I128252DictValue +}; +use satoru::utils::serializable_dict::{SerializableFelt252Dict, SerializableFelt252DictTrait}; use satoru::fee::fee_utils; use satoru::gas::gas_utils::pay_execution_fee_deposit; use satoru::market::{ @@ -237,10 +240,11 @@ fn execute_deposit(params: ExecuteDepositParams) { cache.received_market_tokens, ); - let event_data: LogData = Default::default(); - let mut uint_items: UintItems = Default::default(); - set_item_uint_items(uint_items, 0, 'received_market_tokens', cache.received_market_tokens); - after_deposit_execution(params.key, deposit, event_data); + let mut event_data: LogData = Default::default(); + event_data.uint_dict.insert_single('received_market_tokens', cache.received_market_tokens); + let mut serialized_event_data: Array = array![]; + event_data.custom_serialize(ref serialized_event_data); + after_deposit_execution(params.key, deposit, serialized_event_data); pay_execution_fee_deposit( params.data_store, diff --git a/src/event/event_utils.cairo b/src/event/event_utils.cairo index a7ec710d..f4188f09 100644 --- a/src/event/event_utils.cairo +++ b/src/event/event_utils.cairo @@ -1,294 +1,152 @@ -use starknet::{get_caller_address, ContractAddress, contract_address_const}; +use starknet::{ + get_caller_address, ContractAddress, Felt252TryIntoContractAddress, ContractAddressIntoFelt252, + contract_address_const +}; use array::ArrayTrait; use satoru::utils::i128::i128; use traits::Default; use satoru::utils::traits::ContractAddressDefault; -//TODO Switch the append with a set in the functions when its available -#[derive(Drop, Serde)] -struct EventLogData { - cant_be_empty: u128, // remove -// TODO -} +use satoru::utils::serializable_dict::{SerializableFelt252Dict, SerializableFelt252DictTrait}; -#[derive(Default, Serde, Drop)] -struct LogData { - address_items: AddressItems, - uint_items: UintItems, - int_items: IntItems, - bool_items: BoolItems, - felt252_items: Felt252Items, - array_of_felt_items: ArrayOfFeltItems, - string_items: StringItems, -} +// +// NEEDED IMPLEMENTATIONS FOR LOGDATA TYPES +// -//ContractAddress -#[derive(Default, Serde, Drop)] -struct AddressItems { - items: Array, - array_items: Array, +impl Felt252IntoBool of Into { + #[inline(always)] + fn into(self: felt252) -> bool { + let as_u128: u128 = self.try_into().expect('u128 Overflow'); + as_u128 > 0 + } } -#[derive(Default, Serde, Drop)] -struct AddressKeyValue { - key: felt252, - value: ContractAddress, +impl Felt252IntoU128 of Into { + #[inline(always)] + fn into(self: felt252) -> u128 { + self.try_into().expect('u128 Overflow') + } } -#[derive(Default, Serde, Drop)] -struct AddressArrayKeyValue { - key: felt252, - value: Array, -} - -//u128 - -#[derive(Default, Serde, Drop)] -struct UintItems { - items: Array, - array_items: Array, -} - -#[derive(Default, Serde, Drop)] -struct UintKeyValue { - key: felt252, - value: u128, -} - -#[derive(Default, Serde, Drop)] -struct UintArrayKeyValue { - key: felt252, - value: Array, -} - -//i128 -#[derive(Default, Serde, Drop)] -struct IntItems { - items: Array, - array_items: Array, -} - -#[derive(Default, Serde, Drop)] -struct IntKeyValue { - key: felt252, - value: i128, -} - -#[derive(Default, Serde, Drop)] -struct IntArrayKeyValue { - key: felt252, - value: Array, -} - -//bool -#[derive(Default, Serde, Drop)] -struct BoolItems { - items: Array, - array_items: Array, -} - -#[derive(Default, Serde, Drop)] -struct BoolKeyValue { - key: felt252, - value: bool, -} - -#[derive(Default, Serde, Drop)] -struct BoolArrayKeyValue { - key: felt252, - value: Array, -} - -//Felt252 -#[derive(Default, Serde, Drop)] -struct Felt252Items { - items: Array, - array_items: Array, -} - -#[derive(Default, Serde, Drop)] -struct Felt252KeyValue { - key: felt252, - value: felt252, -} - -#[derive(Default, Serde, Drop)] -struct Felt252ArrayKeyValue { - key: felt252, - value: Array, -} - -//Array of Felt -#[derive(Default, Serde, Drop)] -struct ArrayOfFeltItems { - items: Array, - array_items: Array, -} - -#[derive(Default, Serde, Drop)] -struct ArrayOfFeltKeyValue { - key: felt252, - value: Array, -} -#[derive(Default, Serde, Drop)] -struct ArrayOfFeltArrayKeyValue { - key: felt252, - value: Array>, +impl Felt252IntoI128 of Into { + #[inline(always)] + fn into(self: felt252) -> i128 { + self.try_into().expect('i128 Overflow') + } } -//String switch later -#[derive(Default, Serde, Drop)] -struct StringItems { - items: Array, - array_items: Array, +impl Felt252IntoContractAddress of Into { + #[inline(always)] + fn into(self: felt252) -> ContractAddress { + Felt252TryIntoContractAddress::try_into(self).expect('contractaddress overflow') + } } -#[derive(Default, Serde, Drop)] -struct StringKeyValue { - key: felt252, - value: felt252, +impl I128252DictValue of Felt252DictValue { + #[inline(always)] + fn zero_default() -> i128 nopanic { + i128 { mag: 0, sign: false } + } } -#[derive(Default, Serde, Drop)] -struct StringArrayKeyValue { - key: felt252, - value: Array, +impl ContractAddressDictValue of Felt252DictValue { + #[inline(always)] + fn zero_default() -> ContractAddress nopanic { + contract_address_const::<0>() + } } -//TODO for the functions we need to implement the set instead of append and use the set with index. +// +// LOG DATA +// -//AddressItems - -fn set_item_address_items( - mut items: AddressItems, index: u32, key: felt252, value: ContractAddress -) -> AddressItems { - let address_key_value: AddressKeyValue = AddressKeyValue { key, value }; - let mut address: AddressItems = items; - address.items.append(address_key_value); - return address; -} - -fn set_item_array_address_items( - mut items: AddressItems, index: u32, key: felt252, value: Array -) -> AddressItems { - let address_array_key_value: AddressArrayKeyValue = AddressArrayKeyValue { key, value }; - let mut array_address: AddressItems = items; - array_address.array_items.append(address_array_key_value); - return array_address; -} - -// Uint - -fn set_item_uint_items(mut items: UintItems, index: u32, key: felt252, value: u128) -> UintItems { - let uint_key_value: UintKeyValue = UintKeyValue { key, value }; - let mut address: UintItems = items; - address.items.append(uint_key_value); - return address; -} - -fn set_item_array_uint_items( - mut items: UintItems, index: u32, key: felt252, value: Array -) -> UintItems { - let uint_array_key_value: UintArrayKeyValue = UintArrayKeyValue { key, value }; - let mut array_address: UintItems = items; - array_address.array_items.append(uint_array_key_value); - return array_address; -} - -// in128 - -fn set_item_int_items(mut items: IntItems, index: u32, key: felt252, value: i128) -> IntItems { - let int_key_value: IntKeyValue = IntKeyValue { key, value }; - let mut address: IntItems = items; - address.items.append(int_key_value); - return address; -} - -fn set_item_array_int_items( - mut items: IntItems, index: u32, key: felt252, value: Array -) -> IntItems { - let int_array_key_value: IntArrayKeyValue = IntArrayKeyValue { key, value }; - let mut array_address: IntItems = items; - array_address.array_items.append(int_array_key_value); - return array_address; -} - -// bool - -fn set_item_bool_items(mut items: BoolItems, index: u32, key: felt252, value: bool) -> BoolItems { - let bool_key_value: BoolKeyValue = BoolKeyValue { key, value }; - let mut address: BoolItems = items; - address.items.append(bool_key_value); - return address; -} - -fn set_item_array_bool_items( - mut items: BoolItems, index: u32, key: felt252, value: Array -) -> BoolItems { - let bool_array_key_value: BoolArrayKeyValue = BoolArrayKeyValue { key, value }; - let mut array_address: BoolItems = items; - array_address.array_items.append(bool_array_key_value); - return array_address; -} - -// felt252 - -fn set_item_Felt252_items( - mut items: Felt252Items, index: u32, key: felt252, value: felt252 -) -> Felt252Items { - let felt252_key_value: Felt252KeyValue = Felt252KeyValue { key, value }; - let mut address: Felt252Items = items; - address.items.append(felt252_key_value); - return address; -} - -fn set_item_array_Felt252_items( - mut items: Felt252Items, index: u32, key: felt252, value: Array -) -> Felt252Items { - let felt252_array_key_value: Felt252ArrayKeyValue = Felt252ArrayKeyValue { key, value }; - let mut array_address: Felt252Items = items; - array_address.array_items.append(felt252_array_key_value); - return array_address; -} - -// array of felt - -fn set_item_array_of_felt_items_items( - mut items: ArrayOfFeltItems, index: u32, key: felt252, value: Array -) -> ArrayOfFeltItems { - let array_of_felt_items_key_value: ArrayOfFeltKeyValue = ArrayOfFeltKeyValue { key, value }; - let mut address: ArrayOfFeltItems = items; - address.items.append(array_of_felt_items_key_value); - return address; -} - -fn set_item_array_array_of_felt_items( - mut items: ArrayOfFeltItems, index: u32, key: felt252, value: Array> -) -> ArrayOfFeltItems { - let array_of_felt_array_key_value: ArrayOfFeltArrayKeyValue = ArrayOfFeltArrayKeyValue { - key, value - }; - let mut array_address: ArrayOfFeltItems = items; - array_address.array_items.append(array_of_felt_array_key_value); - return array_address; -} - -// string - -fn set_item_string_items( - mut items: StringItems, index: u32, key: felt252, value: felt252 -) -> StringItems { - let string_key_value: StringKeyValue = StringKeyValue { key, value }; - let mut address: StringItems = items; - address.items.append(string_key_value); - return address; +//TODO Switch the append with a set in the functions when its available +#[derive(Default, Serde, Destruct)] +struct EventLogData { + cant_be_empty: u128, // remove +// TODO } -fn set_item_array_string_items( - mut items: StringItems, index: u32, key: felt252, value: Array -) -> StringItems { - let string_array_key_value: StringArrayKeyValue = StringArrayKeyValue { key, value }; - let mut array_address: StringItems = items; - array_address.array_items.append(string_array_key_value); - return array_address; +#[derive(Default, Destruct)] +struct LogData { + address_dict: SerializableFelt252Dict, + uint_dict: SerializableFelt252Dict, + int_dict: SerializableFelt252Dict, + bool_dict: SerializableFelt252Dict, + felt252_dict: SerializableFelt252Dict, + // TODO? Possible? array_of_felt_dict: SerializableFelt252Dict>, + string_dict: SerializableFelt252Dict +} + +#[generate_trait] +impl LogDataImpl of LogDataTrait { + /// Serializes all the sub-dicts of LogData & append all the felt252 array together + fn custom_serialize(ref self: LogData, ref output: Array) { + let mut serialized_dicts: Array> = array![]; + + let mut address_dict_serialized: Array = array![]; + self.address_dict.custom_serialize(ref address_dict_serialized); + serialized_dicts.append(address_dict_serialized); + + let mut uint_dict_serialized: Array = array![]; + self.uint_dict.custom_serialize(ref uint_dict_serialized); + serialized_dicts.append(uint_dict_serialized); + + let mut int_dict_serialized: Array = array![]; + self.int_dict.custom_serialize(ref int_dict_serialized); + serialized_dicts.append(int_dict_serialized); + + let mut bool_dict_serialized: Array = array![]; + self.bool_dict.custom_serialize(ref bool_dict_serialized); + serialized_dicts.append(bool_dict_serialized); + + let mut felt252_dict_serialized: Array = array![]; + self.felt252_dict.custom_serialize(ref felt252_dict_serialized); + serialized_dicts.append(felt252_dict_serialized); + + let mut string_dict_serialized: Array = array![]; + self.string_dict.custom_serialize(ref string_dict_serialized); + serialized_dicts.append(string_dict_serialized); + + append_all_arrays_to_output(serialized_dicts, ref output); + } + /// Deserialize all the sub-dicts serialized into a LogData + fn custom_deserialize(ref serialized: Span) -> Option { + // TODO + needed? + Option::Some(Default::default()) + } +} + +// +// UTILITIES +// + +// When serializing dicts into a unique Array, this is the value that will +// be used to recognized a separation between two dicts. +const DICT_SEPARATION: felt252 = '______'; + +fn append_all_arrays_to_output(array_of_arrays: Array>, ref output: Array) { + let mut span_arrays = array_of_arrays.span(); + + loop { + match span_arrays.pop_front() { + Option::Some(arr) => { + let mut sub_array_span = arr.span(); + loop { + match sub_array_span.pop_front() { + Option::Some(v) => { + output.append(*v); + }, + Option::None => { + break; + } + }; + }; + output.append(DICT_SEPARATION); + }, + Option::None => { + break; + } + }; + } } diff --git a/src/order/decrease_order_utils.cairo b/src/order/decrease_order_utils.cairo index 22c2e777..ec734611 100644 --- a/src/order/decrease_order_utils.cairo +++ b/src/order/decrease_order_utils.cairo @@ -19,8 +19,11 @@ use satoru::position::position_utils; use satoru::position::position::Position; use satoru::swap::swap_utils::{SwapParams}; use satoru::position::position_utils::UpdatePositionParams; -use satoru::event::event_utils::LogData; -use satoru::event::event_utils; +use satoru::event::event_utils::{ + LogData, LogDataTrait, Felt252IntoU128, Felt252IntoContractAddress, ContractAddressDictValue, + I128252DictValue +}; +use satoru::utils::serializable_dict::{SerializableFelt252Dict, SerializableFelt252DictTrait}; use satoru::market::market_token::{IMarketTokenDispatcher, IMarketTokenDispatcherTrait}; use satoru::utils::span32::{Span32, Array32Trait}; use satoru::swap::swap_handler::{ISwapHandlerDispatcher, ISwapHandlerDispatcherTrait}; @@ -31,7 +34,7 @@ use satoru::swap::swap_handler::{ISwapHandlerDispatcher, ISwapHandlerDispatcherT #[inline(always)] fn process_order( params: ExecuteOrderParams -) -> event_utils::LogData { //TODO check with refactor with callback_utils +) -> LogData { //TODO check with refactor with callback_utils let order: Order = params.order; market_utils::validate_position_market_check(params.contracts.data_store, params.market); @@ -239,30 +242,14 @@ fn get_output_event_data( output_amount: u128, secondary_output_token: ContractAddress, secondary_output_amount: u128 -) -> event_utils::LogData { - let mut address_items: event_utils::AddressItems = Default::default(); - let mut uint_items: event_utils::UintItems = Default::default(); - - address_items = - event_utils::set_item_address_items(address_items, 0, 'output_token', output_token); - address_items = - event_utils::set_item_address_items( - address_items, 1, 'secondary_output_token', secondary_output_token - ); +) -> LogData { + let mut log_data: LogData = Default::default(); - uint_items = event_utils::set_item_uint_items(uint_items, 0, 'output_amount', output_amount); - uint_items = - event_utils::set_item_uint_items( - uint_items, 1, 'secondary_output_amount', secondary_output_amount - ); + log_data.address_dict.insert_single('output_token', output_token); + log_data.address_dict.insert_single('secondary_output_token', secondary_output_token); - event_utils::LogData { - address_items, - uint_items, - int_items: Default::default(), - bool_items: Default::default(), - felt252_items: Default::default(), - array_of_felt_items: Default::default(), - string_items: Default::default(), - } + log_data.uint_dict.insert_single('output_amount', output_amount); + log_data.uint_dict.insert_single('secondary_output_amount', secondary_output_amount); + + log_data } diff --git a/src/order/order_utils.cairo b/src/order/order_utils.cairo index 00c896a9..d3d0c4f5 100644 --- a/src/order/order_utils.cairo +++ b/src/order/order_utils.cairo @@ -21,7 +21,11 @@ use satoru::token::token_utils; use satoru::callback::callback_utils; use satoru::gas::gas_utils; use satoru::order::order::{Order, OrderType, OrderTrait}; -use satoru::event::event_utils::LogData; +use satoru::event::event_utils::{ + LogData, LogDataTrait, Felt252IntoU128, Felt252IntoContractAddress, ContractAddressDictValue, + I128252DictValue +}; +use satoru::utils::serializable_dict::{SerializableFelt252Dict, SerializableFelt252DictTrait}; use satoru::order::error::OrderError; use satoru::order::{increase_order_utils, decrease_order_utils, swap_order_utils}; @@ -171,7 +175,7 @@ fn execute_order(params: ExecuteOrderParams) { secondary_order_type: params.secondary_order_type }; - let event_data: LogData = process_order(params_process); + let mut event_data: LogData = process_order(params_process); // validate that internal state changes are correct before calling // external callbacks @@ -189,7 +193,9 @@ fn execute_order(params: ExecuteOrderParams) { params.contracts.event_emitter.emit_order_executed(params.key, params.secondary_order_type); - callback_utils::after_order_execution(params.key, params.order, event_data); + let mut serialized_event_data: Array = array![]; + event_data.custom_serialize(ref serialized_event_data); + callback_utils::after_order_execution(params.key, params.order, serialized_event_data); // the order.executionFee for liquidation / adl orders is zero // gas costs for liquidations / adl is subsidised by the treasury diff --git a/src/order/swap_order_utils.cairo b/src/order/swap_order_utils.cairo index d9741cb5..b79e146c 100644 --- a/src/order/swap_order_utils.cairo +++ b/src/order/swap_order_utils.cairo @@ -7,14 +7,18 @@ use satoru::order::order::OrderType; use satoru::oracle::oracle_utils; use satoru::utils::arrays::u64_are_gte; use satoru::swap::swap_utils; -use satoru::event::event_utils; +use satoru::event::event_utils::{ + LogData, LogDataTrait, Felt252IntoU128, Felt252IntoContractAddress, ContractAddressDictValue, + I128252DictValue +}; +use satoru::utils::serializable_dict::{SerializableFelt252Dict, SerializableFelt252DictTrait}; use satoru::order::error::OrderError; use satoru::bank::bank::{IBankDispatcher, IBankDispatcherTrait}; use satoru::utils::span32::{Span32, DefaultSpan32}; use satoru::oracle::error::OracleError; #[inline(always)] -fn process_order(params: ExecuteOrderParams) -> event_utils::LogData { +fn process_order(params: ExecuteOrderParams) -> LogData { if (params.order.market.is_non_zero()) { panic(array![OrderError::UNEXPECTED_MARKET]); } @@ -44,23 +48,12 @@ fn process_order(params: ExecuteOrderParams) -> event_utils::LogData { } ); - let mut address_items: event_utils::AddressItems = Default::default(); - let mut uint_items: event_utils::UintItems = Default::default(); + let mut log_data: LogData = Default::default(); - address_items = - event_utils::set_item_address_items(address_items, 0, 'output_token', output_token); + log_data.address_dict.insert_single('output_token', output_token); + log_data.uint_dict.insert_single('output_amount', output_amount); - uint_items = event_utils::set_item_uint_items(uint_items, 0, 'output_amount', output_amount); - - event_utils::LogData { - address_items, - uint_items, - int_items: Default::default(), - bool_items: Default::default(), - felt252_items: Default::default(), - array_of_felt_items: Default::default(), - string_items: Default::default(), - } + log_data } diff --git a/tests/callback/test_callback_utils.cairo b/tests/callback/test_callback_utils.cairo index 5eeff2fa..e40d3670 100644 --- a/tests/callback/test_callback_utils.cairo +++ b/tests/callback/test_callback_utils.cairo @@ -64,6 +64,6 @@ fn given_normal_conditions_when_callback_contract_functions_then_works() { deposit.callback_contract = callback_mock.contract_address; assert(callback_mock.get_counter() == 1, 'should be 1'); - after_deposit_execution(42, deposit, log_data); + after_deposit_execution(42, deposit, array![]); assert(callback_mock.get_counter() == 2, 'should be 2'); } From bd9aa004a85c5fc91b88ac488992bb1f5abfbb2e Mon Sep 17 00:00:00 2001 From: akhercha Date: Mon, 30 Oct 2023 17:32:23 +0100 Subject: [PATCH 31/40] feat(log_data_indexes): Removed sandbox file --- src/event/event_utils_sandbox.cairo | 152 ----------------------- src/lib.cairo | 1 - tests/event/test_event_utils.cairo | 2 +- tests/utils/test_serializable_dict.cairo | 2 +- 4 files changed, 2 insertions(+), 155 deletions(-) delete mode 100644 src/event/event_utils_sandbox.cairo diff --git a/src/event/event_utils_sandbox.cairo b/src/event/event_utils_sandbox.cairo deleted file mode 100644 index 7ecec78f..00000000 --- a/src/event/event_utils_sandbox.cairo +++ /dev/null @@ -1,152 +0,0 @@ -use starknet::{ - get_caller_address, ContractAddress, Felt252TryIntoContractAddress, ContractAddressIntoFelt252, - contract_address_const -}; -use array::ArrayTrait; -use satoru::utils::i128::i128; -use traits::Default; -use satoru::utils::traits::ContractAddressDefault; - -use satoru::utils::serializable_dict::{SerializableFelt252Dict, SerializableFelt252DictTrait}; - -// -// NEEDED IMPLEMENTATIONS FOR LOGDATA TYPES -// - -impl Felt252IntoBool of Into { - #[inline(always)] - fn into(self: felt252) -> bool { - let as_u128: u128 = self.try_into().expect('u128 Overflow'); - as_u128 > 0 - } -} - -impl Felt252IntoU128 of Into { - #[inline(always)] - fn into(self: felt252) -> u128 { - self.try_into().expect('u128 Overflow') - } -} - -impl Felt252IntoI128 of Into { - #[inline(always)] - fn into(self: felt252) -> i128 { - self.try_into().expect('i128 Overflow') - } -} - -impl Felt252IntoContractAddress of Into { - #[inline(always)] - fn into(self: felt252) -> ContractAddress { - Felt252TryIntoContractAddress::try_into(self).expect('contractaddress overflow') - } -} - -impl I128252DictValue of Felt252DictValue { - #[inline(always)] - fn zero_default() -> i128 nopanic { - i128 { mag: 0, sign: false } - } -} - -impl ContractAddressDictValue of Felt252DictValue { - #[inline(always)] - fn zero_default() -> ContractAddress nopanic { - contract_address_const::<0>() - } -} - -// -// LOG DATA -// - -//TODO Switch the append with a set in the functions when its available -#[derive(Default, Serde, Destruct)] -struct EventLogData { - cant_be_empty: u128, // remove -// TODO -} - -#[derive(Default, Destruct)] -struct LogData { - address_dict: SerializableFelt252Dict, - uint_dict: SerializableFelt252Dict, - int_dict: SerializableFelt252Dict, - bool_dict: SerializableFelt252Dict, - felt252_dict: SerializableFelt252Dict, - // TODO? Possible? array_of_felt_dict: SerializableFelt252Dict>, - string_dict: SerializableFelt252Dict -} - -#[generate_trait] -impl LogDataImpl of LogDataTrait { - /// Serializes all the sub-dicts of LogData & append all the felt252 array together - fn custom_serialize(ref self: LogData, ref output: Array) { - let mut serialized_dicts: Array> = array![]; - - let mut address_dict_serialized: Array = array![]; - self.address_dict.custom_serialize(ref address_dict_serialized); - serialized_dicts.append(address_dict_serialized); - - let mut uint_dict_serialized: Array = array![]; - self.uint_dict.custom_serialize(ref uint_dict_serialized); - serialized_dicts.append(uint_dict_serialized); - - let mut int_dict_serialized: Array = array![]; - self.int_dict.custom_serialize(ref int_dict_serialized); - serialized_dicts.append(int_dict_serialized); - - let mut bool_dict_serialized: Array = array![]; - self.bool_dict.custom_serialize(ref bool_dict_serialized); - serialized_dicts.append(bool_dict_serialized); - - let mut felt252_dict_serialized: Array = array![]; - self.felt252_dict.custom_serialize(ref felt252_dict_serialized); - serialized_dicts.append(felt252_dict_serialized); - - let mut string_dict_serialized: Array = array![]; - self.string_dict.custom_serialize(ref string_dict_serialized); - serialized_dicts.append(string_dict_serialized); - - append_all_arrays_to_output(serialized_dicts, ref output); - } - /// Deserialize all the sub-dicts serialized into a LogData - fn custom_deserialize(ref serialized: Span) -> Option { - // TODO + needed? - Option::Some(Default::default()) - } -} - -// -// UTILITIES -// - -// When serializing dicts into a unique Array, this is the value that will -// be used to recognized a separation between two dicts. -const DICT_SEPARATION: felt252 = '______'; - -fn append_all_arrays_to_output(array_of_arrays: Array>, ref output: Array) { - let mut span_arrays = array_of_arrays.span(); - - loop { - match span_arrays.pop_front() { - Option::Some(arr) => { - let mut sub_array_span = arr.span(); - loop { - match sub_array_span.pop_front() { - Option::Some(v) => { - output.append(*v); - }, - Option::None => { - break; - } - }; - }; - output.append(DICT_SEPARATION); - }, - Option::None => { - break; - } - }; - } -} diff --git a/src/lib.cairo b/src/lib.cairo index 8d29acc0..1252bed5 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -44,7 +44,6 @@ mod config { // `event` is a module event management functions. mod event { mod event_utils; - mod event_utils_sandbox; mod event_emitter; } diff --git a/tests/event/test_event_utils.cairo b/tests/event/test_event_utils.cairo index c1d72617..2265b59c 100644 --- a/tests/event/test_event_utils.cairo +++ b/tests/event/test_event_utils.cairo @@ -2,7 +2,7 @@ use starknet::{ get_caller_address, ContractAddress, Felt252TryIntoContractAddress, ContractAddressIntoFelt252, contract_address_const }; -use satoru::event::event_utils_sandbox::{ +use satoru::event::event_utils::{ Felt252IntoBool, Felt252IntoU128, Felt252IntoI128, Felt252IntoContractAddress, I128252DictValue, ContractAddressDictValue, LogData }; diff --git a/tests/utils/test_serializable_dict.cairo b/tests/utils/test_serializable_dict.cairo index 66e4b6b3..e12ca4f4 100644 --- a/tests/utils/test_serializable_dict.cairo +++ b/tests/utils/test_serializable_dict.cairo @@ -16,7 +16,7 @@ use alexandria_data_structures::array_ext::ArrayTraitExt; // Local imports. use satoru::utils::traits::ContractAddressDefault; -use satoru::event::event_utils_sandbox::{ +use satoru::event::event_utils::{ Felt252IntoBool, Felt252IntoU128, Felt252IntoI128, Felt252IntoContractAddress, I128252DictValue, ContractAddressDictValue }; From bf951d552ec1b63b3897fee664c4b1cac621c715 Mon Sep 17 00:00:00 2001 From: akhercha Date: Mon, 30 Oct 2023 19:56:09 +0100 Subject: [PATCH 32/40] feat(log_data_indexes): TODO: deserialize + tests --- src/deposit/execute_deposit_utils.cairo | 4 +-- src/event/event_utils.cairo | 42 +++++++++--------------- src/order/order_utils.cairo | 12 +++---- src/utils/serializable_dict.cairo | 15 ++++++--- tests/callback/test_callback_utils.cairo | 6 ++-- tests/utils/test_serializable_dict.cairo | 5 ++- 6 files changed, 37 insertions(+), 47 deletions(-) diff --git a/src/deposit/execute_deposit_utils.cairo b/src/deposit/execute_deposit_utils.cairo index 6311ace2..e436f378 100644 --- a/src/deposit/execute_deposit_utils.cairo +++ b/src/deposit/execute_deposit_utils.cairo @@ -242,9 +242,7 @@ fn execute_deposit(params: ExecuteDepositParams) { let mut event_data: LogData = Default::default(); event_data.uint_dict.insert_single('received_market_tokens', cache.received_market_tokens); - let mut serialized_event_data: Array = array![]; - event_data.custom_serialize(ref serialized_event_data); - after_deposit_execution(params.key, deposit, serialized_event_data); + after_deposit_execution(params.key, deposit, event_data.serialize_into()); pay_execution_fee_deposit( params.data_store, diff --git a/src/event/event_utils.cairo b/src/event/event_utils.cairo index f4188f09..10552796 100644 --- a/src/event/event_utils.cairo +++ b/src/event/event_utils.cairo @@ -81,37 +81,25 @@ struct LogData { #[generate_trait] impl LogDataImpl of LogDataTrait { /// Serializes all the sub-dicts of LogData & append all the felt252 array together - fn custom_serialize(ref self: LogData, ref output: Array) { + fn serialize(ref self: LogData, ref output: Array) { let mut serialized_dicts: Array> = array![]; - - let mut address_dict_serialized: Array = array![]; - self.address_dict.custom_serialize(ref address_dict_serialized); - serialized_dicts.append(address_dict_serialized); - - let mut uint_dict_serialized: Array = array![]; - self.uint_dict.custom_serialize(ref uint_dict_serialized); - serialized_dicts.append(uint_dict_serialized); - - let mut int_dict_serialized: Array = array![]; - self.int_dict.custom_serialize(ref int_dict_serialized); - serialized_dicts.append(int_dict_serialized); - - let mut bool_dict_serialized: Array = array![]; - self.bool_dict.custom_serialize(ref bool_dict_serialized); - serialized_dicts.append(bool_dict_serialized); - - let mut felt252_dict_serialized: Array = array![]; - self.felt252_dict.custom_serialize(ref felt252_dict_serialized); - serialized_dicts.append(felt252_dict_serialized); - - let mut string_dict_serialized: Array = array![]; - self.string_dict.custom_serialize(ref string_dict_serialized); - serialized_dicts.append(string_dict_serialized); - + serialized_dicts.append(self.address_dict.serialize_into()); + serialized_dicts.append(self.uint_dict.serialize_into()); + serialized_dicts.append(self.int_dict.serialize_into()); + serialized_dicts.append(self.bool_dict.serialize_into()); + serialized_dicts.append(self.felt252_dict.serialize_into()); + serialized_dicts.append(self.string_dict.serialize_into()); append_all_arrays_to_output(serialized_dicts, ref output); } + + fn serialize_into(ref self: LogData) -> Array { + let mut serialized_data: Array = array![]; + self.serialize(ref serialized_data); + serialized_data + } + /// Deserialize all the sub-dicts serialized into a LogData - fn custom_deserialize(ref serialized: Span) -> Option { + fn deserialize(ref serialized: Span) -> Option { // TODO + needed? Option::Some(Default::default()) } diff --git a/src/order/order_utils.cairo b/src/order/order_utils.cairo index d3d0c4f5..faeba770 100644 --- a/src/order/order_utils.cairo +++ b/src/order/order_utils.cairo @@ -193,9 +193,7 @@ fn execute_order(params: ExecuteOrderParams) { params.contracts.event_emitter.emit_order_executed(params.key, params.secondary_order_type); - let mut serialized_event_data: Array = array![]; - event_data.custom_serialize(ref serialized_event_data); - callback_utils::after_order_execution(params.key, params.order, serialized_event_data); + callback_utils::after_order_execution(params.key, params.order, event_data.serialize_into()); // the order.executionFee for liquidation / adl orders is zero // gas costs for liquidations / adl is subsidised by the treasury @@ -272,8 +270,8 @@ fn cancel_order( event_emitter.emit_order_cancelled(key, reason, reason_bytes.span()); - let event_data = Default::default(); - callback_utils::after_order_cancellation(key, order, event_data); + let mut event_data: LogData = Default::default(); + callback_utils::after_order_cancellation(key, order, event_data.serialize_into()); gas_utils::pay_execution_fee_order( data_store, @@ -325,8 +323,8 @@ fn freeze_order( event_emitter.emit_order_frozen(key, reason, reason_bytes.span()); - let event_data = Default::default(); - callback_utils::after_order_frozen(key, order, event_data); + let mut event_data: LogData = Default::default(); + callback_utils::after_order_frozen(key, order, event_data.serialize_into()); gas_utils::pay_execution_fee_order( data_store, event_emitter, order_vault, execution_fee, starting_gas, keeper, order.account diff --git a/src/utils/serializable_dict.cairo b/src/utils/serializable_dict.cairo index f2fd7f63..6af5a449 100644 --- a/src/utils/serializable_dict.cairo +++ b/src/utils/serializable_dict.cairo @@ -83,8 +83,9 @@ trait SerializableFelt252DictTrait { fn len(self: @SerializableFelt252Dict) -> usize; /// Checks if a dictionnary is empty. fn is_empty(self: @SerializableFelt252Dict) -> bool; - fn custom_serialize(ref self: SerializableFelt252Dict, ref output: Array); - fn custom_deserialize(ref serialized: Span) -> Option>; + fn serialize_into(ref self: SerializableFelt252Dict) -> Array; + fn serialize(ref self: SerializableFelt252Dict, ref output: Array); + fn deserialize(ref serialized: Span) -> Option>; } impl SerializableFelt252DictTraitImpl< @@ -149,7 +150,13 @@ impl SerializableFelt252DictTraitImpl< self.len() == 0 } - fn custom_serialize(ref self: SerializableFelt252Dict, ref output: Array) { + fn serialize_into(ref self: SerializableFelt252Dict) -> Array { + let mut serialized_data: Array = array![]; + self.serialize(ref serialized_data); + serialized_data + } + + fn serialize(ref self: SerializableFelt252Dict, ref output: Array) { let mut keys: Span = self.keys.span(); loop { match keys.pop_front() { @@ -184,7 +191,7 @@ impl SerializableFelt252DictTraitImpl< }; } - fn custom_deserialize(ref serialized: Span) -> Option> { + fn deserialize(ref serialized: Span) -> Option> { let mut d: SerializableFelt252Dict = SerializableFelt252Dict { keys: array![], values: Default::default() }; diff --git a/tests/callback/test_callback_utils.cairo b/tests/callback/test_callback_utils.cairo index e40d3670..d0bb4592 100644 --- a/tests/callback/test_callback_utils.cairo +++ b/tests/callback/test_callback_utils.cairo @@ -5,7 +5,7 @@ use snforge_std::{declare, start_prank, stop_prank, ContractClassTrait}; use satoru::data::data_store::IDataStoreDispatcherTrait; use satoru::data::keys; use satoru::deposit::deposit::Deposit; -use satoru::event::event_utils::LogData; +use satoru::event::event_utils::{LogData, LogDataTrait}; use satoru::callback::callback_utils::{ validate_callback_gas_limit, set_saved_callback_contract, get_saved_callback_contract, after_deposit_execution @@ -57,13 +57,13 @@ fn given_normal_conditions_when_callback_contract_functions_then_works() { let (_, _, data_store) = setup(); let mut deposit: Deposit = Default::default(); - let log_data: LogData = Default::default(); + let mut log_data: LogData = Default::default(); let (_, event_emitter) = setup_event_emitter(); let callback_mock = deploy_callback_mock(); deposit.callback_contract = callback_mock.contract_address; assert(callback_mock.get_counter() == 1, 'should be 1'); - after_deposit_execution(42, deposit, array![]); + after_deposit_execution(42, deposit, log_data.serialize_into()); assert(callback_mock.get_counter() == 2, 'should be 2'); } diff --git a/tests/utils/test_serializable_dict.cairo b/tests/utils/test_serializable_dict.cairo index e12ca4f4..1938aaed 100644 --- a/tests/utils/test_serializable_dict.cairo +++ b/tests/utils/test_serializable_dict.cairo @@ -97,12 +97,11 @@ fn test_serializable_dict_serialize() { dict.insert_single('test', expected_value); dict.insert_span('test_span', expected_array.span()); - let mut serialized: Array = array![]; - dict.custom_serialize(ref serialized); + let serialized: Array = dict.serialize_into(); let mut span_serialized: Span = serialized.span(); let mut deserialized_dict: SerializableFelt252Dict = - match SerializableFelt252DictTrait::::custom_deserialize(ref span_serialized) { + match SerializableFelt252DictTrait::::deserialize(ref span_serialized) { Option::Some(d) => d, Option::None => panic_with_felt252('err while recreating d') }; From 365cf9c30f03800d98f04a691fd42e975f6ac108 Mon Sep 17 00:00:00 2001 From: akhercha Date: Mon, 30 Oct 2023 20:27:29 +0100 Subject: [PATCH 33/40] feat(log_data_indexes): Implement deserialize; need tests --- src/event/event_utils.cairo | 118 +++++++++++++++++++++++------- src/utils/serializable_dict.cairo | 3 + 2 files changed, 93 insertions(+), 28 deletions(-) diff --git a/src/event/event_utils.cairo b/src/event/event_utils.cairo index 10552796..6a90d2cf 100644 --- a/src/event/event_utils.cairo +++ b/src/event/event_utils.cairo @@ -9,6 +9,9 @@ use satoru::utils::traits::ContractAddressDefault; use satoru::utils::serializable_dict::{SerializableFelt252Dict, SerializableFelt252DictTrait}; +use alexandria_data_structures::array_ext::SpanTraitExt; + + // // NEEDED IMPLEMENTATIONS FOR LOGDATA TYPES // @@ -57,7 +60,7 @@ impl ContractAddressDictValue of Felt252DictValue { } // -// LOG DATA +// LOG DATA IMPLEMENTATION // //TODO Switch the append with a set in the functions when its available @@ -78,9 +81,16 @@ struct LogData { string_dict: SerializableFelt252Dict } +/// Number of dicts presents in LogData +const NUMBER_OF_DICTS: usize = 6; + +/// When serializing dicts into a unique Array, this is the value that will +/// be used to recognized a separation between two dicts. +const END_OF_DICT: felt252 = '______'; + #[generate_trait] impl LogDataImpl of LogDataTrait { - /// Serializes all the sub-dicts of LogData & append all the felt252 array together + /// Serializes all the sub-dicts of LogData & append all of them into a new felt252 array fn serialize(ref self: LogData, ref output: Array) { let mut serialized_dicts: Array> = array![]; serialized_dicts.append(self.address_dict.serialize_into()); @@ -89,9 +99,31 @@ impl LogDataImpl of LogDataTrait { serialized_dicts.append(self.bool_dict.serialize_into()); serialized_dicts.append(self.felt252_dict.serialize_into()); serialized_dicts.append(self.string_dict.serialize_into()); - append_all_arrays_to_output(serialized_dicts, ref output); + let mut span_arrays = serialized_dicts.span(); + loop { + match span_arrays.pop_front() { + Option::Some(arr) => { + let mut sub_array_span = arr.span(); + loop { + match sub_array_span.pop_front() { + Option::Some(v) => { + output.append(*v); + }, + Option::None => { + break; + } + }; + }; + output.append(END_OF_DICT); + }, + Option::None => { + break; + } + }; + }; } + /// Serializes all the sub-dicts of LogData & return the serialized data fn serialize_into(ref self: LogData) -> Array { let mut serialized_data: Array = array![]; self.serialize(ref serialized_data); @@ -100,41 +132,71 @@ impl LogDataImpl of LogDataTrait { /// Deserialize all the sub-dicts serialized into a LogData fn deserialize(ref serialized: Span) -> Option { - // TODO + needed? - Option::Some(Default::default()) + let mut log_data: LogData = Default::default(); + + // There should be the right amount of dictionnaries serializeds + if serialized.occurrences_of(END_OF_DICT) != NUMBER_OF_DICTS { + return Option::None(()); + } + + let mut serialized_dict = retrieve_dict_serialized(ref serialized); + log_data + .address_dict = + SerializableFelt252DictTrait::::deserialize(ref serialized_dict) + .expect('deserialize err address'); + + let mut serialized_dict = retrieve_dict_serialized(ref serialized); + log_data + .uint_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) + .expect('deserialize err uint'); + + let mut serialized_dict = retrieve_dict_serialized(ref serialized); + log_data + .int_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) + .expect('deserialize err int'); + + let mut serialized_dict = retrieve_dict_serialized(ref serialized); + log_data + .bool_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) + .expect('deserialize err bool'); + + let mut serialized_dict = retrieve_dict_serialized(ref serialized); + log_data + .felt252_dict = + SerializableFelt252DictTrait::::deserialize(ref serialized_dict) + .expect('deserialize err felt252'); + + let mut serialized_dict = retrieve_dict_serialized(ref serialized); + log_data + .string_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) + .expect('deserialize err string'); + + Option::Some(log_data) } } + // -// UTILITIES +// UTILITY FUNCTION // -// When serializing dicts into a unique Array, this is the value that will -// be used to recognized a separation between two dicts. -const DICT_SEPARATION: felt252 = '______'; - -fn append_all_arrays_to_output(array_of_arrays: Array>, ref output: Array) { - let mut span_arrays = array_of_arrays.span(); - +/// Pop every elements from the span until the next occurences of END_OF_DICT or +/// the end of the Span and return those values in a Span. +fn retrieve_dict_serialized(ref serialized: Span) -> Span { + let mut dict_data: Array = array![]; loop { - match span_arrays.pop_front() { - Option::Some(arr) => { - let mut sub_array_span = arr.span(); - loop { - match sub_array_span.pop_front() { - Option::Some(v) => { - output.append(*v); - }, - Option::None => { - break; - } - }; - }; - output.append(DICT_SEPARATION); + match serialized.pop_front() { + Option::Some(v) => { + if *v == END_OF_DICT { + break; + } else { + dict_data.append(*v); + } }, Option::None => { break; } }; - } + }; + dict_data.span() } diff --git a/src/utils/serializable_dict.cairo b/src/utils/serializable_dict.cairo index 6af5a449..67596293 100644 --- a/src/utils/serializable_dict.cairo +++ b/src/utils/serializable_dict.cairo @@ -83,8 +83,11 @@ trait SerializableFelt252DictTrait { fn len(self: @SerializableFelt252Dict) -> usize; /// Checks if a dictionnary is empty. fn is_empty(self: @SerializableFelt252Dict) -> bool; + /// Serializes the dictionnary & return the result fn serialize_into(ref self: SerializableFelt252Dict) -> Array; + /// Serializes the dictionnary into the provided output array fn serialize(ref self: SerializableFelt252Dict, ref output: Array); + /// Deserializes the serialized array & return the dictionnary fn deserialize(ref serialized: Span) -> Option>; } From 1601e2c2b7f3633d789cae8962bcfffb8a1935b7 Mon Sep 17 00:00:00 2001 From: akhercha Date: Mon, 30 Oct 2023 21:58:18 +0100 Subject: [PATCH 34/40] feat(log_data_indexes): Added tests for log_data serialization --- src/utils/serializable_dict.cairo | 23 +++++++ tests/event/test_event_utils.cairo | 87 +++++++++++++++++++++++- tests/utils/test_serializable_dict.cairo | 6 +- 3 files changed, 111 insertions(+), 5 deletions(-) diff --git a/src/utils/serializable_dict.cairo b/src/utils/serializable_dict.cairo index 67596293..104a2984 100644 --- a/src/utils/serializable_dict.cairo +++ b/src/utils/serializable_dict.cairo @@ -50,6 +50,27 @@ impl ItemImpl of ItemTrait { } } +impl ItemPartialEq< + T, impl TCopy: Copy, impl TPartialEq: PartialEq, impl TDrop: Drop +> of PartialEq> { + fn eq(lhs: @Item, rhs: @Item) -> bool { + if lhs.is_single() && rhs.is_single() { + return lhs.unwrap_single() == rhs.unwrap_single(); + } else if lhs.is_span() && rhs.is_span() { + return lhs.unwrap_span() == rhs.unwrap_span(); + } + return false; + } + fn ne(lhs: @Item, rhs: @Item) -> bool { + if lhs.is_single() && rhs.is_single() { + return !(lhs.unwrap_single() == rhs.unwrap_single()); + } else if lhs.is_span() && rhs.is_span() { + return !(lhs.unwrap_span() == rhs.unwrap_span()); + } + return true; + } +} + #[derive(Default, Copy)] struct SerializableFelt252Dict { keys: Array, @@ -212,6 +233,7 @@ impl SerializableFelt252DictTraitImpl< Option::None => panic_with_felt252('err getting value') }; let value: Item = Item::Single(value); + d.keys.append(*key); d.values.insert(*key, nullable_from_box(BoxTrait::new(value))); continue; }; @@ -231,6 +253,7 @@ impl SerializableFelt252DictTraitImpl< }; // ... & insert it let values: Item = Item::Span(arr_values.span()); + d.keys.append(*key); d.values.insert(*key, nullable_from_box(BoxTrait::new(values))); }, Option::None => panic_with_felt252('err getting size') diff --git a/tests/event/test_event_utils.cairo b/tests/event/test_event_utils.cairo index 2265b59c..6fa74377 100644 --- a/tests/event/test_event_utils.cairo +++ b/tests/event/test_event_utils.cairo @@ -1,18 +1,26 @@ +//! Test file for `src/event/event_utils.cairo`. + +// ************************************************************************* +// IMPORTS +// ************************************************************************* use starknet::{ get_caller_address, ContractAddress, Felt252TryIntoContractAddress, ContractAddressIntoFelt252, contract_address_const }; use satoru::event::event_utils::{ Felt252IntoBool, Felt252IntoU128, Felt252IntoI128, Felt252IntoContractAddress, I128252DictValue, - ContractAddressDictValue, LogData + ContractAddressDictValue, LogData, LogDataTrait }; use satoru::utils::traits::{ContractAddressDefault}; use traits::Default; use satoru::utils::serializable_dict::{ Item, ItemTrait, SerializableFelt252Dict, SerializableFelt252DictTrait, - SerializableFelt252DictTraitImpl }; +// ********************************************************************************************* +// * TEST LOGIC * +// ********************************************************************************************* + #[test] fn test_log_data_default() { let mut log_data: LogData = Default::default(); @@ -84,3 +92,78 @@ fn test_log_data_multiple_types() { assert(out_span.at(1) == arr_to_add.at(1), 'wrong at idx 1'); assert(out_span.at(2) == arr_to_add.at(2), 'wrong at idx 2'); } + +#[test] +fn test_log_data_serialization() { + let mut log_data: LogData = Default::default(); + + log_data.address_dict.insert_single('addr_test', contract_address_const::<42>()); + log_data.bool_dict.insert_single('bool_test', false); + log_data.felt252_dict.insert_single('felt_test', 1); + log_data.felt252_dict.insert_single('felt_test_two', 2); + log_data.string_dict.insert_single('string_test', 'hello world'); + log_data + .string_dict + .insert_span('string_arr_test', array!['hello', 'world', 'from', 'starknet'].span()); + + // serialize the data + let mut serialized_data = log_data.serialize_into().span(); + + // deserialize + let mut d_log_data: LogData = LogDataTrait::deserialize(ref serialized_data) + .expect('err while deserializing'); + + // Check the values inserted before + // addr dict + let mut expected_dict = log_data.address_dict; + let mut out_dict = d_log_data.address_dict; + assert_same_single_value_for_dicts(ref expected_dict, ref out_dict, 'addr_test'); + + // bool dict + let mut expected_dict = log_data.bool_dict; + let mut out_dict = d_log_data.bool_dict; + assert_same_single_value_for_dicts(ref expected_dict, ref out_dict, 'bool_test'); + + // felt252 dict + let mut expected_dict = log_data.felt252_dict; + let mut out_dict = d_log_data.felt252_dict; + assert_same_single_value_for_dicts(ref expected_dict, ref out_dict, 'felt_test'); + assert_same_single_value_for_dicts(ref expected_dict, ref out_dict, 'felt_test_two'); + + // string dict + assert(d_log_data.string_dict.contains('string_arr_test'), 'key not found'); + let v: Item = d_log_data.string_dict.get('string_arr_test').unwrap(); + let span_strings: Span = v.unwrap_span(); + assert(span_strings.len() == 4, 'err span len'); + assert(span_strings.at(0) == @'hello', 'err idx 0'); + assert(span_strings.at(1) == @'world', 'err idx 1'); + assert(span_strings.at(2) == @'from', 'err idx 2'); + assert(span_strings.at(3) == @'starknet', 'err idx 3'); +} + + +// ********************************************************************************************* +// * UTILITIES * +// ********************************************************************************************* + +use debug::PrintTrait; + +fn assert_same_single_value_for_dicts< + T, + impl TDefault: Felt252DictValue, + impl TDrop: Drop, + impl TCopy: Copy, + impl FeltIntoT: Into, + impl TIntoFelt: Into, + impl TPartialEq: PartialEq, +>( + ref lhs: SerializableFelt252Dict, ref rhs: SerializableFelt252Dict, key: felt252 +) { + assert(lhs.contains(key), 'key not found: lhs'); + assert(rhs.contains(key), 'key not found: rhs'); + + let lhs_value: Item = lhs.get(key).unwrap(); + let rhs_value: Item = rhs.get(key).unwrap(); + + assert(lhs_value == rhs_value, 'err value'); +} diff --git a/tests/utils/test_serializable_dict.cairo b/tests/utils/test_serializable_dict.cairo index 1938aaed..64288d43 100644 --- a/tests/utils/test_serializable_dict.cairo +++ b/tests/utils/test_serializable_dict.cairo @@ -81,7 +81,7 @@ fn test_serializable_dict_insert_span() { let retrieved_item: Item = dict.get(key).expect('key should be in dict'); let out_span: Span = retrieved_item.unwrap_span(); - assert(dict.keys.contains(key), 'key should be in dict'); + assert(dict.contains(key), 'key should be in dict'); assert(out_span.at(0) == expected_array.at(0), 'wrong at idx 0'); assert(out_span.at(1) == expected_array.at(1), 'wrong at idx 1'); assert(out_span.at(2) == expected_array.at(2), 'wrong at idx 2'); @@ -106,11 +106,11 @@ fn test_serializable_dict_serialize() { Option::None => panic_with_felt252('err while recreating d') }; - assert(dict.keys.contains('test'), 'key should be in dict'); + assert(dict.contains('test'), 'key should be in dict'); let retrieved_item: Item = dict.get('test').expect('key should be in dict'); let out_value: u128 = retrieved_item.unwrap_single(); - assert(dict.keys.contains('test_span'), 'key should be in dict'); + assert(dict.contains('test_span'), 'key should be in dict'); let retrieved_item: Item = deserialized_dict .get('test_span') .expect('key should be in dict'); From a9bb259720c5f863ca4103a516b4c4022124d4fc Mon Sep 17 00:00:00 2001 From: akhercha Date: Tue, 31 Oct 2023 06:21:14 +0100 Subject: [PATCH 35/40] feat(log_data_indexes): Typo + Don't serialize too early --- src/callback/callback_utils.cairo | 48 +++++++++++------------- src/deposit/deposit_utils.cairo | 3 +- src/deposit/execute_deposit_utils.cairo | 2 +- src/event/event_utils.cairo | 15 ++++---- src/order/order_utils.cairo | 6 +-- tests/callback/test_callback_utils.cairo | 2 +- 6 files changed, 37 insertions(+), 39 deletions(-) diff --git a/src/callback/callback_utils.cairo b/src/callback/callback_utils.cairo index 61500413..7af56689 100644 --- a/src/callback/callback_utils.cairo +++ b/src/callback/callback_utils.cairo @@ -23,7 +23,7 @@ use starknet::ContractAddress; // Local imports. use satoru::data::data_store::{IDataStoreDispatcher, IDataStoreDispatcherTrait}; use satoru::data::keys; -use satoru::event::event_utils::LogData; +use satoru::event::event_utils::{LogData, LogDataTrait}; use satoru::order::order::Order; use satoru::deposit::deposit::Deposit; use satoru::withdrawal::withdrawal::Withdrawal; @@ -91,103 +91,99 @@ fn get_saved_callback_contract( /// # Arguments /// * `key` - They key of the deposit. /// * `deposit` - The deposit that was executed. -/// * `serialized_log_data` - The log data. -fn after_deposit_execution(key: felt252, deposit: Deposit, serialized_log_data: Array) { +/// * `log_data.serialize_into()` - The log data. +fn after_deposit_execution(key: felt252, deposit: Deposit, mut log_data: LogData) { if !is_valid_callback_contract(deposit.callback_contract) { return; } let dispatcher = IDepositCallbackReceiverDispatcher { contract_address: deposit.callback_contract }; - dispatcher.after_deposit_execution(key, deposit, serialized_log_data) + dispatcher.after_deposit_execution(key, deposit, log_data.serialize_into()) } /// Called after a deposit cancellation. /// # Arguments /// * `key` - They key of the deposit. /// * `deposit` - The deposit that was cancelled. -/// * `serialized_log_data` - The log data. -fn after_deposit_cancellation(key: felt252, deposit: Deposit, serialized_log_data: Array) { +/// * `log_data.serialize_into()` - The log data. +fn after_deposit_cancellation(key: felt252, deposit: Deposit, mut log_data: LogData) { if !is_valid_callback_contract(deposit.callback_contract) { return; } let dispatcher = IDepositCallbackReceiverDispatcher { contract_address: deposit.callback_contract }; - dispatcher.after_deposit_cancellation(key, deposit, serialized_log_data) + dispatcher.after_deposit_cancellation(key, deposit, log_data.serialize_into()) } /// Called after a withdrawal execution. /// # Arguments /// * `key` - They key of the withdrawal. /// * `withdrawal` - The withdrawal that was executed. -/// * `serialized_log_data` - The log data. -fn after_withdrawal_execution( - key: felt252, withdrawal: Withdrawal, serialized_log_data: Array -) { +/// * `log_data.serialize_into()` - The log data. +fn after_withdrawal_execution(key: felt252, withdrawal: Withdrawal, mut log_data: LogData) { if !is_valid_callback_contract(withdrawal.callback_contract) { return; } let dispatcher = IWithdrawalCallbackReceiverDispatcher { contract_address: withdrawal.callback_contract }; - dispatcher.after_withdrawal_execution(key, withdrawal, serialized_log_data) + dispatcher.after_withdrawal_execution(key, withdrawal, log_data.serialize_into()) } /// Called after an withdrawal cancellation. /// # Arguments /// * `key` - They key of the withdrawal. /// * `withdrawal` - The withdrawal that was cancelled. -/// * `serialized_log_data` - The log data. -fn after_withdrawal_cancellation( - key: felt252, withdrawal: Withdrawal, serialized_log_data: Array -) { +/// * `log_data.serialize_into()` - The log data. +fn after_withdrawal_cancellation(key: felt252, withdrawal: Withdrawal, mut log_data: LogData) { if !is_valid_callback_contract(withdrawal.callback_contract) { return; } let dispatcher = IWithdrawalCallbackReceiverDispatcher { contract_address: withdrawal.callback_contract }; - dispatcher.after_withdrawal_cancellation(key, withdrawal, serialized_log_data) + dispatcher.after_withdrawal_cancellation(key, withdrawal, log_data.serialize_into()) } /// Called after an order execution. /// # Arguments /// * `key` - They key of the order. /// * `order` - The order that was executed. -/// * `serialized_log_data` - The log data. -fn after_order_execution(key: felt252, order: Order, serialized_log_data: Array) { +/// * `log_data.serialize_into()` - The log data. +fn after_order_execution(key: felt252, order: Order, mut log_data: LogData) { if !is_valid_callback_contract(order.callback_contract) { return; } let dispatcher = IOrderCallbackReceiverDispatcher { contract_address: order.callback_contract }; - dispatcher.after_order_execution(key, order, serialized_log_data) + dispatcher.after_order_execution(key, order, log_data.serialize_into()) } /// Called after an order cancellation. /// # Arguments /// * `key` - They key of the order. /// * `order` - The order that was cancelled. -/// * `serialized_log_data` - The log data. -fn after_order_cancellation(key: felt252, order: Order, serialized_log_data: Array) { +/// * `log_data.serialize_into()` - The log data. +fn after_order_cancellation(key: felt252, order: Order, mut log_data: LogData) { if !is_valid_callback_contract(order.callback_contract) { return; } let dispatcher = IOrderCallbackReceiverDispatcher { contract_address: order.callback_contract }; - dispatcher.after_order_cancellation(key, order, serialized_log_data) + dispatcher.after_order_cancellation(key, order, log_data.serialize_into()) } /// Called after an order cancellation. /// # Arguments /// * `key` - They key of the order. /// * `order` - The order that was frozen. -/// * `serialized_log_data` - The log data. -fn after_order_frozen(key: felt252, order: Order, serialized_log_data: Array) { +/// * `log_data.serialize_into()` - The log data. +fn after_order_frozen(key: felt252, order: Order, mut log_data: LogData) { if !is_valid_callback_contract(order.callback_contract) { return; } let dispatcher = IOrderCallbackReceiverDispatcher { contract_address: order.callback_contract }; - dispatcher.after_order_frozen(key, order, serialized_log_data) + dispatcher.after_order_frozen(key, order, log_data.serialize_into()) } /// Validates that the given address is a contract. diff --git a/src/deposit/deposit_utils.cairo b/src/deposit/deposit_utils.cairo index 9b9aa81a..d884a367 100644 --- a/src/deposit/deposit_utils.cairo +++ b/src/deposit/deposit_utils.cairo @@ -184,7 +184,8 @@ fn cancel_deposit( event_emitter.emit_deposit_cancelled(key, reason, reason_bytes.span()); - after_deposit_cancellation(key, deposit, array![]); + let mut log_data: LogData = Default::default(); + after_deposit_cancellation(key, deposit, log_data); gas_utils::pay_execution_fee_deposit( data_store, diff --git a/src/deposit/execute_deposit_utils.cairo b/src/deposit/execute_deposit_utils.cairo index e436f378..4d426ad5 100644 --- a/src/deposit/execute_deposit_utils.cairo +++ b/src/deposit/execute_deposit_utils.cairo @@ -242,7 +242,7 @@ fn execute_deposit(params: ExecuteDepositParams) { let mut event_data: LogData = Default::default(); event_data.uint_dict.insert_single('received_market_tokens', cache.received_market_tokens); - after_deposit_execution(params.key, deposit, event_data.serialize_into()); + after_deposit_execution(params.key, deposit, event_data); pay_execution_fee_deposit( params.data_store, diff --git a/src/event/event_utils.cairo b/src/event/event_utils.cairo index 6a90d2cf..e411d5aa 100644 --- a/src/event/event_utils.cairo +++ b/src/event/event_utils.cairo @@ -92,13 +92,14 @@ const END_OF_DICT: felt252 = '______'; impl LogDataImpl of LogDataTrait { /// Serializes all the sub-dicts of LogData & append all of them into a new felt252 array fn serialize(ref self: LogData, ref output: Array) { - let mut serialized_dicts: Array> = array![]; - serialized_dicts.append(self.address_dict.serialize_into()); - serialized_dicts.append(self.uint_dict.serialize_into()); - serialized_dicts.append(self.int_dict.serialize_into()); - serialized_dicts.append(self.bool_dict.serialize_into()); - serialized_dicts.append(self.felt252_dict.serialize_into()); - serialized_dicts.append(self.string_dict.serialize_into()); + let mut serialized_dicts: Array> = array![ + self.address_dict.serialize_into(), + self.uint_dict.serialize_into(), + self.int_dict.serialize_into(), + self.bool_dict.serialize_into(), + self.felt252_dict.serialize_into(), + self.string_dict.serialize_into() + ]; let mut span_arrays = serialized_dicts.span(); loop { match span_arrays.pop_front() { diff --git a/src/order/order_utils.cairo b/src/order/order_utils.cairo index faeba770..e2668772 100644 --- a/src/order/order_utils.cairo +++ b/src/order/order_utils.cairo @@ -193,7 +193,7 @@ fn execute_order(params: ExecuteOrderParams) { params.contracts.event_emitter.emit_order_executed(params.key, params.secondary_order_type); - callback_utils::after_order_execution(params.key, params.order, event_data.serialize_into()); + callback_utils::after_order_execution(params.key, params.order, event_data); // the order.executionFee for liquidation / adl orders is zero // gas costs for liquidations / adl is subsidised by the treasury @@ -271,7 +271,7 @@ fn cancel_order( event_emitter.emit_order_cancelled(key, reason, reason_bytes.span()); let mut event_data: LogData = Default::default(); - callback_utils::after_order_cancellation(key, order, event_data.serialize_into()); + callback_utils::after_order_cancellation(key, order, event_data); gas_utils::pay_execution_fee_order( data_store, @@ -324,7 +324,7 @@ fn freeze_order( event_emitter.emit_order_frozen(key, reason, reason_bytes.span()); let mut event_data: LogData = Default::default(); - callback_utils::after_order_frozen(key, order, event_data.serialize_into()); + callback_utils::after_order_frozen(key, order, event_data); gas_utils::pay_execution_fee_order( data_store, event_emitter, order_vault, execution_fee, starting_gas, keeper, order.account diff --git a/tests/callback/test_callback_utils.cairo b/tests/callback/test_callback_utils.cairo index d0bb4592..b1a8d216 100644 --- a/tests/callback/test_callback_utils.cairo +++ b/tests/callback/test_callback_utils.cairo @@ -64,6 +64,6 @@ fn given_normal_conditions_when_callback_contract_functions_then_works() { deposit.callback_contract = callback_mock.contract_address; assert(callback_mock.get_counter() == 1, 'should be 1'); - after_deposit_execution(42, deposit, log_data.serialize_into()); + after_deposit_execution(42, deposit, log_data); assert(callback_mock.get_counter() == 2, 'should be 2'); } From cf4119a045e946c88683acbcf18ebfd23b3c602d Mon Sep 17 00:00:00 2001 From: akhercha Date: Tue, 31 Oct 2023 06:51:52 +0100 Subject: [PATCH 36/40] feat(log_data_indexes): Docstrings --- src/event/event_utils.cairo | 21 +++++++++------ src/utils/serializable_dict.cairo | 44 +++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/event/event_utils.cairo b/src/event/event_utils.cairo index e411d5aa..a3bf1e23 100644 --- a/src/event/event_utils.cairo +++ b/src/event/event_utils.cairo @@ -77,7 +77,6 @@ struct LogData { int_dict: SerializableFelt252Dict, bool_dict: SerializableFelt252Dict, felt252_dict: SerializableFelt252Dict, - // TODO? Possible? array_of_felt_dict: SerializableFelt252Dict>, string_dict: SerializableFelt252Dict } @@ -140,34 +139,40 @@ impl LogDataImpl of LogDataTrait { return Option::None(()); } - let mut serialized_dict = retrieve_dict_serialized(ref serialized); + // deserialize address_dict + let mut serialized_dict = get_dict_serialized(ref serialized); log_data .address_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) .expect('deserialize err address'); - let mut serialized_dict = retrieve_dict_serialized(ref serialized); + // deserialize uint_dict + let mut serialized_dict = get_dict_serialized(ref serialized); log_data .uint_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) .expect('deserialize err uint'); - let mut serialized_dict = retrieve_dict_serialized(ref serialized); + // deserialize int_dict + let mut serialized_dict = get_dict_serialized(ref serialized); log_data .int_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) .expect('deserialize err int'); - let mut serialized_dict = retrieve_dict_serialized(ref serialized); + // deserialize bool_dict + let mut serialized_dict = get_dict_serialized(ref serialized); log_data .bool_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) .expect('deserialize err bool'); - let mut serialized_dict = retrieve_dict_serialized(ref serialized); + // deserialize felt252_dict + let mut serialized_dict = get_dict_serialized(ref serialized); log_data .felt252_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) .expect('deserialize err felt252'); - let mut serialized_dict = retrieve_dict_serialized(ref serialized); + // deserialize string_dict + let mut serialized_dict = get_dict_serialized(ref serialized); log_data .string_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) .expect('deserialize err string'); @@ -183,7 +188,7 @@ impl LogDataImpl of LogDataTrait { /// Pop every elements from the span until the next occurences of END_OF_DICT or /// the end of the Span and return those values in a Span. -fn retrieve_dict_serialized(ref serialized: Span) -> Span { +fn get_dict_serialized(ref serialized: Span) -> Span { let mut dict_data: Array = array![]; loop { match serialized.pop_front() { diff --git a/src/utils/serializable_dict.cairo b/src/utils/serializable_dict.cairo index 104a2984..ffaa5163 100644 --- a/src/utils/serializable_dict.cairo +++ b/src/utils/serializable_dict.cairo @@ -9,6 +9,13 @@ use nullable::{nullable_from_box, match_nullable, FromNullableResult, Nullable}; use alexandria_data_structures::array_ext::ArrayTraitExt; +/// +/// Item +/// +/// Enumeration used to store a value in a SerializableDict. +/// It allows to store either a simple value (Single) or a +/// Span & comes with utilities functions. +/// #[derive(Drop, Copy)] enum Item { Single: T, @@ -71,6 +78,17 @@ impl ItemPartialEq< } } +/// +/// SerializableFelt252Dict +/// +/// Wrapper around the Felt252Dict. +/// It behaves the same as a regular dict but has also a keys parameter +/// that keeps track of the keys registered. +/// This allows us to serialize & deserialize the struct, which is not +/// possible with a regular Felt252Dict. +/// The values are wrapped around an Item struct that allows to store +/// different types of data: a simple value or a span. +/// #[derive(Default, Copy)] struct SerializableFelt252Dict { keys: Array, @@ -180,6 +198,26 @@ impl SerializableFelt252DictTraitImpl< serialized_data } + // + // Serialization of an SerializableFelt252Dict + // + // An SerializableFelt252Dict is serialized as follow: + // [ KEY | NB_ELEMENTS | X | Y | ... | KEY | NB_ELEMENTS | X | ...] + // + // + // e.g. if we try to serialize this Dict: + // keys: [0, 1] + // values: { + // 0: 1, + // 1: [1, 2, 3] + // } + // + // will give: + // + // key: 0 key: 1 + // | ------ | ----------- | + // [0, 1, 1, 1, 3, 1, 2, 3] (Array) + // fn serialize(ref self: SerializableFelt252Dict, ref output: Array) { let mut keys: Span = self.keys.span(); loop { @@ -215,6 +253,12 @@ impl SerializableFelt252DictTraitImpl< }; } + // + // Deserialization of an SerializableFelt252Dict + // + // An SerializableFelt252Dict is serialized as follow: + // [ KEY | NB_ELEMENTS | X | Y | ... | KEY | NB_ELEMENTS | X | ...] + // fn deserialize(ref serialized: Span) -> Option> { let mut d: SerializableFelt252Dict = SerializableFelt252Dict { keys: array![], values: Default::default() From 5ebed4f1cfc65d0b1b0aaf058ebecd2fdd3a98a8 Mon Sep 17 00:00:00 2001 From: akhercha Date: Tue, 31 Oct 2023 16:26:48 +0100 Subject: [PATCH 37/40] feat(log_data_indexes): Updated failed docstring --- src/callback/callback_utils.cairo | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/callback/callback_utils.cairo b/src/callback/callback_utils.cairo index 7af56689..6d74cafe 100644 --- a/src/callback/callback_utils.cairo +++ b/src/callback/callback_utils.cairo @@ -91,7 +91,7 @@ fn get_saved_callback_contract( /// # Arguments /// * `key` - They key of the deposit. /// * `deposit` - The deposit that was executed. -/// * `log_data.serialize_into()` - The log data. +/// * `log_data` - The log data. fn after_deposit_execution(key: felt252, deposit: Deposit, mut log_data: LogData) { if !is_valid_callback_contract(deposit.callback_contract) { return; @@ -106,7 +106,7 @@ fn after_deposit_execution(key: felt252, deposit: Deposit, mut log_data: LogData /// # Arguments /// * `key` - They key of the deposit. /// * `deposit` - The deposit that was cancelled. -/// * `log_data.serialize_into()` - The log data. +/// * `log_data` - The log data. fn after_deposit_cancellation(key: felt252, deposit: Deposit, mut log_data: LogData) { if !is_valid_callback_contract(deposit.callback_contract) { return; @@ -121,7 +121,7 @@ fn after_deposit_cancellation(key: felt252, deposit: Deposit, mut log_data: LogD /// # Arguments /// * `key` - They key of the withdrawal. /// * `withdrawal` - The withdrawal that was executed. -/// * `log_data.serialize_into()` - The log data. +/// * `log_data` - The log data. fn after_withdrawal_execution(key: felt252, withdrawal: Withdrawal, mut log_data: LogData) { if !is_valid_callback_contract(withdrawal.callback_contract) { return; @@ -136,7 +136,7 @@ fn after_withdrawal_execution(key: felt252, withdrawal: Withdrawal, mut log_data /// # Arguments /// * `key` - They key of the withdrawal. /// * `withdrawal` - The withdrawal that was cancelled. -/// * `log_data.serialize_into()` - The log data. +/// * `log_data` - The log data. fn after_withdrawal_cancellation(key: felt252, withdrawal: Withdrawal, mut log_data: LogData) { if !is_valid_callback_contract(withdrawal.callback_contract) { return; @@ -151,7 +151,7 @@ fn after_withdrawal_cancellation(key: felt252, withdrawal: Withdrawal, mut log_d /// # Arguments /// * `key` - They key of the order. /// * `order` - The order that was executed. -/// * `log_data.serialize_into()` - The log data. +/// * `log_data` - The log data. fn after_order_execution(key: felt252, order: Order, mut log_data: LogData) { if !is_valid_callback_contract(order.callback_contract) { return; @@ -164,7 +164,7 @@ fn after_order_execution(key: felt252, order: Order, mut log_data: LogData) { /// # Arguments /// * `key` - They key of the order. /// * `order` - The order that was cancelled. -/// * `log_data.serialize_into()` - The log data. +/// * `log_data` - The log data. fn after_order_cancellation(key: felt252, order: Order, mut log_data: LogData) { if !is_valid_callback_contract(order.callback_contract) { return; @@ -177,7 +177,7 @@ fn after_order_cancellation(key: felt252, order: Order, mut log_data: LogData) { /// # Arguments /// * `key` - They key of the order. /// * `order` - The order that was frozen. -/// * `log_data.serialize_into()` - The log data. +/// * `log_data` - The log data. fn after_order_frozen(key: felt252, order: Order, mut log_data: LogData) { if !is_valid_callback_contract(order.callback_contract) { return; From fab23c7e8dbb2623a693ff59ba39ae7fb46bdc5d Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 1 Nov 2023 09:45:22 +0100 Subject: [PATCH 38/40] feat(log_data_indexes): Refacto + Added serializable_dict to Satoru's book --- .../utils-module.md | 2 + src/event/event_utils.cairo | 58 ++++++++----------- 2 files changed, 27 insertions(+), 33 deletions(-) diff --git a/book/src/smart-contracts-architecture/utils-module.md b/book/src/smart-contracts-architecture/utils-module.md index d497077a..c908f7f4 100644 --- a/book/src/smart-contracts-architecture/utils-module.md +++ b/book/src/smart-contracts-architecture/utils-module.md @@ -32,6 +32,8 @@ It contains the following files: - [precision.cairo](https://github.com/keep-starknet-strange/satoru/blob/main/src/utils/precision.cairo): This offers utility functions for detailed math and changing units, helping with accurate calculations and conversions between different measures, like from float to wei, applying factors, and managing rounding in the Satoru Starknet smart contract environment. +- [serializable_dict](https://github.com/keep-starknet-strange/satoru/blob/main/src/utils/serializable_dict.cairo): This file defines the SerializableFelt252Dict structure that allows us to use a Felt252Dict and serialize/deserialize it. + - [span32.cairo](https://github.com/keep-starknet-strange/satoru/blob/main/src/utils/span32.cairo): Provides utility functions for managing and manipulating fixed-size arrays (span32). A wrapper around Span type with a maximum size of 32. Used to prevent size overflow when storing Span. - [starknet_utils.cairo](https://github.com/keep-starknet-strange/satoru/blob/main/src/utils/starknet_utils.cairo): This puts in place fake utilities to mimic Starknet environment features, like `gasleft` and `tx.gasprice`, in the Satoru Starknet smart contract environment. These functions give back set values based on the given parameters, allowing a way to mimic Starknet gas actions during testing and development. diff --git a/src/event/event_utils.cairo b/src/event/event_utils.cairo index a3bf1e23..f2df87d3 100644 --- a/src/event/event_utils.cairo +++ b/src/event/event_utils.cairo @@ -81,7 +81,7 @@ struct LogData { } /// Number of dicts presents in LogData -const NUMBER_OF_DICTS: usize = 6; +const DICTS_IN_LOGDATA: usize = 6; /// When serializing dicts into a unique Array, this is the value that will /// be used to recognized a separation between two dicts. @@ -132,51 +132,43 @@ impl LogDataImpl of LogDataTrait { /// Deserialize all the sub-dicts serialized into a LogData fn deserialize(ref serialized: Span) -> Option { - let mut log_data: LogData = Default::default(); - - // There should be the right amount of dictionnaries serializeds - if serialized.occurrences_of(END_OF_DICT) != NUMBER_OF_DICTS { - return Option::None(()); + // There should be the right amount of dictionnaries serialized + if serialized.occurrences_of(END_OF_DICT) != DICTS_IN_LOGDATA { + panic_with_felt252('serialized format error'); } - // deserialize address_dict - let mut serialized_dict = get_dict_serialized(ref serialized); - log_data - .address_dict = - SerializableFelt252DictTrait::::deserialize(ref serialized_dict) + // Deserialize all dicts one by one + let mut serialized_dict = get_next_dict_serialized(ref serialized); + let address_dict = SerializableFelt252DictTrait::::deserialize( + ref serialized_dict + ) .expect('deserialize err address'); - // deserialize uint_dict - let mut serialized_dict = get_dict_serialized(ref serialized); - log_data - .uint_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) + let mut serialized_dict = get_next_dict_serialized(ref serialized); + let uint_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) .expect('deserialize err uint'); - // deserialize int_dict - let mut serialized_dict = get_dict_serialized(ref serialized); - log_data - .int_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) + let mut serialized_dict = get_next_dict_serialized(ref serialized); + let int_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) .expect('deserialize err int'); - // deserialize bool_dict - let mut serialized_dict = get_dict_serialized(ref serialized); - log_data - .bool_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) + let mut serialized_dict = get_next_dict_serialized(ref serialized); + let bool_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) .expect('deserialize err bool'); - // deserialize felt252_dict - let mut serialized_dict = get_dict_serialized(ref serialized); - log_data - .felt252_dict = - SerializableFelt252DictTrait::::deserialize(ref serialized_dict) + let mut serialized_dict = get_next_dict_serialized(ref serialized); + let felt252_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) .expect('deserialize err felt252'); - // deserialize string_dict - let mut serialized_dict = get_dict_serialized(ref serialized); - log_data - .string_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) + let mut serialized_dict = get_next_dict_serialized(ref serialized); + let string_dict = SerializableFelt252DictTrait::::deserialize(ref serialized_dict) .expect('deserialize err string'); + // Create the LogData struct with every dicts + let log_data: LogData = LogData { + address_dict, uint_dict, int_dict, bool_dict, felt252_dict, string_dict + }; + Option::Some(log_data) } } @@ -188,7 +180,7 @@ impl LogDataImpl of LogDataTrait { /// Pop every elements from the span until the next occurences of END_OF_DICT or /// the end of the Span and return those values in a Span. -fn get_dict_serialized(ref serialized: Span) -> Span { +fn get_next_dict_serialized(ref serialized: Span) -> Span { let mut dict_data: Array = array![]; loop { match serialized.pop_front() { From 3458b48a63ac22997be4a80d957a1ddc1504270e Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 1 Nov 2023 10:43:08 +0100 Subject: [PATCH 39/40] feat(log_data_indexes): Removed Copy Trait for SerializableDict --- src/utils/serializable_dict.cairo | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/utils/serializable_dict.cairo b/src/utils/serializable_dict.cairo index ffaa5163..e5baed05 100644 --- a/src/utils/serializable_dict.cairo +++ b/src/utils/serializable_dict.cairo @@ -89,7 +89,7 @@ impl ItemPartialEq< /// The values are wrapped around an Item struct that allows to store /// different types of data: a simple value or a span. /// -#[derive(Default, Copy)] +#[derive(Default)] struct SerializableFelt252Dict { keys: Array, values: Felt252Dict>> @@ -104,9 +104,6 @@ impl SerializableFelt252DictDestruct< } } -impl ArrayTCopy of Copy>; -impl Felt252DictItemCopy of Copy>; - trait SerializableFelt252DictTrait { /// Creates a new SerializableFelt252Dict object. fn new() -> SerializableFelt252Dict; From ea32b238a2e40240738b73bb451fba083459c5d4 Mon Sep 17 00:00:00 2001 From: akhercha Date: Wed, 1 Nov 2023 10:52:07 +0100 Subject: [PATCH 40/40] feat(log_data_indexes): Added .cairo ext --- book/src/smart-contracts-architecture/utils-module.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/src/smart-contracts-architecture/utils-module.md b/book/src/smart-contracts-architecture/utils-module.md index c908f7f4..98b2881f 100644 --- a/book/src/smart-contracts-architecture/utils-module.md +++ b/book/src/smart-contracts-architecture/utils-module.md @@ -32,7 +32,7 @@ It contains the following files: - [precision.cairo](https://github.com/keep-starknet-strange/satoru/blob/main/src/utils/precision.cairo): This offers utility functions for detailed math and changing units, helping with accurate calculations and conversions between different measures, like from float to wei, applying factors, and managing rounding in the Satoru Starknet smart contract environment. -- [serializable_dict](https://github.com/keep-starknet-strange/satoru/blob/main/src/utils/serializable_dict.cairo): This file defines the SerializableFelt252Dict structure that allows us to use a Felt252Dict and serialize/deserialize it. +- [serializable_dict.cairo](https://github.com/keep-starknet-strange/satoru/blob/main/src/utils/serializable_dict.cairo): This file defines the SerializableFelt252Dict structure that allows us to use a Felt252Dict and serialize/deserialize it. - [span32.cairo](https://github.com/keep-starknet-strange/satoru/blob/main/src/utils/span32.cairo): Provides utility functions for managing and manipulating fixed-size arrays (span32). A wrapper around Span type with a maximum size of 32. Used to prevent size overflow when storing Span.