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