1use super::*;
2use crate::blueprints::account::*;
3use crate::blueprints::consensus_manager::*;
4use crate::blueprints::resource::*;
5use crate::internal_prelude::*;
6use crate::kernel::kernel::KernelBoot;
7use crate::object_modules::metadata::*;
8use crate::system::system_callback::*;
9use crate::system::system_db_reader::*;
10use crate::vm::*;
11use radix_engine_interface::blueprints::account::*;
12use radix_engine_interface::blueprints::identity::*;
13use radix_transactions::validation::*;
14
15#[derive(Clone, ScryptoSbor)]
16pub struct CuttlefishPart1Settings {
17 pub system_logic_update: UpdateSetting<NoSettings>,
19 pub kernel_version_update: UpdateSetting<NoSettings>,
21 pub transaction_validation_update: UpdateSetting<NoSettings>,
23 pub assert_worktop_resources_methods: UpdateSetting<NoSettings>,
25 pub account_getter_methods: UpdateSetting<NoSettings>,
27 pub update_metadata: UpdateSetting<NoSettings>,
29 pub update_number_of_min_rounds_per_epoch:
31 UpdateSetting<UpdateNumberOfMinRoundsPerEpochSettings>,
32 pub update_identity_to_not_create_royalty_module: UpdateSetting<NoSettings>,
34 pub vm_boot_to_enable_crypto_utils_v2: UpdateSetting<NoSettings>,
39}
40
41impl UpdateSettings for CuttlefishPart1Settings {
42 type UpdateGenerator = CuttlefishPart1Generator;
43
44 fn protocol_version() -> ProtocolVersion {
45 ProtocolVersion::CuttlefishPart1
46 }
47
48 fn all_enabled_as_default_for_network(network: &NetworkDefinition) -> Self {
49 Self {
50 system_logic_update: UpdateSetting::enabled_as_default_for_network(network),
51 kernel_version_update: UpdateSetting::enabled_as_default_for_network(network),
52 transaction_validation_update: UpdateSetting::enabled_as_default_for_network(network),
53 assert_worktop_resources_methods: UpdateSetting::enabled_as_default_for_network(
54 network,
55 ),
56 account_getter_methods: UpdateSetting::enabled_as_default_for_network(network),
57 update_metadata: UpdateSetting::enabled_as_default_for_network(network),
58 update_number_of_min_rounds_per_epoch: UpdateSetting::enabled_as_default_for_network(
59 network,
60 ),
61 update_identity_to_not_create_royalty_module:
62 UpdateSetting::enabled_as_default_for_network(network),
63 vm_boot_to_enable_crypto_utils_v2: UpdateSetting::enabled_as_default_for_network(
64 network,
65 ),
66 }
67 }
68
69 fn all_disabled() -> Self {
70 Self {
71 system_logic_update: UpdateSetting::Disabled,
72 kernel_version_update: UpdateSetting::Disabled,
73 transaction_validation_update: UpdateSetting::Disabled,
74 assert_worktop_resources_methods: UpdateSetting::Disabled,
75 account_getter_methods: UpdateSetting::Disabled,
76 update_metadata: UpdateSetting::Disabled,
77 update_number_of_min_rounds_per_epoch: UpdateSetting::Disabled,
78 update_identity_to_not_create_royalty_module: UpdateSetting::Disabled,
79 vm_boot_to_enable_crypto_utils_v2: UpdateSetting::Disabled,
80 }
81 }
82
83 fn create_generator(&self) -> Self::UpdateGenerator {
84 Self::UpdateGenerator {
85 settings: self.clone(),
86 }
87 }
88}
89
90#[derive(Clone, ScryptoSbor)]
93pub struct CuttlefishPart2Settings {
94 pub another_system_logic_update: UpdateSetting<NoSettings>,
96}
97
98impl UpdateSettings for CuttlefishPart2Settings {
99 type UpdateGenerator = CuttlefishPart2Generator;
100
101 fn protocol_version() -> ProtocolVersion {
102 ProtocolVersion::CuttlefishPart2
103 }
104
105 fn all_enabled_as_default_for_network(network: &NetworkDefinition) -> Self {
106 Self {
107 another_system_logic_update: UpdateSetting::enabled_as_default_for_network(network),
108 }
109 }
110
111 fn all_disabled() -> Self {
112 Self {
113 another_system_logic_update: UpdateSetting::Disabled,
114 }
115 }
116
117 fn create_generator(&self) -> Self::UpdateGenerator {
118 Self::UpdateGenerator {
119 settings: self.clone(),
120 }
121 }
122}
123
124#[derive(Clone, Copy, Debug, Sbor)]
125pub enum UpdateNumberOfMinRoundsPerEpochSettings {
126 Set { value: u64 },
127 SetIfEquals { if_equals: u64, to_value: u64 },
128}
129
130impl Default for UpdateNumberOfMinRoundsPerEpochSettings {
131 fn default() -> Self {
132 Self::SetIfEquals {
133 if_equals: 500,
134 to_value: 100,
135 }
136 }
137}
138
139impl UpdateSettingContent for UpdateNumberOfMinRoundsPerEpochSettings {
140 fn default_setting(_: &NetworkDefinition) -> Self {
141 Self::default()
142 }
143}
144
145pub struct CuttlefishPart1Generator {
146 settings: CuttlefishPart1Settings,
147}
148
149impl ProtocolUpdateGenerator for CuttlefishPart1Generator {
150 fn batch_groups(&self) -> Vec<Box<dyn ProtocolUpdateBatchGroupGenerator + '_>> {
151 vec![FixedBatchGroupGenerator::named("principal")
152 .add_batch("primary", |store| {
153 generate_part1_batch(store, &self.settings)
154 })
155 .build()]
156 }
157}
158
159pub struct CuttlefishPart2Generator {
160 settings: CuttlefishPart2Settings,
161}
162
163impl ProtocolUpdateGenerator for CuttlefishPart2Generator {
164 fn batch_groups(&self) -> Vec<Box<dyn ProtocolUpdateBatchGroupGenerator + '_>> {
165 vec![FixedBatchGroupGenerator::named("principal")
166 .add_batch("primary", |store| {
167 generate_part2_batch(store, &self.settings)
168 })
169 .build()]
170 }
171}
172
173#[deny(unused_variables)]
174fn generate_part1_batch(
175 store: &dyn SubstateDatabase,
176 CuttlefishPart1Settings {
177 system_logic_update,
178 kernel_version_update,
179 transaction_validation_update,
180 assert_worktop_resources_methods,
181 account_getter_methods,
182 update_metadata,
183 update_number_of_min_rounds_per_epoch,
184 update_identity_to_not_create_royalty_module,
185 vm_boot_to_enable_crypto_utils_v2,
186 }: &CuttlefishPart1Settings,
187) -> ProtocolUpdateBatch {
188 let mut batch = ProtocolUpdateBatch::empty();
189
190 if let UpdateSetting::Enabled(NoSettings) = &system_logic_update {
191 batch.mut_add_flash(
192 "cuttlefish-protocol-system-logic-updates",
193 generate_system_logic_v2_updates(store),
194 );
195 }
196
197 if let UpdateSetting::Enabled(NoSettings) = &kernel_version_update {
198 batch.mut_add_flash(
199 "cuttlefish-protocol-kernel-version-update",
200 generate_always_visible_global_nodes_updates(store),
201 );
202 }
203
204 if let UpdateSetting::Enabled(NoSettings) = &transaction_validation_update {
205 batch.mut_add_flash(
206 "cuttlefish-transaction-validation-updates",
207 generate_cuttlefish_transaction_validation_updates(),
208 );
209 }
210 if let UpdateSetting::Enabled(NoSettings) = &assert_worktop_resources_methods {
211 batch.mut_add_flash(
212 "cuttlefish-assert-worktop-resources-methods",
213 generate_cuttlefish_worktop_methods_extension_state_updates(store),
214 );
215 }
216 if let UpdateSetting::Enabled(NoSettings) = &account_getter_methods {
217 batch.mut_add_flash(
218 "cuttlefish-account-getter-methods",
219 generate_cuttlefish_account_getters_extension_state_updates(store),
220 );
221 }
222
223 if let UpdateSetting::Enabled(NoSettings) = &update_metadata {
224 batch.mut_add_flash(
225 "cuttlefish-update-metadata",
226 generate_cuttlefish_metadata_fix(store),
227 );
228 }
229 if let UpdateSetting::Enabled(settings) = &update_number_of_min_rounds_per_epoch {
230 batch.mut_add_flash(
231 "cuttlefish-update-number-of-min-rounds-per-epoch",
232 generate_cuttlefish_update_min_rounds_per_epoch(store, *settings),
233 );
234 }
235
236 if let UpdateSetting::Enabled(NoSettings) = &update_identity_to_not_create_royalty_module {
237 batch.mut_add_flash(
238 "cuttlefish-update-identity-to-not-create-royalty-module",
239 generate_cuttlefish_update_identity_to_not_create_royalty_module(store),
240 );
241 }
242
243 if let UpdateSetting::Enabled(NoSettings) = &vm_boot_to_enable_crypto_utils_v2 {
244 batch.mut_add_flash(
245 "cuttlefish-vm-boot-to-enable-crypto-utils-v2",
246 generate_vm_boot_to_enable_crypto_utils_v2(),
247 );
248 }
249
250 batch
251}
252
253fn generate_part2_batch(
254 store: &dyn SubstateDatabase,
255 CuttlefishPart2Settings {
256 another_system_logic_update: system_logic_update,
257 }: &CuttlefishPart2Settings,
258) -> ProtocolUpdateBatch {
259 let mut batch = ProtocolUpdateBatch::empty();
260
261 if let UpdateSetting::Enabled(NoSettings) = &system_logic_update {
262 batch.mut_add_flash(
263 "cuttlefish-part2-protocol-system-logic-updates",
264 generate_system_logic_v3_updates(store),
265 );
266 }
267
268 batch
269}
270
271fn generate_system_logic_v2_updates<S: SubstateDatabase + ?Sized>(db: &S) -> StateUpdates {
272 let existing_system_boot: SystemBoot = db.get_existing_substate(
273 TRANSACTION_TRACKER,
274 BOOT_LOADER_PARTITION,
275 BootLoaderField::SystemBoot,
276 );
277
278 StateUpdates::empty().set_substate(
279 TRANSACTION_TRACKER,
280 BOOT_LOADER_PARTITION,
281 BootLoaderField::SystemBoot,
282 SystemBoot::cuttlefish_part1_for_previous_parameters(
283 existing_system_boot.into_parameters(),
284 ),
285 )
286}
287
288fn generate_system_logic_v3_updates<S: SubstateDatabase + ?Sized>(db: &S) -> StateUpdates {
289 let existing_system_boot: SystemBoot = db.get_existing_substate(
290 TRANSACTION_TRACKER,
291 BOOT_LOADER_PARTITION,
292 BootLoaderField::SystemBoot,
293 );
294
295 StateUpdates::empty().set_substate(
296 TRANSACTION_TRACKER,
297 BOOT_LOADER_PARTITION,
298 BootLoaderField::SystemBoot,
299 SystemBoot::cuttlefish_part2_for_previous_parameters(
300 existing_system_boot.into_parameters(),
301 ),
302 )
303}
304
305fn generate_always_visible_global_nodes_updates<S: SubstateDatabase + ?Sized>(
306 db: &S,
307) -> StateUpdates {
308 let KernelBoot::V1 = db.get_existing_substate::<KernelBoot>(
309 TRANSACTION_TRACKER,
310 BOOT_LOADER_PARTITION,
311 BootLoaderField::KernelBoot,
312 ) else {
313 panic!("Unexpected KernelBoot version")
314 };
315
316 StateUpdates::empty().set_substate(
317 TRANSACTION_TRACKER,
318 BOOT_LOADER_PARTITION,
319 BootLoaderField::KernelBoot,
320 KernelBoot::cuttlefish(),
321 )
322}
323
324fn generate_cuttlefish_transaction_validation_updates() -> StateUpdates {
325 StateUpdates::empty().set_substate(
326 TRANSACTION_TRACKER,
327 BOOT_LOADER_PARTITION,
328 BootLoaderField::TransactionValidationConfiguration,
329 TransactionValidationConfigurationSubstate::new(
330 TransactionValidationConfigurationVersions::V1(
331 TransactionValidationConfigV1::cuttlefish(),
332 ),
333 ),
334 )
335}
336
337fn generate_cuttlefish_worktop_methods_extension_state_updates<S: SubstateDatabase + ?Sized>(
338 db: &S,
339) -> StateUpdates {
340 let (added_functions, schema) = WorktopBlueprintCuttlefishExtension::added_functions_schema();
341 let auth_config = WorktopBlueprint::get_definition().auth_config;
342
343 add_public_functions_to_blueprint(
344 db,
345 RESOURCE_PACKAGE,
346 WORKTOP_BLUEPRINT,
347 NativeCodeId::ResourceCode2,
348 added_functions,
349 schema,
350 auth_config,
351 )
352}
353
354fn generate_cuttlefish_account_getters_extension_state_updates<S: SubstateDatabase + ?Sized>(
355 db: &S,
356) -> StateUpdates {
357 let (added_functions, schema) = AccountBlueprintCuttlefishExtension::added_functions_schema();
358
359 let auth_config = {
362 let mut auth_config = AccountBlueprint::get_definition().auth_config;
363 let MethodAuthTemplate::StaticRoleDefinition(StaticRoleDefinition {
364 ref mut methods, ..
365 }) = auth_config.method_auth
366 else {
367 panic!("Doesn't have a static role definition")
368 };
369 methods.extend(
370 added_functions
371 .keys()
372 .map(ToOwned::to_owned)
373 .map(|ident| MethodKey { ident })
374 .map(|key| (key, MethodAccessibility::Public)),
375 );
376 auth_config
377 };
378
379 add_public_functions_to_blueprint(
380 db,
381 ACCOUNT_PACKAGE,
382 ACCOUNT_BLUEPRINT,
383 NativeCodeId::AccountCode3,
384 added_functions,
385 schema,
386 auth_config,
387 )
388}
389
390fn generate_cuttlefish_metadata_fix<S: SubstateDatabase + ?Sized>(db: &S) -> StateUpdates {
391 struct MetadataUpdates {
392 pub name: Option<MetadataValue>,
393 pub description: Option<MetadataValue>,
394 pub icon_url: Option<MetadataValue>,
395 }
396
397 impl MetadataUpdates {
398 pub fn into_map(self) -> IndexMap<String, MetadataValue> {
399 [
400 self.name.map(|value| ("name", value)),
401 self.description.map(|value| ("description", value)),
402 self.icon_url.map(|value| ("icon_url", value)),
403 ]
404 .into_iter()
405 .flatten()
406 .map(|(k, v)| (k.to_owned(), v))
407 .collect()
408 }
409 }
410
411 let reader = SystemDatabaseReader::new(db);
412
413 let metadata_updates = indexmap! {
416 XRD => MetadataUpdates {
417 name: None,
418 description: None,
419 icon_url: Some(MetadataValue::Url(UncheckedUrl("https://assets.radixdlt.com/icons/icon-xrd.png".into())))
420 },
421 PACKAGE_OF_DIRECT_CALLER_RESOURCE => MetadataUpdates {
422 name: Some(MetadataValue::String("Package of Direct Caller Resource".into())),
423 description: Some(MetadataValue::String("This is an implicit proof resource, intended for verifying access by specific code. See the info_url for further information.".into())),
424 icon_url: Some(MetadataValue::Url(UncheckedUrl("https://assets.radixdlt.com/icons/icon-package_of_direct_caller_resource.png".into())))
425 },
426 GLOBAL_CALLER_RESOURCE => MetadataUpdates {
427 name: Some(MetadataValue::String("Global Caller Resource".into())),
428 description: Some(MetadataValue::String("This is an implicit proof resource, intended for verifying access by a specific global caller. In cases where you wish to find out the global caller, you can require the caller to pass their claimed global address into the method, and then verify it with this rule. See the info_url for further information.".into())),
429 icon_url: Some(MetadataValue::Url(UncheckedUrl("https://assets.radixdlt.com/icons/icon-global_caller_resource.png".into())))
430 },
431 SECP256K1_SIGNATURE_RESOURCE => MetadataUpdates {
432 name: Some(MetadataValue::String("ECDSA Secp256k1 Signature Resource".into())),
433 description: Some(MetadataValue::String("This is an implicit proof resource, intended for verifying access by a manifest signed with the given ECDSA Secp256k1 key hash. See the info_url for further information.".into())),
434 icon_url: Some(MetadataValue::Url(UncheckedUrl("https://assets.radixdlt.com/icons/icon-ecdsa_secp256k1_signature_resource.png".into())))
435 },
436 ED25519_SIGNATURE_RESOURCE => MetadataUpdates {
437 name: Some(MetadataValue::String("EdDSA Ed25519 Signature Resource".into())),
438 description: Some(MetadataValue::String("This is an implicit proof resource, intended for verifying access by a manifest signed with the given EdDSA Ed25519 key hash. See the info_url for further information.".into())),
439 icon_url: Some(MetadataValue::Url(UncheckedUrl("https://assets.radixdlt.com/icons/icon-eddsa_ed25519_signature_resource.png".into())))
440 },
441 SYSTEM_EXECUTION_RESOURCE => MetadataUpdates {
442 name: Some(MetadataValue::String("System Execution Resource".into())),
443 description: Some(MetadataValue::String("This is an implicit proof resource, intended for verifying access by a manifest of a certain type of system transaction, such as a protocol update or a validator transaction. See the info_url for further information.".into())),
444 icon_url: Some(MetadataValue::Url(UncheckedUrl("https://assets.radixdlt.com/icons/icon-system_execution_resource.png".into())))
445 },
446 };
447
448 let info_url_metadata = [
451 (XRD.into_node_id(), "https://www.radixdlt.com/info-url/xrd"),
452 (
453 SECP256K1_SIGNATURE_RESOURCE.into_node_id(),
454 "https://www.radixdlt.com/info-url/secp256k1-signature-resource",
455 ),
456 (
457 ED25519_SIGNATURE_RESOURCE.into_node_id(),
458 "https://www.radixdlt.com/info-url/ed25519-signature-resource",
459 ),
460 (
461 PACKAGE_OF_DIRECT_CALLER_RESOURCE.into_node_id(),
462 "https://www.radixdlt.com/info-url/package-of-direct-caller-resource",
463 ),
464 (
465 GLOBAL_CALLER_RESOURCE.into_node_id(),
466 "https://www.radixdlt.com/info-url/global-caller-resource",
467 ),
468 (
469 SYSTEM_EXECUTION_RESOURCE.into_node_id(),
470 "https://www.radixdlt.com/info-url/system-execution-resource",
471 ),
472 (
473 PACKAGE_OWNER_BADGE.into_node_id(),
474 "https://www.radixdlt.com/info-url/package-owner-badge",
475 ),
476 (
477 VALIDATOR_OWNER_BADGE.into_node_id(),
478 "https://www.radixdlt.com/info-url/validator-owner-badge",
479 ),
480 (
481 ACCOUNT_OWNER_BADGE.into_node_id(),
482 "https://www.radixdlt.com/info-url/account-owner-badge",
483 ),
484 (
485 IDENTITY_OWNER_BADGE.into_node_id(),
486 "https://www.radixdlt.com/info-url/identity-owner-badge",
487 ),
488 (
489 PACKAGE_PACKAGE.into_node_id(),
490 "https://www.radixdlt.com/info-url/package-package",
491 ),
492 (
493 RESOURCE_PACKAGE.into_node_id(),
494 "https://www.radixdlt.com/info-url/resource-package",
495 ),
496 (
497 ACCOUNT_PACKAGE.into_node_id(),
498 "https://www.radixdlt.com/info-url/account-package",
499 ),
500 (
501 IDENTITY_PACKAGE.into_node_id(),
502 "https://www.radixdlt.com/info-url/identity-package",
503 ),
504 (
505 CONSENSUS_MANAGER_PACKAGE.into_node_id(),
506 "https://www.radixdlt.com/info-url/consensus-manager-package",
507 ),
508 (
509 ACCESS_CONTROLLER_PACKAGE.into_node_id(),
510 "https://www.radixdlt.com/info-url/access-controller-package",
511 ),
512 (
513 POOL_PACKAGE.into_node_id(),
514 "https://www.radixdlt.com/info-url/pool-package",
515 ),
516 (
517 TRANSACTION_PROCESSOR_PACKAGE.into_node_id(),
518 "https://www.radixdlt.com/info-url/transaction-processor-package",
519 ),
520 (
521 METADATA_MODULE_PACKAGE.into_node_id(),
522 "https://www.radixdlt.com/info-url/metadata-module-package",
523 ),
524 (
525 ROYALTY_MODULE_PACKAGE.into_node_id(),
526 "https://www.radixdlt.com/info-url/royalty-module-package",
527 ),
528 (
529 ROLE_ASSIGNMENT_MODULE_PACKAGE.into_node_id(),
530 "https://www.radixdlt.com/info-url/role-assignment-module-package",
531 ),
532 (
533 TEST_UTILS_PACKAGE.into_node_id(),
534 "https://www.radixdlt.com/info-url/test-utils-package",
535 ),
536 (
537 GENESIS_HELPER_PACKAGE.into_node_id(),
538 "https://www.radixdlt.com/info-url/genesis-helper-package",
539 ),
540 (
541 FAUCET_PACKAGE.into_node_id(),
542 "https://www.radixdlt.com/info-url/faucet-package",
543 ),
544 (
545 TRANSACTION_TRACKER_PACKAGE.into_node_id(),
546 "https://www.radixdlt.com/info-url/transaction-tracker-package",
547 ),
548 (
549 LOCKER_PACKAGE.into_node_id(),
550 "https://www.radixdlt.com/info-url/locker-package",
551 ),
552 (
553 CONSENSUS_MANAGER.into_node_id(),
554 "https://www.radixdlt.com/info-url/consensus-manager",
555 ),
556 (
557 GENESIS_HELPER.into_node_id(),
558 "https://www.radixdlt.com/info-url/genesis-helper",
559 ),
560 (
561 FAUCET.into_node_id(),
562 "https://www.radixdlt.com/info-url/faucet",
563 ),
564 (
565 TRANSACTION_TRACKER.into_node_id(),
566 "https://www.radixdlt.com/info-url/transaction-tracker",
567 ),
568 ];
569
570 let mut state_updates = StateUpdates::empty();
571 for (resource_address, metadata_updates) in metadata_updates.into_iter() {
572 for (key, value) in metadata_updates.into_map().into_iter() {
573 let partition_number = reader
574 .get_partition_of_collection(
575 resource_address.as_node_id(),
576 ModuleId::Metadata,
577 MetadataCollection::EntryKeyValue.collection_index(),
578 )
579 .unwrap();
580
581 state_updates = state_updates.set_substate(
582 resource_address,
583 partition_number,
584 SubstateKey::Map(
585 scrypto_encode(&MetadataEntryKeyPayload { content: key }).unwrap(),
586 ),
587 value.into_locked_substate(),
588 );
589 }
590 }
591 for (node_id, info_url) in info_url_metadata.into_iter() {
592 let partition_number = reader
593 .get_partition_of_collection(
594 &node_id,
595 ModuleId::Metadata,
596 MetadataCollection::EntryKeyValue.collection_index(),
597 )
598 .unwrap();
599
600 state_updates = state_updates.set_substate(
601 node_id,
602 partition_number,
603 SubstateKey::Map(
604 scrypto_encode(&MetadataEntryKeyPayload {
605 content: "info_url".to_owned(),
606 })
607 .unwrap(),
608 ),
609 MetadataValue::Url(UncheckedUrl(info_url.into())).into_locked_substate(),
610 );
611 }
612
613 state_updates
614}
615
616fn generate_cuttlefish_update_min_rounds_per_epoch<S: SubstateDatabase + ?Sized>(
617 db: &S,
618 settings: UpdateNumberOfMinRoundsPerEpochSettings,
619) -> StateUpdates {
620 let mut consensus_manager_config = db
621 .get_existing_substate::<FieldSubstate<VersionedConsensusManagerConfiguration>>(
622 CONSENSUS_MANAGER,
623 MAIN_BASE_PARTITION,
624 ConsensusManagerField::Configuration,
625 )
626 .into_payload()
627 .fully_update_and_into_latest_version();
628 let min_rounds_per_epoch = &mut consensus_manager_config
629 .config
630 .epoch_change_condition
631 .min_round_count;
632
633 match settings {
634 UpdateNumberOfMinRoundsPerEpochSettings::Set { value } => *min_rounds_per_epoch = value,
635 UpdateNumberOfMinRoundsPerEpochSettings::SetIfEquals {
636 if_equals,
637 to_value,
638 } => {
639 if *min_rounds_per_epoch == if_equals {
640 *min_rounds_per_epoch = to_value
641 }
642 }
643 }
644
645 StateUpdates::empty().set_substate(
646 CONSENSUS_MANAGER,
647 MAIN_BASE_PARTITION,
648 ConsensusManagerField::Configuration,
649 consensus_manager_config.into_locked_substate(),
650 )
651}
652
653fn generate_cuttlefish_update_identity_to_not_create_royalty_module<
654 S: SubstateDatabase + ?Sized,
655>(
656 db: &S,
657) -> StateUpdates {
658 let reader = SystemDatabaseReader::new(db);
659 let node_id = IDENTITY_PACKAGE.into_node_id();
660 let blueprint_version_key = BlueprintVersionKey {
661 blueprint: IDENTITY_BLUEPRINT.to_string(),
662 version: Default::default(),
663 };
664
665 let (code_hash, (code_substate, vm_type_substate)) = {
667 let original_code = (NativeCodeId::IdentityCode2 as u64).to_be_bytes().to_vec();
668
669 let code_hash = CodeHash::from_hash(hash(&original_code));
670 let code_substate = PackageCodeOriginalCodeV1 {
671 code: original_code,
672 }
673 .into_locked_substate();
674 let vm_type_substate = PackageCodeVmTypeV1 {
675 vm_type: VmType::Native,
676 }
677 .into_locked_substate();
678
679 (code_hash, (code_substate, vm_type_substate))
680 };
681
682 let blueprint_definition_substate = {
684 let mut blueprint_definition = reader
685 .read_object_collection_entry::<_, VersionedPackageBlueprintVersionDefinition>(
686 &node_id,
687 ObjectModuleId::Main,
688 ObjectCollectionKey::KeyValue(
689 PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
690 &blueprint_version_key,
691 ),
692 )
693 .unwrap()
694 .unwrap()
695 .fully_update_and_into_latest_version();
696
697 for function_name in [IDENTITY_CREATE_ADVANCED_IDENT, IDENTITY_CREATE_IDENT] {
698 blueprint_definition
699 .function_exports
700 .get_mut(function_name)
701 .expect("This function must exist")
702 .code_hash = code_hash;
703 }
704
705 blueprint_definition
706 .hook_exports
707 .get_mut(&BlueprintHook::OnVirtualize)
708 .expect("Identity::OnVirtualize hook must exist")
709 .code_hash = code_hash;
710
711 blueprint_definition.into_locked_substate()
712 };
713
714 let [blueprint_version_definition_partition_number, code_vm_type_partition_number, code_original_code_partition_number] =
715 [
716 PackageCollection::BlueprintVersionDefinitionKeyValue,
717 PackageCollection::CodeVmTypeKeyValue,
718 PackageCollection::CodeOriginalCodeKeyValue,
719 ]
720 .map(|package_collection| {
721 reader
722 .get_partition_of_collection(
723 &node_id,
724 ObjectModuleId::Main,
725 package_collection.collection_index(),
726 )
727 .unwrap()
728 });
729
730 StateUpdates::empty().set_node_updates(
732 node_id,
733 NodeStateUpdates::empty()
734 .set_substate(
735 blueprint_version_definition_partition_number,
736 SubstateKey::map(&blueprint_version_key),
737 blueprint_definition_substate,
738 )
739 .set_substate(
740 code_vm_type_partition_number,
741 SubstateKey::map(&code_hash),
742 vm_type_substate,
743 )
744 .set_substate(
745 code_original_code_partition_number,
746 SubstateKey::map(&code_hash),
747 code_substate,
748 ),
749 )
750}
751
752fn generate_vm_boot_to_enable_crypto_utils_v2() -> StateUpdates {
753 StateUpdates::empty().set_substate(
754 TRANSACTION_TRACKER,
755 BOOT_LOADER_PARTITION,
756 BootLoaderField::VmBoot,
757 VmBoot::V1 {
758 scrypto_version: ScryptoVmVersion::crypto_utils_v2().into(),
759 },
760 )
761}
762
763fn add_public_functions_to_blueprint<S: SubstateDatabase + ?Sized>(
764 db: &S,
765 package: PackageAddress,
766 blueprint: &str,
767 native_code_id: NativeCodeId,
768 added_functions: IndexMap<String, FunctionSchemaInit>,
769 schema: VersionedSchema<ScryptoCustomSchema>,
770 auth_config: AuthConfig,
771) -> StateUpdates {
772 let reader = SystemDatabaseReader::new(db);
773 let node_id = package.into_node_id();
774 let blueprint_version_key = BlueprintVersionKey {
775 blueprint: blueprint.to_string(),
776 version: Default::default(),
777 };
778
779 let (code_hash, (code_substate, vm_type_substate)) = {
781 let original_code = (native_code_id as u64).to_be_bytes().to_vec();
782
783 let code_hash = CodeHash::from_hash(hash(&original_code));
784 let code_substate = PackageCodeOriginalCodeV1 {
785 code: original_code,
786 }
787 .into_versioned()
788 .into_locked_substate();
789 let vm_type_substate = PackageCodeVmTypeV1 {
790 vm_type: VmType::Native,
791 }
792 .into_locked_substate();
793
794 (code_hash, (code_substate, vm_type_substate))
795 };
796
797 let (schema_hash, schema_substate) =
799 (schema.generate_schema_hash(), schema.into_locked_substate());
800
801 let blueprint_definition_substate = {
803 let mut blueprint_definition = reader
804 .read_object_collection_entry::<_, VersionedPackageBlueprintVersionDefinition>(
805 &node_id,
806 ObjectModuleId::Main,
807 ObjectCollectionKey::KeyValue(
808 PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
809 &blueprint_version_key,
810 ),
811 )
812 .unwrap()
813 .unwrap()
814 .fully_update_and_into_latest_version();
815
816 for (function_name, added_function) in added_functions.into_iter() {
817 let TypeRef::Static(input_local_id) = added_function.input else {
818 unreachable!()
819 };
820 let TypeRef::Static(output_local_id) = added_function.output else {
821 unreachable!()
822 };
823
824 blueprint_definition.function_exports.insert(
825 function_name.clone(),
826 PackageExport {
827 code_hash,
828 export_name: function_name.clone(),
829 },
830 );
831 blueprint_definition.interface.functions.insert(
832 function_name,
833 FunctionSchema {
834 receiver: added_function.receiver,
835 input: BlueprintPayloadDef::Static(ScopedTypeId(schema_hash, input_local_id)),
836 output: BlueprintPayloadDef::Static(ScopedTypeId(schema_hash, output_local_id)),
837 },
838 );
839 }
840
841 blueprint_definition.into_locked_substate()
842 };
843
844 let blueprint_version_definition_partition_number =
846 PackagePartitionOffset::BlueprintVersionDefinitionKeyValue.as_main_partition();
847 let code_vm_type_partition_number =
848 PackagePartitionOffset::CodeVmTypeKeyValue.as_main_partition();
849 let code_original_code_partition_number =
850 PackagePartitionOffset::CodeOriginalCodeKeyValue.as_main_partition();
851 let schema_partition_number = SCHEMAS_PARTITION.at_offset(PartitionOffset(0)).unwrap();
852 let blueprint_version_auth_config_partition_number =
853 PackagePartitionOffset::BlueprintVersionAuthConfigKeyValue.as_main_partition();
854
855 StateUpdates::empty().set_node_updates(
857 node_id,
858 NodeStateUpdates::empty()
859 .set_substate(
860 blueprint_version_definition_partition_number,
861 SubstateKey::map(&blueprint_version_key),
862 blueprint_definition_substate,
863 )
864 .set_substate(
865 code_vm_type_partition_number,
866 SubstateKey::map(&code_hash),
867 vm_type_substate,
868 )
869 .set_substate(
870 code_original_code_partition_number,
871 SubstateKey::map(&code_hash),
872 code_substate,
873 )
874 .set_substate(
875 schema_partition_number,
876 SubstateKey::map(&schema_hash),
877 schema_substate,
878 )
879 .set_substate(
880 blueprint_version_auth_config_partition_number,
881 SubstateKey::map(&blueprint_version_key),
882 auth_config.into_locked_substate(),
883 ),
884 )
885}