1use super::*;
2use crate::blueprints::consensus_manager::*;
3use crate::blueprints::models::KeyValueEntryContentSource;
4use crate::blueprints::package::*;
5use crate::blueprints::pool::v1::constants::*;
6use crate::internal_prelude::*;
7use crate::system::system_db_reader::*;
8use crate::vm::*;
9use sbor::{generate_full_schema, TypeAggregator};
10
11#[derive(Clone, ScryptoSbor)]
12pub struct AnemoneSettings {
13 pub validator_fee_fix: UpdateSetting<AnemoneValidatorCreationFee>,
15
16 pub seconds_precision: UpdateSetting<NoSettings>,
18
19 pub vm_boot_to_enable_bls128_and_keccak256: UpdateSetting<NoSettings>,
21
22 pub pools_update: UpdateSetting<NoSettings>,
24}
25
26impl UpdateSettings for AnemoneSettings {
27 type UpdateGenerator = AnemoneGenerator;
28
29 fn protocol_version() -> ProtocolVersion {
30 ProtocolVersion::Anemone
31 }
32
33 fn all_enabled_as_default_for_network(network: &NetworkDefinition) -> Self {
34 Self {
35 validator_fee_fix: UpdateSetting::enabled_as_default_for_network(network),
36 seconds_precision: UpdateSetting::enabled_as_default_for_network(network),
37 vm_boot_to_enable_bls128_and_keccak256: UpdateSetting::enabled_as_default_for_network(
38 network,
39 ),
40 pools_update: UpdateSetting::enabled_as_default_for_network(network),
41 }
42 }
43
44 fn all_disabled() -> Self {
45 Self {
46 validator_fee_fix: UpdateSetting::Disabled,
47 seconds_precision: UpdateSetting::Disabled,
48 vm_boot_to_enable_bls128_and_keccak256: UpdateSetting::Disabled,
49 pools_update: UpdateSetting::Disabled,
50 }
51 }
52
53 fn create_generator(&self) -> Self::UpdateGenerator {
54 AnemoneGenerator {
55 settings: self.clone(),
56 }
57 }
58}
59
60#[derive(Debug, Clone, ScryptoSbor)]
61pub struct AnemoneValidatorCreationFee {
62 pub usd_fee: Decimal,
63}
64
65impl UpdateSettingContent for AnemoneValidatorCreationFee {
66 fn default_setting(network_definition: &NetworkDefinition) -> Self {
67 let usd_fee = match network_definition.id {
68 241 => dec!(1), _ => dec!(100), };
71 Self { usd_fee }
72 }
73}
74
75pub struct AnemoneGenerator {
76 settings: AnemoneSettings,
77}
78
79impl ProtocolUpdateGenerator for AnemoneGenerator {
80 fn insert_status_tracking_flash_transactions(&self) -> bool {
81 false
83 }
84
85 fn batch_groups(&self) -> Vec<Box<dyn ProtocolUpdateBatchGroupGenerator + '_>> {
86 vec![FixedBatchGroupGenerator::named("principal")
87 .add_batch("primary", |store| generate_batch(store, &self.settings))
88 .build()]
89 }
90}
91
92#[deny(unused_variables)]
93fn generate_batch(
94 store: &dyn SubstateDatabase,
95 AnemoneSettings {
96 validator_fee_fix,
97 seconds_precision,
98 vm_boot_to_enable_bls128_and_keccak256,
99 pools_update,
100 }: &AnemoneSettings,
101) -> ProtocolUpdateBatch {
102 let mut batch = ProtocolUpdateBatch::empty();
103
104 if let UpdateSetting::Enabled(creation_fee) = &validator_fee_fix {
105 batch.mut_add_flash(
106 "anemone-validator-fee-fix",
107 generate_validator_creation_fee_fix_state_updates(store, creation_fee),
108 );
109 }
110
111 if let UpdateSetting::Enabled(NoSettings) = &seconds_precision {
112 batch.mut_add_flash(
113 "anemone-seconds-precision",
114 generate_seconds_precision_timestamp_state_updates(store),
115 );
116 }
117
118 if let UpdateSetting::Enabled(NoSettings) = &vm_boot_to_enable_bls128_and_keccak256 {
119 batch.mut_add_flash(
120 "anemone-vm-boot",
121 generate_vm_boot_for_bls128_and_keccak256_state_updates(),
122 );
123 }
124
125 if let UpdateSetting::Enabled(NoSettings) = &pools_update {
126 batch.mut_add_flash(
127 "anemone-pools",
128 generate_pool_math_precision_fix_state_updates(store),
129 );
130 }
131
132 batch
133}
134
135fn generate_validator_creation_fee_fix_state_updates<S: SubstateDatabase + ?Sized>(
136 db: &S,
137 validator_creation_fee: &AnemoneValidatorCreationFee,
138) -> StateUpdates {
139 let reader = SystemDatabaseReader::new(db);
140 let consensus_mgr_node_id = CONSENSUS_MANAGER.into_node_id();
141
142 let versioned_config: VersionedConsensusManagerConfiguration = reader
143 .read_typed_object_field(
144 &consensus_mgr_node_id,
145 ModuleId::Main,
146 ConsensusManagerField::Configuration.field_index(),
147 )
148 .unwrap();
149
150 let mut config = versioned_config.fully_update_and_into_latest_version();
151 config.config.validator_creation_usd_cost = validator_creation_fee.usd_fee;
152
153 let updated_substate = config.into_locked_substate();
154
155 StateUpdates {
156 by_node: indexmap!(
157 consensus_mgr_node_id => NodeStateUpdates::Delta {
158 by_partition: indexmap! {
159 MAIN_BASE_PARTITION => PartitionStateUpdates::Delta {
160 by_substate: indexmap! {
161 SubstateKey::Field(ConsensusManagerField::Configuration.field_index()) => DatabaseUpdate::Set(
162 scrypto_encode(&updated_substate).unwrap()
163 )
164 }
165 },
166 }
167 }
168 ),
169 }
170}
171
172fn generate_seconds_precision_timestamp_state_updates<S: SubstateDatabase + ?Sized>(
175 db: &S,
176) -> StateUpdates {
177 let reader = SystemDatabaseReader::new(db);
178 let consensus_mgr_pkg_node_id = CONSENSUS_MANAGER_PACKAGE.into_node_id();
179 let bp_version_key = BlueprintVersionKey {
180 blueprint: CONSENSUS_MANAGER_BLUEPRINT.to_string(),
181 version: BlueprintVersion::default(),
182 };
183
184 let (new_code_substate, new_vm_type_substate, code_hash) = {
186 let original_code = (NativeCodeId::ConsensusManagerCode2 as u64)
187 .to_be_bytes()
188 .to_vec();
189
190 let code_hash = CodeHash::from_hash(hash(&original_code));
191 let code_substate = PackageCodeOriginalCodeV1 {
192 code: original_code,
193 }
194 .into_versioned()
195 .into_locked_substate();
196 let vm_type_substate = PackageCodeVmTypeV1 {
197 vm_type: VmType::Native,
198 }
199 .into_versioned()
200 .into_locked_substate();
201 (
202 scrypto_encode(&code_substate).unwrap(),
203 scrypto_encode(&vm_type_substate).unwrap(),
204 code_hash,
205 )
206 };
207
208 let (
210 new_schema_substate,
211 get_current_time_input_v2_type_id,
212 compare_current_time_input_v2_type_id,
213 new_schema_hash,
214 ) = {
215 let mut aggregator = TypeAggregator::<ScryptoCustomTypeKind>::new();
216 let get_current_time_input_v2 =
217 aggregator.add_child_type_and_descendents::<ConsensusManagerGetCurrentTimeInputV2>();
218 let compare_current_time_input_v2 = aggregator
219 .add_child_type_and_descendents::<ConsensusManagerCompareCurrentTimeInputV2>();
220 let schema = generate_full_schema(aggregator);
221 let schema_hash = schema.generate_schema_hash();
222 let schema_substate = schema.into_locked_substate();
223 (
224 scrypto_encode(&schema_substate).unwrap(),
225 get_current_time_input_v2,
226 compare_current_time_input_v2,
227 schema_hash,
228 )
229 };
230
231 let updated_bp_definition_substate = {
233 let versioned_definition: VersionedPackageBlueprintVersionDefinition = reader
234 .read_object_collection_entry(
235 &consensus_mgr_pkg_node_id,
236 ObjectModuleId::Main,
237 ObjectCollectionKey::KeyValue(
238 PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
239 &bp_version_key,
240 ),
241 )
242 .unwrap()
243 .unwrap();
244
245 let mut definition = versioned_definition.fully_update_and_into_latest_version();
246
247 let export = definition
248 .function_exports
249 .get_mut(CONSENSUS_MANAGER_GET_CURRENT_TIME_IDENT)
250 .unwrap();
251 export.code_hash = code_hash;
252 let function_schema = definition
253 .interface
254 .functions
255 .get_mut(CONSENSUS_MANAGER_GET_CURRENT_TIME_IDENT)
256 .unwrap();
257 function_schema.input = BlueprintPayloadDef::Static(ScopedTypeId(
258 new_schema_hash,
259 get_current_time_input_v2_type_id,
260 ));
261
262 let export = definition
263 .function_exports
264 .get_mut(CONSENSUS_MANAGER_COMPARE_CURRENT_TIME_IDENT)
265 .unwrap();
266 export.code_hash = code_hash;
267 let function_schema = definition
268 .interface
269 .functions
270 .get_mut(CONSENSUS_MANAGER_COMPARE_CURRENT_TIME_IDENT)
271 .unwrap();
272 function_schema.input = BlueprintPayloadDef::Static(ScopedTypeId(
273 new_schema_hash,
274 compare_current_time_input_v2_type_id,
275 ));
276
277 scrypto_encode(
278 &PackageBlueprintVersionDefinitionVersions::V1(definition)
279 .into_versioned()
280 .into_locked_substate(),
281 )
282 .unwrap()
283 };
284
285 let bp_definition_partition_num = reader
286 .get_partition_of_collection(
287 &consensus_mgr_pkg_node_id,
288 ObjectModuleId::Main,
289 PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
290 )
291 .unwrap();
292
293 let code_vm_type_partition_num = reader
294 .get_partition_of_collection(
295 &consensus_mgr_pkg_node_id,
296 ObjectModuleId::Main,
297 PackageCollection::CodeVmTypeKeyValue.collection_index(),
298 )
299 .unwrap();
300
301 let code_partition_num = reader
302 .get_partition_of_collection(
303 &consensus_mgr_pkg_node_id,
304 ObjectModuleId::Main,
305 PackageCollection::CodeOriginalCodeKeyValue.collection_index(),
306 )
307 .unwrap();
308
309 let schema_partition_num = reader
310 .get_partition_of_collection(
311 &consensus_mgr_pkg_node_id,
312 ObjectModuleId::Main,
313 PackageCollection::SchemaKeyValue.collection_index(),
314 )
315 .unwrap();
316
317 StateUpdates {
318 by_node: indexmap!(
319 consensus_mgr_pkg_node_id => NodeStateUpdates::Delta {
320 by_partition: indexmap! {
321 bp_definition_partition_num => PartitionStateUpdates::Delta {
322 by_substate: indexmap! {
323 SubstateKey::Map(scrypto_encode(&bp_version_key).unwrap()) => DatabaseUpdate::Set(
324 updated_bp_definition_substate
325 )
326 }
327 },
328 code_vm_type_partition_num => PartitionStateUpdates::Delta {
329 by_substate: indexmap! {
330 SubstateKey::Map(scrypto_encode(&code_hash).unwrap()) => DatabaseUpdate::Set(new_vm_type_substate)
331 }
332 },
333 code_partition_num => PartitionStateUpdates::Delta {
334 by_substate: indexmap! {
335 SubstateKey::Map(scrypto_encode(&code_hash).unwrap()) => DatabaseUpdate::Set(new_code_substate)
336 }
337 },
338 schema_partition_num => PartitionStateUpdates::Delta {
339 by_substate: indexmap! {
340 SubstateKey::Map(scrypto_encode(&new_schema_hash).unwrap()) => DatabaseUpdate::Set(new_schema_substate)
341 }
342 }
343 }
344 }
345 ),
346 }
347}
348
349fn generate_vm_boot_for_bls128_and_keccak256_state_updates() -> StateUpdates {
350 StateUpdates::empty().set_substate(
351 TRANSACTION_TRACKER,
352 BOOT_LOADER_PARTITION,
353 BootLoaderField::VmBoot,
354 VmBoot::V1 {
355 scrypto_version: ScryptoVmVersion::crypto_utils_v1().into(),
356 },
357 )
358}
359
360fn generate_pool_math_precision_fix_state_updates<S: SubstateDatabase + ?Sized>(
370 db: &S,
371) -> StateUpdates {
372 let reader = SystemDatabaseReader::new(db);
373
374 let pool_package_node_id = POOL_PACKAGE.into_node_id();
375
376 let old_code_id = NativeCodeId::PoolCode1;
378 let new_code_id = NativeCodeId::PoolCode2;
379
380 let old_code = (old_code_id as u64).to_be_bytes().to_vec();
381 let new_code = (new_code_id as u64).to_be_bytes().to_vec();
382
383 let old_code_hash = CodeHash::from_hash(hash(&old_code));
384 let new_code_hash = CodeHash::from_hash(hash(&new_code));
385
386 let new_code_substate = PackageCodeOriginalCodeV1 { code: new_code }
388 .into_versioned()
389 .into_payload()
390 .into_locked_substate();
391
392 let new_vm_type_substate = PackageCodeVmTypeV1 {
394 vm_type: VmType::Native,
395 }
396 .into_versioned()
397 .into_payload()
398 .into_locked_substate();
399
400 let [(one_resource_pool_blueprint_key, one_resource_pool_blueprint_definition), (two_resource_pool_blueprint_key, two_resource_pool_blueprint_definition), (multi_resource_pool_blueprint_key, multi_resource_pool_blueprint_definition)] =
402 [
403 ONE_RESOURCE_POOL_BLUEPRINT_IDENT,
404 TWO_RESOURCE_POOL_BLUEPRINT_IDENT,
405 MULTI_RESOURCE_POOL_BLUEPRINT_IDENT,
406 ]
407 .map(|blueprint_name| {
408 let blueprint_version_key = BlueprintVersionKey {
409 blueprint: blueprint_name.to_owned(),
410 version: BlueprintVersion::default(),
411 };
412
413 let versioned_definition: VersionedPackageBlueprintVersionDefinition = reader
414 .read_object_collection_entry(
415 &pool_package_node_id,
416 ObjectModuleId::Main,
417 ObjectCollectionKey::KeyValue(
418 PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
419 &blueprint_version_key,
420 ),
421 )
422 .unwrap()
423 .unwrap();
424 let mut blueprint_definition =
425 versioned_definition.fully_update_and_into_latest_version();
426
427 for (_, export) in blueprint_definition.function_exports.iter_mut() {
428 export.code_hash = new_code_hash
429 }
430
431 (
432 blueprint_version_key,
433 PackageBlueprintVersionDefinitionVersions::V1(blueprint_definition)
434 .into_versioned()
435 .into_payload()
436 .into_locked_substate(),
437 )
438 });
439
440 let original_code_partition_number = reader
441 .get_partition_of_collection(
442 &pool_package_node_id,
443 ObjectModuleId::Main,
444 PackageCollection::CodeOriginalCodeKeyValue.collection_index(),
445 )
446 .unwrap();
447
448 let code_vm_type_partition_number = reader
449 .get_partition_of_collection(
450 &pool_package_node_id,
451 ObjectModuleId::Main,
452 PackageCollection::CodeVmTypeKeyValue.collection_index(),
453 )
454 .unwrap();
455
456 let blueprint_definition_partition_number = reader
457 .get_partition_of_collection(
458 &pool_package_node_id,
459 ObjectModuleId::Main,
460 PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
461 )
462 .unwrap();
463
464 StateUpdates {
465 by_node: indexmap! {
466 pool_package_node_id => NodeStateUpdates::Delta {
467 by_partition: indexmap! {
468 original_code_partition_number => PartitionStateUpdates::Delta {
469 by_substate: indexmap! {
470 SubstateKey::Map(scrypto_encode(&old_code_hash).unwrap())
471 => DatabaseUpdate::Delete,
472 SubstateKey::Map(scrypto_encode(&new_code_hash).unwrap())
473 => DatabaseUpdate::Set(scrypto_encode(&new_code_substate).unwrap()),
474 }
475 },
476 code_vm_type_partition_number => PartitionStateUpdates::Delta {
477 by_substate: indexmap! {
478 SubstateKey::Map(scrypto_encode(&old_code_hash).unwrap())
479 => DatabaseUpdate::Delete,
480 SubstateKey::Map(scrypto_encode(&new_code_hash).unwrap())
481 => DatabaseUpdate::Set(scrypto_encode(&new_vm_type_substate).unwrap()),
482 }
483 },
484 blueprint_definition_partition_number => PartitionStateUpdates::Delta {
485 by_substate: indexmap! {
486 SubstateKey::Map(scrypto_encode(&one_resource_pool_blueprint_key).unwrap())
487 => DatabaseUpdate::Set(scrypto_encode(&one_resource_pool_blueprint_definition).unwrap()),
488 SubstateKey::Map(scrypto_encode(&two_resource_pool_blueprint_key).unwrap())
489 => DatabaseUpdate::Set(scrypto_encode(&two_resource_pool_blueprint_definition).unwrap()),
490 SubstateKey::Map(scrypto_encode(&multi_resource_pool_blueprint_key).unwrap())
491 => DatabaseUpdate::Set(scrypto_encode(&multi_resource_pool_blueprint_definition).unwrap()),
492 }
493 }
494 }
495 }
496 },
497 }
498}