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