1use super::substates::*;
2use crate::blueprints::native_schema::{
3 METADATA_PACKAGE_DEFINITION, PACKAGE_PACKAGE_DEFINITION, ROLE_ASSIGNMENT_PACKAGE_DEFINITION,
4};
5use crate::blueprints::util::{check_name, InvalidNameError, SecurifiedRoleAssignment};
6use crate::internal_prelude::*;
7use crate::object_modules::metadata::{validate_metadata_init, MetadataNativePackage};
8use crate::system::node_init::type_info_partition;
9use crate::system::system_modules::costing::{apply_royalty_cost, RoyaltyRecipient};
10use crate::system::type_info::TypeInfoSubstate;
11use crate::track::interface::NodeSubstates;
12use crate::vm::wasm::PrepareError;
13use radix_blueprint_schema_init::*;
14use radix_engine_interface::api::*;
15pub use radix_engine_interface::blueprints::package::*;
16use radix_engine_interface::blueprints::resource::{require, Bucket};
17use radix_engine_interface::object_modules::metadata::MetadataInit;
18use radix_engine_interface::object_modules::role_assignment::ROLE_ASSIGNMENT_BLUEPRINT;
19use radix_native_sdk::modules::metadata::Metadata;
20use radix_native_sdk::modules::role_assignment::RoleAssignment;
21use radix_native_sdk::resource::NativeVault;
22use radix_native_sdk::resource::ResourceManager;
23use sbor::LocalTypeId;
24
25use crate::object_modules::role_assignment::*;
27use crate::object_modules::royalty::RoyaltyUtil;
28use crate::roles_template;
29use crate::system::system::*;
30use crate::system::system_callback::*;
31use crate::system::system_modules::auth::{AuthError, ResolvedPermission};
32use crate::system::system_type_checker::SystemMapper;
33use crate::vm::{VmApi, VmPackageValidation};
34
35#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Sbor)]
36pub enum PackageV1MinorVersion {
37 Zero,
38 One,
39}
40
41#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
42pub enum PackageError {
43 InvalidWasm(PrepareError),
44
45 InvalidBlueprintSchema(SchemaValidationError),
46 TooManySubstateSchemas,
47 FeatureDoesNotExist(String),
48 InvalidTransientField,
49 SystemInstructionsNotSupported,
50
51 FailedToResolveLocalSchema {
52 local_type_id: LocalTypeId,
53 },
54 EventNameMismatch {
55 expected: String,
56 actual: Option<String>,
57 },
58 TypeNameMismatch {
59 expected: String,
60 actual: Option<String>,
61 },
62 InvalidEventSchema,
63 InvalidSystemFunction,
64 InvalidTypeParent,
65 InvalidName(InvalidNameError),
66 MissingOuterBlueprint,
67 WasmUnsupported(String),
68 InvalidLocalTypeId(LocalTypeId),
69 InvalidGenericId(u8),
70 EventGenericTypeNotSupported,
71 OuterBlueprintCantBeAnInnerBlueprint {
72 inner: String,
73 violating_outer: String,
74 },
75 RoleAssignmentError(RoleAssignmentError),
76
77 InvalidAuthSetup,
78 DefiningReservedRoleKey(String, RoleKey),
79 ExceededMaxRoles {
80 limit: usize,
81 actual: usize,
82 },
83 ExceededMaxRoleNameLen {
84 limit: usize,
85 actual: usize,
86 },
87 ExceededMaxBlueprintNameLen {
88 limit: usize,
89 actual: usize,
90 },
91 ExceededMaxEventNameLen {
92 limit: usize,
93 actual: usize,
94 },
95 ExceededMaxTypeNameLen {
96 limit: usize,
97 actual: usize,
98 },
99 ExceededMaxFunctionNameLen {
100 limit: usize,
101 actual: usize,
102 },
103 ExceededMaxFeatureNameLen {
104 limit: usize,
105 actual: usize,
106 },
107 MissingRole(RoleKey),
108 UnexpectedNumberOfMethodAuth {
109 blueprint: String,
110 expected: usize,
111 actual: usize,
112 },
113 MissingMethodPermission {
114 blueprint: String,
115 ident: String,
116 },
117
118 UnexpectedNumberOfFunctionAuth {
119 blueprint: String,
120 expected: usize,
121 actual: usize,
122 },
123 MissingFunctionPermission {
124 blueprint: String,
125 ident: String,
126 },
127
128 UnexpectedNumberOfFunctionRoyalties {
129 blueprint: String,
130 expected: usize,
131 actual: usize,
132 },
133 MissingFunctionRoyalty {
134 blueprint: String,
135 ident: String,
136 },
137 RoyaltyAmountIsGreaterThanAllowed {
138 max: RoyaltyAmount,
139 actual: RoyaltyAmount,
140 },
141
142 InvalidMetadataKey(String),
143
144 RoyaltiesNotEnabled,
145 RoyaltyAmountIsNegative(RoyaltyAmount),
146
147 ReservedRoleKeyIsNotDefined(String),
148}
149
150impl From<InvalidNameError> for PackageError {
151 fn from(error: InvalidNameError) -> Self {
152 Self::InvalidName(error)
153 }
154}
155
156fn validate_package_schema(
157 blueprints: &IndexMap<String, BlueprintDefinitionInit>,
158) -> Result<(), PackageError> {
159 for (bp_name, bp_def) in blueprints.iter() {
160 let bp_schema = &bp_def.schema;
161
162 match &bp_def.blueprint_type {
163 BlueprintType::Outer => Ok(()),
164 BlueprintType::Inner { outer_blueprint } if outer_blueprint != bp_name => {
165 match blueprints
166 .get(outer_blueprint)
167 .map(|bp_def| &bp_def.blueprint_type)
168 {
169 Some(BlueprintType::Outer) => Ok(()),
170 Some(BlueprintType::Inner { .. }) => {
171 Err(PackageError::OuterBlueprintCantBeAnInnerBlueprint {
172 inner: bp_name.clone(),
173 violating_outer: outer_blueprint.clone(),
174 })
175 }
176 None => Err(PackageError::MissingOuterBlueprint),
177 }
178 }
179 BlueprintType::Inner { .. } => Err(PackageError::MissingOuterBlueprint),
180 }?;
181
182 validate_schema(bp_schema.schema.v1()).map_err(PackageError::InvalidBlueprintSchema)?;
183
184 if bp_schema.state.fields.len() > MAX_NUMBER_OF_BLUEPRINT_FIELDS {
185 return Err(PackageError::TooManySubstateSchemas);
186 }
187
188 for field in &bp_schema.state.fields {
189 validate_package_schema_type_ref(bp_schema, field.field)?;
190
191 match &field.condition {
192 Condition::IfFeature(feature) => {
193 if !bp_def.feature_set.contains(feature) {
194 return Err(PackageError::FeatureDoesNotExist(feature.clone()));
195 }
196 }
197 Condition::IfOuterFeature(feature) => match &bp_def.blueprint_type {
198 BlueprintType::Inner { outer_blueprint } => {
199 if let Some(outer_bp_def) = blueprints.get(outer_blueprint) {
200 if !outer_bp_def.feature_set.contains(feature) {
201 return Err(PackageError::FeatureDoesNotExist(feature.clone()));
202 }
203 } else {
204 return Err(PackageError::FeatureDoesNotExist(feature.clone()));
209 }
210 }
211 _ => {
212 return Err(PackageError::FeatureDoesNotExist(feature.clone()));
213 }
214 },
215 Condition::Always => {}
216 }
217
218 match &field.transience {
219 FieldTransience::NotTransient => {}
220 FieldTransience::TransientStatic { default_value } => match field.field {
221 TypeRef::Static(local_index) => {
222 validate_payload_against_schema::<ScryptoCustomExtension, ()>(
223 default_value,
224 bp_schema.schema.v1(),
225 local_index,
226 &(),
227 TRANSIENT_SUBSTATE_DEFAULT_VALUE_MAX_DEPTH,
228 )
229 .map_err(|_| PackageError::InvalidTransientField)?;
230 }
231 TypeRef::Generic(..) => return Err(PackageError::InvalidTransientField),
232 },
233 }
234 }
235
236 for collection in &bp_schema.state.collections {
237 match collection {
238 BlueprintCollectionSchema::KeyValueStore(kv_store_schema) => {
239 validate_package_schema_type_ref(bp_schema, kv_store_schema.key)?;
240 validate_package_schema_type_ref(bp_schema, kv_store_schema.value)?;
241 }
242 BlueprintCollectionSchema::SortedIndex(kv_store_schema) => {
243 validate_package_schema_type_ref(bp_schema, kv_store_schema.key)?;
244 validate_package_schema_type_ref(bp_schema, kv_store_schema.value)?;
245 }
246 BlueprintCollectionSchema::Index(kv_store_schema) => {
247 validate_package_schema_type_ref(bp_schema, kv_store_schema.key)?;
248 validate_package_schema_type_ref(bp_schema, kv_store_schema.value)?;
249 }
250 }
251 }
252
253 for (_name, event) in &bp_schema.events.event_schema {
254 validate_package_schema_type_ref(bp_schema, *event)?;
255 }
256
257 for (_name, function) in &bp_schema.functions.functions {
258 validate_package_schema_type_ref(bp_schema, function.input)?;
259 validate_package_schema_type_ref(bp_schema, function.output)?;
260 }
261 }
262
263 Ok(())
264}
265
266fn validate_package_schema_type_ref(
267 radix_blueprint_schema_init: &BlueprintSchemaInit,
268 type_ref: TypeRef<LocalTypeId>,
269) -> Result<(), PackageError> {
270 match type_ref {
271 TypeRef::Static(local_type_id) => {
272 if radix_blueprint_schema_init
273 .schema
274 .v1()
275 .resolve_type_kind(local_type_id)
276 .is_some()
277 {
278 Ok(())
279 } else {
280 Err(PackageError::InvalidLocalTypeId(local_type_id))
281 }
282 }
283 TypeRef::Generic(generic_id) => {
284 if (generic_id as usize) < radix_blueprint_schema_init.generics.len() {
285 Ok(())
286 } else {
287 Err(PackageError::InvalidGenericId(generic_id))
288 }
289 }
290 }
291}
292
293fn extract_package_event_static_type_id(
294 blueprint_init: &BlueprintSchemaInit,
295 type_ref: TypeRef<LocalTypeId>,
296) -> Result<LocalTypeId, PackageError> {
297 match type_ref {
298 TypeRef::Static(local_type_id) => {
299 if blueprint_init
300 .schema
301 .v1()
302 .resolve_type_kind(local_type_id)
303 .is_some()
304 {
305 Ok(local_type_id)
306 } else {
307 Err(PackageError::InvalidLocalTypeId(local_type_id))
308 }
309 }
310 TypeRef::Generic(_) => Err(PackageError::EventGenericTypeNotSupported),
311 }
312}
313
314fn validate_event_schemas<'a, I: Iterator<Item = &'a BlueprintDefinitionInit>>(
315 blueprints: I,
316) -> Result<(), PackageError> {
317 for blueprint_init in blueprints {
318 let radix_blueprint_schema_init = &blueprint_init.schema;
319 let BlueprintSchemaInit { schema, events, .. } = radix_blueprint_schema_init;
320
321 for (expected_event_name, type_ref) in events.event_schema.iter() {
322 let local_type_id =
323 extract_package_event_static_type_id(radix_blueprint_schema_init, *type_ref)?;
324
325 let type_kind = schema
327 .v1()
328 .resolve_type_kind(local_type_id)
329 .ok_or(PackageError::FailedToResolveLocalSchema { local_type_id })?;
330 match type_kind {
331 TypeKind::Enum { .. } | TypeKind::Tuple { .. } => Ok(()),
333 _ => Err(PackageError::InvalidEventSchema),
334 }?;
335
336 let actual_event_name = schema.v1().resolve_type_metadata(local_type_id).map_or(
338 Err(PackageError::FailedToResolveLocalSchema { local_type_id }),
339 |metadata| Ok(metadata.get_name_string()),
340 )?;
341
342 if Some(expected_event_name) != actual_event_name.as_ref() {
343 Err(PackageError::EventNameMismatch {
344 expected: expected_event_name.to_string(),
345 actual: actual_event_name,
346 })?
347 }
348 }
349 }
350
351 Ok(())
352}
353
354fn validate_type_schemas<'a, I: Iterator<Item = &'a BlueprintDefinitionInit>>(
355 blueprints: I,
356) -> Result<(), PackageError> {
357 for blueprint_init in blueprints {
358 let radix_blueprint_schema_init = &blueprint_init.schema;
359 let BlueprintSchemaInit { schema, types, .. } = radix_blueprint_schema_init;
360
361 for (_, local_type_id) in types.type_schema.iter() {
362 if schema.v1().resolve_type_kind(*local_type_id).is_none() {
363 return Err(PackageError::InvalidLocalTypeId(*local_type_id));
364 }
365
366 }
370 }
371
372 Ok(())
373}
374
375fn validate_royalties<Y: SystemApi<RuntimeError>>(
376 definition: &PackageDefinition,
377 api: &mut Y,
378) -> Result<(), RuntimeError> {
379 for (blueprint, definition_init) in &definition.blueprints {
380 match &definition_init.royalty_config {
381 PackageRoyaltyConfig::Disabled => {}
382 PackageRoyaltyConfig::Enabled(function_royalties) => {
383 let num_functions = definition_init.schema.functions.functions.len();
384
385 if num_functions != function_royalties.len() {
386 return Err(RuntimeError::ApplicationError(
387 ApplicationError::PackageError(
388 PackageError::UnexpectedNumberOfFunctionRoyalties {
389 blueprint: blueprint.clone(),
390 expected: num_functions,
391 actual: function_royalties.len(),
392 },
393 ),
394 ));
395 }
396
397 for name in definition_init.schema.functions.functions.keys() {
398 if !function_royalties.contains_key(name) {
399 return Err(RuntimeError::ApplicationError(
400 ApplicationError::PackageError(PackageError::MissingFunctionRoyalty {
401 blueprint: blueprint.clone(),
402 ident: name.clone(),
403 }),
404 ));
405 }
406 }
407
408 RoyaltyUtil::verify_royalty_amounts(function_royalties.values(), false, api)?;
409 }
410 }
411 }
412
413 Ok(())
414}
415
416fn validate_auth(
417 definition: &PackageDefinition,
418 restrict_reserved_key: bool,
419) -> Result<(), PackageError> {
420 for (blueprint, definition_init) in &definition.blueprints {
421 match &definition_init.auth_config.function_auth {
422 FunctionAuth::AllowAll | FunctionAuth::RootOnly => {}
423 FunctionAuth::AccessRules(functions) => {
424 let num_functions = definition_init
425 .schema
426 .functions
427 .functions
428 .values()
429 .filter(|schema| schema.receiver.is_none())
430 .count();
431
432 if num_functions != functions.len() {
433 return Err(PackageError::UnexpectedNumberOfFunctionAuth {
434 blueprint: blueprint.clone(),
435 expected: num_functions,
436 actual: functions.len(),
437 });
438 }
439
440 for (name, schema_init) in &definition_init.schema.functions.functions {
441 if schema_init.receiver.is_none() && !functions.contains_key(name) {
442 return Err(PackageError::MissingFunctionPermission {
443 blueprint: blueprint.clone(),
444 ident: name.clone(),
445 });
446 }
447 }
448
449 for access_rule in functions.values() {
450 RoleAssignmentNativePackage::verify_access_rule(access_rule)
451 .map_err(PackageError::RoleAssignmentError)?;
452 }
453 }
454 }
455
456 match (
457 &definition_init.blueprint_type,
458 &definition_init.auth_config.method_auth,
459 ) {
460 (_, MethodAuthTemplate::AllowAll) => {}
461 (
462 blueprint_type,
463 MethodAuthTemplate::StaticRoleDefinition(StaticRoleDefinition { roles, methods }),
464 ) => {
465 let role_specification = match (blueprint_type, roles) {
466 (_, RoleSpecification::Normal(roles)) => roles,
467 (BlueprintType::Inner { outer_blueprint }, RoleSpecification::UseOuter) => {
468 if let Some(blueprint) = definition.blueprints.get(outer_blueprint) {
469 match &blueprint.auth_config.method_auth {
470 MethodAuthTemplate::StaticRoleDefinition(
471 StaticRoleDefinition {
472 roles: RoleSpecification::Normal(roles),
473 ..
474 },
475 ) => roles,
476 _ => return Err(PackageError::InvalidAuthSetup),
477 }
478 } else {
479 return Err(PackageError::InvalidAuthSetup);
480 }
481 }
482 _ => {
483 return Err(PackageError::InvalidAuthSetup);
484 }
485 };
486
487 let check_list = |list: &RoleList| {
488 for role_key in &list.list {
489 if RoleAssignmentNativePackage::is_role_key_reserved(role_key) {
490 if restrict_reserved_key
491 && !RoleAssignmentNativePackage::is_role_key_reserved_and_defined(
492 role_key,
493 )
494 {
495 return Err(PackageError::ReservedRoleKeyIsNotDefined(
496 role_key.key.clone(),
497 ));
498 }
499 continue;
500 }
501 if !role_specification.contains_key(role_key) {
502 return Err(PackageError::MissingRole(role_key.clone()));
503 }
504 }
505 Ok(())
506 };
507
508 if let RoleSpecification::Normal(roles) = roles {
509 if roles.len() > MAX_ROLES {
510 return Err(PackageError::ExceededMaxRoles {
511 limit: MAX_ROLES,
512 actual: roles.len(),
513 });
514 }
515
516 for (role_key, role_list) in roles {
517 check_list(role_list)?;
518
519 if RoleAssignmentNativePackage::is_role_key_reserved(role_key) {
520 return Err(PackageError::DefiningReservedRoleKey(
521 blueprint.to_string(),
522 role_key.clone(),
523 ));
524 }
525 }
526 }
527
528 for (_method, accessibility) in methods {
529 match accessibility {
530 MethodAccessibility::RoleProtected(role_list) => {
531 check_list(role_list)?;
532 }
533 MethodAccessibility::OwnPackageOnly
534 | MethodAccessibility::Public
535 | MethodAccessibility::OuterObjectOnly => {}
536 }
537 }
538
539 let num_methods = definition_init
540 .schema
541 .functions
542 .functions
543 .values()
544 .filter(|schema| schema.receiver.is_some())
545 .count();
546
547 if num_methods != methods.len() {
548 return Err(PackageError::UnexpectedNumberOfMethodAuth {
549 blueprint: blueprint.clone(),
550 expected: num_methods,
551 actual: methods.len(),
552 });
553 }
554
555 for (name, schema_init) in &definition_init.schema.functions.functions {
556 if schema_init.receiver.is_some()
557 && !methods.contains_key(&MethodKey::new(name))
558 {
559 return Err(PackageError::MissingMethodPermission {
560 blueprint: blueprint.clone(),
561 ident: name.clone(),
562 });
563 }
564 }
565 }
566 }
567 }
568
569 Ok(())
570}
571
572fn validate_names(definition: &PackageDefinition) -> Result<(), PackageError> {
573 for (bp_name, bp_init) in definition.blueprints.iter() {
574 check_name(bp_name)?;
575 if bp_name.len() > MAX_BLUEPRINT_NAME_LEN {
576 return Err(PackageError::ExceededMaxBlueprintNameLen {
577 limit: MAX_BLUEPRINT_NAME_LEN,
578 actual: bp_name.len(),
579 });
580 }
581
582 for (name, _) in bp_init.schema.events.event_schema.iter() {
583 if name.len() > MAX_EVENT_NAME_LEN {
584 return Err(PackageError::ExceededMaxEventNameLen {
585 limit: MAX_EVENT_NAME_LEN,
586 actual: name.len(),
587 });
588 }
589
590 check_name(name)?;
591 }
592
593 for (name, _) in bp_init.schema.types.type_schema.iter() {
594 if name.len() > MAX_TYPE_NAME_LEN {
595 return Err(PackageError::ExceededMaxTypeNameLen {
596 limit: MAX_TYPE_NAME_LEN,
597 actual: name.len(),
598 });
599 }
600
601 check_name(name)?;
602 }
603
604 for (name, _) in bp_init.schema.functions.functions.iter() {
605 if name.len() > MAX_FUNCTION_NAME_LEN {
606 return Err(PackageError::ExceededMaxFunctionNameLen {
607 limit: MAX_FUNCTION_NAME_LEN,
608 actual: name.len(),
609 });
610 }
611
612 check_name(name)?;
613 }
614
615 for (_, export_name) in bp_init.schema.hooks.hooks.iter() {
616 check_name(export_name)?;
617 }
618
619 for name in bp_init.feature_set.iter() {
620 if name.len() > MAX_FEATURE_NAME_LEN {
621 return Err(PackageError::ExceededMaxFeatureNameLen {
622 limit: MAX_FEATURE_NAME_LEN,
623 actual: name.len(),
624 });
625 }
626
627 check_name(name)?;
628 }
629
630 if let PackageRoyaltyConfig::Enabled(list) = &bp_init.royalty_config {
631 for (name, _) in list.iter() {
632 check_name(name)?;
633 }
634 }
635
636 if let FunctionAuth::AccessRules(list) = &bp_init.auth_config.function_auth {
637 for (name, _) in list.iter() {
638 check_name(name)?;
639 }
640 }
641
642 if let MethodAuthTemplate::StaticRoleDefinition(static_roles) =
643 &bp_init.auth_config.method_auth
644 {
645 if let RoleSpecification::Normal(list) = &static_roles.roles {
646 for (role_key, _) in list.iter() {
647 if role_key.key.len() > MAX_ROLE_NAME_LEN {
648 return Err(PackageError::ExceededMaxRoleNameLen {
649 limit: MAX_ROLE_NAME_LEN,
650 actual: role_key.key.len(),
651 });
652 }
653 check_name(&role_key.key)?;
654 }
655 }
656
657 for (key, accessibility) in static_roles.methods.iter() {
658 check_name(&key.ident)?;
659 if let MethodAccessibility::RoleProtected(role_list) = accessibility {
660 for role_key in &role_list.list {
661 check_name(&role_key.key)?;
662 }
663 }
664 }
665 }
666 }
667
668 Ok(())
669}
670
671const SECURIFY_OWNER_ROLE: &str = "securify_owner";
672
673struct SecurifiedPackage;
674
675impl SecurifiedRoleAssignment for SecurifiedPackage {
676 type OwnerBadgeNonFungibleData = PackageOwnerBadgeData;
677 const OWNER_BADGE: ResourceAddress = PACKAGE_OWNER_BADGE;
678}
679
680fn blueprint_state_schema(
681 package: &PackageDefinition,
682 blueprint_name: &str,
683 system_mappings: IndexMap<usize, PartitionNumber>,
684) -> IndexedStateSchema {
685 let package_blueprint = package.blueprints.get(blueprint_name).unwrap();
686 IndexedStateSchema::from_schema(
687 package_blueprint.schema.schema.generate_schema_hash(),
688 package_blueprint.schema.state.clone(),
689 system_mappings,
690 )
691}
692
693pub fn create_package_partition_substates(
694 package_structure: PackageStructure,
695 metadata: MetadataInit,
696 royalty_vault: Option<Vault>,
697) -> NodeSubstates {
698 let mut node_substates = NodeSubstates::new();
699
700 let own_features = PackageFeatureSet {
701 package_royalty: royalty_vault.is_some(),
702 };
703
704 {
709 let package_schema = blueprint_state_schema(
711 &PACKAGE_PACKAGE_DEFINITION,
712 PACKAGE_BLUEPRINT,
713 indexmap!(PackageCollection::SchemaKeyValue.collection_index() as usize => SCHEMAS_PARTITION),
714 );
715 let package_system_struct =
716 PackageNativePackage::init_system_struct(royalty_vault, package_structure);
717 let package_substates = SystemMapper::system_struct_to_node_substates(
718 &package_schema,
719 package_system_struct,
720 MAIN_BASE_PARTITION,
721 );
722 node_substates.extend(package_substates);
723 }
724
725 {
731 node_substates.extend(create_metadata_substates(metadata));
732 }
733
734 {
735 let role_assignment_schema = blueprint_state_schema(
736 &ROLE_ASSIGNMENT_PACKAGE_DEFINITION,
737 ROLE_ASSIGNMENT_BLUEPRINT,
738 indexmap!(),
739 );
740 let role_assignment_system_struct =
741 RoleAssignmentNativePackage::init_system_struct(OwnerRole::None.into(), indexmap!())
742 .unwrap();
743 let role_assignment_substates = SystemMapper::system_struct_to_node_substates(
744 &role_assignment_schema,
745 role_assignment_system_struct,
746 ROLE_ASSIGNMENT_BASE_PARTITION,
747 );
748 node_substates.extend(role_assignment_substates);
749 }
750
751 {
755 node_substates.insert(
756 TYPE_INFO_FIELD_PARTITION,
757 type_info_partition(TypeInfoSubstate::Object(ObjectInfo {
758 blueprint_info: BlueprintInfo {
759 blueprint_id: BlueprintId::new(&PACKAGE_PACKAGE, PACKAGE_BLUEPRINT),
760 blueprint_version: BlueprintVersion::default(),
761 outer_obj_info: OuterObjectInfo::default(),
762 features: own_features.feature_names_string_set(),
763 generic_substitutions: vec![],
764 },
765 object_type: ObjectType::Global {
766 modules: indexmap!(
767 AttachedModuleId::Metadata => BlueprintVersion::default(),
768 AttachedModuleId::RoleAssignment => BlueprintVersion::default(),
769 ),
770 },
771 })),
772 );
773 }
774
775 node_substates
776}
777
778pub fn create_metadata_substates(metadata: MetadataInit) -> NodeSubstates {
779 let metadata_schema = blueprint_state_schema(
780 &METADATA_PACKAGE_DEFINITION,
781 METADATA_BLUEPRINT,
782 indexmap!(),
783 );
784 let metadata_system_struct =
787 MetadataNativePackage::init_system_struct(validate_metadata_init(metadata).unwrap())
788 .unwrap();
789 SystemMapper::system_struct_to_node_substates(
790 &metadata_schema,
791 metadata_system_struct,
792 METADATA_BASE_PARTITION,
793 )
794}
795
796fn globalize_package<Y: SystemApi<RuntimeError>>(
797 package_address_reservation: Option<GlobalAddressReservation>,
798 package_structure: PackageStructure,
799 metadata: Own,
800 role_assignment: RoleAssignment,
801 api: &mut Y,
802) -> Result<PackageAddress, RuntimeError> {
803 let vault = Vault(ResourceManager(XRD).new_empty_vault(api)?);
804
805 let (fields, kv_entries) =
806 PackageNativePackage::init_system_struct(Some(vault), package_structure);
807
808 let package_object = api.new_object(
809 PACKAGE_BLUEPRINT,
810 vec![PackageFeature::PackageRoyalty.feature_name()],
811 GenericArgs::default(),
812 fields,
813 kv_entries,
814 )?;
815
816 let address = api.globalize(
817 package_object,
818 indexmap!(
819 AttachedModuleId::Metadata => metadata.0,
820 AttachedModuleId::RoleAssignment => role_assignment.0.0,
821 ),
822 package_address_reservation,
823 )?;
824
825 Ok(PackageAddress::new_or_panic(address.into_node_id().0))
826}
827
828pub struct PackageStructure {
829 pub definitions: IndexMap<String, PackageBlueprintVersionDefinitionEntryPayload>,
830 pub dependencies: IndexMap<String, PackageBlueprintVersionDependenciesEntryPayload>,
831 pub schemas: IndexMap<SchemaHash, PackageSchemaEntryPayload>,
832 pub vm_type: IndexMap<CodeHash, PackageCodeVmTypeEntryPayload>,
833 pub original_code: IndexMap<CodeHash, PackageCodeOriginalCodeEntryPayload>,
834 pub instrumented_code: IndexMap<CodeHash, PackageCodeInstrumentedCodeEntryPayload>,
835 pub auth_configs: IndexMap<String, PackageBlueprintVersionAuthConfigEntryPayload>,
836 pub package_royalties: IndexMap<String, PackageBlueprintVersionRoyaltyConfigEntryPayload>,
837}
838
839pub struct PackageNativePackage;
840
841impl PackageNativePackage {
842 pub fn definition() -> PackageDefinition {
843 let mut aggregator = TypeAggregator::<ScryptoCustomTypeKind>::new();
844
845 let state = PackageStateSchemaInit::create_schema_init(&mut aggregator);
846
847 let mut functions = index_map_new();
848 functions.insert(
849 PACKAGE_PUBLISH_WASM_IDENT.to_string(),
850 FunctionSchemaInit {
851 receiver: None,
852 input: TypeRef::Static(
853 aggregator.add_child_type_and_descendents::<PackagePublishWasmInput>(),
854 ),
855 output: TypeRef::Static(
856 aggregator.add_child_type_and_descendents::<PackagePublishWasmOutput>(),
857 ),
858 export: PACKAGE_PUBLISH_WASM_IDENT.to_string(),
859 },
860 );
861 functions.insert(
862 PACKAGE_PUBLISH_WASM_ADVANCED_IDENT.to_string(),
863 FunctionSchemaInit {
864 receiver: None,
865 input: TypeRef::Static(
866 aggregator.add_child_type_and_descendents::<PackagePublishWasmAdvancedInput>(),
867 ),
868 output: TypeRef::Static(
869 aggregator.add_child_type_and_descendents::<PackagePublishWasmAdvancedOutput>(),
870 ),
871 export: PACKAGE_PUBLISH_WASM_ADVANCED_IDENT.to_string(),
872 },
873 );
874 functions.insert(
875 PACKAGE_PUBLISH_NATIVE_IDENT.to_string(),
876 FunctionSchemaInit {
877 receiver: None,
878 input: TypeRef::Static(
879 aggregator.add_child_type_and_descendents::<PackagePublishNativeInput>(),
880 ),
881 output: TypeRef::Static(
882 aggregator.add_child_type_and_descendents::<PackagePublishNativeOutput>(),
883 ),
884 export: PACKAGE_PUBLISH_NATIVE_IDENT.to_string(),
885 },
886 );
887 functions.insert(
888 PACKAGE_CLAIM_ROYALTIES_IDENT.to_string(),
889 FunctionSchemaInit {
890 receiver: Some(ReceiverInfo::normal_ref_mut()),
891 input: TypeRef::Static(
892 aggregator.add_child_type_and_descendents::<PackageClaimRoyaltiesInput>(),
893 ),
894 output: TypeRef::Static(
895 aggregator.add_child_type_and_descendents::<PackageClaimRoyaltiesOutput>(),
896 ),
897 export: PACKAGE_CLAIM_ROYALTIES_IDENT.to_string(),
898 },
899 );
900
901 let schema = generate_full_schema(aggregator);
902 let blueprints = indexmap!(
903 PACKAGE_BLUEPRINT.to_string() => BlueprintDefinitionInit {
904 blueprint_type: BlueprintType::default(),
905 is_transient: false,
906 feature_set: PackageFeatureSet::all_features(),
907 dependencies: indexset!(
908 PACKAGE_OF_DIRECT_CALLER_RESOURCE.into(),
909 PACKAGE_OWNER_BADGE.into(),
910 ),
911 schema: BlueprintSchemaInit {
912 generics: vec![],
913 schema,
914 state,
915 events: BlueprintEventSchemaInit::default(),
916 types: BlueprintTypeSchemaInit::default(),
917 functions: BlueprintFunctionsSchemaInit {
918 functions,
919 },
920 hooks: BlueprintHooksInit::default(),
921 },
922 royalty_config: PackageRoyaltyConfig::default(),
923 auth_config: AuthConfig {
924 function_auth: FunctionAuth::AccessRules(
925 indexmap!(
926 PACKAGE_PUBLISH_WASM_IDENT.to_string() => rule!(require(package_of_direct_caller(TRANSACTION_PROCESSOR_PACKAGE))),
927 PACKAGE_PUBLISH_WASM_ADVANCED_IDENT.to_string() => rule!(require(package_of_direct_caller(TRANSACTION_PROCESSOR_PACKAGE))),
928 PACKAGE_PUBLISH_NATIVE_IDENT.to_string() => rule!(require(system_execution(SystemExecution::Protocol))),
929 )
930 ),
931 method_auth: MethodAuthTemplate::StaticRoleDefinition(
932 roles_template! {
933 roles {
934 SECURIFY_OWNER_ROLE;
935 },
936 methods {
937 PACKAGE_CLAIM_ROYALTIES_IDENT => [SECURIFY_OWNER_ROLE];
938 }
939 },
940 ),
941 },
942 }
943 );
944
945 PackageDefinition { blueprints }
946 }
947
948 pub fn invoke_export<Y: SystemApi<RuntimeError>, V: VmApi>(
949 export_name: &str,
950 input: &IndexedScryptoValue,
951 version: PackageV1MinorVersion,
952 api: &mut Y,
953 vm_api: &V,
954 ) -> Result<IndexedScryptoValue, RuntimeError> {
955 let restrict_reserved_key = match version {
956 PackageV1MinorVersion::Zero => false,
957 PackageV1MinorVersion::One => true,
958 };
959
960 match export_name {
961 PACKAGE_PUBLISH_NATIVE_IDENT => {
962 let input: PackagePublishNativeInput = input.as_typed().map_err(|e| {
963 RuntimeError::ApplicationError(ApplicationError::InputDecodeError(e))
964 })?;
965
966 let rtn = Self::publish_native(
967 input.package_address,
968 input.native_package_code_id,
969 input.definition,
970 input.metadata,
971 restrict_reserved_key,
972 api,
973 vm_api,
974 )?;
975
976 Ok(IndexedScryptoValue::from_typed(&rtn))
977 }
978 PACKAGE_PUBLISH_WASM_IDENT => {
979 let input: PackagePublishWasmInput = input.as_typed().map_err(|e| {
980 RuntimeError::ApplicationError(ApplicationError::InputDecodeError(e))
981 })?;
982
983 let rtn = Self::publish_wasm(
984 input.code,
985 input.definition,
986 input.metadata,
987 restrict_reserved_key,
988 api,
989 vm_api,
990 )?;
991
992 Ok(IndexedScryptoValue::from_typed(&rtn))
993 }
994 PACKAGE_PUBLISH_WASM_ADVANCED_IDENT => {
995 let input: PackagePublishWasmAdvancedInput = input.as_typed().map_err(|e| {
996 RuntimeError::ApplicationError(ApplicationError::InputDecodeError(e))
997 })?;
998
999 let rtn = Self::publish_wasm_advanced(
1000 input.package_address,
1001 input.code,
1002 input.definition,
1003 input.metadata,
1004 input.owner_role,
1005 restrict_reserved_key,
1006 api,
1007 vm_api,
1008 )?;
1009
1010 Ok(IndexedScryptoValue::from_typed(&rtn))
1011 }
1012 PACKAGE_CLAIM_ROYALTIES_IDENT => {
1013 let _input: PackageClaimRoyaltiesInput = input.as_typed().map_err(|e| {
1014 RuntimeError::ApplicationError(ApplicationError::InputDecodeError(e))
1015 })?;
1016 let rtn = PackageRoyaltyNativeBlueprint::claim_royalties(api)?;
1017 Ok(IndexedScryptoValue::from_typed(&rtn))
1018 }
1019 _ => Err(RuntimeError::ApplicationError(
1020 ApplicationError::ExportDoesNotExist(export_name.to_string()),
1021 )),
1022 }
1023 }
1024
1025 #[allow(clippy::type_complexity)]
1026 pub(crate) fn init_system_struct(
1027 royalty_vault: Option<Vault>,
1028 package_structure: PackageStructure,
1029 ) -> (
1030 IndexMap<u8, FieldValue>,
1031 IndexMap<u8, IndexMap<Vec<u8>, KVEntry>>,
1032 ) {
1033 let mut fields = index_map_new();
1034 if let Some(vault) = royalty_vault {
1035 let royalty = PackageRoyaltyAccumulator {
1036 royalty_vault: vault,
1037 }
1038 .into_payload();
1039 fields.insert(0u8, FieldValue::immutable(royalty));
1040 }
1041
1042 let mut kv_entries: IndexMap<u8, IndexMap<Vec<u8>, KVEntry>> = index_map_new();
1043 {
1044 let mut definition_partition = index_map_new();
1045 for (blueprint, definition) in package_structure.definitions {
1046 let key = BlueprintVersionKey::new_default(blueprint);
1047 let entry = KVEntry {
1048 value: Some(scrypto_encode(&definition).unwrap()),
1049 locked: true,
1050 };
1051 definition_partition.insert(scrypto_encode(&key).unwrap(), entry);
1052 }
1053 kv_entries.insert(
1054 PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
1055 definition_partition,
1056 );
1057 }
1058
1059 {
1060 let mut dependency_partition = index_map_new();
1061 for (blueprint, dependencies) in package_structure.dependencies {
1062 let key = BlueprintVersionKey::new_default(blueprint);
1063 let entry = KVEntry {
1064 value: Some(scrypto_encode(&dependencies).unwrap()),
1065 locked: true,
1066 };
1067 dependency_partition.insert(scrypto_encode(&key).unwrap(), entry);
1068 }
1069 kv_entries.insert(
1070 PackageCollection::BlueprintVersionDependenciesKeyValue.collection_index(),
1071 dependency_partition,
1072 );
1073 }
1074
1075 {
1076 let mut package_royalties_partition = index_map_new();
1077 for (blueprint, package_royalty) in package_structure.package_royalties {
1078 let key = BlueprintVersionKey::new_default(blueprint);
1079 let entry = KVEntry {
1080 value: Some(scrypto_encode(&package_royalty).unwrap()),
1081 locked: true,
1082 };
1083 package_royalties_partition.insert(scrypto_encode(&key).unwrap(), entry);
1084 }
1085 kv_entries.insert(
1086 PackageCollection::BlueprintVersionRoyaltyConfigKeyValue.collection_index(),
1087 package_royalties_partition,
1088 );
1089 }
1090
1091 {
1092 let mut auth_partition = index_map_new();
1093 for (blueprint, auth_config) in package_structure.auth_configs {
1094 let key = BlueprintVersionKey::new_default(blueprint);
1095 let entry = KVEntry {
1096 value: Some(scrypto_encode(&auth_config).unwrap()),
1097 locked: true,
1098 };
1099 auth_partition.insert(scrypto_encode(&key).unwrap(), entry);
1100 }
1101 kv_entries.insert(
1102 PackageCollection::BlueprintVersionAuthConfigKeyValue.collection_index(),
1103 auth_partition,
1104 );
1105 }
1106
1107 {
1108 let mut vm_type_partition = index_map_new();
1109 for (hash, vm_type) in package_structure.vm_type {
1110 let entry = KVEntry {
1111 value: Some(scrypto_encode(&vm_type).unwrap()),
1112 locked: true,
1113 };
1114 vm_type_partition.insert(scrypto_encode(&hash).unwrap(), entry);
1115 }
1116 kv_entries.insert(
1117 PackageCollection::CodeVmTypeKeyValue.collection_index(),
1118 vm_type_partition,
1119 );
1120 }
1121
1122 {
1123 let mut original_code_partition = index_map_new();
1124 for (hash, code_substate) in package_structure.original_code {
1125 let entry = KVEntry {
1126 value: Some(scrypto_encode(&code_substate).unwrap()),
1127 locked: true,
1128 };
1129 original_code_partition.insert(scrypto_encode(&hash).unwrap(), entry);
1130 }
1131 kv_entries.insert(
1132 PackageCollection::CodeOriginalCodeKeyValue.collection_index(),
1133 original_code_partition,
1134 );
1135 }
1136
1137 {
1138 let mut instrumented_code_partition = index_map_new();
1139 for (hash, code_substate) in package_structure.instrumented_code {
1140 let entry = KVEntry {
1141 value: Some(scrypto_encode(&code_substate).unwrap()),
1142 locked: true,
1143 };
1144 instrumented_code_partition.insert(scrypto_encode(&hash).unwrap(), entry);
1145 }
1146 kv_entries.insert(
1147 PackageCollection::CodeInstrumentedCodeKeyValue.collection_index(),
1148 instrumented_code_partition,
1149 );
1150 }
1151
1152 {
1153 let mut schemas_partition = index_map_new();
1154 for (hash, schema) in package_structure.schemas {
1155 let entry = KVEntry {
1156 value: Some(scrypto_encode(&schema).unwrap()),
1157 locked: true,
1158 };
1159 schemas_partition.insert(scrypto_encode(&hash).unwrap(), entry);
1160 }
1161 kv_entries.insert(
1162 PackageCollection::SchemaKeyValue.collection_index(),
1163 schemas_partition,
1164 );
1165 }
1166
1167 (fields, kv_entries)
1168 }
1169
1170 pub fn validate_and_build_package_structure<V: VmApi>(
1171 definition: PackageDefinition,
1172 vm_type: VmType,
1173 original_code: Vec<u8>,
1174 system_instructions: BTreeMap<String, Vec<SystemInstruction>>,
1175 restrict_reserved_key: bool,
1176 vm_api: &V,
1177 ) -> Result<PackageStructure, RuntimeError> {
1178 validate_package_schema(&definition.blueprints)
1180 .map_err(|e| RuntimeError::ApplicationError(ApplicationError::PackageError(e)))?;
1181 validate_event_schemas(definition.blueprints.values())
1182 .map_err(|e| RuntimeError::ApplicationError(ApplicationError::PackageError(e)))?;
1183 validate_type_schemas(definition.blueprints.values())
1184 .map_err(|e| RuntimeError::ApplicationError(ApplicationError::PackageError(e)))?;
1185 validate_auth(&definition, restrict_reserved_key)
1186 .map_err(|e| RuntimeError::ApplicationError(ApplicationError::PackageError(e)))?;
1187 validate_names(&definition)
1188 .map_err(|e| RuntimeError::ApplicationError(ApplicationError::PackageError(e)))?;
1189
1190 let instrumented_code =
1192 VmPackageValidation::validate(&definition, vm_type, &original_code, vm_api)?;
1193
1194 let mut definitions = index_map_new();
1196 let mut dependencies = index_map_new();
1197 let mut schemas = index_map_new();
1198 let mut package_royalties = index_map_new();
1199 let mut auth_configs = index_map_new();
1200 let mut vm_type_substates = index_map_new();
1201 let mut original_code_substates = index_map_new();
1202 let mut instrumented_code_substates = index_map_new();
1203
1204 let code_hash = CodeHash::from_hash(hash(&original_code));
1205 vm_type_substates.insert(code_hash, PackageCodeVmType { vm_type }.into_payload());
1206 original_code_substates.insert(
1207 code_hash,
1208 PackageCodeOriginalCode {
1209 code: original_code,
1210 }
1211 .into_payload(),
1212 );
1213 if let Some(instrumented_code) = instrumented_code {
1214 instrumented_code_substates.insert(
1215 code_hash,
1216 PackageCodeInstrumentedCode { instrumented_code }.into_payload(),
1217 );
1218 };
1219
1220 {
1221 for (blueprint, definition_init) in definition.blueprints {
1222 auth_configs.insert(
1223 blueprint.clone(),
1224 definition_init.auth_config.into_payload(),
1225 );
1226
1227 let blueprint_schema = definition_init.schema.schema.clone();
1228 let schema_hash = blueprint_schema.generate_schema_hash();
1229 schemas.insert(schema_hash, blueprint_schema.into_payload());
1230
1231 let mut functions = index_map_new();
1232 let mut function_exports = index_map_new();
1233 for (function, function_schema_init) in definition_init.schema.functions.functions {
1234 let input = match function_schema_init.input {
1235 TypeRef::Static(input_type_id) => input_type_id,
1236 TypeRef::Generic(..) => {
1237 return Err(RuntimeError::ApplicationError(
1238 ApplicationError::PackageError(PackageError::WasmUnsupported(
1239 "Generics not supported".to_string(),
1240 )),
1241 ))
1242 }
1243 };
1244 let output = match function_schema_init.output {
1245 TypeRef::Static(output_type_id) => output_type_id,
1246 TypeRef::Generic(..) => {
1247 return Err(RuntimeError::ApplicationError(
1248 ApplicationError::PackageError(PackageError::WasmUnsupported(
1249 "Generics not supported".to_string(),
1250 )),
1251 ))
1252 }
1253 };
1254 functions.insert(
1255 function.clone(),
1256 FunctionSchema {
1257 receiver: function_schema_init.receiver,
1258 input: BlueprintPayloadDef::Static(ScopedTypeId(schema_hash, input)),
1259 output: BlueprintPayloadDef::Static(ScopedTypeId(schema_hash, output)),
1260 },
1261 );
1262 let export = PackageExport {
1263 code_hash,
1264 export_name: function_schema_init.export.clone(),
1265 };
1266 function_exports.insert(function, export);
1267 }
1268
1269 let mut events = index_map_new();
1270 for (key, type_ref) in definition_init.schema.events.event_schema {
1271 events.insert(
1272 key,
1273 BlueprintPayloadDef::from_type_ref(type_ref, schema_hash),
1274 );
1275 }
1276
1277 let mut types = index_map_new();
1278 for (key, local_type_id) in definition_init.schema.types.type_schema {
1279 types.insert(key, ScopedTypeId(schema_hash, local_type_id));
1280 }
1281
1282 let system_instructions = system_instructions
1283 .get(&blueprint)
1284 .cloned()
1285 .unwrap_or_default();
1286
1287 let mut system_mappings = index_map_new();
1288 for system_instruction in system_instructions {
1289 match system_instruction {
1290 SystemInstruction::MapCollectionToPhysicalPartition {
1291 collection_index,
1292 partition_num,
1293 } => {
1294 system_mappings.insert(collection_index as usize, partition_num);
1295 }
1296 }
1297 }
1298
1299 let definition = BlueprintDefinition {
1300 interface: BlueprintInterface {
1301 blueprint_type: definition_init.blueprint_type,
1302 is_transient: definition_init.is_transient,
1303 generics: definition_init.schema.generics,
1304 feature_set: definition_init.feature_set,
1305 functions,
1306 events,
1307 types,
1308 state: IndexedStateSchema::from_schema(
1309 schema_hash,
1310 definition_init.schema.state,
1311 system_mappings,
1312 ),
1313 },
1314 function_exports,
1315 hook_exports: {
1316 definition_init
1317 .schema
1318 .hooks
1319 .hooks
1320 .into_iter()
1321 .map(|(k, v)| {
1322 (
1323 k,
1324 PackageExport {
1325 code_hash,
1326 export_name: v,
1327 },
1328 )
1329 })
1330 .collect()
1331 },
1332 };
1333 definitions.insert(blueprint.clone(), definition.into_payload());
1334
1335 let minor_version_config = BlueprintDependencies {
1336 dependencies: definition_init.dependencies,
1337 };
1338 dependencies.insert(blueprint.clone(), minor_version_config.into_payload());
1339
1340 package_royalties.insert(
1341 blueprint.clone(),
1342 definition_init.royalty_config.into_payload(),
1343 );
1344 }
1345 };
1346
1347 let package_structure = PackageStructure {
1348 definitions,
1349 dependencies,
1350 schemas,
1351 vm_type: vm_type_substates,
1352 original_code: original_code_substates,
1353 instrumented_code: instrumented_code_substates,
1354 auth_configs,
1355 package_royalties,
1356 };
1357
1358 Ok(package_structure)
1359 }
1360
1361 pub(crate) fn publish_native<Y: SystemApi<RuntimeError>, V: VmApi>(
1362 package_address: Option<GlobalAddressReservation>,
1363 native_package_code_id: u64,
1364 definition: PackageDefinition,
1365 metadata_init: MetadataInit,
1366 restrict_reserved_key: bool,
1367 api: &mut Y,
1368 vm_api: &V,
1369 ) -> Result<PackageAddress, RuntimeError> {
1370 validate_royalties(&definition, api)?;
1371 let package_structure = Self::validate_and_build_package_structure(
1372 definition,
1373 VmType::Native,
1374 native_package_code_id.to_be_bytes().to_vec(),
1375 Default::default(),
1376 restrict_reserved_key,
1377 vm_api,
1378 )?;
1379 let role_assignment = RoleAssignment::create(OwnerRole::None, indexmap!(), api)?;
1380 let metadata = Metadata::create_with_data(metadata_init, api)?;
1381
1382 globalize_package(
1383 package_address,
1384 package_structure,
1385 metadata,
1386 role_assignment,
1387 api,
1388 )
1389 }
1390
1391 pub(crate) fn publish_wasm<Y: SystemApi<RuntimeError>, V: VmApi>(
1392 code: Vec<u8>,
1393 definition: PackageDefinition,
1394 metadata_init: MetadataInit,
1395 restrict_reserved_key: bool,
1396 api: &mut Y,
1397 vm_api: &V,
1398 ) -> Result<(PackageAddress, Bucket), RuntimeError> {
1399 validate_royalties(&definition, api)?;
1400
1401 let package_structure = Self::validate_and_build_package_structure(
1402 definition,
1403 VmType::ScryptoV1,
1404 code,
1405 Default::default(),
1406 restrict_reserved_key,
1407 vm_api,
1408 )?;
1409
1410 let (address_reservation, address) = api.allocate_global_address(BlueprintId {
1411 package_address: PACKAGE_PACKAGE,
1412 blueprint_name: PACKAGE_BLUEPRINT.to_string(),
1413 })?;
1414
1415 let (role_assignment, bucket) = SecurifiedPackage::create_securified(
1416 PackageOwnerBadgeData {
1417 name: "Package Owner Badge".to_owned(),
1418 package: address.try_into().expect("Impossible Case"),
1419 },
1420 Some(NonFungibleLocalId::bytes(address.as_node_id().0).unwrap()),
1421 api,
1422 )?;
1423 let metadata = Metadata::create_with_data(metadata_init, api)?;
1424
1425 let address = globalize_package(
1426 Some(address_reservation),
1427 package_structure,
1428 metadata,
1429 role_assignment,
1430 api,
1431 )?;
1432
1433 Ok((address, bucket))
1434 }
1435
1436 #[allow(clippy::too_many_arguments)]
1437 pub(crate) fn publish_wasm_advanced<Y: SystemApi<RuntimeError>, V: VmApi>(
1438 package_address: Option<GlobalAddressReservation>,
1439 code: Vec<u8>,
1440 definition: PackageDefinition,
1441 metadata_init: MetadataInit,
1442 owner_role: OwnerRole,
1443 restrict_reserved_key: bool,
1444 api: &mut Y,
1445 vm_api: &V,
1446 ) -> Result<PackageAddress, RuntimeError> {
1447 validate_royalties(&definition, api)?;
1448 let package_structure = Self::validate_and_build_package_structure(
1449 definition,
1450 VmType::ScryptoV1,
1451 code,
1452 Default::default(),
1453 restrict_reserved_key,
1454 vm_api,
1455 )?;
1456 let metadata = Metadata::create_with_data(metadata_init, api)?;
1457 let role_assignment = SecurifiedPackage::create_advanced(owner_role, api)?;
1458
1459 globalize_package(
1460 package_address,
1461 package_structure,
1462 metadata,
1463 role_assignment,
1464 api,
1465 )
1466 }
1467}
1468
1469pub struct PackageRoyaltyNativeBlueprint;
1470
1471impl PackageRoyaltyNativeBlueprint {
1472 pub fn charge_package_royalty<Y: SystemBasedKernelApi>(
1473 receiver: &NodeId,
1474 bp_version_key: &BlueprintVersionKey,
1475 ident: &str,
1476 api: &mut Y,
1477 ) -> Result<(), RuntimeError> {
1478 {
1479 let mut service = SystemService::new(api);
1480 if !service.is_feature_enabled(
1481 receiver,
1482 None,
1483 PackageFeature::PackageRoyalty.feature_name(),
1484 )? {
1485 return Ok(());
1486 }
1487 }
1488
1489 let handle = api.kernel_open_substate_with_default(
1490 receiver,
1491 MAIN_BASE_PARTITION
1492 .at_offset(PACKAGE_ROYALTY_PARTITION_OFFSET)
1493 .unwrap(),
1494 &SubstateKey::Map(scrypto_encode(&bp_version_key).unwrap()),
1495 LockFlags::read_only(),
1496 Some(|| {
1497 let kv_entry = KeyValueEntrySubstate::<()>::default();
1498 IndexedScryptoValue::from_typed(&kv_entry)
1499 }),
1500 SystemLockData::default(),
1501 )?;
1502
1503 let substate: PackageBlueprintVersionRoyaltyConfigEntrySubstate =
1504 api.kernel_read_substate(handle)?.as_typed().unwrap();
1505 api.kernel_close_substate(handle)?;
1506
1507 let royalty_charge = substate
1508 .into_value()
1509 .and_then(|royalty_config| {
1510 match royalty_config.fully_update_and_into_latest_version() {
1511 PackageRoyaltyConfig::Enabled(royalty_amounts) => {
1512 royalty_amounts.get(ident).cloned()
1513 }
1514 PackageRoyaltyConfig::Disabled => Some(RoyaltyAmount::Free),
1515 }
1516 })
1517 .unwrap_or(RoyaltyAmount::Free);
1518
1519 assert!(!royalty_charge.is_negative());
1521
1522 if royalty_charge.is_non_zero() {
1523 let handle = api.kernel_open_substate(
1524 receiver,
1525 MAIN_BASE_PARTITION,
1526 &PackageField::RoyaltyAccumulator.into(),
1527 LockFlags::MUTABLE,
1528 SystemLockData::default(),
1529 )?;
1530
1531 let substate: PackageRoyaltyAccumulatorFieldSubstate =
1532 api.kernel_read_substate(handle)?.as_typed().unwrap();
1533
1534 let vault_id = substate
1535 .into_payload()
1536 .fully_update_and_into_latest_version()
1537 .royalty_vault
1538 .0;
1539 let package_address = PackageAddress::new_or_panic(receiver.0);
1540 apply_royalty_cost(
1541 &mut api.system_module_api(),
1542 royalty_charge,
1543 RoyaltyRecipient::Package(package_address, vault_id.0),
1544 )?;
1545
1546 api.kernel_close_substate(handle)?;
1547 }
1548
1549 Ok(())
1550 }
1551
1552 pub(crate) fn claim_royalties<Y: SystemApi<RuntimeError>>(
1553 api: &mut Y,
1554 ) -> Result<Bucket, RuntimeError> {
1555 if !api.actor_is_feature_enabled(
1556 ACTOR_STATE_SELF,
1557 PackageFeature::PackageRoyalty.feature_name(),
1558 )? {
1559 return Err(RuntimeError::ApplicationError(
1560 ApplicationError::PackageError(PackageError::RoyaltiesNotEnabled),
1561 ));
1562 }
1563
1564 let handle = api.actor_open_field(
1565 ACTOR_STATE_SELF,
1566 PackageField::RoyaltyAccumulator.into(),
1567 LockFlags::read_only(),
1568 )?;
1569
1570 let substate: PackageRoyaltyAccumulatorFieldPayload = api.field_read_typed(handle)?;
1571 let bucket = substate
1572 .fully_update_and_into_latest_version()
1573 .royalty_vault
1574 .take_all(api)?;
1575
1576 Ok(bucket)
1577 }
1578}
1579
1580pub struct PackageAuthNativeBlueprint;
1581
1582impl PackageAuthNativeBlueprint {
1583 pub fn resolve_function_permission(
1584 receiver: &NodeId,
1585 bp_version_key: &BlueprintVersionKey,
1586 ident: &str,
1587 api: &mut impl SystemBasedKernelApi,
1588 ) -> Result<ResolvedPermission, RuntimeError> {
1589 let auth_config = Self::get_bp_auth_template(receiver, bp_version_key, api)?;
1590 match auth_config.function_auth {
1591 FunctionAuth::AllowAll => Ok(ResolvedPermission::AllowAll),
1592 FunctionAuth::RootOnly => {
1593 let is_root = api.kernel_get_system_state().current_call_frame.is_root();
1594 if is_root {
1595 Ok(ResolvedPermission::AllowAll)
1596 } else {
1597 Ok(ResolvedPermission::AccessRule(AccessRule::DenyAll))
1598 }
1599 }
1600 FunctionAuth::AccessRules(rules) => {
1601 let access_rule = rules.get(ident);
1602 if let Some(access_rule) = access_rule {
1603 Ok(ResolvedPermission::AccessRule(access_rule.clone()))
1604 } else {
1605 let package_address = PackageAddress::new_or_panic(receiver.0);
1606 let blueprint_id =
1607 BlueprintId::new(&package_address, &bp_version_key.blueprint);
1608 Err(RuntimeError::SystemModuleError(
1609 SystemModuleError::AuthError(AuthError::NoFunction(FnIdentifier {
1610 blueprint_id,
1611 ident: ident.to_string(),
1612 })),
1613 ))
1614 }
1615 }
1616 }
1617 }
1618
1619 pub fn get_bp_auth_template(
1620 receiver: &NodeId,
1621 bp_version_key: &BlueprintVersionKey,
1622 api: &mut impl SystemBasedKernelApi,
1623 ) -> Result<AuthConfig, RuntimeError> {
1624 let package_bp_version_id = CanonicalBlueprintId {
1625 address: PackageAddress::new_or_panic(receiver.0),
1626 blueprint: bp_version_key.blueprint.to_string(),
1627 version: bp_version_key.version,
1628 };
1629
1630 let auth_template = api
1631 .kernel_get_system_state()
1632 .system
1633 .auth_cache
1634 .get(&package_bp_version_id);
1635 if let Some(auth_template) = auth_template {
1636 return Ok(auth_template.clone());
1637 }
1638
1639 let handle = api.kernel_open_substate_with_default(
1640 receiver,
1641 MAIN_BASE_PARTITION
1642 .at_offset(PACKAGE_AUTH_TEMPLATE_PARTITION_OFFSET)
1643 .unwrap(),
1644 &SubstateKey::Map(scrypto_encode(&bp_version_key).unwrap()),
1645 LockFlags::read_only(),
1646 Some(|| {
1647 let kv_entry = KeyValueEntrySubstate::<()>::default();
1648 IndexedScryptoValue::from_typed(&kv_entry)
1649 }),
1650 SystemLockData::default(),
1651 )?;
1652
1653 let auth_template: PackageBlueprintVersionAuthConfigEntrySubstate =
1654 api.kernel_read_substate(handle)?.as_typed().unwrap();
1655 api.kernel_close_substate(handle)?;
1656
1657 let template = match auth_template.into_value() {
1658 Some(template) => template.fully_update_and_into_latest_version(),
1659 None => {
1660 return Err(RuntimeError::SystemError(
1661 SystemError::AuthTemplateDoesNotExist(package_bp_version_id),
1662 ))
1663 }
1664 };
1665
1666 api.kernel_get_system_state()
1667 .system
1668 .auth_cache
1669 .insert(package_bp_version_id, template.clone());
1670
1671 Ok(template)
1672 }
1673}
1674
1675#[derive(ScryptoSbor)]
1676pub struct PackageOwnerBadgeData {
1677 pub name: String,
1678 pub package: PackageAddress,
1679}
1680
1681impl NonFungibleData for PackageOwnerBadgeData {
1682 const MUTABLE_FIELDS: &'static [&'static str] = &[];
1683}