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
85pub 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 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 {
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 {
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 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 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 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 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 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 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 self.api
605 .kernel_get_system()
606 .modules
607 .checked_add_event(event)?;
608
609 Ok(())
610 }
611
612 fn key_value_entry_remove_and_close_substate(
614 &mut self,
615 handle: KeyValueEntryHandle,
616 ) -> Result<Vec<u8>, RuntimeError> {
617 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(¤t_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 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 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 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, 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 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 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 let mut object_info = self.get_object_info(&node_id)?;
944
945 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 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 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 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 {
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 {
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 #[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 #[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 #[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 #[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 #[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 #[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 let global_address_reservation =
1245 self.prepare_global_address(blueprint_id, global_address)?;
1246
1247 Ok((global_address_reservation, global_address))
1252 }
1253
1254 #[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 #[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 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 #[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 #[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 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 #[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 #[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 #[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 #[trace_resources]
1509 fn drop_object(&mut self, node_id: &NodeId) -> Result<Vec<Vec<u8>>, RuntimeError> {
1510 let info = self.get_object_info(node_id)?;
1513 let actor = self.current_actor();
1514
1515 let instance_context_check = {
1516 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 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 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 #[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 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 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(¤t_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 #[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 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 #[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 #[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 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 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 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 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 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 #[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 #[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 #[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 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 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 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_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 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 {
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 #[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 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 #[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 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 #[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}