radix_engine/blueprints/package/
package.rs

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
25// Import and re-export substate types
26use 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                            // It's impossible for us to get to this point here. We have checked
205                            // earlier in this same function that each inner blueprint has an outer
206                            // blueprint. Thus, we can't get to this point if this invariant was not
207                            // upheld.
208                            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            // Checking that the event is either a struct or an enum
326            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                // Structs and Enums are allowed
332                TypeKind::Enum { .. } | TypeKind::Tuple { .. } => Ok(()),
333                _ => Err(PackageError::InvalidEventSchema),
334            }?;
335
336            // Checking that the event name is indeed what the user claims it to be
337            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            // Notes:
367            // - The "type name" length and char check is done within `validate_names`
368            // - We do no require the type identifier to be equal to the type name in metadata
369        }
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    //-----------------
705    // MAIN PARTITIONS:
706    //-----------------
707
708    {
709        // Note: We don't include royalty field because it's been disabled
710        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    //-------------------
726    // MODULE PARTITIONS:
727    //-------------------
728
729    // Metadata
730    {
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    //-------------------
752    // SYSTEM PARTITIONS:
753    //-------------------
754    {
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    // Additional validation has been added as part of this commit.
785    // The logic is backward compatible, as it's used by protocol updates only.
786    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 schema
1179        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        // Validate VM specific properties
1191        let instrumented_code =
1192            VmPackageValidation::validate(&definition, vm_type, &original_code, vm_api)?;
1193
1194        // Build Package structure
1195        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        // we check for negative royalties at the instantiation time of the royalty module.
1520        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}