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)
527            .to_be_bytes()
528            .to_vec(),
529    ));
530    let (new_code_hash, (new_code_substate, new_vm_type_substate)) = {
531        let original_code = (NativeCodeId::AccessControllerCode2 as u64)
532            .to_be_bytes()
533            .to_vec();
534
535        let code_hash = CodeHash::from_hash(hash(&original_code));
536        let code_substate = PackageCodeOriginalCodeV1 {
537            code: original_code,
538        }
539        .into_versioned()
540        .into_locked_substate();
541        let vm_type_substate = PackageCodeVmTypeV1 {
542            vm_type: VmType::Native,
543        }
544        .into_locked_substate();
545
546        (code_hash, (code_substate, vm_type_substate))
547    };
548
549    let new_blueprint_auth_config = new_blueprint_definition.auth_config.into_locked_substate();
550
551    let blueprint_definition_substate = {
552        let mut blueprint_definition = reader
553            .read_object_collection_entry::<_, VersionedPackageBlueprintVersionDefinition>(
554                &node_id,
555                ObjectModuleId::Main,
556                ObjectCollectionKey::KeyValue(
557                    PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
558                    &blueprint_version_key,
559                ),
560            )
561            .unwrap()
562            .unwrap()
563            .fully_update_and_into_latest_version();
564
565        blueprint_definition.interface.state = IndexedStateSchema::from_schema(
566            new_blueprint_definition
567                .schema
568                .schema
569                .generate_schema_hash(),
570            new_blueprint_definition.schema.state,
571            Default::default(),
572        );
573
574        blueprint_definition.interface.functions = new_blueprint_definition
575            .schema
576            .functions
577            .clone()
578            .functions
579            .into_iter()
580            .map(|(ident, func)| {
581                (
582                    ident,
583                    FunctionSchema {
584                        receiver: func.receiver,
585                        input: BlueprintPayloadDef::Static(ScopedTypeId(
586                            new_schema_hash,
587                            func.input.assert_static(),
588                        )),
589                        output: BlueprintPayloadDef::Static(ScopedTypeId(
590                            new_schema_hash,
591                            func.output.assert_static(),
592                        )),
593                    },
594                )
595            })
596            .collect();
597
598        blueprint_definition.function_exports = new_blueprint_definition
599            .schema
600            .functions
601            .clone()
602            .functions
603            .into_iter()
604            .map(|(ident, func)| {
605                (
606                    ident,
607                    PackageExport {
608                        code_hash: new_code_hash,
609                        export_name: func.export,
610                    },
611                )
612            })
613            .collect();
614
615        blueprint_definition.interface.events = new_blueprint_definition
616            .schema
617            .events
618            .clone()
619            .event_schema
620            .into_iter()
621            .map(|(ident, type_ref)| {
622                (
623                    ident,
624                    BlueprintPayloadDef::Static(ScopedTypeId(
625                        new_schema_hash,
626                        type_ref.assert_static(),
627                    )),
628                )
629            })
630            .collect();
631
632        blueprint_definition.into_locked_substate()
633    };
634
635    let original_code_partition_number = reader
636        .get_partition_of_collection(
637            &node_id,
638            ObjectModuleId::Main,
639            PackageCollection::CodeOriginalCodeKeyValue.collection_index(),
640        )
641        .unwrap();
642
643    let code_vm_type_partition_number = reader
644        .get_partition_of_collection(
645            &node_id,
646            ObjectModuleId::Main,
647            PackageCollection::CodeVmTypeKeyValue.collection_index(),
648        )
649        .unwrap();
650
651    let blueprint_definition_partition_number = reader
652        .get_partition_of_collection(
653            &node_id,
654            ObjectModuleId::Main,
655            PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
656        )
657        .unwrap();
658
659    let blueprint_auth_configs = reader
660        .get_partition_of_collection(
661            &node_id,
662            ObjectModuleId::Main,
663            PackageCollection::BlueprintVersionAuthConfigKeyValue.collection_index(),
664        )
665        .unwrap();
666
667    let schema_partition_num = reader
668        .get_partition_of_collection(
669            &node_id,
670            ObjectModuleId::Main,
671            PackageCollection::SchemaKeyValue.collection_index(),
672        )
673        .unwrap();
674
675    StateUpdates {
676        by_node: indexmap! {
677            node_id => NodeStateUpdates::Delta {
678                by_partition: indexmap! {
679                    blueprint_definition_partition_number => PartitionStateUpdates::Delta {
680                        by_substate: indexmap! {
681                            SubstateKey::Map(scrypto_encode!(&blueprint_version_key)) => DatabaseUpdate::Set(
682                                scrypto_encode!(&blueprint_definition_substate)
683                            )
684                        }
685                    },
686                    blueprint_auth_configs => PartitionStateUpdates::Delta {
687                        by_substate: indexmap! {
688                            SubstateKey::Map(scrypto_encode!(&blueprint_version_key)) => DatabaseUpdate::Set(
689                                scrypto_encode!(&new_blueprint_auth_config)
690                            )
691                        }
692                    },
693                    original_code_partition_number => PartitionStateUpdates::Delta {
694                        by_substate: indexmap! {
695                            SubstateKey::Map(scrypto_encode!(&old_code_hash))
696                                => DatabaseUpdate::Delete,
697                            SubstateKey::Map(scrypto_encode!(&new_code_hash))
698                                => DatabaseUpdate::Set(scrypto_encode!(&new_code_substate)),
699                        }
700                    },
701                    code_vm_type_partition_number => PartitionStateUpdates::Delta {
702                        by_substate: indexmap! {
703                            SubstateKey::Map(scrypto_encode!(&old_code_hash))
704                                => DatabaseUpdate::Delete,
705                            SubstateKey::Map(scrypto_encode!(&new_code_hash))
706                                => DatabaseUpdate::Set(scrypto_encode!(&new_vm_type_substate)),
707                        }
708                    },
709                    schema_partition_num => PartitionStateUpdates::Delta {
710                        by_substate: indexmap! {
711                            SubstateKey::Map(scrypto_encode!(&old_schema_hash))
712                                => DatabaseUpdate::Delete,
713                            SubstateKey::Map(scrypto_encode!(&new_schema_hash))
714                                => DatabaseUpdate::Set(scrypto_encode!(&new_schema_substate))
715                        }
716                    }
717                }
718            }
719        },
720    }
721}
722
723/// Generates the state updates required for restricting reserved role key.
724fn generate_restrict_reserved_role_key_state_updates<S: SubstateDatabase + ?Sized>(
725    db: &S,
726) -> StateUpdates {
727    let reader = SystemDatabaseReader::new(db);
728    let tx_processor_pkg_node_id = PACKAGE_PACKAGE.into_node_id();
729    let bp_version_key = BlueprintVersionKey {
730        blueprint: PACKAGE_BLUEPRINT.to_string(),
731        version: BlueprintVersion::default(),
732    };
733
734    // Generate the new code substates
735    let (new_code_substate, new_vm_type_substate, old_code_hash, new_code_hash) = {
736        let old_code = (NativeCodeId::PackageCode1 as u64).to_be_bytes().to_vec();
737        let old_code_hash = CodeHash::from_hash(hash(&old_code));
738
739        let new_code = (NativeCodeId::PackageCode2 as u64).to_be_bytes().to_vec();
740        let new_code_hash = CodeHash::from_hash(hash(&new_code));
741
742        let versioned_code = PackageCodeOriginalCodeV1 { code: new_code }.into_versioned();
743        let code_payload = versioned_code.into_payload();
744        let code_substate = code_payload.into_locked_substate();
745        let vm_type_substate = PackageCodeVmTypeV1 {
746            vm_type: VmType::Native,
747        }
748        .into_versioned()
749        .into_locked_substate();
750        (
751            scrypto_encode(&code_substate).unwrap(),
752            scrypto_encode(&vm_type_substate).unwrap(),
753            old_code_hash,
754            new_code_hash,
755        )
756    };
757
758    // Generate the blueprint definition substate updates
759    let updated_bp_definition_substate = {
760        let versioned_definition: VersionedPackageBlueprintVersionDefinition = reader
761            .read_object_collection_entry(
762                &tx_processor_pkg_node_id,
763                ObjectModuleId::Main,
764                ObjectCollectionKey::KeyValue(
765                    PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
766                    &bp_version_key,
767                ),
768            )
769            .unwrap()
770            .unwrap();
771
772        let mut definition = versioned_definition.fully_update_and_into_latest_version();
773
774        for (_, export) in definition.function_exports.iter_mut() {
775            export.code_hash = new_code_hash
776        }
777
778        scrypto_encode(&definition.into_versioned().into_locked_substate()).unwrap()
779    };
780
781    let bp_definition_partition_num = reader
782        .get_partition_of_collection(
783            &tx_processor_pkg_node_id,
784            ObjectModuleId::Main,
785            PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
786        )
787        .unwrap();
788
789    let vm_type_partition_num = reader
790        .get_partition_of_collection(
791            &tx_processor_pkg_node_id,
792            ObjectModuleId::Main,
793            PackageCollection::CodeVmTypeKeyValue.collection_index(),
794        )
795        .unwrap();
796
797    let original_code_partition_num = reader
798        .get_partition_of_collection(
799            &tx_processor_pkg_node_id,
800            ObjectModuleId::Main,
801            PackageCollection::CodeOriginalCodeKeyValue.collection_index(),
802        )
803        .unwrap();
804
805    StateUpdates {
806        by_node: indexmap!(
807            tx_processor_pkg_node_id => NodeStateUpdates::Delta {
808                by_partition: indexmap! {
809                    bp_definition_partition_num => PartitionStateUpdates::Delta {
810                        by_substate: indexmap! {
811                            SubstateKey::Map(scrypto_encode(&bp_version_key).unwrap()) => DatabaseUpdate::Set(
812                                updated_bp_definition_substate
813                            )
814                        }
815                    },
816                    vm_type_partition_num => PartitionStateUpdates::Delta {
817                        by_substate: indexmap! {
818                            SubstateKey::Map(scrypto_encode(&old_code_hash).unwrap()) => DatabaseUpdate::Delete,
819                            SubstateKey::Map(scrypto_encode(&new_code_hash).unwrap()) => DatabaseUpdate::Set(new_vm_type_substate)
820                        }
821                    },
822                    original_code_partition_num => PartitionStateUpdates::Delta {
823                        by_substate: indexmap! {
824                            SubstateKey::Map(scrypto_encode(&old_code_hash).unwrap()) => DatabaseUpdate::Delete,
825                            SubstateKey::Map(scrypto_encode(&new_code_hash).unwrap()) => DatabaseUpdate::Set(new_code_substate)
826                        }
827                    },
828                }
829            }
830        ),
831    }
832}
833
834/// Generates the state updates required for updating the TransactionProcessor blueprint
835/// to limit blob memory usage
836fn generate_transaction_processor_blob_limits_state_updates<S: SubstateDatabase + ?Sized>(
837    db: &S,
838) -> StateUpdates {
839    let reader = SystemDatabaseReader::new(db);
840    let tx_processor_pkg_node_id = TRANSACTION_PROCESSOR_PACKAGE.into_node_id();
841    let bp_version_key = BlueprintVersionKey {
842        blueprint: TRANSACTION_PROCESSOR_BLUEPRINT.to_string(),
843        version: BlueprintVersion::default(),
844    };
845
846    // Generate the new code substates
847    let (new_code_substate, new_vm_type_substate, old_code_hash, new_code_hash) = {
848        let old_code = (NativeCodeId::TransactionProcessorCode1 as u64)
849            .to_be_bytes()
850            .to_vec();
851        let old_code_hash = CodeHash::from_hash(hash(&old_code));
852
853        let new_code = (NativeCodeId::TransactionProcessorCode2 as u64)
854            .to_be_bytes()
855            .to_vec();
856        let new_code_hash = CodeHash::from_hash(hash(&new_code));
857
858        let versioned_code = PackageCodeOriginalCodeV1 { code: new_code }.into_versioned();
859        let code_payload = versioned_code.into_payload();
860        let code_substate = code_payload.into_locked_substate();
861        let vm_type_substate = PackageCodeVmTypeV1 {
862            vm_type: VmType::Native,
863        }
864        .into_versioned()
865        .into_locked_substate();
866        (
867            scrypto_encode(&code_substate).unwrap(),
868            scrypto_encode(&vm_type_substate).unwrap(),
869            old_code_hash,
870            new_code_hash,
871        )
872    };
873
874    // Generate the blueprint definition substate updates
875    let updated_bp_definition_substate = {
876        let versioned_definition: VersionedPackageBlueprintVersionDefinition = reader
877            .read_object_collection_entry(
878                &tx_processor_pkg_node_id,
879                ObjectModuleId::Main,
880                ObjectCollectionKey::KeyValue(
881                    PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
882                    &bp_version_key,
883                ),
884            )
885            .unwrap()
886            .unwrap();
887
888        let mut definition = versioned_definition.fully_update_and_into_latest_version();
889
890        for (_, export) in definition.function_exports.iter_mut() {
891            export.code_hash = new_code_hash
892        }
893
894        scrypto_encode(&definition.into_versioned().into_locked_substate()).unwrap()
895    };
896
897    let bp_definition_partition_num = reader
898        .get_partition_of_collection(
899            &tx_processor_pkg_node_id,
900            ObjectModuleId::Main,
901            PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
902        )
903        .unwrap();
904
905    let vm_type_partition_num = reader
906        .get_partition_of_collection(
907            &tx_processor_pkg_node_id,
908            ObjectModuleId::Main,
909            PackageCollection::CodeVmTypeKeyValue.collection_index(),
910        )
911        .unwrap();
912
913    let original_code_partition_num = reader
914        .get_partition_of_collection(
915            &tx_processor_pkg_node_id,
916            ObjectModuleId::Main,
917            PackageCollection::CodeOriginalCodeKeyValue.collection_index(),
918        )
919        .unwrap();
920
921    StateUpdates {
922        by_node: indexmap!(
923            tx_processor_pkg_node_id => NodeStateUpdates::Delta {
924                by_partition: indexmap! {
925                    bp_definition_partition_num => PartitionStateUpdates::Delta {
926                        by_substate: indexmap! {
927                            SubstateKey::Map(scrypto_encode(&bp_version_key).unwrap()) => DatabaseUpdate::Set(
928                                updated_bp_definition_substate
929                            )
930                        }
931                    },
932                    vm_type_partition_num => PartitionStateUpdates::Delta {
933                        by_substate: indexmap! {
934                            SubstateKey::Map(scrypto_encode(&old_code_hash).unwrap()) => DatabaseUpdate::Delete,
935                            SubstateKey::Map(scrypto_encode(&new_code_hash).unwrap()) => DatabaseUpdate::Set(new_vm_type_substate)
936                        }
937                    },
938                    original_code_partition_num => PartitionStateUpdates::Delta {
939                        by_substate: indexmap! {
940                            SubstateKey::Map(scrypto_encode(&old_code_hash).unwrap()) => DatabaseUpdate::Delete,
941                            SubstateKey::Map(scrypto_encode(&new_code_hash).unwrap()) => DatabaseUpdate::Set(new_code_substate)
942                        }
943                    },
944                }
945            }
946        ),
947    }
948}
949
950/// Generates the state updates required for introducing deferred reference check costs
951fn generate_ref_check_costs_state_updates() -> StateUpdates {
952    StateUpdates::empty().set_substate(
953        TRANSACTION_TRACKER,
954        BOOT_LOADER_PARTITION,
955        BootLoaderField::KernelBoot,
956        KernelBoot::V1,
957    )
958}