1use crate::internal_prelude::*;
2use crate::kernel::kernel_callback_api::CallFrameReferences;
3use radix_engine_interface::api::{AttachedModuleId, ModuleId};
4
5#[derive(Debug, Clone, ScryptoSbor, PartialEq, Eq)]
6pub struct InstanceContext {
7 pub outer_object: GlobalAddress,
8}
9
10#[derive(Debug, Clone, ScryptoSbor, PartialEq, Eq)]
11pub enum MethodType {
12 Main,
13 Direct,
14 Module(AttachedModuleId),
15}
16
17impl MethodType {
18 pub fn module_id(&self) -> ModuleId {
19 match self {
20 MethodType::Module(module_id) => module_id.clone().into(),
21 MethodType::Main | MethodType::Direct => ModuleId::Main,
22 }
23 }
24}
25
26#[derive(Debug, Clone, ScryptoSbor, PartialEq, Eq)]
27pub struct MethodActor {
28 pub method_type: MethodType,
29 pub node_id: NodeId,
30 pub ident: String,
31
32 pub auth_zone: NodeId,
33
34 pub object_info: ObjectInfo,
36}
37
38impl MethodActor {
39 pub fn get_blueprint_id(&self) -> BlueprintId {
40 match self.method_type {
41 MethodType::Main | MethodType::Direct => {
42 self.object_info.blueprint_info.blueprint_id.clone()
43 }
44 MethodType::Module(module_id) => module_id.static_blueprint(),
45 }
46 }
47}
48
49#[derive(Debug, Clone, ScryptoSbor, PartialEq, Eq)]
50pub struct FunctionActor {
51 pub blueprint_id: BlueprintId,
52 pub ident: String,
53
54 pub auth_zone: NodeId,
55}
56
57impl FunctionActor {
58 pub fn as_global_caller(&self) -> GlobalCaller {
59 GlobalCaller::PackageBlueprint(self.blueprint_id.clone())
60 }
61}
62
63#[derive(Debug, Clone, ScryptoSbor, PartialEq, Eq)]
64pub struct BlueprintHookActor {
65 pub receiver: Option<NodeId>,
66 pub hook: BlueprintHook,
67 pub blueprint_id: BlueprintId,
68}
69
70#[derive(Debug, Clone, ScryptoSbor, PartialEq, Eq)]
71pub enum Actor {
72 Root,
81 Method(MethodActor),
82 Function(FunctionActor),
83 BlueprintHook(BlueprintHookActor),
84}
85
86impl Default for Actor {
88 fn default() -> Self {
89 Self::Root
90 }
91}
92
93impl CallFrameReferences for Actor {
94 fn global_references(&self) -> Vec<NodeId> {
95 let mut global_refs = Vec::new();
96
97 if let Some(blueprint_id) = self.blueprint_id() {
98 global_refs.push(blueprint_id.package_address.into_node_id());
99 }
100
101 if let Actor::Method(MethodActor {
102 node_id,
103 object_info,
104 ..
105 }) = self
106 {
107 if let OuterObjectInfo::Some { outer_object } =
108 object_info.blueprint_info.outer_obj_info
109 {
110 global_refs.push(outer_object.clone().into_node_id());
111 }
112
113 if node_id.is_global() {
114 global_refs.push(node_id.clone());
115 }
116 }
117
118 global_refs
119 }
120
121 fn direct_access_references(&self) -> Vec<NodeId> {
122 if self.is_direct_access() {
123 self.node_id().into_iter().collect()
124 } else {
125 vec![]
126 }
127 }
128
129 fn stable_transient_references(&self) -> Vec<NodeId> {
130 let mut references = vec![];
131 references.extend(self.self_auth_zone());
132
133 if !self.is_direct_access() {
134 references.extend(self.node_id().filter(|n| !n.is_global()));
135 }
136
137 references
138 }
139
140 fn len(&self) -> usize {
141 match self {
142 Actor::Root => 1,
143 Actor::Method(MethodActor { ident, node_id, .. }) => {
144 node_id.as_bytes().len() + ident.len()
145 }
146 Actor::Function(FunctionActor {
147 blueprint_id,
148 ident,
149 ..
150 }) => {
151 blueprint_id.package_address.as_bytes().len()
152 + blueprint_id.blueprint_name.len()
153 + ident.len()
154 }
155 Actor::BlueprintHook(BlueprintHookActor { blueprint_id, .. }) => {
156 blueprint_id.package_address.as_bytes().len()
157 + blueprint_id.blueprint_name.len()
158 + 1
159 }
160 }
161 }
162}
163
164impl Actor {
165 pub fn is_root(&self) -> bool {
166 matches!(self, Actor::Root)
167 }
168
169 pub fn self_auth_zone(&self) -> Option<NodeId> {
170 match self {
171 Actor::Root | Actor::BlueprintHook(..) => None,
172 Actor::Method(method_actor) => Some(method_actor.auth_zone),
173 Actor::Function(function_actor) => Some(function_actor.auth_zone),
174 }
175 }
176
177 pub fn instance_context(&self) -> Option<InstanceContext> {
178 let method_actor = match self {
179 Actor::Method(method_actor) => method_actor,
180 _ => return None,
181 };
182
183 match method_actor.method_type {
184 MethodType::Main | MethodType::Direct => {
185 if method_actor.object_info.is_global() {
186 Some(InstanceContext {
187 outer_object: GlobalAddress::new_or_panic(method_actor.node_id.0),
188 })
189 } else {
190 match &method_actor.object_info.blueprint_info.outer_obj_info {
191 OuterObjectInfo::Some { outer_object } => Some(InstanceContext {
192 outer_object: outer_object.clone(),
193 }),
194 OuterObjectInfo::None { .. } => None,
195 }
196 }
197 }
198 _ => None,
199 }
200 }
201
202 pub fn get_object_id(&self) -> Option<(NodeId, Option<AttachedModuleId>)> {
203 match self {
204 Actor::Method(method_actor) => Some((
205 method_actor.node_id,
206 method_actor.method_type.module_id().into(),
207 )),
208 Actor::BlueprintHook(BlueprintHookActor {
209 receiver: Some(node_id),
210 ..
211 }) => Some((*node_id, None)),
212 Actor::BlueprintHook(..) | Actor::Root | Actor::Function(..) => None,
213 }
214 }
215
216 pub fn is_barrier(&self) -> bool {
217 match self {
218 Actor::Method(MethodActor { object_info, .. }) => object_info.is_global(),
219 Actor::Function { .. } => true,
220 Actor::BlueprintHook { .. } => true,
221 Actor::Root { .. } => false,
222 }
223 }
224
225 pub fn node_id(&self) -> Option<NodeId> {
226 match self {
227 Actor::Method(MethodActor { node_id, .. }) => Some(*node_id),
228 Actor::BlueprintHook(BlueprintHookActor {
229 receiver: node_id, ..
230 }) => node_id.clone(),
231 _ => None,
232 }
233 }
234
235 pub fn is_direct_access(&self) -> bool {
236 match self {
237 Actor::Method(MethodActor { method_type, .. }) => {
238 matches!(method_type, MethodType::Direct)
239 }
240 _ => false,
241 }
242 }
243
244 pub fn blueprint_id(&self) -> Option<BlueprintId> {
245 match self {
246 Actor::Method(actor) => Some(actor.get_blueprint_id()),
247 Actor::Function(FunctionActor { blueprint_id, .. })
248 | Actor::BlueprintHook(BlueprintHookActor { blueprint_id, .. }) => {
249 Some(blueprint_id.clone())
250 }
251 Actor::Root => None,
252 }
253 }
254
255 pub fn package_address(&self) -> Option<PackageAddress> {
256 self.blueprint_id().map(|id| id.package_address)
257 }
258}