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    #[inline]
158    pub fn is_auth_enabled(&self) -> bool {
159        self.enabled_modules.contains(EnabledModules::AUTH)
160    }
161
162    pub fn unpack_costing(self) -> CostingModule {
163        self.costing
164    }
165
166    pub fn unpack(
167        self,
168    ) -> (
169        CostingModule,
170        TransactionRuntimeModule,
171        ExecutionTraceModule,
172    ) {
173        (self.costing, self.transaction_runtime, self.execution_trace)
174    }
175}
176
177//====================================================================
178// NOTE: Modules are applied in the reverse order of initialization!
179// This has an impact if there is module dependency.
180//====================================================================
181
182impl InitSystemModule for SystemModuleMixer {
183    #[trace_resources]
184    fn init(&mut self) -> Result<(), BootloadingError> {
185        let modules: EnabledModules = self.enabled_modules;
186
187        // Enable execution trace
188        if modules.contains(EnabledModules::EXECUTION_TRACE) {
189            self.execution_trace.init()?;
190        }
191
192        // Enable transaction runtime
193        if modules.contains(EnabledModules::TRANSACTION_RUNTIME) {
194            self.transaction_runtime.init()?;
195        }
196
197        // Enable auth
198        if modules.contains(EnabledModules::AUTH) {
199            self.auth.init()?;
200        }
201
202        // Enable costing
203        if modules.contains(EnabledModules::COSTING) {
204            self.costing.init()?;
205        }
206
207        // Enable transaction limits
208        if modules.contains(EnabledModules::LIMITS) {
209            self.limits.init()?;
210        }
211
212        // Enable kernel trace
213        if modules.contains(EnabledModules::KERNEL_TRACE) {
214            self.kernel_trace.init()?;
215        }
216
217        Ok(())
218    }
219
220    #[trace_resources]
221    fn on_teardown(&mut self) -> Result<(), RuntimeError> {
222        let modules: EnabledModules = self.enabled_modules;
223        if modules.contains(EnabledModules::KERNEL_TRACE) {
224            self.kernel_trace.on_teardown()?;
225        }
226        if modules.contains(EnabledModules::LIMITS) {
227            self.limits.on_teardown()?;
228        }
229        if modules.contains(EnabledModules::COSTING) {
230            self.costing.on_teardown()?;
231        }
232        if modules.contains(EnabledModules::AUTH) {
233            self.auth.on_teardown()?;
234        }
235        if modules.contains(EnabledModules::TRANSACTION_RUNTIME) {
236            self.transaction_runtime.on_teardown()?;
237        }
238        if modules.contains(EnabledModules::EXECUTION_TRACE) {
239            self.execution_trace.on_teardown()?;
240        }
241
242        Ok(())
243    }
244}
245
246impl SystemModuleMixer {
247    #[trace_resources(log=invocation.len())]
248    pub fn before_invoke(
249        api: &mut impl SystemBasedKernelApi,
250        invocation: &KernelInvocation<Actor>,
251    ) -> Result<(), RuntimeError> {
252        internal_call_dispatch!(
253            api.kernel_get_system(),
254            before_invoke(&mut api.system_module_api(), invocation),
255            privileged_before_invoke(api, invocation)
256        )
257    }
258
259    #[trace_resources]
260    pub fn on_execution_start(
261        api: &mut impl SystemBasedKernelInternalApi,
262    ) -> Result<(), RuntimeError> {
263        internal_call_dispatch!(
264            api.kernel_get_system(),
265            on_execution_start(&mut api.system_module_api())
266        )
267    }
268
269    #[trace_resources]
270    pub fn on_execution_finish(
271        api: &mut impl SystemBasedKernelInternalApi,
272        message: &CallFrameMessage,
273    ) -> Result<(), RuntimeError> {
274        internal_call_dispatch!(
275            api.kernel_get_system(),
276            on_execution_finish(&mut api.system_module_api(), message)
277        )
278    }
279
280    #[trace_resources]
281    pub fn after_invoke(
282        api: &mut impl SystemBasedKernelInternalApi,
283        output: &IndexedScryptoValue,
284    ) -> Result<(), RuntimeError> {
285        internal_call_dispatch!(
286            api.kernel_get_system(),
287            after_invoke(&mut api.system_module_api(), output)
288        )
289    }
290
291    #[trace_resources]
292    pub fn on_pin_node(
293        api: &mut impl SystemBasedKernelInternalApi,
294        node_id: &NodeId,
295    ) -> Result<(), RuntimeError> {
296        internal_call_dispatch!(
297            api.kernel_get_system(),
298            on_pin_node(&mut api.system_module_api(), node_id)
299        )
300    }
301
302    #[trace_resources(log=entity_type)]
303    pub fn on_allocate_node_id(
304        api: &mut impl SystemBasedKernelInternalApi,
305        entity_type: EntityType,
306    ) -> Result<(), RuntimeError> {
307        internal_call_dispatch!(
308            api.kernel_get_system(),
309            on_allocate_node_id(&mut api.system_module_api(), entity_type)
310        )
311    }
312
313    #[trace_resources]
314    pub fn on_create_node(
315        api: &mut impl SystemBasedKernelInternalApi,
316        event: &CreateNodeEvent,
317    ) -> Result<(), RuntimeError> {
318        internal_call_dispatch!(
319            api.kernel_get_system(),
320            on_create_node(&mut api.system_module_api(), event)
321        )
322    }
323
324    #[trace_resources]
325    pub fn on_move_module(
326        api: &mut impl SystemBasedKernelInternalApi,
327        event: &MoveModuleEvent,
328    ) -> Result<(), RuntimeError> {
329        internal_call_dispatch!(
330            api.kernel_get_system(),
331            on_move_module(&mut api.system_module_api(), event)
332        )
333    }
334
335    #[trace_resources]
336    pub fn on_drop_node(
337        api: &mut impl SystemBasedKernelInternalApi,
338        event: &DropNodeEvent,
339    ) -> Result<(), RuntimeError> {
340        internal_call_dispatch!(
341            api.kernel_get_system(),
342            on_drop_node(&mut api.system_module_api(), event)
343        )
344    }
345
346    #[trace_resources]
347    pub fn on_mark_substate_as_transient(
348        api: &mut impl SystemBasedKernelInternalApi,
349        node_id: &NodeId,
350        partition_number: &PartitionNumber,
351        substate_key: &SubstateKey,
352    ) -> Result<(), RuntimeError> {
353        internal_call_dispatch!(
354            api.kernel_get_system(),
355            on_mark_substate_as_transient(
356                &mut api.system_module_api(),
357                node_id,
358                partition_number,
359                substate_key
360            )
361        )
362    }
363
364    #[trace_resources]
365    pub fn on_open_substate(
366        api: &mut impl SystemBasedKernelInternalApi,
367        event: &OpenSubstateEvent,
368    ) -> Result<(), RuntimeError> {
369        internal_call_dispatch!(
370            api.kernel_get_system(),
371            on_open_substate(&mut api.system_module_api(), event)
372        )
373    }
374
375    #[trace_resources(log=event.is_about_heap())]
376    pub fn on_read_substate(
377        api: &mut impl SystemBasedKernelInternalApi,
378        event: &ReadSubstateEvent,
379    ) -> Result<(), RuntimeError> {
380        internal_call_dispatch!(
381            api.kernel_get_system(),
382            on_read_substate(&mut api.system_module_api(), event)
383        )
384    }
385
386    #[trace_resources]
387    pub fn on_write_substate(
388        api: &mut impl SystemBasedKernelInternalApi,
389        event: &WriteSubstateEvent,
390    ) -> Result<(), RuntimeError> {
391        internal_call_dispatch!(
392            api.kernel_get_system(),
393            on_write_substate(&mut api.system_module_api(), event)
394        )
395    }
396
397    #[trace_resources]
398    pub fn on_close_substate(
399        api: &mut impl SystemBasedKernelInternalApi,
400        event: &CloseSubstateEvent,
401    ) -> Result<(), RuntimeError> {
402        internal_call_dispatch!(
403            api.kernel_get_system(),
404            on_close_substate(&mut api.system_module_api(), event)
405        )
406    }
407
408    #[trace_resources]
409    pub fn on_set_substate(
410        api: &mut impl SystemBasedKernelInternalApi,
411        event: &SetSubstateEvent,
412    ) -> Result<(), RuntimeError> {
413        internal_call_dispatch!(
414            api.kernel_get_system(),
415            on_set_substate(&mut api.system_module_api(), event)
416        )
417    }
418
419    #[trace_resources]
420    pub fn on_remove_substate(
421        api: &mut impl SystemBasedKernelInternalApi,
422        event: &RemoveSubstateEvent,
423    ) -> Result<(), RuntimeError> {
424        internal_call_dispatch!(
425            api.kernel_get_system(),
426            on_remove_substate(&mut api.system_module_api(), event)
427        )
428    }
429
430    #[trace_resources]
431    pub fn on_scan_keys(
432        api: &mut impl SystemBasedKernelInternalApi,
433        event: &ScanKeysEvent,
434    ) -> Result<(), RuntimeError> {
435        internal_call_dispatch!(
436            api.kernel_get_system(),
437            on_scan_keys(&mut api.system_module_api(), event)
438        )
439    }
440
441    #[trace_resources]
442    pub fn on_drain_substates(
443        api: &mut impl SystemBasedKernelInternalApi,
444        event: &DrainSubstatesEvent,
445    ) -> Result<(), RuntimeError> {
446        internal_call_dispatch!(
447            api.kernel_get_system(),
448            on_drain_substates(&mut api.system_module_api(), event)
449        )
450    }
451
452    #[trace_resources]
453    pub fn on_scan_sorted_substates(
454        api: &mut impl SystemBasedKernelInternalApi,
455        event: &ScanSortedSubstatesEvent,
456    ) -> Result<(), RuntimeError> {
457        internal_call_dispatch!(
458            api.kernel_get_system(),
459            on_scan_sorted_substates(&mut api.system_module_api(), event)
460        )
461    }
462
463    #[trace_resources]
464    pub fn on_get_stack_id(
465        api: &mut impl SystemBasedKernelInternalApi,
466    ) -> Result<(), RuntimeError> {
467        internal_call_dispatch!(
468            api.kernel_get_system(),
469            on_get_stack_id(&mut api.system_module_api())
470        )
471    }
472
473    #[trace_resources]
474    pub fn on_switch_stack(
475        api: &mut impl SystemBasedKernelInternalApi,
476    ) -> Result<(), RuntimeError> {
477        internal_call_dispatch!(
478            api.kernel_get_system(),
479            on_switch_stack(&mut api.system_module_api())
480        )
481    }
482
483    #[trace_resources]
484    pub fn on_send_to_stack(
485        api: &mut impl SystemBasedKernelInternalApi,
486        data_len: usize,
487    ) -> Result<(), RuntimeError> {
488        internal_call_dispatch!(
489            api.kernel_get_system(),
490            on_send_to_stack(&mut api.system_module_api(), data_len)
491        )
492    }
493
494    #[trace_resources]
495    pub fn on_set_call_frame_data(
496        api: &mut impl SystemBasedKernelInternalApi,
497        data_len: usize,
498    ) -> Result<(), RuntimeError> {
499        internal_call_dispatch!(
500            api.kernel_get_system(),
501            on_set_call_frame_data(&mut api.system_module_api(), data_len)
502        )
503    }
504
505    #[trace_resources]
506    pub fn on_get_owned_nodes(
507        api: &mut impl SystemBasedKernelInternalApi,
508    ) -> Result<(), RuntimeError> {
509        internal_call_dispatch!(
510            api.kernel_get_system(),
511            on_get_owned_nodes(&mut api.system_module_api())
512        )
513    }
514}
515
516impl SystemModuleMixer {
517    // Note that module mixer is called by both kernel and system.
518    // - Kernel uses the `SystemModule<SystemConfig<V>>` trait above;
519    // - System uses methods defined below (TODO: add a trait?)
520
521    pub fn on_call_method<Y: SystemBasedKernelApi>(
522        api: &mut SystemService<Y>,
523        receiver: &NodeId,
524        module_id: ModuleId,
525        direct_access: bool,
526        ident: &str,
527        args: &IndexedScryptoValue,
528    ) -> Result<NodeId, RuntimeError> {
529        let auth_zone = if api
530            .kernel_get_system_state()
531            .system
532            .modules
533            .enabled_modules
534            .contains(EnabledModules::AUTH)
535        {
536            AuthModule::on_call_method(api, receiver, module_id, direct_access, ident, args)?
537        } else {
538            AuthModule::on_call_fn_mock(
539                api,
540                Some((receiver, direct_access)),
541                btreeset!(),
542                btreeset!(),
543            )?
544        };
545
546        Ok(auth_zone)
547    }
548
549    pub fn on_call_method_finish<Y: SystemBasedKernelApi>(
550        api: &mut SystemService<Y>,
551        auth_zone: NodeId,
552    ) -> Result<(), RuntimeError> {
553        AuthModule::on_call_method_finish(api, auth_zone)
554    }
555
556    pub fn on_call_function<Y: SystemBasedKernelApi>(
557        api: &mut SystemService<Y>,
558        blueprint_id: &BlueprintId,
559        ident: &str,
560    ) -> Result<NodeId, RuntimeError> {
561        let auth_zone = if api
562            .kernel_get_system_state()
563            .system
564            .modules
565            .enabled_modules
566            .contains(EnabledModules::AUTH)
567        {
568            AuthModule::on_call_function(api, blueprint_id, ident)?
569        } else {
570            AuthModule::on_call_fn_mock(api, None, btreeset!(), btreeset!())?
571        };
572
573        Ok(auth_zone)
574    }
575
576    pub fn on_call_function_finish<Y: SystemBasedKernelApi>(
577        api: &mut SystemService<Y>,
578        auth_zone: NodeId,
579    ) -> Result<(), RuntimeError> {
580        AuthModule::on_call_function_finish(api, auth_zone)
581    }
582
583    pub fn add_log(&mut self, level: Level, message: String) -> Result<(), RuntimeError> {
584        if self.enabled_modules.contains(EnabledModules::LIMITS) {
585            if self.transaction_runtime.logs.len() >= self.limits.config().max_number_of_logs {
586                return Err(RuntimeError::SystemModuleError(
587                    SystemModuleError::TransactionLimitsError(TransactionLimitsError::TooManyLogs),
588                ));
589            }
590            if message.len() > self.limits.config().max_log_size {
591                return Err(RuntimeError::SystemModuleError(
592                    SystemModuleError::TransactionLimitsError(
593                        TransactionLimitsError::LogSizeTooLarge {
594                            actual: message.len(),
595                            max: self.limits.config().max_log_size,
596                        },
597                    ),
598                ));
599            }
600        }
601
602        if self
603            .enabled_modules
604            .contains(EnabledModules::TRANSACTION_RUNTIME)
605        {
606            self.transaction_runtime.add_log(level, message);
607        }
608
609        Ok(())
610    }
611
612    pub fn assert_can_add_event(&mut self) -> Result<(), RuntimeError> {
613        if self.enabled_modules.contains(EnabledModules::LIMITS)
614            && self.transaction_runtime.events.len() >= self.limits.config().max_number_of_events
615        {
616            return Err(RuntimeError::SystemModuleError(
617                SystemModuleError::TransactionLimitsError(TransactionLimitsError::TooManyEvents),
618            ));
619        }
620
621        Ok(())
622    }
623
624    pub fn add_event_unchecked(&mut self, event: Event) -> Result<(), RuntimeError> {
625        if self.enabled_modules.contains(EnabledModules::LIMITS)
626            && event.payload.len() > self.limits.config().max_event_size
627        {
628            return Err(RuntimeError::SystemModuleError(
629                SystemModuleError::TransactionLimitsError(
630                    TransactionLimitsError::EventSizeTooLarge {
631                        actual: event.payload.len(),
632                        max: self.limits.config().max_event_size,
633                    },
634                ),
635            ));
636        }
637
638        if self
639            .enabled_modules
640            .contains(EnabledModules::TRANSACTION_RUNTIME)
641        {
642            self.transaction_runtime.add_event(event);
643        }
644
645        Ok(())
646    }
647
648    pub fn checked_add_event(&mut self, event: Event) -> Result<(), RuntimeError> {
649        self.assert_can_add_event()?;
650        self.add_event_unchecked(event)?;
651        Ok(())
652    }
653
654    pub fn set_panic_message(&mut self, message: String) -> Result<(), RuntimeError> {
655        if self.enabled_modules.contains(EnabledModules::LIMITS)
656            && message.len() > self.limits.config().max_panic_message_size
657        {
658            return Err(RuntimeError::SystemModuleError(
659                SystemModuleError::TransactionLimitsError(
660                    TransactionLimitsError::PanicMessageSizeTooLarge {
661                        actual: message.len(),
662                        max: self.limits.config().max_panic_message_size,
663                    },
664                ),
665            ));
666        }
667
668        Ok(())
669    }
670
671    pub fn add_replacement(&mut self, old: (NodeId, ModuleId), new: (NodeId, ModuleId)) {
672        if self
673            .enabled_modules
674            .contains(EnabledModules::TRANSACTION_RUNTIME)
675        {
676            self.transaction_runtime.add_replacement(old, new)
677        }
678    }
679
680    pub fn fee_reserve(&mut self) -> Option<&SystemLoanFeeReserve> {
681        if self.enabled_modules.contains(EnabledModules::COSTING) {
682            Some(&self.costing.fee_reserve)
683        } else {
684            None
685        }
686    }
687
688    pub fn costing(&self) -> Option<&CostingModule> {
689        if self.enabled_modules.contains(EnabledModules::COSTING) {
690            Some(&self.costing)
691        } else {
692            None
693        }
694    }
695
696    pub fn costing_mut(&mut self) -> Option<&mut CostingModule> {
697        if self.enabled_modules.contains(EnabledModules::COSTING) {
698            Some(&mut self.costing)
699        } else {
700            None
701        }
702    }
703
704    pub fn costing_mut_even_if_disabled(&mut self) -> &mut CostingModule {
705        &mut self.costing
706    }
707
708    pub fn limits_mut(&mut self) -> Option<&mut LimitsModule> {
709        if self.enabled_modules.contains(EnabledModules::LIMITS) {
710            Some(&mut self.limits)
711        } else {
712            None
713        }
714    }
715
716    pub fn transaction_runtime(&mut self) -> Option<&TransactionRuntimeModule> {
717        if self
718            .enabled_modules
719            .contains(EnabledModules::TRANSACTION_RUNTIME)
720        {
721            Some(&self.transaction_runtime)
722        } else {
723            None
724        }
725    }
726
727    pub fn transaction_hash(&self) -> Option<Hash> {
728        if self
729            .enabled_modules
730            .contains(EnabledModules::TRANSACTION_RUNTIME)
731        {
732            Some(self.transaction_runtime.tx_hash)
733        } else {
734            None
735        }
736    }
737
738    pub fn generate_ruid(&mut self) -> Option<[u8; 32]> {
739        if self
740            .enabled_modules
741            .contains(EnabledModules::TRANSACTION_RUNTIME)
742        {
743            Some(self.transaction_runtime.generate_ruid())
744        } else {
745            None
746        }
747    }
748
749    pub fn update_instruction_index(&mut self, new_index: usize) {
750        if self
751            .enabled_modules
752            .contains(EnabledModules::EXECUTION_TRACE)
753        {
754            self.execution_trace.update_instruction_index(new_index)
755        }
756    }
757
758    pub fn apply_execution_cost(
759        &mut self,
760        costing_entry: ExecutionCostingEntry,
761    ) -> Result<(), RuntimeError> {
762        if self.enabled_modules.contains(EnabledModules::COSTING) {
763            self.costing
764                .apply_execution_cost(costing_entry)
765                .map_err(|e| RuntimeError::SystemModuleError(SystemModuleError::CostingError(e)))
766        } else {
767            Ok(())
768        }
769    }
770
771    pub fn apply_finalization_cost(
772        &mut self,
773        costing_entry: FinalizationCostingEntry,
774    ) -> Result<(), CostingError> {
775        if self.enabled_modules.contains(EnabledModules::COSTING) {
776            self.costing.apply_finalization_cost(costing_entry)
777        } else {
778            Ok(())
779        }
780    }
781
782    pub fn apply_storage_cost(
783        &mut self,
784        storage_type: StorageType,
785        size_increase: usize,
786    ) -> Result<(), CostingError> {
787        if self.enabled_modules.contains(EnabledModules::COSTING) {
788            self.costing.apply_storage_cost(storage_type, size_increase)
789        } else {
790            Ok(())
791        }
792    }
793
794    pub fn lock_fee(
795        &mut self,
796        vault_id: NodeId,
797        locked_fee: LiquidFungibleResource,
798        contingent: bool,
799    ) {
800        if self.enabled_modules.contains(EnabledModules::COSTING) {
801            self.costing.lock_fee(vault_id, locked_fee, contingent);
802        } else {
803            panic!("Fungible Vault Application layer should prevent call to credit if costing not enabled");
804        }
805    }
806
807    pub fn events(&self) -> &Vec<Event> {
808        &self.transaction_runtime.events
809    }
810
811    pub fn logs(&self) -> &Vec<(Level, String)> {
812        &self.transaction_runtime.logs
813    }
814}