scrypto_test/ledger_simulator/
inject_costing_err.rs

1use radix_engine::init::InitializationParameters;
2
3use crate::prelude::*;
4
5#[derive(Clone)]
6pub struct InjectCostingErrorInit<I> {
7    pub system_input: I,
8    pub error_after_count: u64,
9}
10
11impl<I: InitializationParameters<For: KernelTransactionExecutor>> InitializationParameters
12    for InjectCostingErrorInit<I>
13{
14    type For = InjectCostingError<I::For>;
15}
16
17pub struct InjectCostingError<Y: KernelTransactionExecutor> {
18    fail_after: Rc<RefCell<u64>>,
19    wrapped: Y,
20}
21
22impl<Y: KernelTransactionExecutor> InjectCostingError<Y> {
23    fn maybe_err(&mut self) -> Result<(), RuntimeError> {
24        if *self.fail_after.borrow() == 0 {
25            return Ok(());
26        }
27
28        *self.fail_after.borrow_mut() -= 1;
29
30        if *self.fail_after.borrow() == 0 {
31            return Err(RuntimeError::SystemModuleError(
32                SystemModuleError::CostingError(CostingError::FeeReserveError(
33                    FeeReserveError::InsufficientBalance {
34                        required: Decimal::MAX,
35                        remaining: Decimal::ONE,
36                    },
37                )),
38            ));
39        }
40
41        Ok(())
42    }
43}
44
45macro_rules! wrapped_api {
46    ($api:ident) => {
47        WrappedKernelApi { api: $api }
48    };
49}
50
51macro_rules! wrapped_internal_api {
52    ($api:ident) => {
53        WrappedKernelInternalApi { api: $api }
54    };
55}
56
57impl<
58        E: KernelTransactionExecutor<
59                Executable = ExecutableTransaction,
60                ExecutionOutput = Vec<InstructionOutput>,
61                Receipt = TransactionReceipt,
62            > + HasModules,
63    > KernelTransactionExecutor for InjectCostingError<E>
64{
65    type Init = InjectCostingErrorInit<E::Init>;
66    type Executable = ExecutableTransaction;
67    type ExecutionOutput = Vec<InstructionOutput>;
68    type Receipt = TransactionReceipt;
69
70    fn init(
71        store: &mut impl CommitableSubstateStore,
72        executable: &ExecutableTransaction,
73        init_input: Self::Init,
74        always_visible_global_nodes: &'static IndexSet<NodeId>,
75    ) -> Result<(Self, Vec<CallFrameInit<Self::CallFrameData>>), Self::Receipt> {
76        let (mut system, call_frame_inits) = E::init(
77            store,
78            executable,
79            init_input.system_input,
80            always_visible_global_nodes,
81        )?;
82
83        let fail_after = Rc::new(RefCell::new(init_input.error_after_count));
84        system.modules_mut().costing_mut().unwrap().on_apply_cost = OnApplyCost::ForceFailOnCount {
85            fail_after: fail_after.clone(),
86        };
87
88        Ok((
89            Self {
90                fail_after,
91                wrapped: system,
92            },
93            call_frame_inits,
94        ))
95    }
96
97    fn execute<Y: KernelApi<CallbackObject = Self>>(
98        api: &mut Y,
99        executable: &ExecutableTransaction,
100    ) -> Result<Vec<InstructionOutput>, RuntimeError> {
101        let mut api = wrapped_api!(api);
102        E::execute(&mut api, executable)
103    }
104
105    fn finalize(
106        &mut self,
107        executable: &ExecutableTransaction,
108        store_commit_info: StoreCommitInfo,
109    ) -> Result<(), RuntimeError> {
110        self.maybe_err()?;
111        self.wrapped.finalize(executable, store_commit_info)
112    }
113
114    fn create_receipt<S: SubstateDatabase>(
115        self,
116        track: Track<S>,
117        result: Result<Vec<InstructionOutput>, TransactionExecutionError>,
118    ) -> TransactionReceipt {
119        self.wrapped.create_receipt(track, result)
120    }
121}
122
123impl<E: KernelTransactionExecutor> KernelCallbackObject for InjectCostingError<E> {
124    type LockData = E::LockData;
125    type CallFrameData = E::CallFrameData;
126
127    fn on_pin_node<Y: KernelInternalApi<System = Self>>(
128        node_id: &NodeId,
129        api: &mut Y,
130    ) -> Result<(), RuntimeError> {
131        api.kernel_get_system_state().system.maybe_err()?;
132        let mut api = wrapped_internal_api!(api);
133        E::on_pin_node(node_id, &mut api)
134    }
135
136    fn on_create_node<Y: KernelInternalApi<System = Self>>(
137        event: CreateNodeEvent,
138        api: &mut Y,
139    ) -> Result<(), RuntimeError> {
140        api.kernel_get_system_state().system.maybe_err()?;
141        let mut api = wrapped_internal_api!(api);
142        E::on_create_node(event, &mut api)
143    }
144
145    fn on_drop_node<Y: KernelInternalApi<System = Self>>(
146        event: DropNodeEvent,
147        api: &mut Y,
148    ) -> Result<(), RuntimeError> {
149        api.kernel_get_system_state().system.maybe_err()?;
150        let mut api = wrapped_internal_api!(api);
151        E::on_drop_node(event, &mut api)
152    }
153
154    fn on_move_module<Y: KernelInternalApi<System = Self>>(
155        event: MoveModuleEvent,
156        api: &mut Y,
157    ) -> Result<(), RuntimeError> {
158        api.kernel_get_system_state().system.maybe_err()?;
159        let mut api = wrapped_internal_api!(api);
160        E::on_move_module(event, &mut api)
161    }
162
163    fn on_open_substate<Y: KernelInternalApi<System = Self>>(
164        event: OpenSubstateEvent,
165        api: &mut Y,
166    ) -> Result<(), RuntimeError> {
167        api.kernel_get_system_state().system.maybe_err()?;
168        let mut api = wrapped_internal_api!(api);
169        E::on_open_substate(event, &mut api)
170    }
171
172    fn on_close_substate<Y: KernelInternalApi<System = Self>>(
173        event: CloseSubstateEvent,
174        api: &mut Y,
175    ) -> Result<(), RuntimeError> {
176        api.kernel_get_system_state().system.maybe_err()?;
177        let mut api = wrapped_internal_api!(api);
178        E::on_close_substate(event, &mut api)
179    }
180
181    fn on_read_substate<Y: KernelInternalApi<System = Self>>(
182        event: ReadSubstateEvent,
183        api: &mut Y,
184    ) -> Result<(), RuntimeError> {
185        api.kernel_get_system_state().system.maybe_err()?;
186        let mut api = wrapped_internal_api!(api);
187        E::on_read_substate(event, &mut api)
188    }
189
190    fn on_write_substate<Y: KernelInternalApi<System = Self>>(
191        event: WriteSubstateEvent,
192        api: &mut Y,
193    ) -> Result<(), RuntimeError> {
194        api.kernel_get_system_state().system.maybe_err()?;
195        let mut api = wrapped_internal_api!(api);
196        E::on_write_substate(event, &mut api)
197    }
198
199    fn on_set_substate<Y: KernelInternalApi<System = Self>>(
200        event: SetSubstateEvent,
201        api: &mut Y,
202    ) -> Result<(), RuntimeError> {
203        api.kernel_get_system_state().system.maybe_err()?;
204        let mut api = wrapped_internal_api!(api);
205        E::on_set_substate(event, &mut api)
206    }
207
208    fn on_remove_substate<Y: KernelInternalApi<System = Self>>(
209        event: RemoveSubstateEvent,
210        api: &mut Y,
211    ) -> Result<(), RuntimeError> {
212        api.kernel_get_system_state().system.maybe_err()?;
213        let mut api = wrapped_internal_api!(api);
214        E::on_remove_substate(event, &mut api)
215    }
216
217    fn on_scan_keys<Y: KernelInternalApi<System = Self>>(
218        event: ScanKeysEvent,
219        api: &mut Y,
220    ) -> Result<(), RuntimeError> {
221        api.kernel_get_system_state().system.maybe_err()?;
222        let mut api = wrapped_internal_api!(api);
223        E::on_scan_keys(event, &mut api)
224    }
225
226    fn on_drain_substates<Y: KernelInternalApi<System = Self>>(
227        event: DrainSubstatesEvent,
228        api: &mut Y,
229    ) -> Result<(), RuntimeError> {
230        api.kernel_get_system_state().system.maybe_err()?;
231        let mut api = wrapped_internal_api!(api);
232        E::on_drain_substates(event, &mut api)
233    }
234
235    fn on_scan_sorted_substates<Y: KernelInternalApi<System = Self>>(
236        event: ScanSortedSubstatesEvent,
237        api: &mut Y,
238    ) -> Result<(), RuntimeError> {
239        api.kernel_get_system_state().system.maybe_err()?;
240        let mut api = wrapped_internal_api!(api);
241        E::on_scan_sorted_substates(event, &mut api)
242    }
243
244    fn before_invoke<Y: KernelApi<CallbackObject = Self>>(
245        invocation: &KernelInvocation<Self::CallFrameData>,
246        api: &mut Y,
247    ) -> Result<(), RuntimeError> {
248        api.kernel_get_system_state().system.maybe_err()?;
249        let mut api = wrapped_api!(api);
250        E::before_invoke(invocation, &mut api)
251    }
252
253    fn on_execution_start<Y: KernelInternalApi<System = Self>>(
254        api: &mut Y,
255    ) -> Result<(), RuntimeError> {
256        api.kernel_get_system_state().system.maybe_err()?;
257        let mut api = wrapped_internal_api!(api);
258        E::on_execution_start(&mut api)
259    }
260
261    fn invoke_upstream<Y: KernelApi<CallbackObject = Self>>(
262        args: &IndexedScryptoValue,
263        api: &mut Y,
264    ) -> Result<IndexedScryptoValue, RuntimeError> {
265        api.kernel_get_system_state().system.maybe_err()?;
266        let mut api = wrapped_api!(api);
267        E::invoke_upstream(args, &mut api)
268    }
269
270    fn auto_drop<Y: KernelApi<CallbackObject = Self>>(
271        nodes: Vec<NodeId>,
272        api: &mut Y,
273    ) -> Result<(), RuntimeError> {
274        api.kernel_get_system_state().system.maybe_err()?;
275        let mut api = wrapped_api!(api);
276        E::auto_drop(nodes, &mut api)
277    }
278
279    fn on_execution_finish<Y: KernelInternalApi<System = Self>>(
280        message: &CallFrameMessage,
281        api: &mut Y,
282    ) -> Result<(), RuntimeError> {
283        api.kernel_get_system_state().system.maybe_err()?;
284        let mut api = wrapped_internal_api!(api);
285        E::on_execution_finish(message, &mut api)
286    }
287
288    fn after_invoke<Y: KernelApi<CallbackObject = Self>>(
289        output: &IndexedScryptoValue,
290        api: &mut Y,
291    ) -> Result<(), RuntimeError> {
292        api.kernel_get_system_state().system.maybe_err()?;
293        let mut api = wrapped_api!(api);
294        E::after_invoke(output, &mut api)
295    }
296
297    fn on_allocate_node_id<Y: KernelInternalApi<System = Self>>(
298        entity_type: EntityType,
299        api: &mut Y,
300    ) -> Result<(), RuntimeError> {
301        api.kernel_get_system_state().system.maybe_err()?;
302        let mut api = wrapped_internal_api!(api);
303        E::on_allocate_node_id(entity_type, &mut api)
304    }
305
306    fn on_mark_substate_as_transient<Y: KernelInternalApi<System = Self>>(
307        node_id: &NodeId,
308        partition_number: &PartitionNumber,
309        substate_key: &SubstateKey,
310        api: &mut Y,
311    ) -> Result<(), RuntimeError> {
312        api.kernel_get_system_state().system.maybe_err()?;
313        let mut api = wrapped_internal_api!(api);
314        E::on_mark_substate_as_transient(node_id, partition_number, substate_key, &mut api)
315    }
316
317    fn on_substate_lock_fault<Y: KernelApi<CallbackObject = Self>>(
318        node_id: NodeId,
319        partition_num: PartitionNumber,
320        offset: &SubstateKey,
321        api: &mut Y,
322    ) -> Result<bool, RuntimeError> {
323        api.kernel_get_system_state().system.maybe_err()?;
324        let mut api = wrapped_api!(api);
325        E::on_substate_lock_fault(node_id, partition_num, offset, &mut api)
326    }
327
328    fn on_drop_node_mut<Y: KernelApi<CallbackObject = Self>>(
329        node_id: &NodeId,
330        api: &mut Y,
331    ) -> Result<(), RuntimeError> {
332        api.kernel_get_system_state().system.maybe_err()?;
333        let mut api = wrapped_api!(api);
334        E::on_drop_node_mut(node_id, &mut api)
335    }
336
337    fn on_get_stack_id<Y: KernelInternalApi<System = Self>>(
338        api: &mut Y,
339    ) -> Result<(), RuntimeError> {
340        api.kernel_get_system_state().system.maybe_err()?;
341        let mut api = wrapped_internal_api!(api);
342        E::on_get_stack_id(&mut api)
343    }
344
345    fn on_switch_stack<Y: KernelInternalApi<System = Self>>(
346        api: &mut Y,
347    ) -> Result<(), RuntimeError> {
348        api.kernel_get_system_state().system.maybe_err()?;
349        let mut api = wrapped_internal_api!(api);
350        E::on_switch_stack(&mut api)
351    }
352
353    fn on_send_to_stack<Y: KernelInternalApi<System = Self>>(
354        value: &IndexedScryptoValue,
355        api: &mut Y,
356    ) -> Result<(), RuntimeError> {
357        api.kernel_get_system_state().system.maybe_err()?;
358        let mut api = wrapped_internal_api!(api);
359        E::on_send_to_stack(value, &mut api)
360    }
361
362    fn on_set_call_frame_data<Y: KernelInternalApi<System = Self>>(
363        data: &Self::CallFrameData,
364        api: &mut Y,
365    ) -> Result<(), RuntimeError> {
366        api.kernel_get_system_state().system.maybe_err()?;
367        let mut api = wrapped_internal_api!(api);
368        E::on_set_call_frame_data(data, &mut api)
369    }
370
371    fn on_get_owned_nodes<Y: KernelInternalApi<System = Self>>(
372        api: &mut Y,
373    ) -> Result<(), RuntimeError> {
374        api.kernel_get_system_state().system.maybe_err()?;
375        let mut api = wrapped_internal_api!(api);
376        E::on_get_owned_nodes(&mut api)
377    }
378}
379
380pub struct WrappedKernelApi<
381    'a,
382    E: KernelTransactionExecutor + 'a,
383    K: KernelApi<CallbackObject = InjectCostingError<E>>,
384> {
385    api: &'a mut K,
386}
387
388impl<
389        'a,
390        E: KernelTransactionExecutor + 'a,
391        K: KernelApi<CallbackObject = InjectCostingError<E>>,
392    > KernelNodeApi for WrappedKernelApi<'a, E, K>
393{
394    fn kernel_pin_node(&mut self, node_id: NodeId) -> Result<(), RuntimeError> {
395        self.api.kernel_pin_node(node_id)
396    }
397
398    fn kernel_allocate_node_id(&mut self, entity_type: EntityType) -> Result<NodeId, RuntimeError> {
399        self.api.kernel_allocate_node_id(entity_type)
400    }
401
402    fn kernel_create_node(
403        &mut self,
404        node_id: NodeId,
405        node_substates: NodeSubstates,
406    ) -> Result<(), RuntimeError> {
407        self.api.kernel_create_node(node_id, node_substates)
408    }
409
410    fn kernel_create_node_from(
411        &mut self,
412        node_id: NodeId,
413        partitions: BTreeMap<PartitionNumber, (NodeId, PartitionNumber)>,
414    ) -> Result<(), RuntimeError> {
415        self.api.kernel_create_node_from(node_id, partitions)
416    }
417
418    fn kernel_drop_node(&mut self, node_id: &NodeId) -> Result<DroppedNode, RuntimeError> {
419        self.api.kernel_drop_node(node_id)
420    }
421}
422
423impl<
424        'a,
425        E: KernelTransactionExecutor + 'a,
426        Y: KernelApi<CallbackObject = InjectCostingError<E>>,
427    > KernelSubstateApi<E::LockData> for WrappedKernelApi<'a, E, Y>
428{
429    fn kernel_mark_substate_as_transient(
430        &mut self,
431        node_id: NodeId,
432        partition_num: PartitionNumber,
433        key: SubstateKey,
434    ) -> Result<(), RuntimeError> {
435        self.api
436            .kernel_mark_substate_as_transient(node_id, partition_num, key)
437    }
438
439    fn kernel_open_substate_with_default<F: FnOnce() -> IndexedScryptoValue>(
440        &mut self,
441        node_id: &NodeId,
442        partition_num: PartitionNumber,
443        substate_key: &SubstateKey,
444        flags: LockFlags,
445        default: Option<F>,
446        lock_data: E::LockData,
447    ) -> Result<SubstateHandle, RuntimeError> {
448        self.api.kernel_open_substate_with_default(
449            node_id,
450            partition_num,
451            substate_key,
452            flags,
453            default,
454            lock_data,
455        )
456    }
457
458    fn kernel_get_lock_data(
459        &mut self,
460        lock_handle: SubstateHandle,
461    ) -> Result<E::LockData, RuntimeError> {
462        self.api.kernel_get_lock_data(lock_handle)
463    }
464
465    fn kernel_close_substate(&mut self, lock_handle: SubstateHandle) -> Result<(), RuntimeError> {
466        self.api.kernel_close_substate(lock_handle)
467    }
468
469    fn kernel_read_substate(
470        &mut self,
471        lock_handle: SubstateHandle,
472    ) -> Result<&IndexedScryptoValue, RuntimeError> {
473        self.api.kernel_read_substate(lock_handle)
474    }
475
476    fn kernel_write_substate(
477        &mut self,
478        lock_handle: SubstateHandle,
479        value: IndexedScryptoValue,
480    ) -> Result<(), RuntimeError> {
481        self.api.kernel_write_substate(lock_handle, value)
482    }
483
484    fn kernel_set_substate(
485        &mut self,
486        node_id: &NodeId,
487        partition_num: PartitionNumber,
488        substate_key: SubstateKey,
489        value: IndexedScryptoValue,
490    ) -> Result<(), RuntimeError> {
491        self.api
492            .kernel_set_substate(node_id, partition_num, substate_key, value)
493    }
494
495    fn kernel_remove_substate(
496        &mut self,
497        node_id: &NodeId,
498        partition_num: PartitionNumber,
499        substate_key: &SubstateKey,
500    ) -> Result<Option<IndexedScryptoValue>, RuntimeError> {
501        self.api
502            .kernel_remove_substate(node_id, partition_num, substate_key)
503    }
504
505    fn kernel_scan_sorted_substates(
506        &mut self,
507        node_id: &NodeId,
508        partition_num: PartitionNumber,
509        count: u32,
510    ) -> Result<Vec<(SortedKey, IndexedScryptoValue)>, RuntimeError> {
511        self.api
512            .kernel_scan_sorted_substates(node_id, partition_num, count)
513    }
514
515    fn kernel_scan_keys<K: SubstateKeyContent>(
516        &mut self,
517        node_id: &NodeId,
518        partition_num: PartitionNumber,
519        count: u32,
520    ) -> Result<Vec<SubstateKey>, RuntimeError> {
521        self.api
522            .kernel_scan_keys::<K>(node_id, partition_num, count)
523    }
524
525    fn kernel_drain_substates<K: SubstateKeyContent>(
526        &mut self,
527        node_id: &NodeId,
528        partition_num: PartitionNumber,
529        count: u32,
530    ) -> Result<Vec<(SubstateKey, IndexedScryptoValue)>, RuntimeError> {
531        self.api
532            .kernel_drain_substates::<K>(node_id, partition_num, count)
533    }
534}
535
536impl<
537        'a,
538        E: KernelTransactionExecutor + 'a,
539        K: KernelApi<CallbackObject = InjectCostingError<E>>,
540    > KernelInvokeApi<E::CallFrameData> for WrappedKernelApi<'a, E, K>
541{
542    fn kernel_invoke(
543        &mut self,
544        invocation: Box<KernelInvocation<E::CallFrameData>>,
545    ) -> Result<IndexedScryptoValue, RuntimeError> {
546        self.api.kernel_invoke(invocation)
547    }
548}
549
550impl<
551        'a,
552        E: KernelTransactionExecutor + 'a,
553        K: KernelApi<CallbackObject = InjectCostingError<E>>,
554    > KernelStackApi for WrappedKernelApi<'a, E, K>
555{
556    type CallFrameData = E::CallFrameData;
557
558    fn kernel_get_stack_id(&mut self) -> Result<usize, RuntimeError> {
559        self.api.kernel_get_stack_id()
560    }
561
562    fn kernel_switch_stack(&mut self, id: usize) -> Result<(), RuntimeError> {
563        self.api.kernel_switch_stack(id)
564    }
565
566    fn kernel_send_to_stack(
567        &mut self,
568        id: usize,
569        value: &IndexedScryptoValue,
570    ) -> Result<(), RuntimeError> {
571        self.api.kernel_send_to_stack(id, value)
572    }
573
574    fn kernel_set_call_frame_data(&mut self, data: E::CallFrameData) -> Result<(), RuntimeError> {
575        self.api.kernel_set_call_frame_data(data)
576    }
577
578    fn kernel_get_owned_nodes(&mut self) -> Result<Vec<NodeId>, RuntimeError> {
579        self.api.kernel_get_owned_nodes()
580    }
581}
582
583impl<
584        'a,
585        E: KernelTransactionExecutor + 'a,
586        K: KernelApi<CallbackObject = InjectCostingError<E>>,
587    > KernelInternalApi for WrappedKernelApi<'a, E, K>
588{
589    type System = E;
590
591    fn kernel_get_system_state(&mut self) -> SystemState<'_, E> {
592        let state = self.api.kernel_get_system_state();
593        SystemState {
594            system: &mut state.system.wrapped,
595            caller_call_frame: state.caller_call_frame,
596            current_call_frame: state.current_call_frame,
597        }
598    }
599
600    fn kernel_get_current_stack_depth_uncosted(&self) -> usize {
601        self.api.kernel_get_current_stack_depth_uncosted()
602    }
603
604    fn kernel_get_current_stack_id_uncosted(&self) -> usize {
605        self.api.kernel_get_current_stack_id_uncosted()
606    }
607
608    fn kernel_get_node_visibility_uncosted(&self, node_id: &NodeId) -> NodeVisibility {
609        self.api.kernel_get_node_visibility_uncosted(node_id)
610    }
611
612    fn kernel_read_substate_uncosted(
613        &self,
614        node_id: &NodeId,
615        partition_num: PartitionNumber,
616        substate_key: &SubstateKey,
617    ) -> Option<&IndexedScryptoValue> {
618        self.api
619            .kernel_read_substate_uncosted(node_id, partition_num, substate_key)
620    }
621}
622
623impl<
624        'a,
625        E: KernelTransactionExecutor + 'a,
626        K: KernelApi<CallbackObject = InjectCostingError<E>>,
627    > KernelApi for WrappedKernelApi<'a, E, K>
628{
629    type CallbackObject = E;
630}
631
632pub struct WrappedKernelInternalApi<
633    'a,
634    E: KernelTransactionExecutor + 'a,
635    K: KernelInternalApi<System = InjectCostingError<E>>,
636> {
637    api: &'a mut K,
638}
639
640impl<
641        'a,
642        E: KernelTransactionExecutor + 'a,
643        K: KernelInternalApi<System = InjectCostingError<E>>,
644    > KernelInternalApi for WrappedKernelInternalApi<'a, E, K>
645{
646    type System = E;
647
648    fn kernel_get_system_state(&mut self) -> SystemState<'_, E> {
649        let state = self.api.kernel_get_system_state();
650        SystemState {
651            system: &mut state.system.wrapped,
652            caller_call_frame: state.caller_call_frame,
653            current_call_frame: state.current_call_frame,
654        }
655    }
656
657    fn kernel_get_current_stack_depth_uncosted(&self) -> usize {
658        self.api.kernel_get_current_stack_depth_uncosted()
659    }
660
661    fn kernel_get_current_stack_id_uncosted(&self) -> usize {
662        self.api.kernel_get_current_stack_id_uncosted()
663    }
664
665    fn kernel_get_node_visibility_uncosted(&self, node_id: &NodeId) -> NodeVisibility {
666        self.api.kernel_get_node_visibility_uncosted(node_id)
667    }
668
669    fn kernel_read_substate_uncosted(
670        &self,
671        node_id: &NodeId,
672        partition_num: PartitionNumber,
673        substate_key: &SubstateKey,
674    ) -> Option<&IndexedScryptoValue> {
675        self.api
676            .kernel_read_substate_uncosted(node_id, partition_num, substate_key)
677    }
678}