radix_engine/updates/
bottlenose.rs

1use super::*;
2use crate::blueprints::access_controller::v1::AccessControllerV1NativePackage;
3use crate::blueprints::access_controller::v2::AccessControllerV2NativePackage;
4use crate::blueprints::locker::LockerNativePackage;
5use crate::blueprints::models::KeyValueEntryContentSource;
6use crate::blueprints::package::*;
7use crate::internal_prelude::*;
8use crate::kernel::kernel::*;
9use crate::object_modules::role_assignment::*;
10use crate::system::system_callback::*;
11use crate::system::system_db_reader::*;
12use crate::vm::*;
13use radix_engine_interface::blueprints::access_controller::*;
14use radix_engine_interface::blueprints::account::*;
15use radix_engine_interface::blueprints::transaction_processor::*;
16
17#[derive(Clone, ScryptoSbor)]
18pub struct BottlenoseSettings {
19    /// Exposes a getter method for reading owner role rule.
20    pub add_owner_role_getter: UpdateSetting<NoSettings>,
21
22    /// Introduces the account locker blueprint.
23    pub add_locker_package: UpdateSetting<NoSettings>,
24
25    /// Makes some behavioral changes to the try_deposit_or_refund (and batch variants too) method
26    /// on the account blueprint.
27    pub fix_account_try_deposit_or_refund_behaviour: UpdateSetting<NoSettings>,
28
29    /// Moves various protocol parameters to state.
30    pub move_protocol_params_to_state: UpdateSetting<ProtocolParamsSettings>,
31
32    /// Adds an XRD vault to the access controller for locking fees.
33    pub update_access_controller_to_add_xrd_fee_vault: UpdateSetting<NoSettings>,
34
35    /// Imposes a limits on the blobs in the transaction processor
36    pub impose_a_limit_on_transaction_processor_blobs: UpdateSetting<NoSettings>,
37
38    /// Adds differed reference cost checks.    
39    pub apply_costing_for_ref_checks: UpdateSetting<NoSettings>,
40
41    /// Add restrictions to use of role key in role list.
42    pub restrict_reserved_role_key: UpdateSetting<NoSettings>,
43}
44
45#[derive(Clone, Sbor)]
46pub struct ProtocolParamsSettings {
47    pub network_definition: NetworkDefinition,
48}
49
50impl UpdateSettingContent for ProtocolParamsSettings {
51    fn default_setting(network_definition: &NetworkDefinition) -> Self {
52        Self {
53            network_definition: network_definition.clone(),
54        }
55    }
56}
57
58impl UpdateSettings for BottlenoseSettings {
59    type UpdateGenerator = BottlenoseGenerator;
60
61    fn protocol_version() -> ProtocolVersion {
62        ProtocolVersion::Bottlenose
63    }
64
65    fn all_enabled_as_default_for_network(network: &NetworkDefinition) -> Self {
66        Self {
67            add_owner_role_getter: UpdateSetting::enabled_as_default_for_network(network),
68            add_locker_package: UpdateSetting::enabled_as_default_for_network(network),
69            move_protocol_params_to_state: UpdateSetting::enabled_as_default_for_network(network),
70            fix_account_try_deposit_or_refund_behaviour:
71                UpdateSetting::enabled_as_default_for_network(network),
72            update_access_controller_to_add_xrd_fee_vault:
73                UpdateSetting::enabled_as_default_for_network(network),
74            impose_a_limit_on_transaction_processor_blobs:
75                UpdateSetting::enabled_as_default_for_network(network),
76            apply_costing_for_ref_checks: UpdateSetting::enabled_as_default_for_network(network),
77            restrict_reserved_role_key: UpdateSetting::enabled_as_default_for_network(network),
78        }
79    }
80
81    fn all_disabled() -> Self {
82        Self {
83            add_owner_role_getter: UpdateSetting::Disabled,
84            add_locker_package: UpdateSetting::Disabled,
85            move_protocol_params_to_state: UpdateSetting::Disabled,
86            fix_account_try_deposit_or_refund_behaviour: UpdateSetting::Disabled,
87            update_access_controller_to_add_xrd_fee_vault: UpdateSetting::Disabled,
88            impose_a_limit_on_transaction_processor_blobs: UpdateSetting::Disabled,
89            apply_costing_for_ref_checks: UpdateSetting::Disabled,
90            restrict_reserved_role_key: UpdateSetting::Disabled,
91        }
92    }
93
94    fn create_generator(&self) -> Self::UpdateGenerator {
95        BottlenoseGenerator {
96            settings: self.clone(),
97        }
98    }
99}
100
101pub struct BottlenoseGenerator {
102    settings: BottlenoseSettings,
103}
104
105impl ProtocolUpdateGenerator for BottlenoseGenerator {
106    fn insert_status_tracking_flash_transactions(&self) -> bool {
107        // This was launched without status tracking, so we can't add it in later to avoid divergence
108        false
109    }
110
111    fn batch_groups(&self) -> Vec<Box<dyn ProtocolUpdateBatchGroupGenerator<'_> + '_>> {
112        vec![FixedBatchGroupGenerator::named("principal")
113            .add_batch("primary", |store| generate_batch(store, &self.settings))
114            .build()]
115    }
116}
117
118#[deny(unused_variables)]
119fn generate_batch(
120    store: &dyn SubstateDatabase,
121    BottlenoseSettings {
122        add_owner_role_getter,
123        add_locker_package,
124        fix_account_try_deposit_or_refund_behaviour,
125        move_protocol_params_to_state,
126        update_access_controller_to_add_xrd_fee_vault,
127        impose_a_limit_on_transaction_processor_blobs,
128        apply_costing_for_ref_checks: ref_cost_checks,
129        restrict_reserved_role_key,
130    }: &BottlenoseSettings,
131) -> ProtocolUpdateBatch {
132    let mut transactions = vec![];
133    if let UpdateSetting::Enabled(NoSettings) = &add_owner_role_getter {
134        transactions.push(ProtocolUpdateTransaction::flash(
135            "bottlenose-owner-role-getter",
136            generate_owner_role_getter_state_updates(store),
137        ));
138    }
139    if let UpdateSetting::Enabled(NoSettings) = &add_locker_package {
140        transactions.push(ProtocolUpdateTransaction::flash(
141            "bottlenose-locker-package",
142            generate_locker_package_state_updates(),
143        ));
144    }
145    if let UpdateSetting::Enabled(NoSettings) = &fix_account_try_deposit_or_refund_behaviour {
146        transactions.push(ProtocolUpdateTransaction::flash(
147            "bottlenose-account-try-deposit-or-refund",
148            generate_account_bottlenose_extension_state_updates(store),
149        ));
150    }
151    if let UpdateSetting::Enabled(settings) = &move_protocol_params_to_state {
152        transactions.push(ProtocolUpdateTransaction::flash(
153            "bottlenose-protocol-params-to-state",
154            generate_protocol_params_to_state_updates(settings.network_definition.clone()),
155        ));
156    }
157    if let UpdateSetting::Enabled(NoSettings) = &update_access_controller_to_add_xrd_fee_vault {
158        transactions.push(ProtocolUpdateTransaction::flash(
159            "bottlenose-access-controller-xrd-fee-vault",
160            generate_access_controller_state_updates(store),
161        ));
162    }
163    if let UpdateSetting::Enabled(NoSettings) = &impose_a_limit_on_transaction_processor_blobs {
164        transactions.push(ProtocolUpdateTransaction::flash(
165            "bottlenose-transaction-processor-blob-limits",
166            generate_transaction_processor_blob_limits_state_updates(store),
167        ));
168    }
169    if let UpdateSetting::Enabled(NoSettings) = &ref_cost_checks {
170        transactions.push(ProtocolUpdateTransaction::flash(
171            "bottlenose-add-deferred-reference-check-cost",
172            generate_ref_check_costs_state_updates(),
173        ));
174    }
175    if let UpdateSetting::Enabled(NoSettings) = &restrict_reserved_role_key {
176        transactions.push(ProtocolUpdateTransaction::flash(
177            "bottlenose-restrict-role-assignment-reserved-role-key",
178            generate_restrict_reserved_role_key_state_updates(store),
179        ));
180    }
181    ProtocolUpdateBatch { transactions }
182}
183
184/// A quick macro for encoding and unwrapping.
185macro_rules! scrypto_encode {
186    (
187        $expr: expr
188    ) => {
189        ::radix_common::prelude::scrypto_encode($expr).unwrap()
190    };
191}
192
193fn generate_owner_role_getter_state_updates<S: SubstateDatabase + ?Sized>(db: &S) -> StateUpdates {
194    let reader = SystemDatabaseReader::new(db);
195    let node_id = ROLE_ASSIGNMENT_MODULE_PACKAGE.into_node_id();
196    let blueprint_version_key = BlueprintVersionKey {
197        blueprint: ROLE_ASSIGNMENT_BLUEPRINT.to_string(),
198        version: Default::default(),
199    };
200
201    // Creating the original code substates for extension.
202    let (code_hash, (code_substate, vm_type_substate)) = {
203        let original_code = (NativeCodeId::RoleAssignmentCode2 as u64)
204            .to_be_bytes()
205            .to_vec();
206
207        let code_hash = CodeHash::from_hash(hash(&original_code));
208        let code_substate = PackageCodeOriginalCodeV1 {
209            code: original_code,
210        }
211        .into_versioned()
212        .into_locked_substate();
213        let vm_type_substate = PackageCodeVmTypeV1 {
214            vm_type: VmType::Native,
215        }
216        .into_locked_substate();
217
218        (code_hash, (code_substate, vm_type_substate))
219    };
220
221    // Creating the new schema substate with the methods added by the extension
222    let (added_functions, schema) = RoleAssignmentBottlenoseExtension::added_functions_schema();
223    let (schema_hash, schema_substate) =
224        (schema.generate_schema_hash(), schema.into_locked_substate());
225
226    // Updating the blueprint definition of the existing blueprint with the added functions.
227    let blueprint_definition_substate = {
228        let mut blueprint_definition = reader
229            .read_object_collection_entry::<_, VersionedPackageBlueprintVersionDefinition>(
230                &node_id,
231                ObjectModuleId::Main,
232                ObjectCollectionKey::KeyValue(
233                    PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
234                    &blueprint_version_key,
235                ),
236            )
237            .unwrap()
238            .unwrap()
239            .fully_update_and_into_latest_version();
240
241        for (function_name, added_function) in added_functions.into_iter() {
242            let TypeRef::Static(input_local_id) = added_function.input else {
243                unreachable!()
244            };
245            let TypeRef::Static(output_local_id) = added_function.output else {
246                unreachable!()
247            };
248
249            blueprint_definition.function_exports.insert(
250                function_name.clone(),
251                PackageExport {
252                    code_hash,
253                    export_name: function_name.clone(),
254                },
255            );
256            blueprint_definition.interface.functions.insert(
257                function_name,
258                FunctionSchema {
259                    receiver: added_function.receiver,
260                    input: BlueprintPayloadDef::Static(ScopedTypeId(schema_hash, input_local_id)),
261                    output: BlueprintPayloadDef::Static(ScopedTypeId(schema_hash, output_local_id)),
262                },
263            );
264        }
265
266        blueprint_definition.into_locked_substate()
267    };
268
269    // Getting the partition number of the various collections that we're updating
270    let [blueprint_version_definition_partition_number, code_vm_type_partition_number, code_original_code_partition_number, schema_partition_number] =
271        [
272            PackageCollection::BlueprintVersionDefinitionKeyValue,
273            PackageCollection::CodeVmTypeKeyValue,
274            PackageCollection::CodeOriginalCodeKeyValue,
275            PackageCollection::SchemaKeyValue,
276        ]
277        .map(|package_collection| {
278            reader
279                .get_partition_of_collection(
280                    &node_id,
281                    ObjectModuleId::Main,
282                    package_collection.collection_index(),
283                )
284                .unwrap()
285        });
286
287    // Generating the state updates
288    StateUpdates {
289        by_node: indexmap!(
290            node_id => NodeStateUpdates::Delta {
291                by_partition: indexmap! {
292                    blueprint_version_definition_partition_number => PartitionStateUpdates::Delta {
293                        by_substate: indexmap! {
294                            SubstateKey::Map(scrypto_encode!(&blueprint_version_key)) => DatabaseUpdate::Set(
295                                scrypto_encode!(&blueprint_definition_substate)
296                            )
297                        }
298                    },
299                    code_vm_type_partition_number => PartitionStateUpdates::Delta {
300                        by_substate: indexmap! {
301                            SubstateKey::Map(scrypto_encode!(&code_hash)) => DatabaseUpdate::Set(
302                                scrypto_encode!(&vm_type_substate)
303                            )
304                        }
305                    },
306                    code_original_code_partition_number => PartitionStateUpdates::Delta {
307                        by_substate: indexmap! {
308                            SubstateKey::Map(scrypto_encode!(&code_hash)) => DatabaseUpdate::Set(
309                                scrypto_encode!(&code_substate)
310                            )
311                        }
312                    },
313                    schema_partition_number => PartitionStateUpdates::Delta {
314                        by_substate: indexmap! {
315                            SubstateKey::Map(scrypto_encode!(&schema_hash)) => DatabaseUpdate::Set(
316                                scrypto_encode!(&schema_substate)
317                            )
318                        }
319                    }
320                }
321            }
322        ),
323    }
324}
325
326fn generate_locker_package_state_updates() -> StateUpdates {
327    let package_definition = LockerNativePackage::definition();
328    let package_structure = PackageNativePackage::validate_and_build_package_structure(
329        package_definition,
330        VmType::Native,
331        (NativeCodeId::LockerCode1 as u64).to_be_bytes().to_vec(),
332        Default::default(),
333        false,
334        &VmBoot::latest(),
335    )
336    .unwrap_or_else(|err| {
337        panic!(
338            "Invalid flashed Package definition with native_code_id {}: {:?}",
339            NativeCodeId::LockerCode1 as u64,
340            err
341        )
342    });
343
344    let partitions = create_package_partition_substates(
345        package_structure,
346        metadata_init! {
347            "name" => "Locker Package", locked;
348            "description" => "A native package that defines the logic for dApp-owned lockers to send resources to specified account addresses.", locked;
349        },
350        None,
351    );
352
353    StateUpdates {
354        by_node: indexmap! {
355            LOCKER_PACKAGE.into_node_id() => NodeStateUpdates::Delta {
356                by_partition: partitions
357                    .into_iter()
358                    .map(|(partition_num, substates)| {
359                        (
360                            partition_num,
361                            PartitionStateUpdates::Delta {
362                                by_substate: substates
363                                    .into_iter()
364                                    .map(|(key, value)| {
365                                        (key, DatabaseUpdate::Set(value.as_vec_ref().clone()))
366                                    })
367                                    .collect(),
368                            },
369                        )
370                    })
371                    .collect(),
372            }
373        },
374    }
375}
376
377fn generate_account_bottlenose_extension_state_updates<S: SubstateDatabase + ?Sized>(
378    db: &S,
379) -> StateUpdates {
380    let reader = SystemDatabaseReader::new(db);
381    let node_id = ACCOUNT_PACKAGE.into_node_id();
382    let blueprint_version_key = BlueprintVersionKey {
383        blueprint: ACCOUNT_BLUEPRINT.to_string(),
384        version: Default::default(),
385    };
386
387    // Creating the original code substates for extension.
388    let (code_hash, (code_substate, vm_type_substate)) = {
389        let original_code = (NativeCodeId::AccountCode2 as u64).to_be_bytes().to_vec();
390
391        let code_hash = CodeHash::from_hash(hash(&original_code));
392        let code_substate = PackageCodeOriginalCodeV1 {
393            code: original_code,
394        }
395        .into_locked_substate();
396        let vm_type_substate = PackageCodeVmTypeV1 {
397            vm_type: VmType::Native,
398        }
399        .into_locked_substate();
400
401        (code_hash, (code_substate, vm_type_substate))
402    };
403
404    // Updating the blueprint definition of the existing blueprint so that the code used is the new
405    // one.
406    let blueprint_definition_substate = {
407        let mut blueprint_definition = reader
408            .read_object_collection_entry::<_, VersionedPackageBlueprintVersionDefinition>(
409                &node_id,
410                ObjectModuleId::Main,
411                ObjectCollectionKey::KeyValue(
412                    PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
413                    &blueprint_version_key,
414                ),
415            )
416            .unwrap()
417            .unwrap()
418            .fully_update_and_into_latest_version();
419
420        for function_name in [
421            ACCOUNT_TRY_DEPOSIT_OR_REFUND_IDENT,
422            ACCOUNT_TRY_DEPOSIT_BATCH_OR_REFUND_IDENT,
423        ] {
424            blueprint_definition
425                .function_exports
426                .get_mut(function_name)
427                .expect("This function must exist")
428                .code_hash = code_hash;
429        }
430
431        blueprint_definition.into_locked_substate()
432    };
433
434    // Getting the partition number of the various collections that we're updating
435    let [blueprint_version_definition_partition_number, code_vm_type_partition_number, code_original_code_partition_number] =
436        [
437            PackageCollection::BlueprintVersionDefinitionKeyValue,
438            PackageCollection::CodeVmTypeKeyValue,
439            PackageCollection::CodeOriginalCodeKeyValue,
440        ]
441        .map(|package_collection| {
442            reader
443                .get_partition_of_collection(
444                    &node_id,
445                    ObjectModuleId::Main,
446                    package_collection.collection_index(),
447                )
448                .unwrap()
449        });
450
451    // Generating the state updates
452    StateUpdates {
453        by_node: indexmap!(
454            node_id => NodeStateUpdates::Delta {
455                by_partition: indexmap! {
456                    blueprint_version_definition_partition_number => PartitionStateUpdates::Delta {
457                        by_substate: indexmap! {
458                            SubstateKey::Map(scrypto_encode!(&blueprint_version_key)) => DatabaseUpdate::Set(
459                                scrypto_encode!(&blueprint_definition_substate)
460                            )
461                        }
462                    },
463                    code_vm_type_partition_number => PartitionStateUpdates::Delta {
464                        by_substate: indexmap! {
465                            SubstateKey::Map(scrypto_encode!(&code_hash)) => DatabaseUpdate::Set(
466                                scrypto_encode!(&vm_type_substate)
467                            )
468                        }
469                    },
470                    code_original_code_partition_number => PartitionStateUpdates::Delta {
471                        by_substate: indexmap! {
472                            SubstateKey::Map(scrypto_encode!(&code_hash)) => DatabaseUpdate::Set(
473                                scrypto_encode!(&code_substate)
474                            )
475                        }
476                    },
477                }
478            }
479        ),
480    }
481}
482
483fn generate_protocol_params_to_state_updates(
484    network_definition: NetworkDefinition,
485) -> StateUpdates {
486    StateUpdates::empty().set_substate(
487        TRANSACTION_TRACKER,
488        BOOT_LOADER_PARTITION,
489        BootLoaderField::SystemBoot,
490        SystemBoot::bottlenose(network_definition),
491    )
492}
493
494fn generate_access_controller_state_updates<S: SubstateDatabase + ?Sized>(db: &S) -> StateUpdates {
495    let reader = SystemDatabaseReader::new(db);
496    let node_id = ACCESS_CONTROLLER_PACKAGE.into_node_id();
497    let blueprint_version_key = BlueprintVersionKey {
498        blueprint: ACCESS_CONTROLLER_BLUEPRINT.to_string(),
499        version: Default::default(),
500    };
501    let old_blueprint_definition = AccessControllerV1NativePackage::definition()
502        .blueprints
503        .swap_remove(ACCESS_CONTROLLER_BLUEPRINT)
504        .unwrap();
505    let new_blueprint_definition = AccessControllerV2NativePackage::definition()
506        .blueprints
507        .swap_remove(ACCESS_CONTROLLER_BLUEPRINT)
508        .unwrap();
509
510    let old_schema_hash = old_blueprint_definition
511        .schema
512        .schema
513        .generate_schema_hash();
514    let new_schema_hash = new_blueprint_definition
515        .schema
516        .schema
517        .generate_schema_hash();
518    let new_schema_substate = new_blueprint_definition
519        .schema
520        .schema
521        .clone()
522        .into_locked_substate();
523
524    // Creating the original code substates for extension.
525    let old_code_hash = CodeHash::from_hash(hash(
526        (NativeCodeId::AccessControllerCode1 as u64).to_be_bytes(),
527    ));
528    let (new_code_hash, (new_code_substate, new_vm_type_substate)) = {
529        let original_code = (NativeCodeId::AccessControllerCode2 as u64)
530            .to_be_bytes()
531            .to_vec();
532
533        let code_hash = CodeHash::from_hash(hash(&original_code));
534        let code_substate = PackageCodeOriginalCodeV1 {
535            code: original_code,
536        }
537        .into_versioned()
538        .into_locked_substate();
539        let vm_type_substate = PackageCodeVmTypeV1 {
540            vm_type: VmType::Native,
541        }
542        .into_locked_substate();
543
544        (code_hash, (code_substate, vm_type_substate))
545    };
546
547    let new_blueprint_auth_config = new_blueprint_definition.auth_config.into_locked_substate();
548
549    let blueprint_definition_substate = {
550        let mut blueprint_definition = reader
551            .read_object_collection_entry::<_, VersionedPackageBlueprintVersionDefinition>(
552                &node_id,
553                ObjectModuleId::Main,
554                ObjectCollectionKey::KeyValue(
555                    PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
556                    &blueprint_version_key,
557                ),
558            )
559            .unwrap()
560            .unwrap()
561            .fully_update_and_into_latest_version();
562
563        blueprint_definition.interface.state = IndexedStateSchema::from_schema(
564            new_blueprint_definition
565                .schema
566                .schema
567                .generate_schema_hash(),
568            new_blueprint_definition.schema.state,
569            Default::default(),
570        );
571
572        blueprint_definition.interface.functions = new_blueprint_definition
573            .schema
574            .functions
575            .clone()
576            .functions
577            .into_iter()
578            .map(|(ident, func)| {
579                (
580                    ident,
581                    FunctionSchema {
582                        receiver: func.receiver,
583                        input: BlueprintPayloadDef::Static(ScopedTypeId(
584                            new_schema_hash,
585                            func.input.assert_static(),
586                        )),
587                        output: BlueprintPayloadDef::Static(ScopedTypeId(
588                            new_schema_hash,
589                            func.output.assert_static(),
590                        )),
591                    },
592                )
593            })
594            .collect();
595
596        blueprint_definition.function_exports = new_blueprint_definition
597            .schema
598            .functions
599            .clone()
600            .functions
601            .into_iter()
602            .map(|(ident, func)| {
603                (
604                    ident,
605                    PackageExport {
606                        code_hash: new_code_hash,
607                        export_name: func.export,
608                    },
609                )
610            })
611            .collect();
612
613        blueprint_definition.interface.events = new_blueprint_definition
614            .schema
615            .events
616            .clone()
617            .event_schema
618            .into_iter()
619            .map(|(ident, type_ref)| {
620                (
621                    ident,
622                    BlueprintPayloadDef::Static(ScopedTypeId(
623                        new_schema_hash,
624                        type_ref.assert_static(),
625                    )),
626                )
627            })
628            .collect();
629
630        blueprint_definition.into_locked_substate()
631    };
632
633    let original_code_partition_number = reader
634        .get_partition_of_collection(
635            &node_id,
636            ObjectModuleId::Main,
637            PackageCollection::CodeOriginalCodeKeyValue.collection_index(),
638        )
639        .unwrap();
640
641    let code_vm_type_partition_number = reader
642        .get_partition_of_collection(
643            &node_id,
644            ObjectModuleId::Main,
645            PackageCollection::CodeVmTypeKeyValue.collection_index(),
646        )
647        .unwrap();
648
649    let blueprint_definition_partition_number = reader
650        .get_partition_of_collection(
651            &node_id,
652            ObjectModuleId::Main,
653            PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
654        )
655        .unwrap();
656
657    let blueprint_auth_configs = reader
658        .get_partition_of_collection(
659            &node_id,
660            ObjectModuleId::Main,
661            PackageCollection::BlueprintVersionAuthConfigKeyValue.collection_index(),
662        )
663        .unwrap();
664
665    let schema_partition_num = reader
666        .get_partition_of_collection(
667            &node_id,
668            ObjectModuleId::Main,
669            PackageCollection::SchemaKeyValue.collection_index(),
670        )
671        .unwrap();
672
673    StateUpdates {
674        by_node: indexmap! {
675            node_id => NodeStateUpdates::Delta {
676                by_partition: indexmap! {
677                    blueprint_definition_partition_number => PartitionStateUpdates::Delta {
678                        by_substate: indexmap! {
679                            SubstateKey::Map(scrypto_encode!(&blueprint_version_key)) => DatabaseUpdate::Set(
680                                scrypto_encode!(&blueprint_definition_substate)
681                            )
682                        }
683                    },
684                    blueprint_auth_configs => PartitionStateUpdates::Delta {
685                        by_substate: indexmap! {
686                            SubstateKey::Map(scrypto_encode!(&blueprint_version_key)) => DatabaseUpdate::Set(
687                                scrypto_encode!(&new_blueprint_auth_config)
688                            )
689                        }
690                    },
691                    original_code_partition_number => PartitionStateUpdates::Delta {
692                        by_substate: indexmap! {
693                            SubstateKey::Map(scrypto_encode!(&old_code_hash))
694                                => DatabaseUpdate::Delete,
695                            SubstateKey::Map(scrypto_encode!(&new_code_hash))
696                                => DatabaseUpdate::Set(scrypto_encode!(&new_code_substate)),
697                        }
698                    },
699                    code_vm_type_partition_number => PartitionStateUpdates::Delta {
700                        by_substate: indexmap! {
701                            SubstateKey::Map(scrypto_encode!(&old_code_hash))
702                                => DatabaseUpdate::Delete,
703                            SubstateKey::Map(scrypto_encode!(&new_code_hash))
704                                => DatabaseUpdate::Set(scrypto_encode!(&new_vm_type_substate)),
705                        }
706                    },
707                    schema_partition_num => PartitionStateUpdates::Delta {
708                        by_substate: indexmap! {
709                            SubstateKey::Map(scrypto_encode!(&old_schema_hash))
710                                => DatabaseUpdate::Delete,
711                            SubstateKey::Map(scrypto_encode!(&new_schema_hash))
712                                => DatabaseUpdate::Set(scrypto_encode!(&new_schema_substate))
713                        }
714                    }
715                }
716            }
717        },
718    }
719}
720
721/// Generates the state updates required for restricting reserved role key.
722fn generate_restrict_reserved_role_key_state_updates<S: SubstateDatabase + ?Sized>(
723    db: &S,
724) -> StateUpdates {
725    let reader = SystemDatabaseReader::new(db);
726    let tx_processor_pkg_node_id = PACKAGE_PACKAGE.into_node_id();
727    let bp_version_key = BlueprintVersionKey {
728        blueprint: PACKAGE_BLUEPRINT.to_string(),
729        version: BlueprintVersion::default(),
730    };
731
732    // Generate the new code substates
733    let (new_code_substate, new_vm_type_substate, old_code_hash, new_code_hash) = {
734        let old_code = (NativeCodeId::PackageCode1 as u64).to_be_bytes().to_vec();
735        let old_code_hash = CodeHash::from_hash(hash(&old_code));
736
737        let new_code = (NativeCodeId::PackageCode2 as u64).to_be_bytes().to_vec();
738        let new_code_hash = CodeHash::from_hash(hash(&new_code));
739
740        let versioned_code = PackageCodeOriginalCodeV1 { code: new_code }.into_versioned();
741        let code_payload = versioned_code.into_payload();
742        let code_substate = code_payload.into_locked_substate();
743        let vm_type_substate = PackageCodeVmTypeV1 {
744            vm_type: VmType::Native,
745        }
746        .into_versioned()
747        .into_locked_substate();
748        (
749            scrypto_encode(&code_substate).unwrap(),
750            scrypto_encode(&vm_type_substate).unwrap(),
751            old_code_hash,
752            new_code_hash,
753        )
754    };
755
756    // Generate the blueprint definition substate updates
757    let updated_bp_definition_substate = {
758        let versioned_definition: VersionedPackageBlueprintVersionDefinition = reader
759            .read_object_collection_entry(
760                &tx_processor_pkg_node_id,
761                ObjectModuleId::Main,
762                ObjectCollectionKey::KeyValue(
763                    PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
764                    &bp_version_key,
765                ),
766            )
767            .unwrap()
768            .unwrap();
769
770        let mut definition = versioned_definition.fully_update_and_into_latest_version();
771
772        for (_, export) in definition.function_exports.iter_mut() {
773            export.code_hash = new_code_hash
774        }
775
776        scrypto_encode(&definition.into_versioned().into_locked_substate()).unwrap()
777    };
778
779    let bp_definition_partition_num = reader
780        .get_partition_of_collection(
781            &tx_processor_pkg_node_id,
782            ObjectModuleId::Main,
783            PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
784        )
785        .unwrap();
786
787    let vm_type_partition_num = reader
788        .get_partition_of_collection(
789            &tx_processor_pkg_node_id,
790            ObjectModuleId::Main,
791            PackageCollection::CodeVmTypeKeyValue.collection_index(),
792        )
793        .unwrap();
794
795    let original_code_partition_num = reader
796        .get_partition_of_collection(
797            &tx_processor_pkg_node_id,
798            ObjectModuleId::Main,
799            PackageCollection::CodeOriginalCodeKeyValue.collection_index(),
800        )
801        .unwrap();
802
803    StateUpdates {
804        by_node: indexmap!(
805            tx_processor_pkg_node_id => NodeStateUpdates::Delta {
806                by_partition: indexmap! {
807                    bp_definition_partition_num => PartitionStateUpdates::Delta {
808                        by_substate: indexmap! {
809                            SubstateKey::Map(scrypto_encode(&bp_version_key).unwrap()) => DatabaseUpdate::Set(
810                                updated_bp_definition_substate
811                            )
812                        }
813                    },
814                    vm_type_partition_num => PartitionStateUpdates::Delta {
815                        by_substate: indexmap! {
816                            SubstateKey::Map(scrypto_encode(&old_code_hash).unwrap()) => DatabaseUpdate::Delete,
817                            SubstateKey::Map(scrypto_encode(&new_code_hash).unwrap()) => DatabaseUpdate::Set(new_vm_type_substate)
818                        }
819                    },
820                    original_code_partition_num => PartitionStateUpdates::Delta {
821                        by_substate: indexmap! {
822                            SubstateKey::Map(scrypto_encode(&old_code_hash).unwrap()) => DatabaseUpdate::Delete,
823                            SubstateKey::Map(scrypto_encode(&new_code_hash).unwrap()) => DatabaseUpdate::Set(new_code_substate)
824                        }
825                    },
826                }
827            }
828        ),
829    }
830}
831
832/// Generates the state updates required for updating the TransactionProcessor blueprint
833/// to limit blob memory usage
834fn generate_transaction_processor_blob_limits_state_updates<S: SubstateDatabase + ?Sized>(
835    db: &S,
836) -> StateUpdates {
837    let reader = SystemDatabaseReader::new(db);
838    let tx_processor_pkg_node_id = TRANSACTION_PROCESSOR_PACKAGE.into_node_id();
839    let bp_version_key = BlueprintVersionKey {
840        blueprint: TRANSACTION_PROCESSOR_BLUEPRINT.to_string(),
841        version: BlueprintVersion::default(),
842    };
843
844    // Generate the new code substates
845    let (new_code_substate, new_vm_type_substate, old_code_hash, new_code_hash) = {
846        let old_code = (NativeCodeId::TransactionProcessorCode1 as u64)
847            .to_be_bytes()
848            .to_vec();
849        let old_code_hash = CodeHash::from_hash(hash(&old_code));
850
851        let new_code = (NativeCodeId::TransactionProcessorCode2 as u64)
852            .to_be_bytes()
853            .to_vec();
854        let new_code_hash = CodeHash::from_hash(hash(&new_code));
855
856        let versioned_code = PackageCodeOriginalCodeV1 { code: new_code }.into_versioned();
857        let code_payload = versioned_code.into_payload();
858        let code_substate = code_payload.into_locked_substate();
859        let vm_type_substate = PackageCodeVmTypeV1 {
860            vm_type: VmType::Native,
861        }
862        .into_versioned()
863        .into_locked_substate();
864        (
865            scrypto_encode(&code_substate).unwrap(),
866            scrypto_encode(&vm_type_substate).unwrap(),
867            old_code_hash,
868            new_code_hash,
869        )
870    };
871
872    // Generate the blueprint definition substate updates
873    let updated_bp_definition_substate = {
874        let versioned_definition: VersionedPackageBlueprintVersionDefinition = reader
875            .read_object_collection_entry(
876                &tx_processor_pkg_node_id,
877                ObjectModuleId::Main,
878                ObjectCollectionKey::KeyValue(
879                    PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
880                    &bp_version_key,
881                ),
882            )
883            .unwrap()
884            .unwrap();
885
886        let mut definition = versioned_definition.fully_update_and_into_latest_version();
887
888        for (_, export) in definition.function_exports.iter_mut() {
889            export.code_hash = new_code_hash
890        }
891
892        scrypto_encode(&definition.into_versioned().into_locked_substate()).unwrap()
893    };
894
895    let bp_definition_partition_num = reader
896        .get_partition_of_collection(
897            &tx_processor_pkg_node_id,
898            ObjectModuleId::Main,
899            PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
900        )
901        .unwrap();
902
903    let vm_type_partition_num = reader
904        .get_partition_of_collection(
905            &tx_processor_pkg_node_id,
906            ObjectModuleId::Main,
907            PackageCollection::CodeVmTypeKeyValue.collection_index(),
908        )
909        .unwrap();
910
911    let original_code_partition_num = reader
912        .get_partition_of_collection(
913            &tx_processor_pkg_node_id,
914            ObjectModuleId::Main,
915            PackageCollection::CodeOriginalCodeKeyValue.collection_index(),
916        )
917        .unwrap();
918
919    StateUpdates {
920        by_node: indexmap!(
921            tx_processor_pkg_node_id => NodeStateUpdates::Delta {
922                by_partition: indexmap! {
923                    bp_definition_partition_num => PartitionStateUpdates::Delta {
924                        by_substate: indexmap! {
925                            SubstateKey::Map(scrypto_encode(&bp_version_key).unwrap()) => DatabaseUpdate::Set(
926                                updated_bp_definition_substate
927                            )
928                        }
929                    },
930                    vm_type_partition_num => PartitionStateUpdates::Delta {
931                        by_substate: indexmap! {
932                            SubstateKey::Map(scrypto_encode(&old_code_hash).unwrap()) => DatabaseUpdate::Delete,
933                            SubstateKey::Map(scrypto_encode(&new_code_hash).unwrap()) => DatabaseUpdate::Set(new_vm_type_substate)
934                        }
935                    },
936                    original_code_partition_num => PartitionStateUpdates::Delta {
937                        by_substate: indexmap! {
938                            SubstateKey::Map(scrypto_encode(&old_code_hash).unwrap()) => DatabaseUpdate::Delete,
939                            SubstateKey::Map(scrypto_encode(&new_code_hash).unwrap()) => DatabaseUpdate::Set(new_code_substate)
940                        }
941                    },
942                }
943            }
944        ),
945    }
946}
947
948/// Generates the state updates required for introducing deferred reference check costs
949fn generate_ref_check_costs_state_updates() -> StateUpdates {
950    StateUpdates::empty().set_substate(
951        TRANSACTION_TRACKER,
952        BOOT_LOADER_PARTITION,
953        BootLoaderField::KernelBoot,
954        KernelBoot::V1,
955    )
956}