radix_engine/system/system_modules/
module_mixer.rs

1use super::costing::{CostingError, ExecutionCostingEntry, FinalizationCostingEntry, StorageType};
2use super::limits::TransactionLimitsError;
3use crate::errors::*;
4use crate::internal_prelude::*;
5use crate::kernel::call_frame::CallFrameMessage;
6use crate::kernel::kernel_api::*;
7use crate::kernel::kernel_callback_api::*;
8use crate::system::actor::Actor;
9use crate::system::module::PrivilegedSystemModule;
10use crate::system::module::{InitSystemModule, SystemModule};
11use crate::system::system::SystemService;
12use crate::system::system_callback::*;
13use crate::system::system_modules::auth::AuthModule;
14use crate::system::system_modules::costing::CostingModule;
15use crate::system::system_modules::costing::SystemLoanFeeReserve;
16use crate::system::system_modules::execution_trace::ExecutionTraceModule;
17use crate::system::system_modules::kernel_trace::KernelTraceModule;
18use crate::system::system_modules::limits::LimitsModule;
19use crate::system::system_modules::transaction_runtime::{Event, TransactionRuntimeModule};
20use bitflags::bitflags;
21use paste::paste;
22use radix_common::crypto::Hash;
23use radix_engine_interface::api::ModuleId;
24use radix_engine_profiling_derive::trace_resources;
25
26bitflags! {
27    pub struct EnabledModules: u32 {
28        // Kernel trace, for debugging only
29        const KERNEL_TRACE = 0x1 << 0;
30
31        // Limits, costing and auth
32        const LIMITS = 0x01 << 1;
33        const COSTING = 0x01 << 2;
34        const AUTH = 0x01 << 3;
35        const TRANSACTION_RUNTIME = 0x01 << 5;
36
37        // Execution trace, for preview only
38        const EXECUTION_TRACE = 0x01 << 6;
39    }
40}
41
42impl EnabledModules {
43    /// The difference between genesis transaction and system transaction is "no auth".
44    /// TODO: double check if this is the right assumption.
45    pub fn for_genesis_transaction() -> Self {
46        Self::TRANSACTION_RUNTIME
47    }
48
49    pub fn for_system_transaction() -> Self {
50        Self::AUTH | Self::TRANSACTION_RUNTIME
51    }
52
53    pub fn for_notarized_transaction() -> Self {
54        Self::LIMITS | Self::COSTING | Self::AUTH | Self::TRANSACTION_RUNTIME
55    }
56
57    pub fn for_test_transaction() -> Self {
58        Self::for_notarized_transaction() | Self::KERNEL_TRACE
59    }
60
61    pub fn for_preview() -> Self {
62        Self::for_notarized_transaction() | Self::EXECUTION_TRACE
63    }
64
65    pub fn for_preview_no_auth() -> Self {
66        Self::for_preview() - Self::AUTH
67    }
68}
69
70#[allow(dead_code)]
71pub struct SystemModuleMixer {
72    // TODO: Use option instead of default for module states?
73    // The original reason for performance, but we should double check.
74
75    /* flags */
76    pub enabled_modules: EnabledModules,
77
78    /* states */
79    pub(super) kernel_trace: KernelTraceModule,
80    pub(super) limits: LimitsModule,
81    pub(super) costing: CostingModule,
82    pub(super) auth: AuthModule,
83    pub(crate) transaction_runtime: TransactionRuntimeModule,
84    pub(super) execution_trace: ExecutionTraceModule,
85}
86
87// Macro generates default modules dispatches call based on passed function name and arguments.
88macro_rules! internal_call_dispatch {
89    (
90        $system:expr,
91        $fn:ident ( $($param:expr),* )
92        $(, $privileged_fn:ident ( $($privileged_fn_param:expr),* ))?
93    ) => {
94        paste! {{
95            let modules: EnabledModules = $system.modules.enabled_modules;
96            if modules.contains(EnabledModules::KERNEL_TRACE) {
97                KernelTraceModule::[< $fn >]($($param, )*)?;
98                $(KernelTraceModule::[< $privileged_fn >]($($privileged_fn_param, )*)?;)?
99            }
100            if modules.contains(EnabledModules::LIMITS) {
101                LimitsModule::[< $fn >]($($param, )*)?;
102                $(LimitsModule::[< $privileged_fn >]($($privileged_fn_param, )*)?;)?
103            }
104            if modules.contains(EnabledModules::COSTING) {
105                CostingModule::[< $fn >]($($param, )*)?;
106                $(CostingModule::[< $privileged_fn >]($($privileged_fn_param, )*)?;)?
107            }
108            if modules.contains(EnabledModules::AUTH) {
109                AuthModule::[< $fn >]($($param, )*)?;
110                $(AuthModule::[< $privileged_fn >]($($privileged_fn_param, )*)?;)?
111            }
112            if modules.contains(EnabledModules::TRANSACTION_RUNTIME) {
113                TransactionRuntimeModule::[< $fn >]($($param, )*)?;
114                $(TransactionRuntimeModule::[< $privileged_fn >]($($privileged_fn_param, )*)?;)?
115            }
116            if modules.contains(EnabledModules::EXECUTION_TRACE) {
117                ExecutionTraceModule::[< $fn >]($($param, )*)?;
118                $(ExecutionTraceModule::[< $privileged_fn >]($($privileged_fn_param, )*)?;)?
119            }
120            Ok(())
121        }}
122    };
123}
124
125impl SystemModuleMixer {
126    pub fn new(
127        enabled_modules: EnabledModules,
128        kernel_trace: KernelTraceModule,
129        transaction_runtime: TransactionRuntimeModule,
130        auth: AuthModule,
131        limits: LimitsModule,
132        costing: CostingModule,
133        execution_trace: ExecutionTraceModule,
134    ) -> Self {
135        Self {
136            enabled_modules,
137            kernel_trace,
138            transaction_runtime,
139            auth,
140            costing,
141            limits,
142            execution_trace,
143        }
144    }
145
146    #[inline]
147    pub fn is_kernel_trace_enabled(&self) -> bool {
148        self.enabled_modules.contains(EnabledModules::KERNEL_TRACE)
149    }
150
151    #[inline]
152    pub fn is_execution_trace_enabled(&self) -> bool {
153        self.enabled_modules
154            .contains(EnabledModules::EXECUTION_TRACE)
155    }
156
157    pub fn unpack_costing(self) -> CostingModule {
158        self.costing
159    }
160
161    pub fn unpack(
162        self,
163    ) -> (
164        CostingModule,
165        TransactionRuntimeModule,
166        ExecutionTraceModule,
167    ) {
168        (self.costing, self.transaction_runtime, self.execution_trace)
169    }
170}
171
172//====================================================================
173// NOTE: Modules are applied in the reverse order of initialization!
174// This has an impact if there is module dependency.
175//====================================================================
176
177impl InitSystemModule for SystemModuleMixer {
178    #[trace_resources]
179    fn init(&mut self) -> Result<(), BootloadingError> {
180        let modules: EnabledModules = self.enabled_modules;
181
182        // Enable execution trace
183        if modules.contains(EnabledModules::EXECUTION_TRACE) {
184            self.execution_trace.init()?;
185        }
186
187        // Enable transaction runtime
188        if modules.contains(EnabledModules::TRANSACTION_RUNTIME) {
189            self.transaction_runtime.init()?;
190        }
191
192        // Enable auth
193        if modules.contains(EnabledModules::AUTH) {
194            self.auth.init()?;
195        }
196
197        // Enable costing
198        if modules.contains(EnabledModules::COSTING) {
199            self.costing.init()?;
200        }
201
202        // Enable transaction limits
203        if modules.contains(EnabledModules::LIMITS) {
204            self.limits.init()?;
205        }
206
207        // Enable kernel trace
208        if modules.contains(EnabledModules::KERNEL_TRACE) {
209            self.kernel_trace.init()?;
210        }
211
212        Ok(())
213    }
214
215    #[trace_resources]
216    fn on_teardown(&mut self) -> Result<(), RuntimeError> {
217        let modules: EnabledModules = self.enabled_modules;
218        if modules.contains(EnabledModules::KERNEL_TRACE) {
219            self.kernel_trace.on_teardown()?;
220        }
221        if modules.contains(EnabledModules::LIMITS) {
222            self.limits.on_teardown()?;
223        }
224        if modules.contains(EnabledModules::COSTING) {
225            self.costing.on_teardown()?;
226        }
227        if modules.contains(EnabledModules::AUTH) {
228            self.auth.on_teardown()?;
229        }
230        if modules.contains(EnabledModules::TRANSACTION_RUNTIME) {
231            self.transaction_runtime.on_teardown()?;
232        }
233        if modules.contains(EnabledModules::EXECUTION_TRACE) {
234            self.execution_trace.on_teardown()?;
235        }
236
237        Ok(())
238    }
239}
240
241impl SystemModuleMixer {
242    #[trace_resources(log=invocation.len())]
243    pub fn before_invoke(
244        api: &mut impl SystemBasedKernelApi,
245        invocation: &KernelInvocation<Actor>,
246    ) -> Result<(), RuntimeError> {
247        internal_call_dispatch!(
248            api.kernel_get_system(),
249            before_invoke(&mut api.system_module_api(), invocation),
250            privileged_before_invoke(api, invocation)
251        )
252    }
253
254    #[trace_resources]
255    pub fn on_execution_start(
256        api: &mut impl SystemBasedKernelInternalApi,
257    ) -> Result<(), RuntimeError> {
258        internal_call_dispatch!(
259            api.kernel_get_system(),
260            on_execution_start(&mut api.system_module_api())
261        )
262    }
263
264    #[trace_resources]
265    pub fn on_execution_finish(
266        api: &mut impl SystemBasedKernelInternalApi,
267        message: &CallFrameMessage,
268    ) -> Result<(), RuntimeError> {
269        internal_call_dispatch!(
270            api.kernel_get_system(),
271            on_execution_finish(&mut api.system_module_api(), message)
272        )
273    }
274
275    #[trace_resources]
276    pub fn after_invoke(
277        api: &mut impl SystemBasedKernelInternalApi,
278        output: &IndexedScryptoValue,
279    ) -> Result<(), RuntimeError> {
280        internal_call_dispatch!(
281            api.kernel_get_system(),
282            after_invoke(&mut api.system_module_api(), output)
283        )
284    }
285
286    #[trace_resources]
287    pub fn on_pin_node(
288        api: &mut impl SystemBasedKernelInternalApi,
289        node_id: &NodeId,
290    ) -> Result<(), RuntimeError> {
291        internal_call_dispatch!(
292            api.kernel_get_system(),
293            on_pin_node(&mut api.system_module_api(), node_id)
294        )
295    }
296
297    #[trace_resources(log=entity_type)]
298    pub fn on_allocate_node_id(
299        api: &mut impl SystemBasedKernelInternalApi,
300        entity_type: EntityType,
301    ) -> Result<(), RuntimeError> {
302        internal_call_dispatch!(
303            api.kernel_get_system(),
304            on_allocate_node_id(&mut api.system_module_api(), entity_type)
305        )
306    }
307
308    #[trace_resources]
309    pub fn on_create_node(
310        api: &mut impl SystemBasedKernelInternalApi,
311        event: &CreateNodeEvent,
312    ) -> Result<(), RuntimeError> {
313        internal_call_dispatch!(
314            api.kernel_get_system(),
315            on_create_node(&mut api.system_module_api(), event)
316        )
317    }
318
319    #[trace_resources]
320    pub fn on_move_module(
321        api: &mut impl SystemBasedKernelInternalApi,
322        event: &MoveModuleEvent,
323    ) -> Result<(), RuntimeError> {
324        internal_call_dispatch!(
325            api.kernel_get_system(),
326            on_move_module(&mut api.system_module_api(), event)
327        )
328    }
329
330    #[trace_resources]
331    pub fn on_drop_node(
332        api: &mut impl SystemBasedKernelInternalApi,
333        event: &DropNodeEvent,
334    ) -> Result<(), RuntimeError> {
335        internal_call_dispatch!(
336            api.kernel_get_system(),
337            on_drop_node(&mut api.system_module_api(), event)
338        )
339    }
340
341    #[trace_resources]
342    pub fn on_mark_substate_as_transient(
343        api: &mut impl SystemBasedKernelInternalApi,
344        node_id: &NodeId,
345        partition_number: &PartitionNumber,
346        substate_key: &SubstateKey,
347    ) -> Result<(), RuntimeError> {
348        internal_call_dispatch!(
349            api.kernel_get_system(),
350            on_mark_substate_as_transient(
351                &mut api.system_module_api(),
352                node_id,
353                partition_number,
354                substate_key
355            )
356        )
357    }
358
359    #[trace_resources]
360    pub fn on_open_substate(
361        api: &mut impl SystemBasedKernelInternalApi,
362        event: &OpenSubstateEvent,
363    ) -> Result<(), RuntimeError> {
364        internal_call_dispatch!(
365            api.kernel_get_system(),
366            on_open_substate(&mut api.system_module_api(), event)
367        )
368    }
369
370    #[trace_resources(log=event.is_about_heap())]
371    pub fn on_read_substate(
372        api: &mut impl SystemBasedKernelInternalApi,
373        event: &ReadSubstateEvent,
374    ) -> Result<(), RuntimeError> {
375        internal_call_dispatch!(
376            api.kernel_get_system(),
377            on_read_substate(&mut api.system_module_api(), event)
378        )
379    }
380
381    #[trace_resources]
382    pub fn on_write_substate(
383        api: &mut impl SystemBasedKernelInternalApi,
384        event: &WriteSubstateEvent,
385    ) -> Result<(), RuntimeError> {
386        internal_call_dispatch!(
387            api.kernel_get_system(),
388            on_write_substate(&mut api.system_module_api(), event)
389        )
390    }
391
392    #[trace_resources]
393    pub fn on_close_substate(
394        api: &mut impl SystemBasedKernelInternalApi,
395        event: &CloseSubstateEvent,
396    ) -> Result<(), RuntimeError> {
397        internal_call_dispatch!(
398            api.kernel_get_system(),
399            on_close_substate(&mut api.system_module_api(), event)
400        )
401    }
402
403    #[trace_resources]
404    pub fn on_set_substate(
405        api: &mut impl SystemBasedKernelInternalApi,
406        event: &SetSubstateEvent,
407    ) -> Result<(), RuntimeError> {
408        internal_call_dispatch!(
409            api.kernel_get_system(),
410            on_set_substate(&mut api.system_module_api(), event)
411        )
412    }
413
414    #[trace_resources]
415    pub fn on_remove_substate(
416        api: &mut impl SystemBasedKernelInternalApi,
417        event: &RemoveSubstateEvent,
418    ) -> Result<(), RuntimeError> {
419        internal_call_dispatch!(
420            api.kernel_get_system(),
421            on_remove_substate(&mut api.system_module_api(), event)
422        )
423    }
424
425    #[trace_resources]
426    pub fn on_scan_keys(
427        api: &mut impl SystemBasedKernelInternalApi,
428        event: &ScanKeysEvent,
429    ) -> Result<(), RuntimeError> {
430        internal_call_dispatch!(
431            api.kernel_get_system(),
432            on_scan_keys(&mut api.system_module_api(), event)
433        )
434    }
435
436    #[trace_resources]
437    pub fn on_drain_substates(
438        api: &mut impl SystemBasedKernelInternalApi,
439        event: &DrainSubstatesEvent,
440    ) -> Result<(), RuntimeError> {
441        internal_call_dispatch!(
442            api.kernel_get_system(),
443            on_drain_substates(&mut api.system_module_api(), event)
444        )
445    }
446
447    #[trace_resources]
448    pub fn on_scan_sorted_substates(
449        api: &mut impl SystemBasedKernelInternalApi,
450        event: &ScanSortedSubstatesEvent,
451    ) -> Result<(), RuntimeError> {
452        internal_call_dispatch!(
453            api.kernel_get_system(),
454            on_scan_sorted_substates(&mut api.system_module_api(), event)
455        )
456    }
457
458    #[trace_resources]
459    pub fn on_get_stack_id(
460        api: &mut impl SystemBasedKernelInternalApi,
461    ) -> Result<(), RuntimeError> {
462        internal_call_dispatch!(
463            api.kernel_get_system(),
464            on_get_stack_id(&mut api.system_module_api())
465        )
466    }
467
468    #[trace_resources]
469    pub fn on_switch_stack(
470        api: &mut impl SystemBasedKernelInternalApi,
471    ) -> Result<(), RuntimeError> {
472        internal_call_dispatch!(
473            api.kernel_get_system(),
474            on_switch_stack(&mut api.system_module_api())
475        )
476    }
477
478    #[trace_resources]
479    pub fn on_send_to_stack(
480        api: &mut impl SystemBasedKernelInternalApi,
481        data_len: usize,
482    ) -> Result<(), RuntimeError> {
483        internal_call_dispatch!(
484            api.kernel_get_system(),
485            on_send_to_stack(&mut api.system_module_api(), data_len)
486        )
487    }
488
489    #[trace_resources]
490    pub fn on_set_call_frame_data(
491        api: &mut impl SystemBasedKernelInternalApi,
492        data_len: usize,
493    ) -> Result<(), RuntimeError> {
494        internal_call_dispatch!(
495            api.kernel_get_system(),
496            on_set_call_frame_data(&mut api.system_module_api(), data_len)
497        )
498    }
499
500    #[trace_resources]
501    pub fn on_get_owned_nodes(
502        api: &mut impl SystemBasedKernelInternalApi,
503    ) -> Result<(), RuntimeError> {
504        internal_call_dispatch!(
505            api.kernel_get_system(),
506            on_get_owned_nodes(&mut api.system_module_api())
507        )
508    }
509}
510
511impl SystemModuleMixer {
512    // Note that module mixer is called by both kernel and system.
513    // - Kernel uses the `SystemModule<SystemConfig<V>>` trait above;
514    // - System uses methods defined below (TODO: add a trait?)
515
516    pub fn on_call_method<Y: SystemBasedKernelApi>(
517        api: &mut SystemService<Y>,
518        receiver: &NodeId,
519        module_id: ModuleId,
520        direct_access: bool,
521        ident: &str,
522        args: &IndexedScryptoValue,
523    ) -> Result<NodeId, RuntimeError> {
524        let auth_zone = if api
525            .kernel_get_system_state()
526            .system
527            .modules
528            .enabled_modules
529            .contains(EnabledModules::AUTH)
530        {
531            AuthModule::on_call_method(api, receiver, module_id, direct_access, ident, args)?
532        } else {
533            AuthModule::on_call_fn_mock(
534                api,
535                Some((receiver, direct_access)),
536                btreeset!(),
537                btreeset!(),
538            )?
539        };
540
541        Ok(auth_zone)
542    }
543
544    pub fn on_call_method_finish<Y: SystemBasedKernelApi>(
545        api: &mut SystemService<Y>,
546        auth_zone: NodeId,
547    ) -> Result<(), RuntimeError> {
548        AuthModule::on_call_method_finish(api, auth_zone)
549    }
550
551    pub fn on_call_function<Y: SystemBasedKernelApi>(
552        api: &mut SystemService<Y>,
553        blueprint_id: &BlueprintId,
554        ident: &str,
555    ) -> Result<NodeId, RuntimeError> {
556        let auth_zone = if api
557            .kernel_get_system_state()
558            .system
559            .modules
560            .enabled_modules
561            .contains(EnabledModules::AUTH)
562        {
563            AuthModule::on_call_function(api, blueprint_id, ident)?
564        } else {
565            AuthModule::on_call_fn_mock(api, None, btreeset!(), btreeset!())?
566        };
567
568        Ok(auth_zone)
569    }
570
571    pub fn on_call_function_finish<Y: SystemBasedKernelApi>(
572        api: &mut SystemService<Y>,
573        auth_zone: NodeId,
574    ) -> Result<(), RuntimeError> {
575        AuthModule::on_call_function_finish(api, auth_zone)
576    }
577
578    pub fn add_log(&mut self, level: Level, message: String) -> Result<(), RuntimeError> {
579        if self.enabled_modules.contains(EnabledModules::LIMITS) {
580            if self.transaction_runtime.logs.len() >= self.limits.config().max_number_of_logs {
581                return Err(RuntimeError::SystemModuleError(
582                    SystemModuleError::TransactionLimitsError(TransactionLimitsError::TooManyLogs),
583                ));
584            }
585            if message.len() > self.limits.config().max_log_size {
586                return Err(RuntimeError::SystemModuleError(
587                    SystemModuleError::TransactionLimitsError(
588                        TransactionLimitsError::LogSizeTooLarge {
589                            actual: message.len(),
590                            max: self.limits.config().max_log_size,
591                        },
592                    ),
593                ));
594            }
595        }
596
597        if self
598            .enabled_modules
599            .contains(EnabledModules::TRANSACTION_RUNTIME)
600        {
601            self.transaction_runtime.add_log(level, message);
602        }
603
604        Ok(())
605    }
606
607    pub fn assert_can_add_event(&mut self) -> Result<(), RuntimeError> {
608        if self.enabled_modules.contains(EnabledModules::LIMITS) {
609            if self.transaction_runtime.events.len() >= self.limits.config().max_number_of_events {
610                return Err(RuntimeError::SystemModuleError(
611                    SystemModuleError::TransactionLimitsError(
612                        TransactionLimitsError::TooManyEvents,
613                    ),
614                ));
615            }
616        }
617
618        Ok(())
619    }
620
621    pub fn add_event_unchecked(&mut self, event: Event) -> Result<(), RuntimeError> {
622        if self.enabled_modules.contains(EnabledModules::LIMITS) {
623            if event.payload.len() > self.limits.config().max_event_size {
624                return Err(RuntimeError::SystemModuleError(
625                    SystemModuleError::TransactionLimitsError(
626                        TransactionLimitsError::EventSizeTooLarge {
627                            actual: event.payload.len(),
628                            max: self.limits.config().max_event_size,
629                        },
630                    ),
631                ));
632            }
633        }
634
635        if self
636            .enabled_modules
637            .contains(EnabledModules::TRANSACTION_RUNTIME)
638        {
639            self.transaction_runtime.add_event(event);
640        }
641
642        Ok(())
643    }
644
645    pub fn checked_add_event(&mut self, event: Event) -> Result<(), RuntimeError> {
646        self.assert_can_add_event()?;
647        self.add_event_unchecked(event)?;
648        Ok(())
649    }
650
651    pub fn set_panic_message(&mut self, message: String) -> Result<(), RuntimeError> {
652        if self.enabled_modules.contains(EnabledModules::LIMITS) {
653            if message.len() > self.limits.config().max_panic_message_size {
654                return Err(RuntimeError::SystemModuleError(
655                    SystemModuleError::TransactionLimitsError(
656                        TransactionLimitsError::PanicMessageSizeTooLarge {
657                            actual: message.len(),
658                            max: self.limits.config().max_panic_message_size,
659                        },
660                    ),
661                ));
662            }
663        }
664
665        Ok(())
666    }
667
668    pub fn add_replacement(&mut self, old: (NodeId, ModuleId), new: (NodeId, ModuleId)) {
669        if self
670            .enabled_modules
671            .contains(EnabledModules::TRANSACTION_RUNTIME)
672        {
673            self.transaction_runtime.add_replacement(old, new)
674        }
675    }
676
677    pub fn fee_reserve(&mut self) -> Option<&SystemLoanFeeReserve> {
678        if self.enabled_modules.contains(EnabledModules::COSTING) {
679            Some(&self.costing.fee_reserve)
680        } else {
681            None
682        }
683    }
684
685    pub fn costing(&self) -> Option<&CostingModule> {
686        if self.enabled_modules.contains(EnabledModules::COSTING) {
687            Some(&self.costing)
688        } else {
689            None
690        }
691    }
692
693    pub fn costing_mut(&mut self) -> Option<&mut CostingModule> {
694        if self.enabled_modules.contains(EnabledModules::COSTING) {
695            Some(&mut self.costing)
696        } else {
697            None
698        }
699    }
700
701    pub fn costing_mut_even_if_disabled(&mut self) -> &mut CostingModule {
702        &mut self.costing
703    }
704
705    pub fn limits_mut(&mut self) -> Option<&mut LimitsModule> {
706        if self.enabled_modules.contains(EnabledModules::LIMITS) {
707            Some(&mut self.limits)
708        } else {
709            None
710        }
711    }
712
713    pub fn transaction_runtime(&mut self) -> Option<&TransactionRuntimeModule> {
714        if self
715            .enabled_modules
716            .contains(EnabledModules::TRANSACTION_RUNTIME)
717        {
718            Some(&self.transaction_runtime)
719        } else {
720            None
721        }
722    }
723
724    pub fn transaction_hash(&self) -> Option<Hash> {
725        if self
726            .enabled_modules
727            .contains(EnabledModules::TRANSACTION_RUNTIME)
728        {
729            Some(self.transaction_runtime.tx_hash)
730        } else {
731            None
732        }
733    }
734
735    pub fn generate_ruid(&mut self) -> Option<[u8; 32]> {
736        if self
737            .enabled_modules
738            .contains(EnabledModules::TRANSACTION_RUNTIME)
739        {
740            Some(self.transaction_runtime.generate_ruid())
741        } else {
742            None
743        }
744    }
745
746    pub fn update_instruction_index(&mut self, new_index: usize) {
747        if self
748            .enabled_modules
749            .contains(EnabledModules::EXECUTION_TRACE)
750        {
751            self.execution_trace.update_instruction_index(new_index)
752        }
753    }
754
755    pub fn apply_execution_cost(
756        &mut self,
757        costing_entry: ExecutionCostingEntry,
758    ) -> Result<(), RuntimeError> {
759        if self.enabled_modules.contains(EnabledModules::COSTING) {
760            self.costing
761                .apply_execution_cost(costing_entry)
762                .map_err(|e| RuntimeError::SystemModuleError(SystemModuleError::CostingError(e)))
763        } else {
764            Ok(())
765        }
766    }
767
768    pub fn apply_finalization_cost(
769        &mut self,
770        costing_entry: FinalizationCostingEntry,
771    ) -> Result<(), CostingError> {
772        if self.enabled_modules.contains(EnabledModules::COSTING) {
773            self.costing.apply_finalization_cost(costing_entry)
774        } else {
775            Ok(())
776        }
777    }
778
779    pub fn apply_storage_cost(
780        &mut self,
781        storage_type: StorageType,
782        size_increase: usize,
783    ) -> Result<(), CostingError> {
784        if self.enabled_modules.contains(EnabledModules::COSTING) {
785            self.costing.apply_storage_cost(storage_type, size_increase)
786        } else {
787            Ok(())
788        }
789    }
790
791    pub fn lock_fee(
792        &mut self,
793        vault_id: NodeId,
794        locked_fee: LiquidFungibleResource,
795        contingent: bool,
796    ) {
797        if self.enabled_modules.contains(EnabledModules::COSTING) {
798            self.costing.lock_fee(vault_id, locked_fee, contingent);
799        } else {
800            panic!("Fungible Vault Application layer should prevent call to credit if costing not enabled");
801        }
802    }
803
804    pub fn events(&self) -> &Vec<Event> {
805        &self.transaction_runtime.events
806    }
807
808    pub fn logs(&self) -> &Vec<(Level, String)> {
809        &self.transaction_runtime.logs
810    }
811}