scrypto_test/environment/
system_api.rs

1//! This module has the implementation of the [`SystemApi`] for the [`TestEnvironment`] in order not
2//! to clutter up the other modules.
3//!
4//! [`SystemApi`]: crate::prelude::SystemApi
5//! [`TestEnvironment`]: crate::prelude::TestEnvironment
6
7use crate::prelude::*;
8
9/// Implements the [`SystemApi`] for the [`TestEnvironment`] struct.
10///
11/// This macro exposes a high-level API for specifying the [`SystemApi`] traits to implement for the
12/// [`TestEnvironment`]. The trait methods are implements through a simple mechanism which creates a
13/// [`SystemService`] object from the kernel and calls the trait method on the [`SystemService`]
14/// object.
15///
16/// The syntax supported by this macro is as follows:
17///
18/// ```rust,ignore
19/// # // Ignoring because the macro isn't exported, so this test can't use it
20/// implement_system_api! {
21///     trait_name: {
22///         trait_method1: (args: ArgTypes) -> ReturnTypes,
23///         trait_method2: (args: ArgTypes) -> ReturnTypes,
24///     }
25/// }
26/// ```
27///
28/// This macro is only used internally in this crate for easy implementation of the [`SystemApi`]
29/// and is not meant to be used outside or exported.
30///
31/// [`SystemApi`]: crate::prelude::SystemApi
32/// [`TestEnvironment`]: crate::prelude::TestEnvironment
33/// [`SystemService`]: crate::prelude::SystemService
34macro_rules! implement_system_api {
35    (
36        $(
37            $trait: ident: {
38                $(
39                    $func_ident: ident: (
40                        &mut self
41                        $(, $input_ident: ident: $input_type: ty)* $(,)?
42                    ) -> $outputs: ty
43                ),* $(,)?
44            }
45        ),* $(,)*
46    ) => {
47        $(
48            impl<D> $trait<RuntimeError> for TestEnvironment<D>
49            where
50                D: SubstateDatabase + CommittableSubstateDatabase + 'static
51            {
52                $(
53                    #[inline]
54                    fn $func_ident(&mut self, $($input_ident: $input_type),*) -> $outputs {
55                        let logs_before = self.0.with_kernel_mut(|kernel| {
56                            kernel
57                                .kernel_get_system_state()
58                                .system
59                                .modules
60                                .transaction_runtime()
61                                .map(|runtime| runtime.logs.len())
62                                .unwrap_or(0)
63                        });
64
65                        let rtn = self.0.with_kernel_mut(|kernel| {
66                            SystemService::new(kernel).$func_ident( $($input_ident),* )
67                        });
68
69                        self.0.with_kernel_mut(|kernel| {
70                            let logs_after = kernel
71                                .kernel_get_system_state()
72                                .system
73                                .modules
74                                .transaction_runtime()
75                                .map(|runtime| runtime.logs.len())
76                                .unwrap_or(0);
77
78                            if logs_before != logs_after {
79                                for (level, message) in kernel
80                                    .kernel_get_system_state()
81                                    .system
82                                    .modules
83                                    .transaction_runtime()
84                                    .map(|module| module.logs.iter())
85                                    .unwrap_or_default()
86                                    .into_iter()
87                                    .skip(logs_before)
88                                {
89                                    println!("[{}]: {}", level, message)
90                                }
91                            }
92                        });
93
94                        rtn
95                    }
96                )*
97            }
98        )*
99    };
100}
101implement_system_api! {
102    SystemApi: {},
103    SystemActorApi: {
104        actor_get_blueprint_id: (&mut self) -> Result<BlueprintId, RuntimeError>,
105        actor_open_field: (
106            &mut self,
107            object_handle: ActorStateHandle,
108            field: FieldIndex,
109            flags: LockFlags,
110        ) -> Result<FieldHandle, RuntimeError>,
111        actor_is_feature_enabled: (
112            &mut self,
113            object_handle: ActorStateHandle,
114            feature: &str,
115        ) -> Result<bool, RuntimeError>,
116        actor_get_node_id: (&mut self, ref_handle: ActorRefHandle) -> Result<NodeId, RuntimeError>,
117        actor_emit_event: (
118            &mut self,
119            event_name: String,
120            event_data: Vec<u8>,
121            event_flags: EventFlags,
122        ) -> Result<(), RuntimeError>
123    },
124    SystemActorIndexApi: {
125        actor_index_insert: (
126            &mut self,
127            object_handle: ActorStateHandle,
128            collection_index: CollectionIndex,
129            key: Vec<u8>,
130            buffer: Vec<u8>,
131        ) -> Result<(), RuntimeError>,
132        actor_index_remove: (
133            &mut self,
134            object_handle: ActorStateHandle,
135            collection_index: CollectionIndex,
136            key: Vec<u8>,
137        ) -> Result<Option<Vec<u8>>, RuntimeError>,
138        actor_index_scan_keys: (
139            &mut self,
140            object_handle: ActorStateHandle,
141            collection_index: CollectionIndex,
142            limit: u32,
143        ) -> Result<Vec<Vec<u8>>, RuntimeError>,
144        actor_index_drain: (
145            &mut self,
146            object_handle: ActorStateHandle,
147            collection_index: CollectionIndex,
148            limit: u32,
149        ) -> Result<Vec<(Vec<u8>, Vec<u8>)>, RuntimeError>,
150    },
151    SystemActorKeyValueEntryApi: {
152        actor_open_key_value_entry: (
153            &mut self,
154            object_handle: ActorStateHandle,
155            collection_index: CollectionIndex,
156            key: &Vec<u8>,
157            flags: LockFlags,
158        ) -> Result<KeyValueEntryHandle, RuntimeError>,
159        actor_remove_key_value_entry: (
160            &mut self,
161            object_handle: ActorStateHandle,
162            collection_index: CollectionIndex,
163            key: &Vec<u8>,
164        ) -> Result<Vec<u8>, RuntimeError>,
165    },
166    SystemActorSortedIndexApi: {
167        actor_sorted_index_insert: (
168            &mut self,
169            object_handle: ActorStateHandle,
170            collection_index: CollectionIndex,
171            sorted_key: SortedKey,
172            buffer: Vec<u8>,
173        ) -> Result<(), RuntimeError>,
174        actor_sorted_index_remove: (
175            &mut self,
176            object_handle: ActorStateHandle,
177            collection_index: CollectionIndex,
178            sorted_key: &SortedKey,
179        ) -> Result<Option<Vec<u8>>, RuntimeError>,
180        actor_sorted_index_scan: (
181            &mut self,
182            object_handle: ActorStateHandle,
183            collection_index: CollectionIndex,
184            count: u32,
185        ) -> Result<Vec<(SortedKey, Vec<u8>)>, RuntimeError>,
186    },
187    SystemBlueprintApi: {
188        call_function: (
189            &mut self,
190            package_address: PackageAddress,
191            blueprint_name: &str,
192            function_name: &str,
193            args: Vec<u8>,
194        ) -> Result<Vec<u8>, RuntimeError>,
195        resolve_blueprint_type: (
196            &mut self,
197            blueprint_type_id: &BlueprintTypeIdentifier,
198        ) -> Result<(Rc<VersionedScryptoSchema>, ScopedTypeId), RuntimeError>
199    },
200    SystemFieldApi: {
201        field_read: (&mut self, handle: field_api::FieldHandle) -> Result<Vec<u8>, RuntimeError>,
202        field_write: (&mut self, handle: FieldHandle, buffer: Vec<u8>) -> Result<(), RuntimeError>,
203        field_lock: (&mut self, handle: FieldHandle) -> Result<(), RuntimeError>,
204        field_close: (&mut self, handle: FieldHandle) -> Result<(), RuntimeError>
205    },
206    SystemKeyValueEntryApi: {
207        key_value_entry_get: (&mut self, handle: KeyValueEntryHandle) -> Result<Vec<u8>, RuntimeError>,
208        key_value_entry_set: (
209            &mut self,
210            handle: KeyValueEntryHandle,
211            buffer: Vec<u8>,
212        ) -> Result<(), RuntimeError>,
213        key_value_entry_remove: (&mut self, handle: KeyValueEntryHandle) -> Result<Vec<u8>, RuntimeError>,
214        key_value_entry_lock: (&mut self, handle: KeyValueEntryHandle) -> Result<(), RuntimeError>,
215        key_value_entry_close: (&mut self, handle: KeyValueEntryHandle) -> Result<(), RuntimeError>,
216    },
217    SystemKeyValueStoreApi: {
218        key_value_store_new: (&mut self, data_schema: KeyValueStoreDataSchema) -> Result<NodeId, RuntimeError>,
219        key_value_store_open_entry: (
220            &mut self,
221            node_id: &NodeId,
222            key: &Vec<u8>,
223            flags: LockFlags,
224        ) -> Result<KeyValueEntryHandle, RuntimeError>,
225        key_value_store_remove_entry: (
226            &mut self,
227            node_id: &NodeId,
228            key: &Vec<u8>,
229        ) -> Result<Vec<u8>, RuntimeError>,
230    },
231    SystemObjectApi: {
232        new_object: (
233            &mut self,
234            blueprint_ident: &str,
235            features: Vec<&str>,
236            generic_args: GenericArgs,
237            fields: IndexMap<FieldIndex, FieldValue>,
238            kv_entries: IndexMap<u8, IndexMap<Vec<u8>, KVEntry>>,
239        ) -> Result<NodeId, RuntimeError>,
240        drop_object: (&mut self, node_id: &NodeId) -> Result<Vec<Vec<u8>>, RuntimeError>,
241        get_blueprint_id: (&mut self, node_id: &NodeId) -> Result<BlueprintId, RuntimeError>,
242        get_outer_object: (&mut self, node_id: &NodeId) -> Result<GlobalAddress, RuntimeError>,
243        allocate_global_address: (
244            &mut self,
245            blueprint_id: BlueprintId,
246        ) -> Result<(GlobalAddressReservation, GlobalAddress), RuntimeError>,
247        allocate_virtual_global_address: (
248            &mut self,
249            blueprint_id: BlueprintId,
250            global_address: GlobalAddress,
251        ) -> Result<GlobalAddressReservation, RuntimeError>,
252        get_reservation_address: (&mut self, node_id: &NodeId) -> Result<GlobalAddress, RuntimeError>,
253        globalize: (
254            &mut self,
255            node_id: NodeId,
256            modules: IndexMap<AttachedModuleId, NodeId>,
257            address_reservation: Option<GlobalAddressReservation>,
258        ) -> Result<GlobalAddress, RuntimeError>,
259        globalize_with_address_and_create_inner_object_and_emit_event: (
260            &mut self,
261            node_id: NodeId,
262            modules: IndexMap<AttachedModuleId, NodeId>,
263            address_reservation: GlobalAddressReservation,
264            inner_object_blueprint: &str,
265            inner_object_fields: IndexMap<u8, FieldValue>,
266            event_name: &str,
267            event_data: Vec<u8>,
268        ) -> Result<(GlobalAddress, NodeId), RuntimeError>,
269        call_method: (
270            &mut self,
271            receiver: &NodeId,
272            method_name: &str,
273            args: Vec<u8>,
274        ) -> Result<Vec<u8>, RuntimeError>,
275        call_direct_access_method: (
276            &mut self,
277            receiver: &NodeId,
278            method_name: &str,
279            args: Vec<u8>,
280        ) -> Result<Vec<u8>, RuntimeError>,
281        call_module_method: (
282            &mut self,
283            receiver: &NodeId,
284            module_id: AttachedModuleId,
285            method_name: &str,
286            args: Vec<u8>,
287        ) -> Result<Vec<u8>, RuntimeError>,
288    },
289    SystemExecutionTraceApi: {
290        update_instruction_index: (&mut self, new_index: usize) -> Result<(), RuntimeError>,
291    },
292    SystemTransactionRuntimeApi: {
293        bech32_encode_address: (&mut self, address: GlobalAddress) -> Result<String, RuntimeError>,
294        get_transaction_hash: (&mut self) -> Result<Hash, RuntimeError>,
295        generate_ruid: (&mut self) -> Result<[u8; 32], RuntimeError>,
296        emit_log: (&mut self, level: Level, message: String) -> Result<(), RuntimeError>,
297        panic: (&mut self, message: String) -> Result<(), RuntimeError>,
298    },
299    SystemCostingApi: {
300        start_lock_fee: (&mut self, amount: Decimal, contingent: bool) -> Result<bool, RuntimeError>,
301        lock_fee: (
302            &mut self,
303            locked_fee: LiquidFungibleResource,
304            contingent: bool,
305        ) -> (),
306        consume_cost_units: (&mut self, costing_entry: ClientCostingEntry) -> Result<(), RuntimeError>,
307        execution_cost_unit_limit: (&mut self) -> Result<u32, RuntimeError>,
308        execution_cost_unit_price: (&mut self) -> Result<Decimal, RuntimeError>,
309        finalization_cost_unit_limit: (&mut self) -> Result<u32, RuntimeError>,
310        finalization_cost_unit_price: (&mut self) -> Result<Decimal, RuntimeError>,
311        usd_price: (&mut self) -> Result<Decimal, RuntimeError>,
312        max_per_function_royalty_in_xrd: (&mut self) -> Result<Decimal, RuntimeError>,
313        tip_percentage_truncated: (&mut self) -> Result<u32, RuntimeError>,
314        fee_balance: (&mut self) -> Result<Decimal, RuntimeError>,
315    }
316}