radix_engine/system/
system.rs

1use super::id_allocation::IDAllocation;
2use super::system_modules::costing::ExecutionCostingEntry;
3use crate::blueprints::package::PackageBlueprintVersionDefinitionEntrySubstate;
4use crate::blueprints::resource::fungible_vault::LockFeeEvent;
5use crate::errors::*;
6use crate::errors::{EventError, SystemUpstreamError};
7use crate::internal_prelude::*;
8use crate::kernel::call_frame::{NodeVisibility, ReferenceOrigin};
9use crate::kernel::kernel_api::*;
10use crate::system::actor::{Actor, FunctionActor, InstanceContext, MethodActor, MethodType};
11use crate::system::node_init::type_info_partition;
12use crate::system::system_callback::*;
13use crate::system::system_modules::transaction_runtime::Event;
14use crate::system::system_modules::{EnabledModules, SystemModuleMixer};
15use crate::system::system_substates::{KeyValueEntrySubstate, LockStatus};
16use crate::system::system_type_checker::{
17    BlueprintTypeTarget, KVStoreTypeTarget, SchemaValidationMeta, SystemMapper,
18};
19use crate::system::type_info::{TypeInfoBlueprint, TypeInfoSubstate};
20use crate::track::interface::NodeSubstates;
21use radix_blueprint_schema_init::{Condition, KeyValueStoreGenericSubstitutions};
22#[cfg(not(feature = "alloc"))]
23use radix_common_derive::*;
24use radix_engine_interface::api::actor_api::EventFlags;
25use radix_engine_interface::api::actor_index_api::SystemActorIndexApi;
26use radix_engine_interface::api::field_api::{FieldHandle, LockFlags};
27use radix_engine_interface::api::key_value_entry_api::{
28    KeyValueEntryHandle, SystemKeyValueEntryApi,
29};
30use radix_engine_interface::api::key_value_store_api::{
31    KeyValueStoreDataSchema, SystemKeyValueStoreApi,
32};
33use radix_engine_interface::api::object_api::ModuleId;
34use radix_engine_interface::api::*;
35use radix_engine_interface::blueprints::package::*;
36use radix_engine_interface::blueprints::resource::*;
37use radix_engine_profiling_derive::trace_resources;
38use radix_substate_store_interface::db_key_mapper::SubstateKeyContent;
39
40enum ActorStateRef {
41    SELF,
42    OuterObject,
43}
44
45impl TryFrom<ActorStateHandle> for ActorStateRef {
46    type Error = RuntimeError;
47    fn try_from(value: ActorStateHandle) -> Result<Self, Self::Error> {
48        match value {
49            ACTOR_STATE_SELF => Ok(ActorStateRef::SELF),
50            ACTOR_STATE_OUTER_OBJECT => Ok(ActorStateRef::OuterObject),
51            _ => Err(RuntimeError::SystemError(
52                SystemError::InvalidActorStateHandle,
53            )),
54        }
55    }
56}
57
58enum ActorObjectRef {
59    SELF,
60    Outer,
61    Global,
62    AuthZone,
63}
64
65impl TryFrom<ActorRefHandle> for ActorObjectRef {
66    type Error = RuntimeError;
67    fn try_from(value: ActorStateHandle) -> Result<Self, Self::Error> {
68        match value {
69            ACTOR_REF_SELF => Ok(ActorObjectRef::SELF),
70            ACTOR_REF_OUTER => Ok(ActorObjectRef::Outer),
71            ACTOR_REF_GLOBAL => Ok(ActorObjectRef::Global),
72            ACTOR_REF_AUTH_ZONE => Ok(ActorObjectRef::AuthZone),
73            _ => Err(RuntimeError::SystemError(
74                SystemError::InvalidActorRefHandle,
75            )),
76        }
77    }
78}
79
80enum EmitterActor {
81    CurrentActor,
82    AsObject(NodeId, Option<AttachedModuleId>),
83}
84
85/// A wrapper offering a comprehensive system api to callers. It is built on top
86/// of a [`SystemBasedKernelApi`], and you are free to access it.
87/// You can also construct a [`SystemService`] from the api with `api.system_service()`.
88///
89/// Like [`SystemModuleApiImpl`], we use a wrapper type rather than implementing this functionality
90/// directly on a `SystemBasedKernelApi` for a few reasons:
91/// * Trait coherence - the System traits aren't defined in this crate, so it prevents us
92///   from implementing them on any type implementing `SystemBasedKernelApi`.
93/// * Separation of APIs - we avoid exposing the methods of a [`SystemServiceApi`] directly
94///   if someone happens to have a [`SystemBasedKernelApi`], which prevents some
95///   possible confusion.
96pub struct SystemService<'a, Y: SystemBasedKernelApi + ?Sized> {
97    api: &'a mut Y,
98}
99
100impl<'a, Y: SystemBasedKernelApi + ?Sized> SystemService<'a, Y> {
101    pub fn new(api: &'a mut Y) -> Self {
102        Self { api }
103    }
104
105    pub fn api(&mut self) -> &mut Y {
106        self.api
107    }
108
109    pub fn system(&mut self) -> &mut System<Y::SystemCallback> {
110        self.api.kernel_get_system()
111    }
112}
113
114#[cfg_attr(
115    feature = "std",
116    catch_unwind(crate::utils::catch_unwind_system_panic_transformer)
117)]
118impl<'a, Y: SystemBasedKernelApi> SystemService<'a, Y> {
119    fn validate_new_object(
120        &mut self,
121        blueprint_id: &BlueprintId,
122        blueprint_interface: &BlueprintInterface,
123        outer_obj_info: OuterObjectInfo,
124        features: IndexSet<String>,
125        outer_object_features: &IndexSet<String>,
126        generic_args: GenericArgs,
127        fields: IndexMap<u8, FieldValue>,
128        mut kv_entries: IndexMap<u8, IndexMap<Vec<u8>, KVEntry>>,
129    ) -> Result<(BlueprintInfo, NodeSubstates), RuntimeError> {
130        // Validate generic arguments
131        let (generic_substitutions, additional_schemas) = {
132            let mut additional_schemas = index_map_new();
133
134            if let Some(schema) = generic_args.additional_schema {
135                validate_schema(schema.v1())
136                    .map_err(|_| RuntimeError::SystemError(SystemError::InvalidGenericArgs))?;
137                let schema_hash = schema.generate_schema_hash();
138                additional_schemas.insert(schema_hash, schema);
139            }
140
141            self.validate_bp_generic_args(
142                blueprint_interface,
143                &additional_schemas,
144                &generic_args.generic_substitutions,
145            )
146            .map_err(|e| RuntimeError::SystemError(SystemError::TypeCheckError(e)))?;
147
148            (generic_args.generic_substitutions, additional_schemas)
149        };
150
151        let blueprint_info = BlueprintInfo {
152            blueprint_id: blueprint_id.clone(),
153            blueprint_version: BlueprintVersion::default(),
154            outer_obj_info,
155            features: features.clone(),
156            generic_substitutions: generic_substitutions.clone(),
157        };
158
159        let validation_target = BlueprintTypeTarget {
160            blueprint_info,
161            meta: SchemaValidationMeta::NewObject {
162                additional_schemas: additional_schemas.clone().into_iter().collect(),
163            },
164        };
165
166        // Fields
167        {
168            let expected_num_fields = blueprint_interface.state.num_fields();
169            for field_index in fields.keys() {
170                let field_index: usize = (*field_index) as usize;
171                if field_index >= expected_num_fields {
172                    return Err(RuntimeError::SystemError(SystemError::CreateObjectError(
173                        Box::new(CreateObjectError::InvalidFieldIndex(
174                            blueprint_id.clone(),
175                            field_index as u8,
176                        )),
177                    )));
178                }
179            }
180
181            if let Some((_partition, field_schemas)) = &blueprint_interface.state.fields {
182                for (i, field) in field_schemas.iter().enumerate() {
183                    let index = i as u8;
184
185                    let maybe_field = fields.get(&index);
186
187                    let field_value = match &field.condition {
188                        Condition::IfFeature(feature) => {
189                            match (features.contains(feature), maybe_field) {
190                                (false, Some(..)) => {
191                                    return Err(RuntimeError::SystemError(
192                                        SystemError::CreateObjectError(Box::new(
193                                            CreateObjectError::InvalidFieldDueToFeature(
194                                                blueprint_id.clone(),
195                                                index,
196                                            ),
197                                        )),
198                                    ));
199                                }
200                                (true, None) => {
201                                    return Err(RuntimeError::SystemError(
202                                        SystemError::CreateObjectError(Box::new(
203                                            CreateObjectError::MissingField(
204                                                blueprint_id.clone(),
205                                                index,
206                                            ),
207                                        )),
208                                    ));
209                                }
210                                (false, None) => continue,
211                                (true, Some(field_value)) => field_value,
212                            }
213                        }
214                        Condition::IfOuterFeature(feature) => {
215                            match (outer_object_features.contains(feature), maybe_field) {
216                                (false, Some(..)) => {
217                                    return Err(RuntimeError::SystemError(
218                                        SystemError::CreateObjectError(Box::new(
219                                            CreateObjectError::InvalidFieldDueToFeature(
220                                                blueprint_id.clone(),
221                                                index,
222                                            ),
223                                        )),
224                                    ));
225                                }
226                                (true, None) => {
227                                    return Err(RuntimeError::SystemError(
228                                        SystemError::CreateObjectError(Box::new(
229                                            CreateObjectError::MissingField(
230                                                blueprint_id.clone(),
231                                                index,
232                                            ),
233                                        )),
234                                    ));
235                                }
236                                (false, None) => continue,
237                                (true, Some(field_value)) => field_value,
238                            }
239                        }
240                        Condition::Always => match maybe_field {
241                            None => {
242                                return Err(RuntimeError::SystemError(
243                                    SystemError::CreateObjectError(Box::new(
244                                        CreateObjectError::MissingField(
245                                            blueprint_id.clone(),
246                                            index,
247                                        ),
248                                    )),
249                                ));
250                            }
251                            Some(field_value) => field_value,
252                        },
253                    };
254
255                    self.validate_blueprint_payload(
256                        &validation_target,
257                        BlueprintPayloadIdentifier::Field(i as u8),
258                        &field_value.value,
259                    )?;
260                }
261            }
262        };
263
264        // Collections
265        {
266            for (collection_index, entries) in &kv_entries {
267                let payloads: Vec<(&Vec<u8>, &Vec<u8>)> = entries
268                    .iter()
269                    .filter_map(|(key, entry)| entry.value.as_ref().map(|e| (key, e)))
270                    .collect();
271
272                self.validate_blueprint_kv_collection(
273                    &validation_target,
274                    *collection_index,
275                    &payloads,
276                )?;
277            }
278
279            for (collection_index, ..) in blueprint_interface.state.collections.iter().enumerate() {
280                let index = collection_index as u8;
281                if !kv_entries.contains_key(&index) {
282                    kv_entries.insert(index, index_map_new());
283                }
284            }
285        }
286
287        let mut node_substates = SystemMapper::system_struct_to_node_substates(
288            &blueprint_interface.state,
289            (fields, kv_entries),
290            MAIN_BASE_PARTITION,
291        );
292
293        let schema_partition = node_substates
294            .entry(SCHEMAS_PARTITION)
295            .or_insert(BTreeMap::new());
296
297        for (schema_hash, schema) in additional_schemas {
298            let key = SubstateKey::Map(scrypto_encode(&schema_hash).unwrap());
299            let value =
300                IndexedScryptoValue::from_typed(&KeyValueEntrySubstate::locked_entry(schema));
301            schema_partition.insert(key, value);
302        }
303
304        Ok((validation_target.blueprint_info, node_substates))
305    }
306
307    pub fn get_blueprint_default_definition(
308        &mut self,
309        blueprint_id: BlueprintId,
310    ) -> Result<Rc<BlueprintDefinition>, RuntimeError> {
311        let bp_version_key = BlueprintVersionKey::new_default(blueprint_id.blueprint_name);
312        Ok(self.load_blueprint_definition(blueprint_id.package_address, &bp_version_key)?)
313    }
314
315    pub fn load_blueprint_definition(
316        &mut self,
317        package_address: PackageAddress,
318        bp_version_key: &BlueprintVersionKey,
319    ) -> Result<Rc<BlueprintDefinition>, RuntimeError> {
320        let canonical_bp_id = CanonicalBlueprintId {
321            address: package_address,
322            blueprint: bp_version_key.blueprint.to_string(),
323            version: bp_version_key.version.clone(),
324        };
325
326        // TODO: Use internment to cache blueprint interface rather than object cache?
327        let def = self
328            .api
329            .kernel_get_system_state()
330            .system
331            .blueprint_cache
332            .get(&canonical_bp_id);
333        if let Some(definition) = def {
334            return Ok(definition.clone());
335        }
336
337        let handle = self.api.kernel_open_substate_with_default(
338            package_address.as_node_id(),
339            MAIN_BASE_PARTITION
340                .at_offset(PACKAGE_BLUEPRINTS_PARTITION_OFFSET)
341                .unwrap(),
342            &SubstateKey::Map(scrypto_encode(bp_version_key).unwrap()),
343            LockFlags::read_only(),
344            Some(|| {
345                let kv_entry = KeyValueEntrySubstate::<()>::default();
346                IndexedScryptoValue::from_typed(&kv_entry)
347            }),
348            SystemLockData::default(),
349        )?;
350
351        let substate: PackageBlueprintVersionDefinitionEntrySubstate =
352            self.api.kernel_read_substate(handle)?.as_typed().unwrap();
353        self.api.kernel_close_substate(handle)?;
354
355        let definition = Rc::new(match substate.into_value() {
356            Some(definition) => definition.fully_update_and_into_latest_version(),
357            None => {
358                return Err(RuntimeError::SystemError(
359                    SystemError::BlueprintDoesNotExist(canonical_bp_id),
360                ))
361            }
362        });
363
364        self.api
365            .kernel_get_system_state()
366            .system
367            .blueprint_cache
368            .insert(canonical_bp_id, definition.clone());
369
370        Ok(definition)
371    }
372
373    pub fn prepare_global_address(
374        &mut self,
375        blueprint_id: BlueprintId,
376        global_address: GlobalAddress,
377    ) -> Result<GlobalAddressReservation, RuntimeError> {
378        // Create global address phantom
379
380        self.api.kernel_create_node(
381            global_address.as_node_id().clone(),
382            btreemap!(
383                TYPE_INFO_FIELD_PARTITION => type_info_partition(
384                    TypeInfoSubstate::GlobalAddressPhantom(GlobalAddressPhantom {
385                        blueprint_id,
386                    })
387                )
388            ),
389        )?;
390
391        // Create global address reservation
392        let global_address_reservation = self
393            .api
394            .kernel_allocate_node_id(EntityType::InternalGenericComponent)?;
395        self.api.kernel_create_node(
396            global_address_reservation,
397            btreemap!(
398                TYPE_INFO_FIELD_PARTITION => type_info_partition(
399                    TypeInfoSubstate::GlobalAddressReservation(global_address.clone())
400                )
401            ),
402        )?;
403
404        self.api.kernel_pin_node(global_address_reservation)?;
405
406        Ok(GlobalAddressReservation(Own(global_address_reservation)))
407    }
408
409    pub fn get_node_type_info(
410        &mut self,
411        node_id: &NodeId,
412    ) -> Result<TypeInfoSubstate, RuntimeError> {
413        let handle = self.api.kernel_open_substate(
414            node_id,
415            TYPE_INFO_FIELD_PARTITION,
416            &TypeInfoField::TypeInfo.into(),
417            LockFlags::read_only(),
418            SystemLockData::default(),
419        )?;
420        let value = self.api.kernel_read_substate(handle)?;
421        let type_info = value.as_typed::<TypeInfoSubstate>().unwrap();
422        self.api.kernel_close_substate(handle)?;
423        Ok(type_info)
424    }
425
426    fn new_object_internal(
427        &mut self,
428        blueprint_id: &BlueprintId,
429        features: Vec<&str>,
430        instance_context: Option<InstanceContext>,
431        generic_args: GenericArgs,
432        fields: IndexMap<u8, FieldValue>,
433        kv_entries: IndexMap<u8, IndexMap<Vec<u8>, KVEntry>>,
434    ) -> Result<NodeId, RuntimeError> {
435        let blueprint_definition = self.get_blueprint_default_definition(blueprint_id.clone())?;
436        let blueprint_type = blueprint_definition.interface.blueprint_type.clone();
437
438        let object_features: IndexSet<String> =
439            features.into_iter().map(|s| s.to_string()).collect();
440        // Validate features
441        for feature in &object_features {
442            if !blueprint_definition.interface.feature_set.contains(feature) {
443                return Err(RuntimeError::SystemError(SystemError::InvalidFeature(
444                    feature.to_string(),
445                )));
446            }
447        }
448
449        let (outer_obj_info, outer_object_features) =
450            if let BlueprintType::Inner { outer_blueprint } = &blueprint_type {
451                match instance_context {
452                    Some(context) => {
453                        let info = self.get_object_info(context.outer_object.as_node_id())?;
454
455                        if !info
456                            .blueprint_info
457                            .blueprint_id
458                            .blueprint_name
459                            .eq(outer_blueprint)
460                        {
461                            return Err(RuntimeError::SystemError(
462                                SystemError::InvalidChildObjectCreation,
463                            ));
464                        }
465
466                        (
467                            OuterObjectInfo::Some {
468                                outer_object: context.outer_object,
469                            },
470                            info.blueprint_info.features,
471                        )
472                    }
473                    _ => {
474                        return Err(RuntimeError::SystemError(
475                            SystemError::InvalidChildObjectCreation,
476                        ));
477                    }
478                }
479            } else {
480                (OuterObjectInfo::None, index_set_new())
481            };
482
483        let (blueprint_info, mut node_substates) = self.validate_new_object(
484            blueprint_id,
485            &blueprint_definition.interface,
486            outer_obj_info,
487            object_features,
488            &outer_object_features,
489            generic_args,
490            fields,
491            kv_entries,
492        )?;
493
494        let node_id = self.api.kernel_allocate_node_id(
495            IDAllocation::Object {
496                blueprint_id: blueprint_id.clone(),
497                global: false,
498            }
499            .entity_type(),
500        )?;
501
502        node_substates.insert(
503            TYPE_INFO_FIELD_PARTITION,
504            type_info_partition(TypeInfoSubstate::Object(ObjectInfo {
505                blueprint_info,
506                object_type: ObjectType::Owned,
507            })),
508        );
509
510        self.api.kernel_create_node(node_id, node_substates)?;
511
512        if blueprint_definition.interface.is_transient {
513            self.api.kernel_pin_node(node_id)?;
514        }
515
516        if let Some((partition_offset, fields)) = &blueprint_definition.interface.state.fields {
517            for (index, field) in fields.iter().enumerate() {
518                if let FieldTransience::TransientStatic { .. } = field.transience {
519                    let partition_number = match partition_offset {
520                        PartitionDescription::Physical(partition_number) => *partition_number,
521                        PartitionDescription::Logical(offset) => {
522                            MAIN_BASE_PARTITION.at_offset(*offset).unwrap()
523                        }
524                    };
525                    self.api.kernel_mark_substate_as_transient(
526                        node_id,
527                        partition_number,
528                        SubstateKey::Field(index as u8),
529                    )?;
530                }
531            }
532        }
533
534        Ok(node_id.into())
535    }
536
537    fn emit_event_internal(
538        &mut self,
539        actor: EmitterActor,
540        event_name: String,
541        event_data: Vec<u8>,
542        event_flags: EventFlags,
543    ) -> Result<(), RuntimeError> {
544        self.api.kernel_get_system().modules.apply_execution_cost(
545            ExecutionCostingEntry::EmitEvent {
546                size: event_data.len(),
547            },
548        )?;
549
550        // Locking the package info substate associated with the emitter's package
551        // Getting the package address and blueprint name associated with the actor
552        let validation_target = match &actor {
553            EmitterActor::AsObject(node_id, module_id) => {
554                let bp_info = self.get_blueprint_info(node_id, *module_id)?;
555
556                BlueprintTypeTarget {
557                    blueprint_info: bp_info,
558                    meta: SchemaValidationMeta::ExistingObject {
559                        additional_schemas: *node_id,
560                    },
561                }
562            }
563            EmitterActor::CurrentActor => self.get_actor_type_target()?,
564        };
565
566        self.validate_blueprint_payload(
567            &validation_target,
568            BlueprintPayloadIdentifier::Event(event_name.clone()),
569            &event_data,
570        )?;
571
572        // Construct the event type identifier based on the current actor
573        let event_type_identifier = match actor {
574            EmitterActor::AsObject(node_id, module_id, ..) => Ok(EventTypeIdentifier(
575                Emitter::Method(node_id, module_id.into()),
576                event_name,
577            )),
578            EmitterActor::CurrentActor => match self.current_actor() {
579                Actor::Method(MethodActor {
580                    method_type,
581                    node_id,
582                    ..
583                }) => Ok(EventTypeIdentifier(
584                    Emitter::Method(node_id, method_type.module_id()),
585                    event_name,
586                )),
587                Actor::Function(FunctionActor { blueprint_id, .. }) => Ok(EventTypeIdentifier(
588                    Emitter::Function(blueprint_id.clone()),
589                    event_name,
590                )),
591                _ => Err(RuntimeError::SystemModuleError(
592                    SystemModuleError::EventError(Box::new(EventError::InvalidActor)),
593                )),
594            },
595        }?;
596
597        let event = Event {
598            type_identifier: event_type_identifier,
599            payload: event_data,
600            flags: event_flags,
601        };
602
603        // Adding the event to the event store
604        self.api
605            .kernel_get_system()
606            .modules
607            .checked_add_event(event)?;
608
609        Ok(())
610    }
611
612    /// Internal, handle must be checked or from trusted sources
613    fn key_value_entry_remove_and_close_substate(
614        &mut self,
615        handle: KeyValueEntryHandle,
616    ) -> Result<Vec<u8>, RuntimeError> {
617        // TODO: Replace with api::replace
618        let current_value = self
619            .api
620            .kernel_read_substate(handle)
621            .map(|v| v.as_slice().to_vec())?;
622
623        let mut kv_entry: KeyValueEntrySubstate<ScryptoValue> =
624            scrypto_decode(&current_value).unwrap();
625        let value = kv_entry.remove();
626        self.kernel_write_substate(handle, IndexedScryptoValue::from_typed(&kv_entry))?;
627
628        self.kernel_close_substate(handle)?;
629
630        let current_value = scrypto_encode(&value).unwrap();
631
632        Ok(current_value)
633    }
634
635    pub fn get_blueprint_info(
636        &mut self,
637        node_id: &NodeId,
638        module_id: Option<AttachedModuleId>,
639    ) -> Result<BlueprintInfo, RuntimeError> {
640        let info = match module_id {
641            None => self.get_object_info(node_id)?.blueprint_info,
642            Some(module_id) => BlueprintInfo {
643                blueprint_id: module_id.static_blueprint(),
644                blueprint_version: BlueprintVersion::default(),
645                outer_obj_info: OuterObjectInfo::None,
646                features: indexset!(),
647                generic_substitutions: vec![],
648            },
649        };
650
651        Ok(info)
652    }
653
654    pub fn get_actor_type_target(&mut self) -> Result<BlueprintTypeTarget, RuntimeError> {
655        let actor = self.current_actor();
656        match actor {
657            Actor::Root => Err(RuntimeError::SystemError(SystemError::RootHasNoType)),
658            Actor::BlueprintHook(actor) => Ok(BlueprintTypeTarget {
659                blueprint_info: BlueprintInfo {
660                    blueprint_id: actor.blueprint_id.clone(),
661                    blueprint_version: BlueprintVersion::default(),
662                    outer_obj_info: OuterObjectInfo::None,
663                    features: indexset!(),
664                    generic_substitutions: vec![],
665                },
666                meta: SchemaValidationMeta::Blueprint,
667            }),
668            Actor::Function(actor) => Ok(BlueprintTypeTarget {
669                blueprint_info: BlueprintInfo {
670                    blueprint_id: actor.blueprint_id.clone(),
671                    blueprint_version: BlueprintVersion::default(),
672                    outer_obj_info: OuterObjectInfo::None,
673                    features: indexset!(),
674                    generic_substitutions: vec![],
675                },
676                meta: SchemaValidationMeta::Blueprint,
677            }),
678            Actor::Method(actor) => {
679                let blueprint_info =
680                    self.get_blueprint_info(&actor.node_id, actor.method_type.module_id().into())?;
681                Ok(BlueprintTypeTarget {
682                    blueprint_info,
683                    meta: SchemaValidationMeta::ExistingObject {
684                        additional_schemas: actor.node_id,
685                    },
686                })
687            }
688        }
689    }
690
691    fn get_actor_object_id(
692        &mut self,
693        actor_object_type: ActorStateRef,
694    ) -> Result<(NodeId, Option<AttachedModuleId>), RuntimeError> {
695        let actor = self.current_actor();
696        let object_id = actor
697            .get_object_id()
698            .ok_or_else(|| RuntimeError::SystemError(SystemError::NotAnObject))?;
699
700        let object_id = match actor_object_type {
701            ActorStateRef::OuterObject => {
702                let module_id = object_id.1;
703
704                match module_id {
705                    None => {
706                        let node_id = object_id.0;
707                        let address = self.get_outer_object(&node_id)?;
708
709                        (address.into_node_id(), None)
710                    }
711                    _ => {
712                        return Err(RuntimeError::SystemError(
713                            SystemError::OuterObjectDoesNotExist,
714                        ));
715                    }
716                }
717            }
718            ActorStateRef::SELF => object_id,
719        };
720
721        Ok(object_id)
722    }
723
724    fn get_actor_collection_partition_info(
725        &mut self,
726        actor_object_type: ActorStateRef,
727        collection_index: u8,
728        expected_type: &BlueprintPartitionType,
729    ) -> Result<(NodeId, BlueprintInfo, PartitionNumber), RuntimeError> {
730        let (node_id, module_id) = self.get_actor_object_id(actor_object_type)?;
731        let blueprint_info = self.get_blueprint_info(&node_id, module_id)?;
732        let blueprint_definition =
733            self.get_blueprint_default_definition(blueprint_info.blueprint_id.clone())?;
734
735        let partition_num = {
736            let (partition_description, partition_type) = blueprint_definition
737                .interface
738                .state
739                .get_partition(collection_index)
740                .ok_or_else(|| {
741                    RuntimeError::SystemError(SystemError::CollectionIndexDoesNotExist(
742                        blueprint_info.blueprint_id.clone(),
743                        collection_index,
744                    ))
745                })?;
746
747            if !partition_type.eq(expected_type) {
748                return Err(RuntimeError::SystemError(
749                    SystemError::CollectionIndexIsOfWrongType(
750                        blueprint_info.blueprint_id.clone(),
751                        collection_index,
752                        expected_type.to_owned(),
753                        partition_type,
754                    ),
755                ));
756            }
757
758            match partition_description {
759                PartitionDescription::Physical(partition_num) => partition_num,
760                PartitionDescription::Logical(offset) => {
761                    let base = match module_id {
762                        None => MAIN_BASE_PARTITION,
763                        Some(module_id) => {
764                            let object_module: ModuleId = module_id.into();
765                            object_module.base_partition_num()
766                        }
767                    };
768                    base.at_offset(offset).expect("Module number overflow")
769                }
770            }
771        };
772
773        Ok((node_id, blueprint_info, partition_num))
774    }
775
776    fn get_actor_info(
777        &mut self,
778        actor_object_type: ActorStateRef,
779    ) -> Result<
780        (
781            NodeId,
782            Option<AttachedModuleId>,
783            Rc<BlueprintDefinition>,
784            BlueprintInfo,
785        ),
786        RuntimeError,
787    > {
788        let (node_id, module_id) = self.get_actor_object_id(actor_object_type)?;
789        let blueprint_info = self.get_blueprint_info(&node_id, module_id)?;
790        let blueprint_definition =
791            self.get_blueprint_default_definition(blueprint_info.blueprint_id.clone())?;
792
793        Ok((node_id, module_id, blueprint_definition, blueprint_info))
794    }
795
796    fn get_actor_field_info(
797        &mut self,
798        actor_object_type: ActorStateRef,
799        field_index: u8,
800    ) -> Result<(NodeId, BlueprintInfo, PartitionNumber, FieldTransience), RuntimeError> {
801        let (node_id, module_id, blueprint_definition, info) =
802            self.get_actor_info(actor_object_type)?;
803
804        let (partition_description, field_schema) = blueprint_definition
805            .interface
806            .state
807            .field(field_index)
808            .ok_or_else(|| {
809                RuntimeError::SystemError(SystemError::FieldDoesNotExist(
810                    info.blueprint_id.clone(),
811                    field_index,
812                ))
813            })?;
814
815        match field_schema.condition {
816            Condition::IfFeature(feature) => {
817                if !self.is_feature_enabled(&node_id, module_id, feature.as_str())? {
818                    return Err(RuntimeError::SystemError(SystemError::FieldDoesNotExist(
819                        info.blueprint_id.clone(),
820                        field_index,
821                    )));
822                }
823            }
824            Condition::IfOuterFeature(feature) => {
825                let parent_id = match info.outer_obj_info {
826                    OuterObjectInfo::Some { outer_object } => outer_object.into_node_id(),
827                    OuterObjectInfo::None => {
828                        panic!("Outer object should not have IfOuterFeature.")
829                    }
830                };
831
832                if !self.is_feature_enabled(&parent_id, None, feature.as_str())? {
833                    return Err(RuntimeError::SystemError(SystemError::FieldDoesNotExist(
834                        info.blueprint_id.clone(),
835                        field_index,
836                    )));
837                }
838            }
839            Condition::Always => {}
840        }
841
842        let partition_num = match partition_description {
843            PartitionDescription::Physical(partition_num) => partition_num,
844            PartitionDescription::Logical(offset) => {
845                let base = match module_id {
846                    None => MAIN_BASE_PARTITION,
847                    Some(module_id) => {
848                        let object_module: ModuleId = module_id.into();
849                        object_module.base_partition_num()
850                    }
851                };
852                base.at_offset(offset).expect("Module number overflow")
853            }
854        };
855
856        Ok((node_id, info, partition_num, field_schema.transience))
857    }
858
859    /// ASSUMPTIONS:
860    /// Assumes the caller has already checked that the entity type on the GlobalAddress is valid
861    /// against the given self module.
862    fn globalize_with_address_internal(
863        &mut self,
864        node_id: NodeId,
865        modules: IndexMap<AttachedModuleId, NodeId>,
866        global_address_reservation: GlobalAddressReservation,
867    ) -> Result<GlobalAddress, RuntimeError> {
868        // Check global address reservation
869        let global_address = {
870            let dropped_node = self.kernel_drop_node(global_address_reservation.0.as_node_id())?;
871
872            let type_info: Option<TypeInfoSubstate> = dropped_node
873                .substates
874                .get(&TYPE_INFO_FIELD_PARTITION)
875                .and_then(|x| x.get(&TypeInfoField::TypeInfo.into()))
876                .and_then(|x| x.as_typed().ok());
877
878            match type_info {
879                Some(TypeInfoSubstate::GlobalAddressReservation(x)) => x,
880                _ => {
881                    return Err(RuntimeError::SystemError(
882                        SystemError::InvalidGlobalAddressReservation,
883                    ));
884                }
885            }
886        };
887
888        // Check blueprint id
889        let reserved_blueprint_id = {
890            let lock_handle = self.kernel_open_substate(
891                global_address.as_node_id(),
892                TYPE_INFO_FIELD_PARTITION,
893                &TypeInfoField::TypeInfo.into(),
894                LockFlags::MUTABLE, // This is to ensure the substate is lock free!
895                SystemLockData::Default,
896            )?;
897            let type_info: TypeInfoSubstate =
898                self.kernel_read_substate(lock_handle)?.as_typed().unwrap();
899            self.kernel_close_substate(lock_handle)?;
900            match type_info {
901                TypeInfoSubstate::GlobalAddressPhantom(GlobalAddressPhantom { blueprint_id }) => {
902                    blueprint_id
903                }
904                _ => unreachable!(),
905            }
906        };
907
908        // For simplicity, a rule is enforced at system layer: only the package can globalize a node
909        // In the future, we may consider allowing customization at blueprint level.
910        let actor = self.current_actor();
911        if Some(reserved_blueprint_id.package_address) != actor.package_address() {
912            return Err(RuntimeError::SystemError(
913                SystemError::InvalidGlobalizeAccess(Box::new(InvalidGlobalizeAccess {
914                    package_address: reserved_blueprint_id.package_address,
915                    blueprint_name: reserved_blueprint_id.blueprint_name,
916                    actor_package: actor.package_address(),
917                })),
918            ));
919        }
920
921        // Check for required modules
922        if !modules.contains_key(&AttachedModuleId::RoleAssignment) {
923            return Err(RuntimeError::SystemError(SystemError::MissingModule(
924                ModuleId::RoleAssignment,
925            )));
926        }
927        if !modules.contains_key(&AttachedModuleId::Metadata) {
928            return Err(RuntimeError::SystemError(SystemError::MissingModule(
929                ModuleId::Metadata,
930            )));
931        }
932
933        self.api
934            .kernel_get_system_state()
935            .system
936            .modules
937            .add_replacement(
938                (node_id, ModuleId::Main),
939                (*global_address.as_node_id(), ModuleId::Main),
940            );
941
942        // Read the type info
943        let mut object_info = self.get_object_info(&node_id)?;
944
945        // Verify can globalize with address
946        let num_main_partitions = {
947            if object_info.is_global() {
948                return Err(RuntimeError::SystemError(SystemError::CannotGlobalize(
949                    CannotGlobalizeError::AlreadyGlobalized,
950                )));
951            }
952            if !object_info
953                .blueprint_info
954                .blueprint_id
955                .eq(&reserved_blueprint_id)
956            {
957                return Err(RuntimeError::SystemError(SystemError::CannotGlobalize(
958                    CannotGlobalizeError::InvalidBlueprintId,
959                )));
960            }
961            let blueprint_definition = self.get_blueprint_default_definition(
962                object_info.blueprint_info.blueprint_id.clone(),
963            )?;
964
965            if blueprint_definition.interface.is_transient {
966                return Err(RuntimeError::SystemError(
967                    SystemError::GlobalizingTransientBlueprint,
968                ));
969            }
970
971            blueprint_definition
972                .interface
973                .state
974                .num_logical_partitions()
975        };
976
977        let mut partitions = btreemap!(
978            SCHEMAS_PARTITION => (node_id, SCHEMAS_PARTITION),
979        );
980
981        // Move self modules to the newly created global node, and drop
982        for offset in 0u8..num_main_partitions {
983            let partition_number = MAIN_BASE_PARTITION
984                .at_offset(PartitionOffset(offset))
985                .unwrap();
986
987            partitions.insert(partition_number, (node_id, partition_number));
988        }
989
990        // Move other modules, and drop
991        for (module_id, node_id) in &modules {
992            match module_id {
993                AttachedModuleId::RoleAssignment
994                | AttachedModuleId::Metadata
995                | AttachedModuleId::Royalty => {
996                    let blueprint_id = self.get_object_info(node_id)?.blueprint_info.blueprint_id;
997                    let expected_blueprint = module_id.static_blueprint();
998                    if !blueprint_id.eq(&expected_blueprint) {
999                        return Err(RuntimeError::SystemError(SystemError::InvalidModuleType(
1000                            Box::new(InvalidModuleType {
1001                                expected_blueprint,
1002                                actual_blueprint: blueprint_id,
1003                            }),
1004                        )));
1005                    }
1006
1007                    self.api
1008                        .kernel_get_system_state()
1009                        .system
1010                        .modules
1011                        .add_replacement(
1012                            (*node_id, ModuleId::Main),
1013                            (*global_address.as_node_id(), module_id.clone().into()),
1014                        );
1015
1016                    // Move and drop
1017                    let blueprint_definition =
1018                        self.get_blueprint_default_definition(blueprint_id.clone())?;
1019                    let num_logical_partitions = blueprint_definition
1020                        .interface
1021                        .state
1022                        .num_logical_partitions();
1023
1024                    let module_id: ModuleId = module_id.clone().into();
1025                    let module_base_partition = module_id.base_partition_num();
1026                    for offset in 0u8..num_logical_partitions {
1027                        let src = MAIN_BASE_PARTITION
1028                            .at_offset(PartitionOffset(offset))
1029                            .unwrap();
1030                        let dest = module_base_partition
1031                            .at_offset(PartitionOffset(offset))
1032                            .unwrap();
1033
1034                        partitions.insert(dest, (*node_id, src));
1035                    }
1036                }
1037            }
1038        }
1039
1040        self.kernel_create_node_from(global_address.into(), partitions)?;
1041
1042        // Update Object Info
1043        {
1044            let mut module_versions = index_map_new();
1045            for module_id in modules.keys() {
1046                module_versions.insert(module_id.clone(), BlueprintVersion::default());
1047            }
1048            object_info.object_type = ObjectType::Global {
1049                modules: module_versions,
1050            };
1051
1052            self.kernel_set_substate(
1053                &global_address.into(),
1054                TYPE_INFO_FIELD_PARTITION,
1055                SubstateKey::Field(0u8),
1056                IndexedScryptoValue::from_typed(&TypeInfoSubstate::Object(object_info)),
1057            )?;
1058        }
1059
1060        // Drop nodes
1061        {
1062            self.kernel_drop_node(&node_id)?;
1063            for (_module_id, node_id) in &modules {
1064                self.kernel_drop_node(&node_id)?;
1065            }
1066        }
1067
1068        Ok(global_address)
1069    }
1070
1071    #[cfg_attr(feature = "std", catch_unwind_ignore)]
1072    pub fn current_actor(&mut self) -> Actor {
1073        self.api
1074            .kernel_get_system_state()
1075            .current_call_frame
1076            .clone()
1077    }
1078
1079    pub fn get_object_info(&mut self, node_id: &NodeId) -> Result<ObjectInfo, RuntimeError> {
1080        let type_info = TypeInfoBlueprint::get_type(&node_id, self.api)?;
1081        let object_info = match type_info {
1082            TypeInfoSubstate::Object(info) => info,
1083            _ => return Err(RuntimeError::SystemError(SystemError::NotAnObject)),
1084        };
1085
1086        Ok(object_info)
1087    }
1088
1089    pub fn is_feature_enabled(
1090        &mut self,
1091        node_id: &NodeId,
1092        module_id: Option<AttachedModuleId>,
1093        feature: &str,
1094    ) -> Result<bool, RuntimeError> {
1095        match module_id {
1096            None => {
1097                let object_info = self.get_object_info(node_id)?;
1098                let enabled = object_info.blueprint_info.features.contains(feature);
1099                Ok(enabled)
1100            }
1101            _ => Ok(false),
1102        }
1103    }
1104}
1105
1106#[cfg_attr(
1107    feature = "std",
1108    catch_unwind(crate::utils::catch_unwind_system_panic_transformer)
1109)]
1110impl<'a, Y: SystemBasedKernelApi> SystemFieldApi<RuntimeError> for SystemService<'a, Y> {
1111    // Costing through kernel
1112    #[trace_resources]
1113    fn field_read(&mut self, handle: FieldHandle) -> Result<Vec<u8>, RuntimeError> {
1114        let data = self.api.kernel_get_lock_data(handle)?;
1115        match data {
1116            SystemLockData::Field(..) => {}
1117            _ => {
1118                return Err(RuntimeError::SystemError(SystemError::NotAFieldHandle));
1119            }
1120        }
1121
1122        self.api.kernel_read_substate(handle).map(|v| {
1123            let wrapper: FieldSubstate<ScryptoValue> = v.as_typed().unwrap();
1124            scrypto_encode(&wrapper.into_payload()).unwrap()
1125        })
1126    }
1127
1128    // Costing through kernel
1129    #[trace_resources]
1130    fn field_write(&mut self, handle: FieldHandle, buffer: Vec<u8>) -> Result<(), RuntimeError> {
1131        let data = self.api.kernel_get_lock_data(handle)?;
1132
1133        match data {
1134            SystemLockData::Field(FieldLockData::Write {
1135                target,
1136                field_index,
1137            }) => {
1138                self.validate_blueprint_payload(
1139                    &target,
1140                    BlueprintPayloadIdentifier::Field(field_index),
1141                    &buffer,
1142                )?;
1143            }
1144            _ => {
1145                return Err(RuntimeError::SystemError(SystemError::NotAFieldWriteHandle));
1146            }
1147        };
1148
1149        let value: ScryptoValue =
1150            scrypto_decode(&buffer).expect("Should be valid due to payload check");
1151
1152        let substate = IndexedScryptoValue::from_typed(&FieldSubstate::new_unlocked_field(value));
1153
1154        self.api.kernel_write_substate(handle, substate)?;
1155
1156        Ok(())
1157    }
1158
1159    // Costing through kernel
1160    #[trace_resources]
1161    fn field_lock(&mut self, handle: FieldHandle) -> Result<(), RuntimeError> {
1162        let data = self.api.kernel_get_lock_data(handle)?;
1163
1164        match data {
1165            SystemLockData::Field(FieldLockData::Write { .. }) => {}
1166            _ => {
1167                return Err(RuntimeError::SystemError(SystemError::NotAFieldWriteHandle));
1168            }
1169        }
1170
1171        let v = self.api.kernel_read_substate(handle)?;
1172        let mut substate: FieldSubstate<ScryptoValue> = v.as_typed().unwrap();
1173        substate.lock();
1174        let indexed = IndexedScryptoValue::from_typed(&substate);
1175        self.api.kernel_write_substate(handle, indexed)?;
1176
1177        Ok(())
1178    }
1179
1180    // Costing through kernel
1181    #[trace_resources]
1182    fn field_close(&mut self, handle: FieldHandle) -> Result<(), RuntimeError> {
1183        let data = self.api.kernel_get_lock_data(handle)?;
1184        match data {
1185            SystemLockData::Field(..) => {}
1186            _ => {
1187                return Err(RuntimeError::SystemError(SystemError::NotAFieldHandle));
1188            }
1189        }
1190
1191        self.api.kernel_close_substate(handle)
1192    }
1193}
1194
1195#[cfg_attr(
1196    feature = "std",
1197    catch_unwind(crate::utils::catch_unwind_system_panic_transformer)
1198)]
1199impl<'a, Y: SystemBasedKernelApi> SystemObjectApi<RuntimeError> for SystemService<'a, Y> {
1200    // Costing through kernel
1201    #[trace_resources]
1202    fn new_object(
1203        &mut self,
1204        blueprint_ident: &str,
1205        features: Vec<&str>,
1206        generic_args: GenericArgs,
1207        fields: IndexMap<u8, FieldValue>,
1208        kv_entries: IndexMap<u8, IndexMap<Vec<u8>, KVEntry>>,
1209    ) -> Result<NodeId, RuntimeError> {
1210        let actor = self.current_actor();
1211        let package_address = actor
1212            .blueprint_id()
1213            .map(|b| b.package_address)
1214            .ok_or(RuntimeError::SystemError(SystemError::NoPackageAddress))?;
1215        let blueprint_id = BlueprintId::new(&package_address, blueprint_ident);
1216        let instance_context = actor.instance_context();
1217
1218        self.new_object_internal(
1219            &blueprint_id,
1220            features,
1221            instance_context,
1222            generic_args,
1223            fields,
1224            kv_entries,
1225        )
1226    }
1227
1228    // Costing through kernel
1229    #[trace_resources]
1230    fn allocate_global_address(
1231        &mut self,
1232        blueprint_id: BlueprintId,
1233    ) -> Result<(GlobalAddressReservation, GlobalAddress), RuntimeError> {
1234        let global_address_node_id = self.api.kernel_allocate_node_id(
1235            IDAllocation::Object {
1236                blueprint_id: blueprint_id.clone(),
1237                global: true,
1238            }
1239            .entity_type(),
1240        )?;
1241        let global_address = GlobalAddress::try_from(global_address_node_id.0).unwrap();
1242
1243        // Create global address reservation
1244        let global_address_reservation =
1245            self.prepare_global_address(blueprint_id, global_address)?;
1246
1247        // NOTE: Because allocated global address is represented as an owned object and nobody is allowed
1248        // to drop it except the system during globalization, we don't track the lifecycle of
1249        // allocated addresses.
1250
1251        Ok((global_address_reservation, global_address))
1252    }
1253
1254    // Costing through kernel
1255    #[trace_resources]
1256    fn allocate_virtual_global_address(
1257        &mut self,
1258        blueprint_id: BlueprintId,
1259        global_address: GlobalAddress,
1260    ) -> Result<GlobalAddressReservation, RuntimeError> {
1261        let global_address_reservation =
1262            self.prepare_global_address(blueprint_id, global_address)?;
1263
1264        Ok(global_address_reservation)
1265    }
1266
1267    // Costing through kernel
1268    #[trace_resources]
1269    fn globalize(
1270        &mut self,
1271        node_id: NodeId,
1272        modules: IndexMap<AttachedModuleId, NodeId>,
1273        address_reservation: Option<GlobalAddressReservation>,
1274    ) -> Result<GlobalAddress, RuntimeError> {
1275        // TODO: optimize by skipping address allocation
1276        let (global_address_reservation, global_address) =
1277            if let Some(reservation) = address_reservation {
1278                let address = self.get_reservation_address(reservation.0.as_node_id())?;
1279                (reservation, address)
1280            } else {
1281                let blueprint_id = self.get_object_info(&node_id)?.blueprint_info.blueprint_id;
1282                self.allocate_global_address(blueprint_id)?
1283            };
1284
1285        self.globalize_with_address_internal(node_id, modules, global_address_reservation)?;
1286
1287        Ok(global_address)
1288    }
1289
1290    // Costing through kernel
1291    #[trace_resources]
1292    fn globalize_with_address_and_create_inner_object_and_emit_event(
1293        &mut self,
1294        node_id: NodeId,
1295        modules: IndexMap<AttachedModuleId, NodeId>,
1296        address_reservation: GlobalAddressReservation,
1297        inner_object_blueprint: &str,
1298        inner_object_fields: IndexMap<u8, FieldValue>,
1299        event_name: &str,
1300        event_data: Vec<u8>,
1301    ) -> Result<(GlobalAddress, NodeId), RuntimeError> {
1302        let actor_blueprint = self.get_object_info(&node_id)?.blueprint_info.blueprint_id;
1303
1304        let global_address =
1305            self.globalize_with_address_internal(node_id, modules, address_reservation)?;
1306
1307        let blueprint_id =
1308            BlueprintId::new(&actor_blueprint.package_address, inner_object_blueprint);
1309
1310        let inner_object = self.new_object_internal(
1311            &blueprint_id,
1312            vec![],
1313            Some(InstanceContext {
1314                outer_object: global_address,
1315            }),
1316            GenericArgs::default(),
1317            inner_object_fields,
1318            indexmap!(),
1319        )?;
1320
1321        self.emit_event_internal(
1322            EmitterActor::AsObject(global_address.as_node_id().clone(), None),
1323            event_name.to_string(),
1324            event_data,
1325            EventFlags::empty(),
1326        )?;
1327
1328        Ok((global_address, inner_object))
1329    }
1330
1331    #[trace_resources]
1332    fn call_method(
1333        &mut self,
1334        receiver: &NodeId,
1335        method_name: &str,
1336        args: Vec<u8>,
1337    ) -> Result<Vec<u8>, RuntimeError> {
1338        let object_info = self.get_object_info(&receiver)?;
1339
1340        let args = IndexedScryptoValue::from_vec(args).map_err(|e| {
1341            RuntimeError::SystemUpstreamError(SystemUpstreamError::InputDecodeError(e))
1342        })?;
1343
1344        let auth_actor_info = SystemModuleMixer::on_call_method(
1345            self,
1346            receiver,
1347            ModuleId::Main,
1348            false,
1349            method_name,
1350            &args,
1351        )?;
1352
1353        let rtn = self
1354            .api
1355            .kernel_invoke(Box::new(KernelInvocation {
1356                call_frame_data: Actor::Method(MethodActor {
1357                    method_type: MethodType::Main,
1358                    node_id: receiver.clone(),
1359                    ident: method_name.to_string(),
1360                    auth_zone: auth_actor_info.clone(),
1361                    object_info,
1362                }),
1363                args,
1364            }))
1365            .map(|v| v.into())?;
1366
1367        SystemModuleMixer::on_call_method_finish(self, auth_actor_info)?;
1368
1369        Ok(rtn)
1370    }
1371
1372    #[trace_resources]
1373    fn call_direct_access_method(
1374        &mut self,
1375        receiver: &NodeId,
1376        method_name: &str,
1377        args: Vec<u8>,
1378    ) -> Result<Vec<u8>, RuntimeError> {
1379        let object_info = self.get_object_info(&receiver)?;
1380
1381        let args = IndexedScryptoValue::from_vec(args).map_err(|e| {
1382            RuntimeError::SystemUpstreamError(SystemUpstreamError::InputDecodeError(e))
1383        })?;
1384
1385        let auth_actor_info = SystemModuleMixer::on_call_method(
1386            self,
1387            receiver,
1388            ModuleId::Main,
1389            true,
1390            method_name,
1391            &args,
1392        )?;
1393
1394        let rtn = self
1395            .api
1396            .kernel_invoke(Box::new(KernelInvocation {
1397                call_frame_data: Actor::Method(MethodActor {
1398                    method_type: MethodType::Direct,
1399                    node_id: receiver.clone(),
1400                    ident: method_name.to_string(),
1401
1402                    auth_zone: auth_actor_info.clone(),
1403                    object_info,
1404                }),
1405                args,
1406            }))
1407            .map(|v| v.into())?;
1408
1409        SystemModuleMixer::on_call_method_finish(self, auth_actor_info)?;
1410
1411        Ok(rtn)
1412    }
1413
1414    // Costing through kernel
1415    #[trace_resources]
1416    fn call_module_method(
1417        &mut self,
1418        receiver: &NodeId,
1419        module_id: AttachedModuleId,
1420        method_name: &str,
1421        args: Vec<u8>,
1422    ) -> Result<Vec<u8>, RuntimeError> {
1423        // Key Value Stores do not have methods so we remove that possibility here
1424        let object_info = self.get_object_info(&receiver)?;
1425        match &object_info.object_type {
1426            ObjectType::Owned => {
1427                return Err(RuntimeError::SystemError(
1428                    SystemError::ObjectModuleDoesNotExist(module_id),
1429                ));
1430            }
1431            ObjectType::Global { modules } => {
1432                if !modules.contains_key(&module_id) {
1433                    return Err(RuntimeError::SystemError(
1434                        SystemError::ObjectModuleDoesNotExist(module_id),
1435                    ));
1436                }
1437            }
1438        }
1439
1440        let args = IndexedScryptoValue::from_vec(args).map_err(|e| {
1441            RuntimeError::SystemUpstreamError(SystemUpstreamError::InputDecodeError(e))
1442        })?;
1443
1444        let auth_actor_info = SystemModuleMixer::on_call_method(
1445            self,
1446            receiver,
1447            module_id.into(),
1448            false,
1449            method_name,
1450            &args,
1451        )?;
1452
1453        let rtn = self
1454            .api
1455            .kernel_invoke(Box::new(KernelInvocation {
1456                call_frame_data: Actor::Method(MethodActor {
1457                    method_type: MethodType::Module(module_id),
1458                    node_id: receiver.clone(),
1459                    ident: method_name.to_string(),
1460
1461                    auth_zone: auth_actor_info.clone(),
1462                    object_info,
1463                }),
1464                args,
1465            }))
1466            .map(|v| v.into())?;
1467
1468        SystemModuleMixer::on_call_method_finish(self, auth_actor_info)?;
1469
1470        Ok(rtn)
1471    }
1472
1473    // Costing through kernel
1474    #[trace_resources]
1475    fn get_blueprint_id(&mut self, node_id: &NodeId) -> Result<BlueprintId, RuntimeError> {
1476        let blueprint_id = self.get_object_info(node_id)?.blueprint_info.blueprint_id;
1477        Ok(blueprint_id)
1478    }
1479
1480    // Costing through kernel
1481    #[trace_resources]
1482    fn get_outer_object(&mut self, node_id: &NodeId) -> Result<GlobalAddress, RuntimeError> {
1483        match self.get_object_info(node_id)?.try_get_outer_object() {
1484            None => Err(RuntimeError::SystemError(
1485                SystemError::OuterObjectDoesNotExist,
1486            )),
1487            Some(address) => Ok(address),
1488        }
1489    }
1490
1491    // Costing through kernel
1492    #[trace_resources]
1493    fn get_reservation_address(&mut self, node_id: &NodeId) -> Result<GlobalAddress, RuntimeError> {
1494        let type_info = TypeInfoBlueprint::get_type(&node_id, self.api)?;
1495        let address = match type_info {
1496            TypeInfoSubstate::GlobalAddressReservation(address) => address,
1497            _ => {
1498                return Err(RuntimeError::SystemError(
1499                    SystemError::NotAnAddressReservation,
1500                ))
1501            }
1502        };
1503
1504        Ok(address)
1505    }
1506
1507    // Costing through kernel
1508    #[trace_resources]
1509    fn drop_object(&mut self, node_id: &NodeId) -> Result<Vec<Vec<u8>>, RuntimeError> {
1510        // For simplicity, a rule is enforced at system layer: only the package can drop a node
1511        // In the future, we may consider allowing customization at blueprint level.
1512        let info = self.get_object_info(node_id)?;
1513        let actor = self.current_actor();
1514
1515        let instance_context_check = {
1516            // Allow proofs to be dropped on their own
1517            if info.blueprint_info.blueprint_id.eq(&BlueprintId::new(
1518                &RESOURCE_PACKAGE,
1519                FUNGIBLE_PROOF_BLUEPRINT,
1520            )) || info.blueprint_info.blueprint_id.eq(&BlueprintId::new(
1521                &RESOURCE_PACKAGE,
1522                NON_FUNGIBLE_PROOF_BLUEPRINT,
1523            )) {
1524                None
1525            } else {
1526                match info.blueprint_info.outer_obj_info {
1527                    OuterObjectInfo::Some { outer_object } => Some(outer_object),
1528                    OuterObjectInfo::None => None,
1529                }
1530            }
1531        };
1532
1533        // If outer object exists, only outer object may drop object
1534        if let Some(outer_object) = instance_context_check {
1535            match actor.instance_context() {
1536                Some(instance_context) if instance_context.outer_object.eq(&outer_object) => {}
1537                _ => {
1538                    return Err(RuntimeError::SystemError(SystemError::InvalidDropAccess(
1539                        Box::new(InvalidDropAccess {
1540                            node_id: (*node_id).into(),
1541                            package_address: info.blueprint_info.blueprint_id.package_address,
1542                            blueprint_name: info.blueprint_info.blueprint_id.blueprint_name,
1543                            actor_package: actor.package_address(),
1544                        }),
1545                    )));
1546                }
1547            }
1548        } else {
1549            // Otherwise, only blueprint may drop object
1550            if Some(info.blueprint_info.blueprint_id.clone()) != actor.blueprint_id() {
1551                return Err(RuntimeError::SystemError(SystemError::InvalidDropAccess(
1552                    Box::new(InvalidDropAccess {
1553                        node_id: (*node_id).into(),
1554                        package_address: info.blueprint_info.blueprint_id.package_address,
1555                        blueprint_name: info.blueprint_info.blueprint_id.blueprint_name,
1556                        actor_package: actor.package_address(),
1557                    }),
1558                )));
1559            }
1560        }
1561
1562        let mut dropped_node = self.api.kernel_drop_node(&node_id)?;
1563        let fields =
1564            if let Some(user_substates) = dropped_node.substates.remove(&MAIN_BASE_PARTITION) {
1565                user_substates
1566                    .into_iter()
1567                    .map(|(_key, v)| {
1568                        let substate: FieldSubstate<ScryptoValue> = v.as_typed().unwrap();
1569                        scrypto_encode(&substate.into_payload()).unwrap()
1570                    })
1571                    .collect()
1572            } else {
1573                vec![]
1574            };
1575
1576        Ok(fields)
1577    }
1578}
1579
1580#[cfg_attr(
1581    feature = "std",
1582    catch_unwind(crate::utils::catch_unwind_system_panic_transformer)
1583)]
1584impl<'a, Y: SystemBasedKernelApi> SystemKeyValueEntryApi<RuntimeError> for SystemService<'a, Y> {
1585    // Costing through kernel
1586    #[trace_resources]
1587    fn key_value_entry_get(
1588        &mut self,
1589        handle: KeyValueEntryHandle,
1590    ) -> Result<Vec<u8>, RuntimeError> {
1591        let data = self.api.kernel_get_lock_data(handle)?;
1592        if !data.is_kv_entry() {
1593            return Err(RuntimeError::SystemError(
1594                SystemError::NotAKeyValueEntryHandle,
1595            ));
1596        }
1597
1598        self.api.kernel_read_substate(handle).map(|v| {
1599            let wrapper: KeyValueEntrySubstate<ScryptoValue> = v.as_typed().unwrap();
1600            scrypto_encode(&wrapper.into_value()).unwrap()
1601        })
1602    }
1603
1604    // Costing through kernel
1605    fn key_value_entry_lock(&mut self, handle: KeyValueEntryHandle) -> Result<(), RuntimeError> {
1606        let data = self.api.kernel_get_lock_data(handle)?;
1607        match data {
1608            SystemLockData::KeyValueEntry(
1609                KeyValueEntryLockData::KVStoreWrite { .. }
1610                | KeyValueEntryLockData::KVCollectionWrite { .. },
1611            ) => {}
1612            _ => {
1613                return Err(RuntimeError::SystemError(
1614                    SystemError::NotAKeyValueEntryWriteHandle,
1615                ));
1616            }
1617        };
1618
1619        let v = self.api.kernel_read_substate(handle)?;
1620        let mut kv_entry: KeyValueEntrySubstate<ScryptoValue> = v.as_typed().unwrap();
1621        kv_entry.lock();
1622        let indexed = IndexedScryptoValue::from_typed(&kv_entry);
1623        self.api.kernel_write_substate(handle, indexed)?;
1624        Ok(())
1625    }
1626
1627    // Costing through kernel
1628    fn key_value_entry_remove(
1629        &mut self,
1630        handle: KeyValueEntryHandle,
1631    ) -> Result<Vec<u8>, RuntimeError> {
1632        let data = self.api.kernel_get_lock_data(handle)?;
1633        if !data.is_kv_entry_with_write() {
1634            return Err(RuntimeError::SystemError(
1635                SystemError::NotAKeyValueEntryWriteHandle,
1636            ));
1637        }
1638
1639        let current_value = self
1640            .api
1641            .kernel_read_substate(handle)
1642            .map(|v| v.as_slice().to_vec())?;
1643
1644        let mut kv_entry: KeyValueEntrySubstate<ScryptoValue> =
1645            scrypto_decode(&current_value).unwrap();
1646        let value = kv_entry.remove();
1647        self.kernel_write_substate(handle, IndexedScryptoValue::from_typed(&kv_entry))?;
1648
1649        let current_value = scrypto_encode(&value).unwrap();
1650
1651        Ok(current_value)
1652    }
1653
1654    // Costing through kernel
1655    #[trace_resources]
1656    fn key_value_entry_set(
1657        &mut self,
1658        handle: KeyValueEntryHandle,
1659        buffer: Vec<u8>,
1660    ) -> Result<(), RuntimeError> {
1661        let data = self.api.kernel_get_lock_data(handle)?;
1662
1663        match data {
1664            SystemLockData::KeyValueEntry(KeyValueEntryLockData::KVCollectionWrite {
1665                collection_index,
1666                target,
1667            }) => {
1668                self.validate_blueprint_payload(
1669                    &target,
1670                    BlueprintPayloadIdentifier::KeyValueEntry(collection_index, KeyOrValue::Value),
1671                    &buffer,
1672                )?;
1673            }
1674            SystemLockData::KeyValueEntry(KeyValueEntryLockData::KVStoreWrite {
1675                kv_store_validation_target,
1676            }) => {
1677                self.validate_kv_store_payload(
1678                    &kv_store_validation_target,
1679                    KeyOrValue::Value,
1680                    &buffer,
1681                )?;
1682            }
1683            _ => {
1684                return Err(RuntimeError::SystemError(
1685                    SystemError::NotAKeyValueEntryWriteHandle,
1686                ));
1687            }
1688        }
1689
1690        let substate =
1691            IndexedScryptoValue::from_slice(&buffer).expect("Should be valid due to payload check");
1692
1693        let value = substate.as_scrypto_value().clone();
1694        let kv_entry = KeyValueEntrySubstate::unlocked_entry(value);
1695        let indexed = IndexedScryptoValue::from_typed(&kv_entry);
1696
1697        self.api.kernel_write_substate(handle, indexed)?;
1698
1699        Ok(())
1700    }
1701
1702    // Costing through kernel
1703    fn key_value_entry_close(&mut self, handle: KeyValueEntryHandle) -> Result<(), RuntimeError> {
1704        let data = self.api.kernel_get_lock_data(handle)?;
1705        if !data.is_kv_entry() {
1706            return Err(RuntimeError::SystemError(
1707                SystemError::NotAKeyValueEntryHandle,
1708            ));
1709        }
1710
1711        self.api.kernel_close_substate(handle)
1712    }
1713}
1714
1715#[cfg_attr(
1716    feature = "std",
1717    catch_unwind(crate::utils::catch_unwind_system_panic_transformer)
1718)]
1719impl<'a, Y: SystemBasedKernelApi> SystemKeyValueStoreApi<RuntimeError> for SystemService<'a, Y> {
1720    // Costing through kernel
1721    #[trace_resources]
1722    fn key_value_store_new(
1723        &mut self,
1724        data_schema: KeyValueStoreDataSchema,
1725    ) -> Result<NodeId, RuntimeError> {
1726        let mut additional_schemas = index_map_new();
1727        let (key_type, value_type, allow_ownership) = match data_schema {
1728            KeyValueStoreDataSchema::Local {
1729                additional_schema,
1730                key_type,
1731                value_type,
1732                allow_ownership,
1733            } => {
1734                validate_schema(additional_schema.v1())
1735                    .map_err(|_| RuntimeError::SystemError(SystemError::InvalidGenericArgs))?;
1736                let schema_hash = additional_schema.generate_schema_hash();
1737                additional_schemas.insert(schema_hash, additional_schema);
1738                (
1739                    GenericSubstitution::Local(ScopedTypeId(schema_hash, key_type)),
1740                    GenericSubstitution::Local(ScopedTypeId(schema_hash, value_type)),
1741                    allow_ownership,
1742                )
1743            }
1744            KeyValueStoreDataSchema::Remote {
1745                key_type,
1746                value_type,
1747                allow_ownership,
1748            } => (
1749                GenericSubstitution::Remote(key_type),
1750                GenericSubstitution::Remote(value_type),
1751                allow_ownership,
1752            ),
1753        };
1754
1755        self.validate_kv_store_generic_args(&additional_schemas, &key_type, &value_type)
1756            .map_err(|e| RuntimeError::SystemError(SystemError::TypeCheckError(e)))?;
1757
1758        let schema_partition = additional_schemas
1759            .into_iter()
1760            .map(|(schema_hash, schema)| {
1761                let key = SubstateKey::Map(scrypto_encode(&schema_hash).unwrap());
1762                let substate = KeyValueEntrySubstate::locked_entry(schema);
1763                let value = IndexedScryptoValue::from_typed(&substate);
1764                (key, value)
1765            })
1766            .collect();
1767
1768        let generic_substitutions = KeyValueStoreGenericSubstitutions {
1769            key_generic_substitution: key_type,
1770            value_generic_substitution: value_type,
1771            allow_ownership: allow_ownership,
1772        };
1773
1774        let node_id = self
1775            .api
1776            .kernel_allocate_node_id(IDAllocation::KeyValueStore.entity_type())?;
1777
1778        self.api.kernel_create_node(
1779            node_id,
1780            btreemap!(
1781                MAIN_BASE_PARTITION => btreemap!(),
1782                TYPE_INFO_FIELD_PARTITION => type_info_partition(
1783                    TypeInfoSubstate::KeyValueStore(KeyValueStoreInfo {
1784                        generic_substitutions,
1785                    })
1786                ),
1787                SCHEMAS_PARTITION => schema_partition,
1788            ),
1789        )?;
1790
1791        Ok(node_id)
1792    }
1793
1794    // Costing through kernel
1795    #[trace_resources]
1796    fn key_value_store_open_entry(
1797        &mut self,
1798        node_id: &NodeId,
1799        key: &Vec<u8>,
1800        flags: LockFlags,
1801    ) -> Result<KeyValueEntryHandle, RuntimeError> {
1802        let type_info = TypeInfoBlueprint::get_type(&node_id, self.api)?;
1803
1804        if flags.contains(LockFlags::UNMODIFIED_BASE) || flags.contains(LockFlags::FORCE_WRITE) {
1805            return Err(RuntimeError::SystemError(SystemError::InvalidLockFlags));
1806        }
1807
1808        let info = match type_info {
1809            TypeInfoSubstate::KeyValueStore(info) => info,
1810            _ => return Err(RuntimeError::SystemError(SystemError::NotAKeyValueStore)),
1811        };
1812
1813        let target = KVStoreTypeTarget {
1814            kv_store_type: info.generic_substitutions,
1815            meta: *node_id,
1816        };
1817
1818        self.validate_kv_store_payload(&target, KeyOrValue::Key, &key)?;
1819
1820        let lock_data = if flags.contains(LockFlags::MUTABLE) {
1821            SystemLockData::KeyValueEntry(KeyValueEntryLockData::KVStoreWrite {
1822                kv_store_validation_target: target,
1823            })
1824        } else {
1825            SystemLockData::KeyValueEntry(KeyValueEntryLockData::Read)
1826        };
1827
1828        let handle = self.api.kernel_open_substate_with_default(
1829            &node_id,
1830            MAIN_BASE_PARTITION,
1831            &SubstateKey::Map(key.clone()),
1832            flags,
1833            Some(|| {
1834                let kv_entry = KeyValueEntrySubstate::<()>::default();
1835                IndexedScryptoValue::from_typed(&kv_entry)
1836            }),
1837            lock_data,
1838        )?;
1839
1840        if flags.contains(LockFlags::MUTABLE) {
1841            let lock_status = self.api.kernel_read_substate(handle).map(|v| {
1842                let kv_entry: KeyValueEntrySubstate<ScryptoValue> = v.as_typed().unwrap();
1843                kv_entry.lock_status()
1844            })?;
1845
1846            if let LockStatus::Locked = lock_status {
1847                return Err(RuntimeError::SystemError(SystemError::KeyValueEntryLocked));
1848            }
1849        }
1850
1851        Ok(handle)
1852    }
1853
1854    // Costing through kernel
1855    fn key_value_store_remove_entry(
1856        &mut self,
1857        node_id: &NodeId,
1858        key: &Vec<u8>,
1859    ) -> Result<Vec<u8>, RuntimeError> {
1860        let handle = self.key_value_store_open_entry(node_id, key, LockFlags::MUTABLE)?;
1861        self.key_value_entry_remove_and_close_substate(handle)
1862    }
1863}
1864
1865#[cfg_attr(
1866    feature = "std",
1867    catch_unwind(crate::utils::catch_unwind_system_panic_transformer)
1868)]
1869impl<'a, Y: SystemBasedKernelApi> SystemActorIndexApi<RuntimeError> for SystemService<'a, Y> {
1870    // Costing through kernel
1871    fn actor_index_insert(
1872        &mut self,
1873        object_handle: ActorStateHandle,
1874        collection_index: CollectionIndex,
1875        key: Vec<u8>,
1876        buffer: Vec<u8>,
1877    ) -> Result<(), RuntimeError> {
1878        let actor_object_type: ActorStateRef = object_handle.try_into()?;
1879
1880        let (node_id, info, partition_num) = self.get_actor_collection_partition_info(
1881            actor_object_type,
1882            collection_index,
1883            &BlueprintPartitionType::IndexCollection,
1884        )?;
1885
1886        let target = BlueprintTypeTarget {
1887            blueprint_info: info,
1888            meta: SchemaValidationMeta::ExistingObject {
1889                additional_schemas: node_id,
1890            },
1891        };
1892
1893        self.validate_blueprint_payload(
1894            &target,
1895            BlueprintPayloadIdentifier::IndexEntry(collection_index, KeyOrValue::Key),
1896            &key,
1897        )?;
1898
1899        self.validate_blueprint_payload(
1900            &target,
1901            BlueprintPayloadIdentifier::IndexEntry(collection_index, KeyOrValue::Value),
1902            &buffer,
1903        )?;
1904
1905        let value: ScryptoValue = scrypto_decode(&buffer).unwrap();
1906        let index_entry = IndexEntrySubstate::entry(value);
1907        let value = IndexedScryptoValue::from_typed(&index_entry);
1908
1909        self.api
1910            .kernel_set_substate(&node_id, partition_num, SubstateKey::Map(key), value)
1911    }
1912
1913    // Costing through kernel
1914    fn actor_index_remove(
1915        &mut self,
1916        object_handle: ActorStateHandle,
1917        collection_index: CollectionIndex,
1918        key: Vec<u8>,
1919    ) -> Result<Option<Vec<u8>>, RuntimeError> {
1920        let actor_object_type: ActorStateRef = object_handle.try_into()?;
1921
1922        let (node_id, _info, partition_num) = self.get_actor_collection_partition_info(
1923            actor_object_type,
1924            collection_index,
1925            &BlueprintPartitionType::IndexCollection,
1926        )?;
1927
1928        let rtn = self
1929            .api
1930            .kernel_remove_substate(&node_id, partition_num, &SubstateKey::Map(key))?
1931            .map(|v| {
1932                let value: IndexEntrySubstate<ScryptoValue> = v.as_typed().unwrap();
1933                scrypto_encode(value.value()).unwrap()
1934            });
1935
1936        Ok(rtn)
1937    }
1938
1939    // Costing through kernel
1940    fn actor_index_scan_keys(
1941        &mut self,
1942        object_handle: ActorStateHandle,
1943        collection_index: CollectionIndex,
1944        limit: u32,
1945    ) -> Result<Vec<Vec<u8>>, RuntimeError> {
1946        let actor_object_type: ActorStateRef = object_handle.try_into()?;
1947
1948        let (node_id, _info, partition_num) = self.get_actor_collection_partition_info(
1949            actor_object_type,
1950            collection_index,
1951            &BlueprintPartitionType::IndexCollection,
1952        )?;
1953
1954        let substates = self
1955            .api
1956            .kernel_scan_keys::<MapKey>(&node_id, partition_num, limit)?
1957            .into_iter()
1958            .map(|key| key.into_map())
1959            .collect();
1960
1961        Ok(substates)
1962    }
1963
1964    // Costing through kernel
1965    fn actor_index_drain(
1966        &mut self,
1967        object_handle: ActorStateHandle,
1968        collection_index: CollectionIndex,
1969        limit: u32,
1970    ) -> Result<Vec<(Vec<u8>, Vec<u8>)>, RuntimeError> {
1971        let actor_object_type: ActorStateRef = object_handle.try_into()?;
1972
1973        let (node_id, _info, partition_num) = self.get_actor_collection_partition_info(
1974            actor_object_type,
1975            collection_index,
1976            &BlueprintPartitionType::IndexCollection,
1977        )?;
1978
1979        let substates = self
1980            .api
1981            .kernel_drain_substates::<MapKey>(&node_id, partition_num, limit)?
1982            .into_iter()
1983            .map(|(key, value)| {
1984                let value: IndexEntrySubstate<ScryptoValue> = value.as_typed().unwrap();
1985                let value = scrypto_encode(value.value()).unwrap();
1986
1987                (key.into_map(), value)
1988            })
1989            .collect();
1990
1991        Ok(substates)
1992    }
1993}
1994
1995#[cfg_attr(
1996    feature = "std",
1997    catch_unwind(crate::utils::catch_unwind_system_panic_transformer)
1998)]
1999impl<'a, Y: SystemBasedKernelApi> SystemActorSortedIndexApi<RuntimeError> for SystemService<'a, Y> {
2000    // Costing through kernel
2001    #[trace_resources]
2002    fn actor_sorted_index_insert(
2003        &mut self,
2004        object_handle: ActorStateHandle,
2005        collection_index: CollectionIndex,
2006        sorted_key: SortedKey,
2007        buffer: Vec<u8>,
2008    ) -> Result<(), RuntimeError> {
2009        let actor_object_type: ActorStateRef = object_handle.try_into()?;
2010
2011        let (node_id, info, partition_num) = self.get_actor_collection_partition_info(
2012            actor_object_type,
2013            collection_index,
2014            &BlueprintPartitionType::SortedIndexCollection,
2015        )?;
2016
2017        let target = BlueprintTypeTarget {
2018            blueprint_info: info,
2019            meta: SchemaValidationMeta::ExistingObject {
2020                additional_schemas: node_id,
2021            },
2022        };
2023
2024        self.validate_blueprint_payload(
2025            &target,
2026            BlueprintPayloadIdentifier::SortedIndexEntry(collection_index, KeyOrValue::Key),
2027            &sorted_key.1,
2028        )?;
2029
2030        self.validate_blueprint_payload(
2031            &target,
2032            BlueprintPayloadIdentifier::SortedIndexEntry(collection_index, KeyOrValue::Value),
2033            &buffer,
2034        )?;
2035
2036        let value: ScryptoValue = scrypto_decode(&buffer).unwrap();
2037        let sorted_entry = SortedIndexEntrySubstate::entry(value);
2038        let value = IndexedScryptoValue::from_typed(&sorted_entry);
2039
2040        self.api.kernel_set_substate(
2041            &node_id,
2042            partition_num,
2043            SubstateKey::Sorted((sorted_key.0, sorted_key.1)),
2044            value,
2045        )
2046    }
2047
2048    // Costing through kernel
2049    #[trace_resources]
2050    fn actor_sorted_index_remove(
2051        &mut self,
2052        object_handle: ActorStateHandle,
2053        collection_index: CollectionIndex,
2054        sorted_key: &SortedKey,
2055    ) -> Result<Option<Vec<u8>>, RuntimeError> {
2056        let actor_object_type: ActorStateRef = object_handle.try_into()?;
2057
2058        let (node_id, _info, partition_num) = self.get_actor_collection_partition_info(
2059            actor_object_type,
2060            collection_index,
2061            &BlueprintPartitionType::SortedIndexCollection,
2062        )?;
2063
2064        let rtn = self
2065            .api
2066            .kernel_remove_substate(
2067                &node_id,
2068                partition_num,
2069                &SubstateKey::Sorted((sorted_key.0, sorted_key.1.clone())),
2070            )?
2071            .map(|v| {
2072                let value: SortedIndexEntrySubstate<ScryptoValue> = v.as_typed().unwrap();
2073                scrypto_encode(value.value()).unwrap()
2074            });
2075
2076        Ok(rtn)
2077    }
2078
2079    // Costing through kernel
2080    #[trace_resources]
2081    fn actor_sorted_index_scan(
2082        &mut self,
2083        object_handle: ActorStateHandle,
2084        collection_index: CollectionIndex,
2085        limit: u32,
2086    ) -> Result<Vec<(SortedKey, Vec<u8>)>, RuntimeError> {
2087        let actor_object_type: ActorStateRef = object_handle.try_into()?;
2088
2089        let (node_id, _info, partition_num) = self.get_actor_collection_partition_info(
2090            actor_object_type,
2091            collection_index,
2092            &BlueprintPartitionType::SortedIndexCollection,
2093        )?;
2094
2095        let substates = self
2096            .api
2097            .kernel_scan_sorted_substates(&node_id, partition_num, limit)?
2098            .into_iter()
2099            .map(|(key, value)| {
2100                let value: SortedIndexEntrySubstate<ScryptoValue> = value.as_typed().unwrap();
2101                let value = scrypto_encode(value.value()).unwrap();
2102
2103                (key, value)
2104            })
2105            .collect();
2106
2107        Ok(substates)
2108    }
2109}
2110
2111#[cfg_attr(
2112    feature = "std",
2113    catch_unwind(crate::utils::catch_unwind_system_panic_transformer)
2114)]
2115impl<'a, Y: SystemBasedKernelApi> SystemBlueprintApi<RuntimeError> for SystemService<'a, Y> {
2116    // Costing through kernel
2117    fn call_function(
2118        &mut self,
2119        package_address: PackageAddress,
2120        blueprint_name: &str,
2121        function_name: &str,
2122        args: Vec<u8>,
2123    ) -> Result<Vec<u8>, RuntimeError> {
2124        let args = IndexedScryptoValue::from_vec(args).map_err(|e| {
2125            RuntimeError::SystemUpstreamError(SystemUpstreamError::InputDecodeError(e))
2126        })?;
2127        let blueprint_id = BlueprintId::new(&package_address, blueprint_name);
2128        let auth_zone = SystemModuleMixer::on_call_function(self, &blueprint_id, function_name)?;
2129
2130        let rtn = self
2131            .api
2132            .kernel_invoke(Box::new(KernelInvocation {
2133                call_frame_data: Actor::Function(FunctionActor {
2134                    blueprint_id,
2135                    ident: function_name.to_string(),
2136                    auth_zone: auth_zone.clone(),
2137                }),
2138                args,
2139            }))
2140            .map(|v| v.into())?;
2141
2142        SystemModuleMixer::on_call_function_finish(self, auth_zone)?;
2143
2144        Ok(rtn)
2145    }
2146
2147    fn resolve_blueprint_type(
2148        &mut self,
2149        blueprint_type_id: &BlueprintTypeIdentifier,
2150    ) -> Result<(Rc<VersionedScryptoSchema>, ScopedTypeId), RuntimeError> {
2151        self.get_blueprint_type_schema(blueprint_type_id)
2152    }
2153}
2154
2155#[cfg_attr(
2156    feature = "std",
2157    catch_unwind(crate::utils::catch_unwind_system_panic_transformer)
2158)]
2159impl<'a, Y: SystemBasedKernelApi> SystemCostingApi<RuntimeError> for SystemService<'a, Y> {
2160    fn consume_cost_units(
2161        &mut self,
2162        costing_entry: ClientCostingEntry,
2163    ) -> Result<(), RuntimeError> {
2164        let system_logic = self
2165            .api
2166            .kernel_get_system_state()
2167            .system
2168            .versioned_system_logic;
2169        if !system_logic.should_consume_cost_units(self.api) {
2170            return Ok(());
2171        }
2172
2173        self.api
2174            .kernel_get_system()
2175            .modules
2176            .apply_execution_cost(match costing_entry {
2177                ClientCostingEntry::RunNativeCode {
2178                    package_address,
2179                    export_name,
2180                    input_size,
2181                } => ExecutionCostingEntry::RunNativeCode {
2182                    package_address,
2183                    export_name,
2184                    input_size,
2185                },
2186                ClientCostingEntry::RunWasmCode {
2187                    package_address,
2188                    export_name,
2189                    wasm_execution_units,
2190                } => ExecutionCostingEntry::RunWasmCode {
2191                    package_address,
2192                    export_name,
2193                    wasm_execution_units,
2194                },
2195                ClientCostingEntry::PrepareWasmCode { size } => {
2196                    ExecutionCostingEntry::PrepareWasmCode { size }
2197                }
2198                ClientCostingEntry::Bls12381V1Verify { size } => {
2199                    ExecutionCostingEntry::Bls12381V1Verify { size }
2200                }
2201                ClientCostingEntry::Bls12381V1AggregateVerify { sizes } => {
2202                    ExecutionCostingEntry::Bls12381V1AggregateVerify { sizes }
2203                }
2204                ClientCostingEntry::Bls12381V1FastAggregateVerify { size, keys_cnt } => {
2205                    ExecutionCostingEntry::Bls12381V1FastAggregateVerify { size, keys_cnt }
2206                }
2207                ClientCostingEntry::Bls12381G2SignatureAggregate { signatures_cnt } => {
2208                    ExecutionCostingEntry::Bls12381G2SignatureAggregate { signatures_cnt }
2209                }
2210                ClientCostingEntry::Keccak256Hash { size } => {
2211                    ExecutionCostingEntry::Keccak256Hash { size }
2212                }
2213                ClientCostingEntry::Blake2b256Hash { size } => {
2214                    ExecutionCostingEntry::Blake2b256Hash { size }
2215                }
2216                ClientCostingEntry::Ed25519Verify { size } => {
2217                    ExecutionCostingEntry::Ed25519Verify { size }
2218                }
2219                ClientCostingEntry::Secp256k1EcdsaVerify => {
2220                    ExecutionCostingEntry::Secp256k1EcdsaVerify
2221                }
2222                ClientCostingEntry::Secp256k1EcdsaKeyRecover => {
2223                    ExecutionCostingEntry::Secp256k1EcdsaVerifyAndKeyRecover
2224                }
2225            })
2226    }
2227
2228    #[trace_resources]
2229    fn start_lock_fee(&mut self, amount: Decimal, contingent: bool) -> Result<bool, RuntimeError> {
2230        // Child subintents are only allowed to use contingent fees
2231        if !contingent {
2232            let stack_id = self.api.kernel_get_current_stack_id_uncosted();
2233            if stack_id != 0 {
2234                return Err(RuntimeError::SystemError(
2235                    SystemError::CannotLockFeeInChildSubintent(stack_id),
2236                ));
2237            }
2238        }
2239
2240        let costing_enabled = self
2241            .api
2242            .kernel_get_system()
2243            .modules
2244            .enabled_modules
2245            .contains(EnabledModules::COSTING);
2246
2247        // We do costing up front
2248        self.api
2249            .kernel_get_system()
2250            .modules
2251            .apply_execution_cost(ExecutionCostingEntry::LockFee)?;
2252
2253        let event_data = {
2254            let lock_fee_event = LockFeeEvent { amount };
2255            scrypto_encode(&lock_fee_event).unwrap()
2256        };
2257
2258        // If costing is enabled, reserve event and pay for the event up front for the call to lock_fee()
2259        // Otherwise, we just simulate the call
2260        if costing_enabled {
2261            self.api
2262                .kernel_get_system()
2263                .modules
2264                .assert_can_add_event()?;
2265            self.api.kernel_get_system().modules.apply_execution_cost(
2266                ExecutionCostingEntry::EmitEvent {
2267                    size: event_data.len(),
2268                },
2269            )?;
2270        } else {
2271            self.emit_event_internal(
2272                EmitterActor::CurrentActor,
2273                LockFeeEvent::EVENT_NAME.to_string(),
2274                event_data,
2275                EventFlags::FORCE_WRITE,
2276            )?;
2277        }
2278
2279        Ok(costing_enabled)
2280    }
2281
2282    #[trace_resources]
2283    #[cfg_attr(feature = "std", catch_unwind_ignore)]
2284    fn lock_fee(&mut self, locked_fee: LiquidFungibleResource, contingent: bool) {
2285        // Credit cost units
2286        let vault_id = self
2287            .current_actor()
2288            .node_id()
2289            .expect("Caller should only be fungible vault method");
2290        self.api
2291            .kernel_get_system()
2292            .modules
2293            .lock_fee(vault_id, locked_fee.clone(), contingent);
2294
2295        // Emit Locked Fee event
2296        {
2297            let type_identifier = EventTypeIdentifier(
2298                Emitter::Method(vault_id, ObjectModuleId::Main),
2299                LockFeeEvent::EVENT_NAME.to_string(),
2300            );
2301
2302            let lock_fee_event = LockFeeEvent {
2303                amount: locked_fee.amount(),
2304            };
2305            let payload = scrypto_encode(&lock_fee_event).unwrap();
2306
2307            let event = Event {
2308                type_identifier,
2309                payload,
2310                flags: EventFlags::FORCE_WRITE,
2311            };
2312
2313            self.api
2314                .kernel_get_system()
2315                .modules
2316                .add_event_unchecked(event)
2317                .expect("Event should never exceed size.");
2318        }
2319    }
2320
2321    fn execution_cost_unit_limit(&mut self) -> Result<u32, RuntimeError> {
2322        self.api
2323            .kernel_get_system()
2324            .modules
2325            .apply_execution_cost(ExecutionCostingEntry::QueryFeeReserve)?;
2326
2327        if let Some(fee_reserve) = self.api.kernel_get_system().modules.fee_reserve() {
2328            Ok(fee_reserve.execution_cost_unit_limit())
2329        } else {
2330            Err(RuntimeError::SystemError(
2331                SystemError::CostingModuleNotEnabled,
2332            ))
2333        }
2334    }
2335
2336    fn execution_cost_unit_price(&mut self) -> Result<Decimal, RuntimeError> {
2337        self.api
2338            .kernel_get_system()
2339            .modules
2340            .apply_execution_cost(ExecutionCostingEntry::QueryFeeReserve)?;
2341
2342        if let Some(fee_reserve) = self.api.kernel_get_system().modules.fee_reserve() {
2343            Ok(fee_reserve.execution_cost_unit_price())
2344        } else {
2345            Err(RuntimeError::SystemError(
2346                SystemError::CostingModuleNotEnabled,
2347            ))
2348        }
2349    }
2350
2351    fn finalization_cost_unit_limit(&mut self) -> Result<u32, RuntimeError> {
2352        self.api
2353            .kernel_get_system()
2354            .modules
2355            .apply_execution_cost(ExecutionCostingEntry::QueryFeeReserve)?;
2356
2357        if let Some(fee_reserve) = self.api.kernel_get_system().modules.fee_reserve() {
2358            Ok(fee_reserve.finalization_cost_unit_limit())
2359        } else {
2360            Err(RuntimeError::SystemError(
2361                SystemError::CostingModuleNotEnabled,
2362            ))
2363        }
2364    }
2365
2366    fn finalization_cost_unit_price(&mut self) -> Result<Decimal, RuntimeError> {
2367        self.api
2368            .kernel_get_system()
2369            .modules
2370            .apply_execution_cost(ExecutionCostingEntry::QueryFeeReserve)?;
2371
2372        if let Some(fee_reserve) = self.api.kernel_get_system().modules.fee_reserve() {
2373            Ok(fee_reserve.finalization_cost_unit_price())
2374        } else {
2375            Err(RuntimeError::SystemError(
2376                SystemError::CostingModuleNotEnabled,
2377            ))
2378        }
2379    }
2380
2381    fn usd_price(&mut self) -> Result<Decimal, RuntimeError> {
2382        if let Some(costing) = self.api.kernel_get_system().modules.costing_mut() {
2383            costing
2384                .apply_execution_cost_2(ExecutionCostingEntry::QueryFeeReserve)
2385                .map_err(|e| RuntimeError::SystemModuleError(SystemModuleError::CostingError(e)))?;
2386        }
2387
2388        if let Some(fee_reserve) = self.api.kernel_get_system().modules.fee_reserve() {
2389            Ok(fee_reserve.usd_price())
2390        } else {
2391            Err(RuntimeError::SystemError(
2392                SystemError::CostingModuleNotEnabled,
2393            ))
2394        }
2395    }
2396
2397    fn max_per_function_royalty_in_xrd(&mut self) -> Result<Decimal, RuntimeError> {
2398        if let Some(costing) = self.api.kernel_get_system().modules.costing_mut() {
2399            costing
2400                .apply_execution_cost_2(ExecutionCostingEntry::QueryCostingModule)
2401                .map_err(|e| RuntimeError::SystemModuleError(SystemModuleError::CostingError(e)))?;
2402            Ok(costing.config.max_per_function_royalty_in_xrd)
2403        } else {
2404            Err(RuntimeError::SystemError(
2405                SystemError::CostingModuleNotEnabled,
2406            ))
2407        }
2408    }
2409
2410    fn tip_percentage_truncated(&mut self) -> Result<u32, RuntimeError> {
2411        self.api
2412            .kernel_get_system()
2413            .modules
2414            .apply_execution_cost(ExecutionCostingEntry::QueryFeeReserve)?;
2415
2416        if let Some(fee_reserve) = self.api.kernel_get_system().modules.fee_reserve() {
2417            Ok(fee_reserve.tip().truncate_to_percentage_u32())
2418        } else {
2419            Err(RuntimeError::SystemError(
2420                SystemError::CostingModuleNotEnabled,
2421            ))
2422        }
2423    }
2424
2425    fn fee_balance(&mut self) -> Result<Decimal, RuntimeError> {
2426        self.api
2427            .kernel_get_system()
2428            .modules
2429            .apply_execution_cost(ExecutionCostingEntry::QueryFeeReserve)?;
2430
2431        if let Some(fee_reserve) = self.api.kernel_get_system().modules.fee_reserve() {
2432            Ok(fee_reserve.fee_balance())
2433        } else {
2434            Err(RuntimeError::SystemError(
2435                SystemError::CostingModuleNotEnabled,
2436            ))
2437        }
2438    }
2439}
2440
2441#[cfg_attr(
2442    feature = "std",
2443    catch_unwind(crate::utils::catch_unwind_system_panic_transformer)
2444)]
2445impl<'a, Y: SystemBasedKernelApi> SystemActorApi<RuntimeError> for SystemService<'a, Y> {
2446    #[trace_resources]
2447    fn actor_get_blueprint_id(&mut self) -> Result<BlueprintId, RuntimeError> {
2448        self.api
2449            .kernel_get_system()
2450            .modules
2451            .apply_execution_cost(ExecutionCostingEntry::QueryActor)?;
2452
2453        self.current_actor()
2454            .blueprint_id()
2455            .ok_or(RuntimeError::SystemError(SystemError::NoBlueprintId))
2456    }
2457
2458    #[trace_resources]
2459    fn actor_get_node_id(&mut self, ref_handle: ActorRefHandle) -> Result<NodeId, RuntimeError> {
2460        self.api
2461            .kernel_get_system()
2462            .modules
2463            .apply_execution_cost(ExecutionCostingEntry::QueryActor)?;
2464
2465        let actor_ref: ActorObjectRef = ref_handle.try_into()?;
2466
2467        let node_id = match actor_ref {
2468            ActorObjectRef::SELF => {
2469                self.current_actor()
2470                    .node_id()
2471                    .ok_or(RuntimeError::SystemError(
2472                        SystemError::ActorNodeIdDoesNotExist,
2473                    ))?
2474            }
2475            ActorObjectRef::Outer => {
2476                let (node_id, module_id) = self.get_actor_object_id(ActorStateRef::SELF)?;
2477                match module_id {
2478                    None => {
2479                        let info = self.get_object_info(&node_id)?;
2480                        match info.blueprint_info.outer_obj_info {
2481                            OuterObjectInfo::Some { outer_object } => {
2482                                Ok(outer_object.into_node_id())
2483                            }
2484                            OuterObjectInfo::None => Err(RuntimeError::SystemError(
2485                                SystemError::OuterObjectDoesNotExist,
2486                            )),
2487                        }
2488                    }
2489                    _ => Err(RuntimeError::SystemError(
2490                        SystemError::ModulesDontHaveOuterObjects,
2491                    )),
2492                }?
2493            }
2494            ActorObjectRef::Global => {
2495                let actor = self.current_actor();
2496                if actor.is_direct_access() {
2497                    return Err(RuntimeError::SystemError(
2498                        SystemError::GlobalAddressDoesNotExist,
2499                    ));
2500                }
2501
2502                if let Some(node_id) = actor.node_id() {
2503                    let visibility = self.kernel_get_node_visibility_uncosted(&node_id);
2504                    if let ReferenceOrigin::Global(address) =
2505                        visibility.reference_origin(node_id).unwrap()
2506                    {
2507                        address.into_node_id()
2508                    } else {
2509                        return Err(RuntimeError::SystemError(
2510                            SystemError::GlobalAddressDoesNotExist,
2511                        ));
2512                    }
2513                } else {
2514                    return Err(RuntimeError::SystemError(
2515                        SystemError::GlobalAddressDoesNotExist,
2516                    ));
2517                }
2518            }
2519            ActorObjectRef::AuthZone => self
2520                .current_actor()
2521                .self_auth_zone()
2522                .ok_or_else(|| RuntimeError::SystemError(SystemError::AuthModuleNotEnabled))?,
2523        };
2524
2525        Ok(node_id)
2526    }
2527
2528    #[trace_resources]
2529    fn actor_is_feature_enabled(
2530        &mut self,
2531        object_handle: ActorStateHandle,
2532        feature: &str,
2533    ) -> Result<bool, RuntimeError> {
2534        self.api
2535            .kernel_get_system()
2536            .modules
2537            .apply_execution_cost(ExecutionCostingEntry::QueryActor)?;
2538
2539        let actor_object_type: ActorStateRef = object_handle.try_into()?;
2540        let (node_id, module_id) = self.get_actor_object_id(actor_object_type)?;
2541        self.is_feature_enabled(&node_id, module_id, feature)
2542    }
2543
2544    // Costing through kernel
2545    #[trace_resources]
2546    fn actor_open_field(
2547        &mut self,
2548        object_handle: ActorStateHandle,
2549        field_index: u8,
2550        flags: LockFlags,
2551    ) -> Result<SubstateHandle, RuntimeError> {
2552        let actor_object_type: ActorStateRef = object_handle.try_into()?;
2553
2554        let (node_id, blueprint_info, partition_num, transient) =
2555            self.get_actor_field_info(actor_object_type, field_index)?;
2556
2557        // TODO: Remove
2558        if flags.contains(LockFlags::UNMODIFIED_BASE) || flags.contains(LockFlags::FORCE_WRITE) {
2559            if !(blueprint_info.blueprint_id.eq(&BlueprintId::new(
2560                &RESOURCE_PACKAGE,
2561                FUNGIBLE_VAULT_BLUEPRINT,
2562            ))) {
2563                return Err(RuntimeError::SystemError(SystemError::InvalidLockFlags));
2564            }
2565        }
2566
2567        let lock_data = if flags.contains(LockFlags::MUTABLE) {
2568            let target = BlueprintTypeTarget {
2569                blueprint_info,
2570                meta: SchemaValidationMeta::ExistingObject {
2571                    additional_schemas: node_id,
2572                },
2573            };
2574
2575            FieldLockData::Write {
2576                target,
2577                field_index,
2578            }
2579        } else {
2580            FieldLockData::Read
2581        };
2582
2583        let handle = match transient {
2584            FieldTransience::NotTransient => self.api.kernel_open_substate(
2585                &node_id,
2586                partition_num,
2587                &SubstateKey::Field(field_index),
2588                flags,
2589                SystemLockData::Field(lock_data),
2590            )?,
2591            FieldTransience::TransientStatic { default_value } => {
2592                let default_value: ScryptoValue = scrypto_decode(&default_value).unwrap();
2593                self.api.kernel_mark_substate_as_transient(
2594                    node_id,
2595                    partition_num,
2596                    SubstateKey::Field(field_index),
2597                )?;
2598                self.api.kernel_open_substate_with_default(
2599                    &node_id,
2600                    partition_num,
2601                    &SubstateKey::Field(field_index),
2602                    flags,
2603                    Some(|| {
2604                        IndexedScryptoValue::from_typed(&FieldSubstate::new_unlocked_field(
2605                            default_value,
2606                        ))
2607                    }),
2608                    SystemLockData::Field(lock_data),
2609                )?
2610            }
2611        };
2612
2613        if flags.contains(LockFlags::MUTABLE) {
2614            let lock_status = self.api.kernel_read_substate(handle).map(|v| {
2615                let field: FieldSubstate<ScryptoValue> = v.as_typed().unwrap();
2616                field.into_lock_status()
2617            })?;
2618
2619            if let LockStatus::Locked = lock_status {
2620                return Err(RuntimeError::SystemError(SystemError::FieldLocked(
2621                    object_handle,
2622                    field_index,
2623                )));
2624            }
2625        }
2626
2627        Ok(handle)
2628    }
2629
2630    #[trace_resources]
2631    fn actor_emit_event(
2632        &mut self,
2633        event_name: String,
2634        event_data: Vec<u8>,
2635        event_flags: EventFlags,
2636    ) -> Result<(), RuntimeError> {
2637        if event_flags.contains(EventFlags::FORCE_WRITE) {
2638            let blueprint_id = self.actor_get_blueprint_id()?;
2639
2640            if !blueprint_id.package_address.eq(&RESOURCE_PACKAGE)
2641                || !blueprint_id.blueprint_name.eq(FUNGIBLE_VAULT_BLUEPRINT)
2642            {
2643                return Err(RuntimeError::SystemError(
2644                    SystemError::ForceWriteEventFlagsNotAllowed,
2645                ));
2646            }
2647        }
2648
2649        self.emit_event_internal(
2650            EmitterActor::CurrentActor,
2651            event_name,
2652            event_data,
2653            event_flags,
2654        )
2655    }
2656}
2657
2658#[cfg_attr(
2659    feature = "std",
2660    catch_unwind(crate::utils::catch_unwind_system_panic_transformer)
2661)]
2662impl<'a, Y: SystemBasedKernelApi> SystemActorKeyValueEntryApi<RuntimeError>
2663    for SystemService<'a, Y>
2664{
2665    // Costing through kernel
2666    #[trace_resources]
2667    fn actor_open_key_value_entry(
2668        &mut self,
2669        object_handle: ActorStateHandle,
2670        collection_index: CollectionIndex,
2671        key: &Vec<u8>,
2672        flags: LockFlags,
2673    ) -> Result<KeyValueEntryHandle, RuntimeError> {
2674        if flags.contains(LockFlags::UNMODIFIED_BASE) || flags.contains(LockFlags::FORCE_WRITE) {
2675            return Err(RuntimeError::SystemError(SystemError::InvalidLockFlags));
2676        }
2677
2678        let actor_object_type: ActorStateRef = object_handle.try_into()?;
2679
2680        let (node_id, info, partition_num) = self.get_actor_collection_partition_info(
2681            actor_object_type,
2682            collection_index,
2683            &BlueprintPartitionType::KeyValueCollection,
2684        )?;
2685
2686        let target = BlueprintTypeTarget {
2687            blueprint_info: info,
2688            meta: SchemaValidationMeta::ExistingObject {
2689                additional_schemas: node_id,
2690            },
2691        };
2692
2693        self.validate_blueprint_payload(
2694            &target,
2695            BlueprintPayloadIdentifier::KeyValueEntry(collection_index, KeyOrValue::Key),
2696            &key,
2697        )?;
2698
2699        let lock_data = if flags.contains(LockFlags::MUTABLE) {
2700            KeyValueEntryLockData::KVCollectionWrite {
2701                collection_index,
2702                target,
2703            }
2704        } else {
2705            KeyValueEntryLockData::Read
2706        };
2707
2708        let handle = self.api.kernel_open_substate_with_default(
2709            &node_id,
2710            partition_num,
2711            &SubstateKey::Map(key.to_vec()),
2712            flags,
2713            Some(|| {
2714                let kv_entry = KeyValueEntrySubstate::<()>::default();
2715                IndexedScryptoValue::from_typed(&kv_entry)
2716            }),
2717            SystemLockData::KeyValueEntry(lock_data),
2718        )?;
2719
2720        if flags.contains(LockFlags::MUTABLE) {
2721            let substate: KeyValueEntrySubstate<ScryptoValue> =
2722                self.api.kernel_read_substate(handle)?.as_typed().unwrap();
2723
2724            if substate.is_locked() {
2725                return Err(RuntimeError::SystemError(SystemError::KeyValueEntryLocked));
2726            }
2727        }
2728
2729        Ok(handle)
2730    }
2731
2732    // Costing through kernel
2733    fn actor_remove_key_value_entry(
2734        &mut self,
2735        object_handle: ActorStateHandle,
2736        collection_index: CollectionIndex,
2737        key: &Vec<u8>,
2738    ) -> Result<Vec<u8>, RuntimeError> {
2739        let handle = self.actor_open_key_value_entry(
2740            object_handle,
2741            collection_index,
2742            key,
2743            LockFlags::MUTABLE,
2744        )?;
2745        self.key_value_entry_remove_and_close_substate(handle)
2746    }
2747}
2748
2749#[cfg_attr(
2750    feature = "std",
2751    catch_unwind(crate::utils::catch_unwind_system_panic_transformer)
2752)]
2753impl<'a, Y: SystemBasedKernelApi> SystemExecutionTraceApi<RuntimeError> for SystemService<'a, Y> {
2754    // No costing should be applied
2755    #[trace_resources]
2756    fn update_instruction_index(&mut self, new_index: usize) -> Result<(), RuntimeError> {
2757        self.api
2758            .kernel_get_system()
2759            .modules
2760            .update_instruction_index(new_index);
2761        Ok(())
2762    }
2763}
2764
2765#[cfg_attr(
2766    feature = "std",
2767    catch_unwind(crate::utils::catch_unwind_system_panic_transformer)
2768)]
2769impl<'a, Y: SystemBasedKernelApi> SystemTransactionRuntimeApi<RuntimeError>
2770    for SystemService<'a, Y>
2771{
2772    #[trace_resources]
2773    fn get_transaction_hash(&mut self) -> Result<Hash, RuntimeError> {
2774        self.api
2775            .kernel_get_system()
2776            .modules
2777            .apply_execution_cost(ExecutionCostingEntry::QueryTransactionHash)?;
2778
2779        if let Some(hash) = self.api.kernel_get_system().modules.transaction_hash() {
2780            Ok(hash)
2781        } else {
2782            Err(RuntimeError::SystemError(
2783                SystemError::TransactionRuntimeModuleNotEnabled,
2784            ))
2785        }
2786    }
2787
2788    #[trace_resources]
2789    fn generate_ruid(&mut self) -> Result<[u8; 32], RuntimeError> {
2790        self.api
2791            .kernel_get_system()
2792            .modules
2793            .apply_execution_cost(ExecutionCostingEntry::GenerateRuid)?;
2794
2795        if let Some(ruid) = self.api.kernel_get_system().modules.generate_ruid() {
2796            Ok(ruid)
2797        } else {
2798            Err(RuntimeError::SystemError(
2799                SystemError::TransactionRuntimeModuleNotEnabled,
2800            ))
2801        }
2802    }
2803
2804    #[trace_resources]
2805    fn bech32_encode_address(&mut self, address: GlobalAddress) -> Result<String, RuntimeError> {
2806        if let Some(costing) = self.api.kernel_get_system().modules.costing_mut() {
2807            costing
2808                .apply_execution_cost_2(ExecutionCostingEntry::EncodeBech32Address)
2809                .map_err(|e| RuntimeError::SystemModuleError(SystemModuleError::CostingError(e)))?;
2810        }
2811
2812        let network_definition = &self
2813            .api
2814            .kernel_get_system()
2815            .modules
2816            .transaction_runtime
2817            .network_definition;
2818
2819        AddressBech32Encoder::new(&network_definition)
2820            .encode(&address.into_node_id().0)
2821            .map_err(|_| RuntimeError::SystemError(SystemError::AddressBech32EncodeError))
2822    }
2823
2824    #[trace_resources]
2825    fn emit_log(&mut self, level: Level, message: String) -> Result<(), RuntimeError> {
2826        self.api.kernel_get_system().modules.apply_execution_cost(
2827            ExecutionCostingEntry::EmitLog {
2828                size: message.len(),
2829            },
2830        )?;
2831
2832        self.api
2833            .kernel_get_system()
2834            .modules
2835            .add_log(level, message)?;
2836
2837        Ok(())
2838    }
2839
2840    fn panic(&mut self, message: String) -> Result<(), RuntimeError> {
2841        self.api.kernel_get_system().modules.apply_execution_cost(
2842            ExecutionCostingEntry::Panic {
2843                size: message.len(),
2844            },
2845        )?;
2846
2847        self.api
2848            .kernel_get_system()
2849            .modules
2850            .set_panic_message(message.clone())?;
2851
2852        Err(RuntimeError::ApplicationError(
2853            ApplicationError::PanicMessage(message),
2854        ))
2855    }
2856}
2857
2858#[cfg_attr(
2859    feature = "std",
2860    catch_unwind(crate::utils::catch_unwind_system_panic_transformer)
2861)]
2862impl<'a, Y: SystemBasedKernelApi> SystemApi<RuntimeError> for SystemService<'a, Y> {}
2863
2864#[cfg_attr(
2865    feature = "std",
2866    catch_unwind(crate::utils::catch_unwind_system_panic_transformer)
2867)]
2868impl<'a, Y: SystemBasedKernelApi> KernelNodeApi for SystemService<'a, Y> {
2869    fn kernel_pin_node(&mut self, node_id: NodeId) -> Result<(), RuntimeError> {
2870        self.api.kernel_pin_node(node_id)
2871    }
2872
2873    fn kernel_drop_node(&mut self, node_id: &NodeId) -> Result<DroppedNode, RuntimeError> {
2874        self.api.kernel_drop_node(node_id)
2875    }
2876
2877    fn kernel_allocate_node_id(&mut self, entity_type: EntityType) -> Result<NodeId, RuntimeError> {
2878        self.api.kernel_allocate_node_id(entity_type)
2879    }
2880
2881    fn kernel_create_node(
2882        &mut self,
2883        node_id: NodeId,
2884        node_substates: NodeSubstates,
2885    ) -> Result<(), RuntimeError> {
2886        self.api.kernel_create_node(node_id, node_substates)
2887    }
2888
2889    fn kernel_create_node_from(
2890        &mut self,
2891        node_id: NodeId,
2892        partitions: BTreeMap<PartitionNumber, (NodeId, PartitionNumber)>,
2893    ) -> Result<(), RuntimeError> {
2894        self.api.kernel_create_node_from(node_id, partitions)
2895    }
2896}
2897
2898#[cfg_attr(
2899    feature = "std",
2900    catch_unwind(crate::utils::catch_unwind_system_panic_transformer)
2901)]
2902impl<'a, Y: SystemBasedKernelApi> KernelSubstateApi<SystemLockData> for SystemService<'a, Y> {
2903    fn kernel_mark_substate_as_transient(
2904        &mut self,
2905        node_id: NodeId,
2906        partition_num: PartitionNumber,
2907        key: SubstateKey,
2908    ) -> Result<(), RuntimeError> {
2909        self.api
2910            .kernel_mark_substate_as_transient(node_id, partition_num, key)
2911    }
2912
2913    fn kernel_open_substate_with_default<F: FnOnce() -> IndexedScryptoValue>(
2914        &mut self,
2915        node_id: &NodeId,
2916        partition_num: PartitionNumber,
2917        substate_key: &SubstateKey,
2918        flags: LockFlags,
2919        default: Option<F>,
2920        data: SystemLockData,
2921    ) -> Result<SubstateHandle, RuntimeError> {
2922        self.api.kernel_open_substate_with_default(
2923            node_id,
2924            partition_num,
2925            substate_key,
2926            flags,
2927            default,
2928            data,
2929        )
2930    }
2931
2932    fn kernel_get_lock_data(
2933        &mut self,
2934        lock_handle: SubstateHandle,
2935    ) -> Result<SystemLockData, RuntimeError> {
2936        self.api.kernel_get_lock_data(lock_handle)
2937    }
2938
2939    fn kernel_close_substate(&mut self, lock_handle: SubstateHandle) -> Result<(), RuntimeError> {
2940        self.api.kernel_close_substate(lock_handle)
2941    }
2942
2943    fn kernel_read_substate(
2944        &mut self,
2945        lock_handle: SubstateHandle,
2946    ) -> Result<&IndexedScryptoValue, RuntimeError> {
2947        self.api.kernel_read_substate(lock_handle)
2948    }
2949
2950    fn kernel_write_substate(
2951        &mut self,
2952        lock_handle: SubstateHandle,
2953        value: IndexedScryptoValue,
2954    ) -> Result<(), RuntimeError> {
2955        self.api.kernel_write_substate(lock_handle, value)
2956    }
2957
2958    fn kernel_set_substate(
2959        &mut self,
2960        node_id: &NodeId,
2961        partition_num: PartitionNumber,
2962        substate_key: SubstateKey,
2963        value: IndexedScryptoValue,
2964    ) -> Result<(), RuntimeError> {
2965        self.api
2966            .kernel_set_substate(node_id, partition_num, substate_key, value)
2967    }
2968
2969    fn kernel_remove_substate(
2970        &mut self,
2971        node_id: &NodeId,
2972        partition_num: PartitionNumber,
2973        substate_key: &SubstateKey,
2974    ) -> Result<Option<IndexedScryptoValue>, RuntimeError> {
2975        self.api
2976            .kernel_remove_substate(node_id, partition_num, substate_key)
2977    }
2978
2979    fn kernel_scan_sorted_substates(
2980        &mut self,
2981        node_id: &NodeId,
2982        partition_num: PartitionNumber,
2983        limit: u32,
2984    ) -> Result<Vec<(SortedKey, IndexedScryptoValue)>, RuntimeError> {
2985        self.api
2986            .kernel_scan_sorted_substates(node_id, partition_num, limit)
2987    }
2988
2989    fn kernel_scan_keys<K: SubstateKeyContent>(
2990        &mut self,
2991        node_id: &NodeId,
2992        partition_num: PartitionNumber,
2993        limit: u32,
2994    ) -> Result<Vec<SubstateKey>, RuntimeError> {
2995        self.api
2996            .kernel_scan_keys::<K>(node_id, partition_num, limit)
2997    }
2998
2999    fn kernel_drain_substates<K: SubstateKeyContent>(
3000        &mut self,
3001        node_id: &NodeId,
3002        partition_num: PartitionNumber,
3003        limit: u32,
3004    ) -> Result<Vec<(SubstateKey, IndexedScryptoValue)>, RuntimeError> {
3005        self.api
3006            .kernel_drain_substates::<K>(node_id, partition_num, limit)
3007    }
3008}
3009
3010impl<'a, Y: SystemBasedKernelApi> KernelInternalApi for SystemService<'a, Y> {
3011    type System = Y::CallbackObject;
3012
3013    fn kernel_get_system_state(&mut self) -> SystemState<'_, Y::CallbackObject> {
3014        self.api.kernel_get_system_state()
3015    }
3016
3017    fn kernel_get_current_stack_depth_uncosted(&self) -> usize {
3018        self.api.kernel_get_current_stack_depth_uncosted()
3019    }
3020
3021    fn kernel_get_current_stack_id_uncosted(&self) -> usize {
3022        self.api.kernel_get_current_stack_id_uncosted()
3023    }
3024
3025    fn kernel_get_node_visibility_uncosted(&self, node_id: &NodeId) -> NodeVisibility {
3026        self.api.kernel_get_node_visibility_uncosted(node_id)
3027    }
3028
3029    fn kernel_read_substate_uncosted(
3030        &self,
3031        node_id: &NodeId,
3032        partition_num: PartitionNumber,
3033        substate_key: &SubstateKey,
3034    ) -> Option<&IndexedScryptoValue> {
3035        self.api
3036            .kernel_read_substate_uncosted(node_id, partition_num, substate_key)
3037    }
3038}