radix_engine/kernel/
kernel_callback_api.rs

1use super::call_frame::{CallFrameInit, CallFrameMessage};
2use crate::errors::*;
3use crate::internal_prelude::*;
4use crate::kernel::kernel_api::KernelInvocation;
5use crate::kernel::kernel_api::{KernelApi, KernelInternalApi};
6use crate::kernel::substate_io::SubstateDevice;
7use crate::track::interface::{IOAccess, NodeSubstates};
8use crate::track::*;
9use crate::transaction::ResourcesUsage;
10use radix_engine_interface::api::field_api::LockFlags;
11use radix_substate_store_interface::interface::SubstateDatabase;
12use radix_transactions::model::ExecutableTransaction;
13
14#[allow(clippy::len_without_is_empty)]
15pub trait CallFrameReferences {
16    fn global_references(&self) -> Vec<NodeId>;
17    fn direct_access_references(&self) -> Vec<NodeId>;
18    fn stable_transient_references(&self) -> Vec<NodeId>;
19
20    fn len(&self) -> usize;
21}
22
23// TODO: Replace Events with separate callback functions
24#[derive(Debug)]
25pub enum CreateNodeEvent<'a> {
26    Start(&'a NodeId, &'a NodeSubstates),
27    IOAccess(&'a IOAccess),
28    End(&'a NodeId),
29}
30
31#[derive(Debug)]
32pub enum DropNodeEvent<'a> {
33    Start(&'a NodeId),
34    IOAccess(&'a IOAccess),
35    End(&'a NodeId, &'a NodeSubstates),
36}
37
38#[derive(Debug)]
39pub enum CheckReferenceEvent<'a> {
40    IOAccess(&'a IOAccess),
41}
42
43#[derive(Debug)]
44pub enum MoveModuleEvent<'a> {
45    IOAccess(&'a IOAccess),
46}
47
48#[derive(Debug)]
49pub enum OpenSubstateEvent<'a> {
50    Start {
51        node_id: &'a NodeId,
52        partition_num: &'a PartitionNumber,
53        substate_key: &'a SubstateKey,
54        flags: &'a LockFlags,
55    },
56    IOAccess(&'a IOAccess),
57    End {
58        handle: SubstateHandle,
59        node_id: &'a NodeId,
60        size: usize,
61    },
62}
63
64#[derive(Debug)]
65pub enum ReadSubstateEvent<'a> {
66    OnRead {
67        handle: SubstateHandle,
68        value: &'a IndexedScryptoValue,
69        device: SubstateDevice,
70    },
71    IOAccess(&'a IOAccess),
72}
73
74impl<'a> ReadSubstateEvent<'a> {
75    pub fn is_about_heap(&self) -> bool {
76        match self {
77            ReadSubstateEvent::OnRead { device, .. } => matches!(device, SubstateDevice::Heap),
78            ReadSubstateEvent::IOAccess(access) => match access {
79                IOAccess::ReadFromDb(_, _) => false,
80                IOAccess::ReadFromDbNotFound(_) => false,
81                IOAccess::TrackSubstateUpdated { .. } => false,
82                IOAccess::HeapSubstateUpdated { .. } => true,
83            },
84        }
85    }
86}
87
88#[derive(Debug)]
89pub enum WriteSubstateEvent<'a> {
90    Start {
91        handle: SubstateHandle,
92        value: &'a IndexedScryptoValue,
93    },
94    IOAccess(&'a IOAccess),
95}
96
97#[derive(Debug)]
98pub enum CloseSubstateEvent {
99    Start(SubstateHandle),
100}
101
102#[derive(Debug)]
103pub enum SetSubstateEvent<'a> {
104    Start(
105        &'a NodeId,
106        &'a PartitionNumber,
107        &'a SubstateKey,
108        &'a IndexedScryptoValue,
109    ),
110    IOAccess(&'a IOAccess),
111}
112
113#[derive(Debug)]
114pub enum RemoveSubstateEvent<'a> {
115    Start(&'a NodeId, &'a PartitionNumber, &'a SubstateKey),
116    IOAccess(&'a IOAccess),
117}
118
119#[derive(Debug)]
120pub enum ScanKeysEvent<'a> {
121    Start,
122    IOAccess(&'a IOAccess),
123}
124
125#[derive(Debug)]
126pub enum DrainSubstatesEvent<'a> {
127    Start(u32),
128    IOAccess(&'a IOAccess),
129}
130
131#[derive(Debug)]
132pub enum ScanSortedSubstatesEvent<'a> {
133    Start,
134    IOAccess(&'a IOAccess),
135}
136
137/// A receipt created from executing a transaction
138pub trait ExecutionReceipt {
139    fn set_resource_usage(&mut self, resources_usage: ResourcesUsage);
140}
141
142/// A transaction which has a unique id, useful for creating an IdAllocator which
143/// requires a unique input
144pub trait UniqueSeed {
145    fn unique_seed_for_id_allocator(&self) -> Hash;
146}
147
148impl UniqueSeed for ExecutableTransaction {
149    fn unique_seed_for_id_allocator(&self) -> Hash {
150        *self.unique_hash()
151    }
152}
153
154pub trait KernelTransactionExecutor: KernelCallbackObject {
155    /// Initialization object
156    type Init;
157    /// The transaction object
158    type Executable: UniqueSeed;
159    /// Output to be returned at the end of execution
160    type ExecutionOutput;
161    /// Final receipt to be created after transaction execution
162    type Receipt: ExecutionReceipt;
163
164    /// Create the callback object (system layer) and the initial call frame configuration for each intent
165    #[allow(clippy::type_complexity)]
166    fn init(
167        store: &mut impl CommitableSubstateStore,
168        executable: &Self::Executable,
169        init: Self::Init,
170        always_visible_global_nodes: &'static IndexSet<NodeId>,
171    ) -> Result<(Self, Vec<CallFrameInit<Self::CallFrameData>>), Self::Receipt>;
172
173    /// Start execution
174    fn execute<Y: KernelApi<CallbackObject = Self>>(
175        api: &mut Y,
176        executable: &Self::Executable,
177    ) -> Result<Self::ExecutionOutput, RuntimeError>;
178
179    /// Finish execution
180    fn finalize(
181        &mut self,
182        executable: &Self::Executable,
183        store_commit_info: StoreCommitInfo,
184    ) -> Result<(), RuntimeError>;
185
186    /// Create final receipt
187    fn create_receipt<S: SubstateDatabase>(
188        self,
189        track: Track<S>,
190        result: Result<Self::ExecutionOutput, TransactionExecutionError>,
191    ) -> Self::Receipt;
192}
193
194/// Upper layer callback object which a kernel interacts with during execution
195pub trait KernelCallbackObject: Sized {
196    /// Data to be stored with each substate lock
197    type LockData: Default + Clone;
198    /// Data to be stored with every call frame
199    type CallFrameData: CallFrameReferences;
200
201    /// Callback before a node is pinned to the heap
202    fn on_pin_node<Y: KernelInternalApi<System = Self>>(
203        node_id: &NodeId,
204        api: &mut Y,
205    ) -> Result<(), RuntimeError>;
206
207    /// Callbacks before/on-io-access/after a new node is created
208    fn on_create_node<Y: KernelInternalApi<System = Self>>(
209        event: CreateNodeEvent,
210        api: &mut Y,
211    ) -> Result<(), RuntimeError>;
212
213    /// Callbacks before/on-io-access/after a node is dropped
214    fn on_drop_node<Y: KernelInternalApi<System = Self>>(
215        event: DropNodeEvent,
216        api: &mut Y,
217    ) -> Result<(), RuntimeError>;
218
219    /// Callback when a module is moved
220    fn on_move_module<Y: KernelInternalApi<System = Self>>(
221        event: MoveModuleEvent,
222        api: &mut Y,
223    ) -> Result<(), RuntimeError>;
224
225    /// Callback before/on-io-access/after a substate is opened
226    fn on_open_substate<Y: KernelInternalApi<System = Self>>(
227        event: OpenSubstateEvent,
228        api: &mut Y,
229    ) -> Result<(), RuntimeError>;
230
231    /// Callback before a substate is closed
232    fn on_close_substate<Y: KernelInternalApi<System = Self>>(
233        event: CloseSubstateEvent,
234        api: &mut Y,
235    ) -> Result<(), RuntimeError>;
236
237    /// Callback before a substate is read
238    fn on_read_substate<Y: KernelInternalApi<System = Self>>(
239        event: ReadSubstateEvent,
240        api: &mut Y,
241    ) -> Result<(), RuntimeError>;
242
243    /// Callback before a substate is written to
244    fn on_write_substate<Y: KernelInternalApi<System = Self>>(
245        event: WriteSubstateEvent,
246        api: &mut Y,
247    ) -> Result<(), RuntimeError>;
248
249    /// Callback before/on-io-access a substate is set
250    fn on_set_substate<Y: KernelInternalApi<System = Self>>(
251        event: SetSubstateEvent,
252        api: &mut Y,
253    ) -> Result<(), RuntimeError>;
254
255    /// Callback before/on-io-access a substate is removed
256    fn on_remove_substate<Y: KernelInternalApi<System = Self>>(
257        event: RemoveSubstateEvent,
258        api: &mut Y,
259    ) -> Result<(), RuntimeError>;
260
261    /// Callback before/on-io-access a key scan occurs
262    fn on_scan_keys<Y: KernelInternalApi<System = Self>>(
263        event: ScanKeysEvent,
264        api: &mut Y,
265    ) -> Result<(), RuntimeError>;
266
267    /// Callback before/on-io-access a substate drain occurs
268    fn on_drain_substates<Y: KernelInternalApi<System = Self>>(
269        event: DrainSubstatesEvent,
270        api: &mut Y,
271    ) -> Result<(), RuntimeError>;
272
273    /// Callback before/on-io-access a sorted substate scan occurs
274    fn on_scan_sorted_substates<Y: KernelInternalApi<System = Self>>(
275        event: ScanSortedSubstatesEvent,
276        api: &mut Y,
277    ) -> Result<(), RuntimeError>;
278
279    /// Callback before an invocation and a new call frame is created
280    fn before_invoke<Y: KernelApi<CallbackObject = Self>>(
281        invocation: &KernelInvocation<Self::CallFrameData>,
282        api: &mut Y,
283    ) -> Result<(), RuntimeError>;
284
285    /// Callback after a new call frame is created for a new invocation
286    fn on_execution_start<Y: KernelInternalApi<System = Self>>(
287        api: &mut Y,
288    ) -> Result<(), RuntimeError>;
289
290    /// Callback on invocation. This is where the callback object should execute application logic.
291    fn invoke_upstream<Y: KernelApi<CallbackObject = Self>>(
292        args: &IndexedScryptoValue,
293        api: &mut Y,
294    ) -> Result<IndexedScryptoValue, RuntimeError>;
295
296    /// Callback after invocation during call frame cleanup and nodes are still owned by the executed
297    /// call frame
298    fn auto_drop<Y: KernelApi<CallbackObject = Self>>(
299        nodes: Vec<NodeId>,
300        api: &mut Y,
301    ) -> Result<(), RuntimeError>;
302
303    /// Callback right after execution of invocation and where call of execution still exists
304    fn on_execution_finish<Y: KernelInternalApi<System = Self>>(
305        message: &CallFrameMessage,
306        api: &mut Y,
307    ) -> Result<(), RuntimeError>;
308
309    /// Callback after an invocation and where invocation's call frame has already been destroyed
310    fn after_invoke<Y: KernelApi<CallbackObject = Self>>(
311        output: &IndexedScryptoValue,
312        api: &mut Y,
313    ) -> Result<(), RuntimeError>;
314
315    /// Callback before node id allocation
316    fn on_allocate_node_id<Y: KernelInternalApi<System = Self>>(
317        entity_type: EntityType,
318        api: &mut Y,
319    ) -> Result<(), RuntimeError>;
320
321    /// Callback before a substate is marked as transient
322    fn on_mark_substate_as_transient<Y: KernelInternalApi<System = Self>>(
323        node_id: &NodeId,
324        partition_number: &PartitionNumber,
325        substate_key: &SubstateKey,
326        api: &mut Y,
327    ) -> Result<(), RuntimeError>;
328
329    /// Callback when a substate does not exist
330    fn on_substate_lock_fault<Y: KernelApi<CallbackObject = Self>>(
331        node_id: NodeId,
332        partition_num: PartitionNumber,
333        offset: &SubstateKey,
334        api: &mut Y,
335    ) -> Result<bool, RuntimeError>;
336
337    /// Callback before a node is dropped
338    fn on_drop_node_mut<Y: KernelApi<CallbackObject = Self>>(
339        node_id: &NodeId,
340        api: &mut Y,
341    ) -> Result<(), RuntimeError>;
342
343    fn on_get_stack_id<Y: KernelInternalApi<System = Self>>(
344        api: &mut Y,
345    ) -> Result<(), RuntimeError>;
346
347    fn on_switch_stack<Y: KernelInternalApi<System = Self>>(
348        api: &mut Y,
349    ) -> Result<(), RuntimeError>;
350
351    fn on_send_to_stack<Y: KernelInternalApi<System = Self>>(
352        value: &IndexedScryptoValue,
353        api: &mut Y,
354    ) -> Result<(), RuntimeError>;
355
356    fn on_set_call_frame_data<Y: KernelInternalApi<System = Self>>(
357        data: &Self::CallFrameData,
358        api: &mut Y,
359    ) -> Result<(), RuntimeError>;
360
361    fn on_get_owned_nodes<Y: KernelInternalApi<System = Self>>(
362        api: &mut Y,
363    ) -> Result<(), RuntimeError>;
364}