1use crate::prelude::*;
2use core::ops::AddAssign;
3use radix_engine::blueprints::models::FieldPayload;
4use radix_engine::blueprints::pool::v1::constants::*;
5use radix_engine::define_composite_checker;
6use radix_engine::object_modules::metadata::{MetadataCollection, MetadataEntryEntryPayload};
7use radix_engine::system::checkers::*;
8use radix_engine::system::system_db_reader::{
9 ObjectCollectionKey, SystemDatabaseReader, SystemDatabaseWriter, SystemReaderError,
10};
11use radix_engine::system::system_substates::FieldSubstate;
12use radix_engine::system::type_info::TypeInfoSubstate;
13use radix_engine::transaction::*;
14use radix_engine::updates::*;
15use radix_engine::vm::wasm::DefaultWasmEngine;
16use radix_engine::vm::{NativeVmExtension, NoExtension, ScryptoVm};
17use radix_engine_interface::api::ModuleId;
18use radix_engine_interface::blueprints::account::ACCOUNT_SECURIFY_IDENT;
19use radix_engine_interface::blueprints::consensus_manager::*;
20use radix_engine_interface::blueprints::pool::{
21 OneResourcePoolInstantiateManifestInput, ONE_RESOURCE_POOL_INSTANTIATE_IDENT,
22};
23use radix_engine_interface::prelude::{dec, freeze_roles, rule};
24use radix_substate_store_impls::memory_db::InMemorySubstateDatabase;
25use radix_substate_store_impls::state_tree_support::StateTreeUpdatingDatabase;
26use radix_substate_store_interface::interface::*;
27use radix_substate_store_queries::query::{ResourceAccounter, StateTreeTraverser, VaultFinder};
28use radix_substate_store_queries::typed_native_events::to_typed_native_event;
29use radix_substate_store_queries::typed_substate_layout::*;
30use radix_transactions::manifest::*;
31use radix_transactions::validation::*;
32use std::path::{Path, PathBuf};
33
34use super::Compile;
35
36pub trait TestDatabase:
37 SubstateDatabase + CommittableSubstateDatabase + ListableSubstateDatabase
38{
39}
40impl<T: SubstateDatabase + CommittableSubstateDatabase + ListableSubstateDatabase> TestDatabase
41 for T
42{
43}
44
45pub type DefaultLedgerSimulator = LedgerSimulator<NoExtension, InMemorySubstateDatabase>;
46
47pub struct LedgerSimulatorBuilder<E, D> {
48 custom_extension: E,
49 custom_database: D,
50 protocol_executor: ProtocolExecutor,
51
52 with_kernel_trace: Option<bool>,
54 with_cost_breakdown: Option<bool>,
55 with_receipt_substate_check: bool,
56}
57
58impl Default for LedgerSimulatorBuilder<NoExtension, InMemorySubstateDatabase> {
59 fn default() -> Self {
60 Self::new()
61 }
62}
63
64impl LedgerSimulatorBuilder<NoExtension, InMemorySubstateDatabase> {
65 pub fn new() -> Self {
66 LedgerSimulatorBuilder {
67 custom_extension: NoExtension,
68 custom_database: InMemorySubstateDatabase::standard(),
69 protocol_executor: ProtocolBuilder::for_network(&NetworkDefinition::simulator())
70 .from_bootstrap_to_latest(),
71 with_kernel_trace: None,
72 with_cost_breakdown: None,
73 with_receipt_substate_check: true,
74 }
75 }
76}
77
78impl<E: NativeVmExtension, D: TestDatabase> LedgerSimulatorBuilder<E, D> {
79 pub fn network_definition() -> NetworkDefinition {
80 NetworkDefinition::simulator()
81 }
82
83 pub fn with_state_hashing(self) -> LedgerSimulatorBuilder<E, StateTreeUpdatingDatabase<D>> {
84 LedgerSimulatorBuilder {
85 custom_extension: self.custom_extension,
86 custom_database: StateTreeUpdatingDatabase::new(self.custom_database),
87 protocol_executor: self.protocol_executor,
88 with_kernel_trace: self.with_kernel_trace,
89 with_cost_breakdown: self.with_cost_breakdown,
90 with_receipt_substate_check: self.with_receipt_substate_check,
91 }
92 }
93
94 pub fn with_kernel_trace(mut self) -> Self {
96 self.with_kernel_trace = Some(true);
97 self
98 }
99
100 pub fn without_kernel_trace(mut self) -> Self {
102 self.with_kernel_trace = Some(false);
103 self
104 }
105
106 pub fn with_cost_breakdown(mut self) -> Self {
108 self.with_cost_breakdown = Some(true);
109 self
110 }
111
112 pub fn without_cost_breakdown(mut self) -> Self {
114 self.with_cost_breakdown = Some(false);
115 self
116 }
117
118 pub fn with_receipt_substate_check(mut self) -> Self {
119 self.with_receipt_substate_check = true;
120 self
121 }
122
123 pub fn without_receipt_substate_check(mut self) -> Self {
124 self.with_receipt_substate_check = false;
125 self
126 }
127
128 pub fn with_custom_extension<NE: NativeVmExtension>(
129 self,
130 extension: NE,
131 ) -> LedgerSimulatorBuilder<NE, D> {
132 LedgerSimulatorBuilder::<NE, D> {
133 custom_extension: extension,
134 custom_database: self.custom_database,
135 protocol_executor: self.protocol_executor,
136 with_kernel_trace: self.with_kernel_trace,
137 with_cost_breakdown: self.with_cost_breakdown,
138 with_receipt_substate_check: self.with_receipt_substate_check,
139 }
140 }
141
142 pub fn with_custom_database<ND: TestDatabase>(
143 self,
144 database: ND,
145 ) -> LedgerSimulatorBuilder<E, ND> {
146 LedgerSimulatorBuilder::<E, ND> {
147 custom_extension: self.custom_extension,
148 custom_database: database,
149 protocol_executor: self.protocol_executor,
150 with_kernel_trace: self.with_kernel_trace,
151 with_cost_breakdown: self.with_cost_breakdown,
152 with_receipt_substate_check: self.with_receipt_substate_check,
153 }
154 }
155
156 #[deprecated = "Use with_custom_protocol(|builder| builder.with_babylon(genesis).from_bootstrap_to_latest()) instead"]
162 pub fn with_custom_genesis(self, genesis: BabylonSettings) -> Self {
163 self.with_custom_protocol(|builder| {
164 builder
165 .configure_babylon(|_| genesis)
166 .from_bootstrap_to_latest()
167 })
168 }
169
170 pub fn with_custom_protocol(
171 mut self,
172 executor: impl FnOnce(ProtocolBuilder) -> ProtocolExecutor,
173 ) -> Self {
174 self.protocol_executor =
175 executor(ProtocolBuilder::for_network(&Self::network_definition()));
176 self
177 }
178
179 #[deprecated = "Use with_custom_protocol(|builder| builder.from_bootstrap_to(protocol_version)) instead"]
182 pub fn with_protocol_version(self, protocol_version: ProtocolVersion) -> Self {
183 self.with_custom_protocol(|builder| builder.from_bootstrap_to(protocol_version))
184 }
185
186 pub fn build_from_snapshot(
187 self,
188 snapshot: LedgerSimulatorSnapshot,
189 ) -> LedgerSimulator<E, InMemorySubstateDatabase> {
190 LedgerSimulator {
191 vm_modules: VmModules {
192 scrypto_vm: ScryptoVm::default(),
193 vm_extension: self.custom_extension,
194 },
195 transaction_validator: snapshot.transaction_validator,
196 database: snapshot.database,
197 next_private_key: snapshot.next_private_key,
198 next_transaction_nonce: snapshot.next_transaction_nonce,
199 collected_events: snapshot.collected_events,
200 xrd_free_credits_used: snapshot.xrd_free_credits_used,
201 with_kernel_trace: snapshot.with_kernel_trace,
202 with_cost_breakdown: snapshot.with_cost_breakdown,
203 with_receipt_substate_check: snapshot.with_receipt_substate_check,
204 }
205 }
206
207 pub fn build_and_get_post_genesis_epoch_change(
209 self,
210 ) -> (LedgerSimulator<E, D>, Option<EpochChangeEvent>) {
211 let bootstrap_trace = false;
213
214 #[cfg(not(feature = "resource_tracker"))]
215 let with_kernel_trace = self.with_kernel_trace;
216 #[cfg(feature = "resource_tracker")]
217 let with_kernel_trace = Some(false);
218
219 #[cfg(not(feature = "resource_tracker"))]
220 let with_cost_breakdown = self.with_cost_breakdown;
221 #[cfg(feature = "resource_tracker")]
222 let with_cost_breakdown = Some(false);
223
224 struct ProtocolUpdateHooks {
226 bootstrap_trace: bool,
227 events: Vec<Vec<(EventTypeIdentifier, Vec<u8>)>>,
228 genesis_next_epoch: Option<EpochChangeEvent>,
229 }
230
231 impl ProtocolUpdateExecutionHooks for ProtocolUpdateHooks {
232 fn adapt_execution_config(&mut self, config: ExecutionConfig) -> ExecutionConfig {
233 config.with_kernel_trace(self.bootstrap_trace)
234 }
235
236 fn on_transaction_executed(&mut self, event: OnProtocolTransactionExecuted) {
237 let OnProtocolTransactionExecuted {
238 protocol_version,
239 receipt,
240 ..
241 } = event;
242 self.events
243 .push(receipt.expect_commit_success().application_events.clone());
244 if protocol_version == ProtocolVersion::GENESIS {
245 if let Some(next_epoch) = receipt.expect_commit_success().next_epoch() {
246 self.genesis_next_epoch = Some(next_epoch);
247 }
248 }
249 }
250 }
251
252 let mut substate_db = self.custom_database;
253
254 let mut hooks = ProtocolUpdateHooks {
255 bootstrap_trace,
256 events: vec![],
257 genesis_next_epoch: None,
258 };
259 let vm_modules = VmModules::default_with_extension(self.custom_extension);
260
261 self.protocol_executor.commit_each_protocol_update_advanced(
263 &mut substate_db,
264 &mut hooks,
265 &vm_modules,
266 );
267
268 let next_private_key = 100;
270
271 let next_transaction_nonce = 100;
273
274 let validator = TransactionValidator::new(&substate_db, &Self::network_definition());
275
276 let runner = LedgerSimulator {
277 vm_modules,
278 database: substate_db,
279 transaction_validator: validator,
280 next_private_key,
281 next_transaction_nonce,
282 collected_events: hooks.events,
283 xrd_free_credits_used: false,
284 with_kernel_trace,
285 with_cost_breakdown,
286 with_receipt_substate_check: self.with_receipt_substate_check,
287 };
288
289 (runner, hooks.genesis_next_epoch)
290 }
291
292 pub fn build(self) -> LedgerSimulator<E, D> {
293 self.build_and_get_post_genesis_epoch_change().0
294 }
295}
296
297pub struct LedgerSimulator<E: NativeVmExtension, D: TestDatabase> {
298 vm_modules: VmModules<DefaultWasmEngine, E>,
299 database: D,
300
301 next_private_key: u64,
302 next_transaction_nonce: u32,
303 transaction_validator: TransactionValidator,
304
305 collected_events: Vec<Vec<(EventTypeIdentifier, Vec<u8>)>>,
307 xrd_free_credits_used: bool,
309
310 with_kernel_trace: Option<bool>,
312 with_cost_breakdown: Option<bool>,
314 with_receipt_substate_check: bool,
316}
317
318#[cfg(feature = "post_run_db_check")]
319impl<E: NativeVmExtension, D: TestDatabase> Drop for LedgerSimulator<E, D> {
320 fn drop(&mut self) {
321 self.check_database()
322 }
323}
324
325#[derive(Clone)]
326pub struct LedgerSimulatorSnapshot {
327 database: InMemorySubstateDatabase,
328 transaction_validator: TransactionValidator,
329 next_private_key: u64,
330 next_transaction_nonce: u32,
331 collected_events: Vec<Vec<(EventTypeIdentifier, Vec<u8>)>>,
332 xrd_free_credits_used: bool,
333 with_kernel_trace: Option<bool>,
334 with_cost_breakdown: Option<bool>,
335 with_receipt_substate_check: bool,
336}
337
338impl<E: NativeVmExtension> LedgerSimulator<E, InMemorySubstateDatabase> {
339 pub fn create_snapshot(&self) -> LedgerSimulatorSnapshot {
340 LedgerSimulatorSnapshot {
341 database: self.database.clone(),
342 transaction_validator: self.transaction_validator,
343 next_private_key: self.next_private_key,
344 next_transaction_nonce: self.next_transaction_nonce,
345 collected_events: self.collected_events.clone(),
346 xrd_free_credits_used: self.xrd_free_credits_used,
347 with_kernel_trace: self.with_kernel_trace,
348 with_cost_breakdown: self.with_cost_breakdown,
349 with_receipt_substate_check: self.with_receipt_substate_check,
350 }
351 }
352
353 pub fn restore_snapshot(&mut self, snapshot: LedgerSimulatorSnapshot) {
354 let LedgerSimulatorSnapshot {
355 database,
356 transaction_validator,
357 next_private_key,
358 next_transaction_nonce,
359 collected_events,
360 xrd_free_credits_used,
361 with_kernel_trace,
362 with_cost_breakdown,
363 with_receipt_substate_check,
364 } = snapshot;
365 self.database = database;
366 self.transaction_validator = transaction_validator;
367 self.next_private_key = next_private_key;
368 self.next_transaction_nonce = next_transaction_nonce;
369 self.collected_events = collected_events;
370 self.xrd_free_credits_used = xrd_free_credits_used;
371 self.with_kernel_trace = with_kernel_trace;
372 self.with_cost_breakdown = with_cost_breakdown;
373 self.with_receipt_substate_check = with_receipt_substate_check;
374 }
375}
376
377impl<E: NativeVmExtension, D: TestDatabase> LedgerSimulator<E, D> {
378 pub fn faucet_component(&self) -> GlobalAddress {
379 FAUCET.into()
380 }
381
382 pub fn substate_db(&self) -> &D {
383 &self.database
384 }
385
386 pub fn substate_db_mut(&mut self) -> &mut D {
387 &mut self.database
388 }
389
390 pub fn transaction_validator(&self) -> &TransactionValidator {
391 &self.transaction_validator
392 }
393
394 pub fn update_transaction_validator_after_manual_protocol_update(&mut self) {
398 self.transaction_validator =
399 TransactionValidator::new(&self.database, &NetworkDefinition::simulator())
400 }
401
402 pub fn collected_events(&self) -> &Vec<Vec<(EventTypeIdentifier, Vec<u8>)>> {
403 self.collected_events.as_ref()
404 }
405
406 pub fn next_private_key(&mut self) -> u64 {
407 self.next_private_key += 1;
408 self.next_private_key - 1
409 }
410
411 pub fn next_transaction_nonce(&mut self) -> u32 {
412 self.next_transaction_nonce += 1;
413 self.next_transaction_nonce - 1
414 }
415
416 pub fn new_key_pair(&mut self) -> (Secp256k1PublicKey, Secp256k1PrivateKey) {
417 let private_key = Secp256k1PrivateKey::from_u64(self.next_private_key()).unwrap();
418 let public_key = private_key.public_key();
419
420 (public_key, private_key)
421 }
422
423 pub fn new_ed25519_key_pair(&mut self) -> (Ed25519PublicKey, Ed25519PrivateKey) {
424 let private_key = Ed25519PrivateKey::from_u64(self.next_private_key()).unwrap();
425 let public_key = private_key.public_key();
426
427 (public_key, private_key)
428 }
429
430 pub fn new_key_pair_with_auth_address(
431 &mut self,
432 ) -> (Secp256k1PublicKey, Secp256k1PrivateKey, NonFungibleGlobalId) {
433 let key_pair = self.new_allocated_account();
434 (
435 key_pair.0,
436 key_pair.1,
437 NonFungibleGlobalId::from_public_key(key_pair.0),
438 )
439 }
440
441 pub fn set_metadata(
442 &mut self,
443 address: GlobalAddress,
444 key: &str,
445 value: &str,
446 proof: NonFungibleGlobalId,
447 ) {
448 let manifest = ManifestBuilder::new()
449 .lock_fee_from_faucet()
450 .set_metadata(
451 address,
452 key.to_string(),
453 MetadataValue::String(value.to_string()),
454 )
455 .build();
456
457 let receipt = self.execute_manifest(manifest, vec![proof]);
458 receipt.expect_commit_success();
459 }
460
461 pub fn get_metadata(&mut self, address: GlobalAddress, key: &str) -> Option<MetadataValue> {
462 let reader = SystemDatabaseReader::new(self.substate_db());
463 reader
464 .read_object_collection_entry::<_, MetadataEntryEntryPayload>(
465 address.as_node_id(),
466 ModuleId::Metadata,
467 ObjectCollectionKey::KeyValue(
468 MetadataCollection::EntryKeyValue.collection_index(),
469 &key.to_string(),
470 ),
471 )
472 .unwrap()
473 .map(|v| v.fully_update_and_into_latest_version())
474 }
475
476 pub fn inspect_component_royalty(
477 &mut self,
478 component_address: ComponentAddress,
479 ) -> Result<Decimal, SystemReaderError> {
480 let reader = SystemDatabaseReader::new(self.substate_db());
481 let accumulator = reader
482 .read_typed_object_field::<ComponentRoyaltyAccumulatorFieldPayload>(
483 component_address.as_node_id(),
484 ModuleId::Royalty,
485 ComponentRoyaltyField::Accumulator.field_index(),
486 )?
487 .fully_update_and_into_latest_version();
488
489 let balance = reader
490 .read_typed_object_field::<FungibleVaultBalanceFieldPayload>(
491 accumulator.royalty_vault.0.as_node_id(),
492 ModuleId::Main,
493 FungibleVaultField::Balance.field_index(),
494 )?
495 .fully_update_and_into_latest_version();
496
497 Ok(balance.amount())
498 }
499
500 pub fn inspect_package_royalty(&mut self, package_address: PackageAddress) -> Option<Decimal> {
501 let reader = SystemDatabaseReader::new(self.substate_db());
502 let accumulator = reader
503 .read_typed_object_field::<PackageRoyaltyAccumulatorFieldPayload>(
504 package_address.as_node_id(),
505 ModuleId::Main,
506 PackageField::RoyaltyAccumulator.field_index(),
507 )
508 .ok()?
509 .fully_update_and_into_latest_version();
510
511 let balance = reader
512 .read_typed_object_field::<FungibleVaultBalanceFieldPayload>(
513 accumulator.royalty_vault.0.as_node_id(),
514 ModuleId::Main,
515 FungibleVaultField::Balance.field_index(),
516 )
517 .unwrap()
518 .fully_update_and_into_latest_version();
519
520 Some(balance.amount())
521 }
522
523 pub fn find_all_nodes(&self) -> IndexSet<NodeId> {
524 self.database
525 .read_partition_keys()
526 .map(|(node_id, _)| node_id)
527 .collect()
528 }
529
530 pub fn find_all_components(&self) -> Vec<ComponentAddress> {
531 let mut addresses: Vec<ComponentAddress> = self
532 .find_all_nodes()
533 .iter()
534 .filter_map(|node_id| ComponentAddress::try_from(node_id.as_bytes()).ok())
535 .collect();
536 addresses.sort();
537 addresses
538 }
539
540 pub fn find_all_packages(&self) -> Vec<PackageAddress> {
541 let mut addresses: Vec<PackageAddress> = self
542 .find_all_nodes()
543 .iter()
544 .filter_map(|node_id| PackageAddress::try_from(node_id.as_bytes()).ok())
545 .collect();
546 addresses.sort();
547 addresses
548 }
549
550 pub fn find_all_resources(&self) -> Vec<ResourceAddress> {
551 let mut addresses: Vec<ResourceAddress> = self
552 .find_all_nodes()
553 .iter()
554 .filter_map(|node_id| ResourceAddress::try_from(node_id.as_bytes()).ok())
555 .collect();
556 addresses.sort();
557 addresses
558 }
559
560 pub fn get_package_radix_blueprint_schema_inits(
561 &self,
562 package_address: &PackageAddress,
563 ) -> IndexMap<SchemaHash, VersionedScryptoSchema> {
564 let reader = SystemDatabaseReader::new(self.substate_db());
565 reader
566 .collection_iter(
567 package_address.as_node_id(),
568 ModuleId::Main,
569 PackageCollection::SchemaKeyValue.collection_index(),
570 )
571 .unwrap()
572 .map(|(key, value)| {
573 let key = key.into_map();
574 let hash: SchemaHash = scrypto_decode(&key).unwrap();
575 let schema: PackageSchemaEntryPayload = scrypto_decode(&value).unwrap();
576 (hash, schema.into_content())
577 })
578 .collect()
579 }
580
581 pub fn get_package_blueprint_definitions(
582 &self,
583 package_address: &PackageAddress,
584 ) -> IndexMap<BlueprintVersionKey, BlueprintDefinition> {
585 let reader = SystemDatabaseReader::new(self.substate_db());
586 reader
587 .collection_iter(
588 package_address.as_node_id(),
589 ModuleId::Main,
590 PackageCollection::BlueprintVersionDefinitionKeyValue.collection_index(),
591 )
592 .unwrap()
593 .map(|(key, value)| {
594 let map_key = key.into_map();
595 let key: BlueprintVersionKey = scrypto_decode(&map_key).unwrap();
596 let definition: PackageBlueprintVersionDefinitionEntryPayload =
597 scrypto_decode(&value).unwrap();
598 (key, definition.fully_update_and_into_latest_version())
599 })
600 .collect()
601 }
602
603 pub fn sum_descendant_balance_changes(
604 &mut self,
605 commit: &CommitResult,
606 node_id: &NodeId,
607 ) -> IndexMap<ResourceAddress, BalanceChange> {
608 SubtreeVaults::new(&self.database)
609 .sum_balance_changes(node_id, commit.vault_balance_changes())
610 }
611
612 pub fn get_component_vaults(
613 &mut self,
614 component_address: ComponentAddress,
615 resource_address: ResourceAddress,
616 ) -> Vec<NodeId> {
617 SubtreeVaults::new(&self.database)
618 .get_all(component_address.as_node_id())
619 .swap_remove(&resource_address)
620 .unwrap_or_default()
621 }
622
623 pub fn get_component_balance(
624 &mut self,
625 account_address: ComponentAddress,
626 resource_address: ResourceAddress,
627 ) -> Decimal {
628 let vaults = self.get_component_vaults(account_address, resource_address);
629 let mut sum = Decimal::ZERO;
630 for vault in vaults {
631 sum = sum
632 .checked_add(self.inspect_vault_balance(vault).unwrap())
633 .unwrap();
634 }
635 sum
636 }
637
638 pub fn inspect_vault_balance(&mut self, vault_id: NodeId) -> Option<Decimal> {
639 if vault_id.is_internal_fungible_vault() {
640 self.inspect_fungible_vault(vault_id)
641 } else {
642 self.inspect_non_fungible_vault(vault_id)
643 .map(|(amount, ..)| amount)
644 }
645 }
646
647 pub fn inspect_fungible_vault(&mut self, vault_id: NodeId) -> Option<Decimal> {
648 let reader = SystemDatabaseReader::new(self.substate_db());
649 let vault: Option<FungibleVaultBalanceFieldPayload> = reader
650 .read_typed_object_field(
651 &vault_id,
652 ModuleId::Main,
653 FungibleVaultField::Balance.into(),
654 )
655 .ok();
656
657 vault.map(|v| v.fully_update_and_into_latest_version().amount())
658 }
659
660 pub fn inspect_non_fungible_vault(
661 &mut self,
662 vault_id: NodeId,
663 ) -> Option<(Decimal, Box<dyn Iterator<Item = NonFungibleLocalId> + '_>)> {
664 let reader = SystemDatabaseReader::new(self.substate_db());
665 let vault_balance: NonFungibleVaultBalanceFieldPayload = reader
666 .read_typed_object_field(
667 &vault_id,
668 ModuleId::Main,
669 NonFungibleVaultField::Balance.into(),
670 )
671 .ok()?;
672 let amount = vault_balance.fully_update_and_into_latest_version().amount;
673
674 let iter: Vec<NonFungibleLocalId> = reader
676 .collection_iter(
677 &vault_id,
678 ModuleId::Main,
679 NonFungibleVaultCollection::NonFungibleIndex.collection_index(),
680 )
681 .unwrap()
682 .map(|(key, _)| {
683 let map_key = key.into_map();
684 let id: NonFungibleLocalId = scrypto_decode(&map_key).unwrap();
685 id
686 })
687 .collect();
688
689 Some((amount, Box::new(iter.into_iter())))
690 }
691
692 pub fn get_component_resources(
693 &mut self,
694 component_address: ComponentAddress,
695 ) -> HashMap<ResourceAddress, Decimal> {
696 let node_id = component_address.as_node_id();
697 let mut accounter = ResourceAccounter::new(&self.database);
698 accounter.traverse(*node_id);
699 accounter.close().balances
700 }
701
702 pub fn component_state<T: ScryptoDecode>(&self, component_address: ComponentAddress) -> T {
703 let node_id: &NodeId = component_address.as_node_id();
704 let component_state = self.substate_db().get_substate::<FieldSubstate<T>>(
705 node_id,
706 MAIN_BASE_PARTITION,
707 ComponentField::State0,
708 );
709 component_state.unwrap().into_payload()
710 }
711
712 pub fn get_non_fungible_data<T: NonFungibleData>(
713 &self,
714 resource: ResourceAddress,
715 non_fungible_id: NonFungibleLocalId,
716 ) -> T {
717 let reader = SystemDatabaseReader::new(self.substate_db());
718 let payload = reader
719 .read_object_collection_entry::<_, NonFungibleResourceManagerDataEntryPayload>(
720 resource.as_node_id(),
721 ModuleId::Main,
722 ObjectCollectionKey::KeyValue(
723 NonFungibleResourceManagerCollection::DataKeyValue.collection_index(),
724 &non_fungible_id,
725 ),
726 )
727 .unwrap()
728 .unwrap();
729
730 scrypto_decode(&scrypto_encode(&payload).unwrap()).unwrap()
731 }
732
733 pub fn get_kv_store_entry<K: ScryptoEncode, V: ScryptoEncode + ScryptoDecode>(
734 &self,
735 kv_store_id: Own,
736 key: &K,
737 ) -> Option<V> {
738 let reader = SystemDatabaseReader::new(self.substate_db());
739 reader.read_typed_kv_entry(kv_store_id.as_node_id(), key)
740 }
741
742 pub fn get_fungible_resource_total_supply(&self, resource: ResourceAddress) -> Decimal {
743 let total_supply = self
744 .substate_db()
745 .get_substate::<FungibleResourceManagerTotalSupplyFieldSubstate>(
746 resource,
747 MAIN_BASE_PARTITION,
748 FungibleResourceManagerField::TotalSupply,
749 )
750 .unwrap()
751 .into_payload()
752 .fully_update_and_into_latest_version();
753 total_supply
754 }
755
756 pub fn load_account_from_faucet(&mut self, account_address: ComponentAddress) {
757 let manifest = ManifestBuilder::new()
758 .lock_fee_from_faucet()
759 .get_free_xrd_from_faucet()
760 .take_all_from_worktop(XRD, "free_xrd")
761 .try_deposit_or_abort(account_address, None, "free_xrd")
762 .build();
763
764 let receipt = self.execute_manifest(manifest, vec![]);
765 receipt.expect_commit_success();
766 }
767
768 pub fn new_account_advanced(&mut self, owner_role: OwnerRole) -> ComponentAddress {
769 let manifest = ManifestBuilder::new()
770 .lock_fee_from_faucet()
771 .new_account_advanced(owner_role, None)
772 .build();
773 let receipt = self.execute_manifest(manifest, vec![]);
774 receipt.expect_commit_success();
775
776 let account = receipt.expect_commit(true).new_component_addresses()[0];
777
778 let manifest = ManifestBuilder::new()
779 .lock_fee_from_faucet()
780 .get_free_xrd_from_faucet()
781 .try_deposit_entire_worktop_or_abort(account, None)
782 .build();
783 let receipt = self.execute_manifest(manifest, vec![]);
784 receipt.expect_commit_success();
785
786 account
787 }
788
789 pub fn new_preallocated_account(
790 &mut self,
791 ) -> (Secp256k1PublicKey, Secp256k1PrivateKey, ComponentAddress) {
792 let (pub_key, priv_key) = self.new_key_pair();
793 let account =
794 ComponentAddress::preallocated_account_from_public_key(&PublicKey::Secp256k1(pub_key));
795 self.load_account_from_faucet(account);
796 (pub_key, priv_key, account)
797 }
798
799 pub fn new_ed25519_preallocated_account(
800 &mut self,
801 ) -> (Ed25519PublicKey, Ed25519PrivateKey, ComponentAddress) {
802 let (pub_key, priv_key) = self.new_ed25519_key_pair();
803 let account =
804 ComponentAddress::preallocated_account_from_public_key(&PublicKey::Ed25519(pub_key));
805 self.load_account_from_faucet(account);
806 (pub_key, priv_key, account)
807 }
808
809 pub fn get_active_validator_info_by_key(&self, key: &Secp256k1PublicKey) -> ValidatorSubstate {
810 let address = self.get_active_validator_with_key(key);
811 self.get_validator_info(address)
812 }
813
814 pub fn get_validator_info(&self, address: ComponentAddress) -> ValidatorSubstate {
815 let reader = SystemDatabaseReader::new(&self.database);
816 let substate = reader
817 .read_typed_object_field::<ValidatorStateFieldPayload>(
818 address.as_node_id(),
819 ModuleId::Main,
820 ValidatorField::State.field_index(),
821 )
822 .unwrap()
823 .fully_update_and_into_latest_version();
824
825 substate
826 }
827
828 pub fn get_active_validator_with_key(&self, key: &Secp256k1PublicKey) -> ComponentAddress {
829 let reader = SystemDatabaseReader::new(&self.database);
830 let substate = reader
831 .read_typed_object_field::<ConsensusManagerCurrentValidatorSetFieldPayload>(
832 CONSENSUS_MANAGER.as_node_id(),
833 ModuleId::Main,
834 ConsensusManagerField::CurrentValidatorSet.field_index(),
835 )
836 .unwrap()
837 .fully_update_and_into_latest_version();
838 *substate.validator_set.get_by_public_key(key).unwrap().0
839 }
840
841 pub fn new_allocated_account(
842 &mut self,
843 ) -> (Secp256k1PublicKey, Secp256k1PrivateKey, ComponentAddress) {
844 let key_pair = self.new_key_pair();
845 let withdraw_auth = rule!(require(signature(key_pair.0)));
846 let account = self.new_account_advanced(OwnerRole::Fixed(withdraw_auth));
847 (key_pair.0, key_pair.1, account)
848 }
849
850 pub fn new_ed25519_preallocated_account_with_access_controller(
851 &mut self,
852 n_out_of_4: u8,
853 ) -> (
854 Ed25519PublicKey,
855 Ed25519PrivateKey,
856 Ed25519PublicKey,
857 Ed25519PrivateKey,
858 Ed25519PublicKey,
859 Ed25519PrivateKey,
860 Ed25519PublicKey,
861 Ed25519PrivateKey,
862 ComponentAddress,
863 ComponentAddress,
864 ) {
865 let (pk1, sk1, account) = self.new_ed25519_preallocated_account();
866 let (pk2, sk2) = self.new_ed25519_key_pair();
867 let (pk3, sk3) = self.new_ed25519_key_pair();
868 let (pk4, sk4) = self.new_ed25519_key_pair();
869
870 let access_rule = AccessRule::Protected(CompositeRequirement::BasicRequirement(
871 BasicRequirement::CountOf(
872 n_out_of_4,
873 vec![
874 ResourceOrNonFungible::NonFungible(NonFungibleGlobalId::from_public_key(pk1)),
875 ResourceOrNonFungible::NonFungible(NonFungibleGlobalId::from_public_key(pk2)),
876 ResourceOrNonFungible::NonFungible(NonFungibleGlobalId::from_public_key(pk3)),
877 ResourceOrNonFungible::NonFungible(NonFungibleGlobalId::from_public_key(pk4)),
878 ],
879 ),
880 ));
881
882 let access_controller = self
883 .execute_manifest(
884 ManifestBuilder::new()
885 .lock_fee_from_faucet()
886 .call_method(account, ACCOUNT_SECURIFY_IDENT, manifest_args!())
887 .take_all_from_worktop(ACCOUNT_OWNER_BADGE, "owner_badge")
888 .call_function_with_name_lookup(
889 ACCESS_CONTROLLER_PACKAGE,
890 ACCESS_CONTROLLER_BLUEPRINT,
891 ACCESS_CONTROLLER_CREATE_IDENT,
892 |lookup| {
893 (
894 lookup.bucket("owner_badge"),
895 ManifestRuleSet {
896 primary_role: access_rule.clone().into(),
897 recovery_role: access_rule.clone().into(),
898 confirmation_role: access_rule.clone().into(),
899 },
900 Some(1000u32),
901 None::<()>,
902 )
903 },
904 )
905 .build(),
906 vec![NonFungibleGlobalId::from_public_key(pk1)],
907 )
908 .expect_commit_success()
909 .new_component_addresses()[0];
910
911 (
912 pk1,
913 sk1,
914 pk2,
915 sk2,
916 pk3,
917 sk3,
918 pk4,
919 sk4,
920 account,
921 access_controller,
922 )
923 }
924
925 pub fn new_account(
926 &mut self,
927 is_preallocated: bool,
928 ) -> (Secp256k1PublicKey, Secp256k1PrivateKey, ComponentAddress) {
929 if is_preallocated {
930 self.new_preallocated_account()
931 } else {
932 self.new_allocated_account()
933 }
934 }
935
936 pub fn new_identity<P: Into<PublicKey> + Clone + HasPublicKeyHash>(
937 &mut self,
938 pk: P,
939 is_virtual: bool,
940 ) -> ComponentAddress {
941 if is_virtual {
942 ComponentAddress::preallocated_identity_from_public_key(&pk)
943 } else {
944 let owner_id = NonFungibleGlobalId::from_public_key(&pk);
945 let manifest = ManifestBuilder::new()
946 .lock_fee_from_faucet()
947 .create_identity_advanced(OwnerRole::Fixed(rule!(require(owner_id))))
948 .build();
949 let receipt = self.execute_manifest(manifest, vec![]);
950 receipt.expect_commit_success();
951 let component_address = receipt.expect_commit(true).new_component_addresses()[0];
952
953 component_address
954 }
955 }
956
957 pub fn new_securified_identity(&mut self, account: ComponentAddress) -> ComponentAddress {
958 let manifest = ManifestBuilder::new()
959 .lock_fee_from_faucet()
960 .create_identity()
961 .try_deposit_entire_worktop_or_abort(account, None)
962 .build();
963 let receipt = self.execute_manifest(manifest, vec![]);
964 receipt.expect_commit_success();
965 let component_address = receipt.expect_commit(true).new_component_addresses()[0];
966
967 component_address
968 }
969
970 pub fn new_validator_with_pub_key(
971 &mut self,
972 pub_key: Secp256k1PublicKey,
973 account: ComponentAddress,
974 ) -> ComponentAddress {
975 let manifest = ManifestBuilder::new()
976 .lock_fee_from_faucet()
977 .get_free_xrd_from_faucet()
978 .take_from_worktop(XRD, *DEFAULT_VALIDATOR_XRD_COST, "xrd_creation_fee")
979 .create_validator(pub_key, Decimal::ONE, "xrd_creation_fee")
980 .try_deposit_entire_worktop_or_abort(account, None)
981 .build();
982 let receipt = self.execute_manifest(manifest, vec![]);
983 let address = receipt.expect_commit(true).new_component_addresses()[0];
984 address
985 }
986
987 pub fn new_staked_validator_with_pub_key(
988 &mut self,
989 pub_key: Secp256k1PublicKey,
990 account: ComponentAddress,
991 ) -> ComponentAddress {
992 let manifest = ManifestBuilder::new()
993 .lock_fee_from_faucet()
994 .get_free_xrd_from_faucet()
995 .take_from_worktop(XRD, *DEFAULT_VALIDATOR_XRD_COST, "xrd_creation_fee")
996 .create_validator(pub_key, Decimal::ONE, "xrd_creation_fee")
997 .try_deposit_entire_worktop_or_abort(account, None)
998 .build();
999 let receipt = self.execute_manifest(manifest, vec![]);
1000 let validator_address = receipt.expect_commit(true).new_component_addresses()[0];
1001
1002 let receipt = self.execute_manifest(
1003 ManifestBuilder::new()
1004 .lock_fee_from_faucet()
1005 .get_free_xrd_from_faucet()
1006 .create_proof_from_account_of_non_fungibles(
1007 account,
1008 VALIDATOR_OWNER_BADGE,
1009 [NonFungibleLocalId::bytes(validator_address.as_node_id().0).unwrap()],
1010 )
1011 .take_all_from_worktop(XRD, "bucket")
1012 .with_bucket("bucket", |builder, bucket| {
1013 builder.call_method(
1014 validator_address,
1015 VALIDATOR_STAKE_AS_OWNER_IDENT,
1016 manifest_args!(bucket),
1017 )
1018 })
1019 .deposit_entire_worktop(account)
1020 .build(),
1021 vec![NonFungibleGlobalId::from_public_key(pub_key)],
1022 );
1023 receipt.expect_commit_success();
1024
1025 validator_address
1026 }
1027
1028 pub fn publish_native_package(
1029 &mut self,
1030 native_package_code_id: u64,
1031 definition: PackageDefinition,
1032 ) -> PackageAddress {
1033 let receipt = self.execute_system_transaction(
1034 ManifestBuilder::new_system_v1()
1035 .call_function(
1036 PACKAGE_PACKAGE,
1037 PACKAGE_BLUEPRINT,
1038 PACKAGE_PUBLISH_NATIVE_IDENT,
1039 PackagePublishNativeManifestInput {
1040 definition: definition.into(),
1041 native_package_code_id,
1042 metadata: MetadataInit::default().into(),
1043 package_address: None,
1044 },
1045 )
1046 .build(),
1047 btreeset!(system_execution(SystemExecution::Protocol)),
1048 );
1049 let package_address: PackageAddress = receipt.expect_commit(true).output(0);
1050 package_address
1051 }
1052
1053 pub fn publish_package_at_address<P: Into<PackagePublishingSource>>(
1057 &mut self,
1058 source: P,
1059 address: PackageAddress,
1060 ) {
1061 let (code, definition) = source.into().code_and_definition();
1062 let mut manifest_builder = ManifestBuilder::new_system_v1();
1063 let reservation =
1064 manifest_builder.use_preallocated_address(address, PACKAGE_PACKAGE, PACKAGE_BLUEPRINT);
1065 let manifest = manifest_builder
1066 .publish_package_advanced(
1067 reservation,
1068 code,
1069 definition,
1070 metadata_init!(),
1071 OwnerRole::Fixed(AccessRule::AllowAll),
1072 )
1073 .build();
1074
1075 let receipt =
1076 self.execute_system_transaction(manifest, [SystemExecution::Protocol.proof()]);
1077
1078 receipt.expect_commit_success();
1079 }
1080
1081 pub fn publish_package<P: Into<PackagePublishingSource>>(
1082 &mut self,
1083 source: P,
1084 metadata: BTreeMap<String, MetadataValue>,
1085 owner_role: OwnerRole,
1086 ) -> PackageAddress {
1087 let (code, definition) = source.into().code_and_definition();
1088 let manifest = ManifestBuilder::new()
1089 .lock_fee_from_faucet()
1090 .publish_package_advanced(
1091 None,
1092 code,
1093 definition,
1094 MetadataInit::from(metadata),
1095 owner_role,
1096 )
1097 .build();
1098
1099 let receipt = self.execute_manifest(manifest, vec![]);
1100 receipt.expect_commit(true).new_package_addresses()[0]
1101 }
1102
1103 pub fn try_publish_package<P: Into<PackagePublishingSource>>(
1104 &mut self,
1105 source: P,
1106 ) -> TransactionReceipt {
1107 let (code, definition) = source.into().code_and_definition();
1108 let manifest = ManifestBuilder::new()
1109 .lock_fee_from_faucet()
1110 .publish_package_advanced(
1111 None,
1112 code,
1113 definition,
1114 MetadataInit::from(BTreeMap::new()),
1115 OwnerRole::None,
1116 )
1117 .build();
1118
1119 self.execute_manifest(manifest, vec![])
1120 }
1121
1122 pub fn publish_package_simple<P: Into<PackagePublishingSource>>(
1123 &mut self,
1124 source: P,
1125 ) -> PackageAddress {
1126 self.publish_package(source, Default::default(), OwnerRole::None)
1127 }
1128
1129 pub fn publish_package_with_owner<P: Into<PackagePublishingSource>>(
1130 &mut self,
1131 source: P,
1132 owner_badge: NonFungibleGlobalId,
1133 ) -> PackageAddress {
1134 let (code, definition) = source.into().code_and_definition();
1135 let manifest = ManifestBuilder::new()
1136 .lock_fee_from_faucet()
1137 .publish_package_with_owner(code, definition, owner_badge)
1138 .build();
1139
1140 let receipt = self.execute_manifest(manifest, vec![]);
1141 receipt.expect_commit(true).new_package_addresses()[0]
1142 }
1143
1144 pub fn compile<P: AsRef<Path>>(&mut self, package_dir: P) -> (Vec<u8>, PackageDefinition) {
1145 self.compile_with_option(package_dir, CompileProfile::FastWithTraceLogs)
1146 }
1147
1148 pub fn compile_with_option<P: AsRef<Path>>(
1149 &mut self,
1150 package_dir: P,
1151 compile_profile: CompileProfile,
1152 ) -> (Vec<u8>, PackageDefinition) {
1153 Compile::compile(package_dir, compile_profile)
1154 }
1155
1156 pub fn compile_and_publish<P: AsRef<Path>>(&mut self, package_dir: P) -> PackageAddress {
1158 self.publish_package(package_dir.as_ref(), BTreeMap::new(), OwnerRole::None)
1159 }
1160
1161 pub fn compile_and_publish_at_address<P: AsRef<Path>>(
1163 &mut self,
1164 package_dir: P,
1165 address: PackageAddress,
1166 ) {
1167 self.publish_package_at_address(package_dir.as_ref(), address);
1168 }
1169
1170 pub fn publish_retain_blueprints<
1171 P: Into<PackagePublishingSource>,
1172 F: FnMut(&String, &mut BlueprintDefinitionInit) -> bool,
1173 >(
1174 &mut self,
1175 source: P,
1176 retain: F,
1177 ) -> PackageAddress {
1178 let (code, mut definition) =
1179 Into::<PackagePublishingSource>::into(source).code_and_definition();
1180 definition.blueprints.retain(retain);
1181 self.publish_package((code, definition), BTreeMap::new(), OwnerRole::None)
1182 }
1183
1184 pub fn compile_and_publish_with_owner<P: AsRef<Path>>(
1186 &mut self,
1187 package_dir: P,
1188 owner_badge: NonFungibleGlobalId,
1189 ) -> PackageAddress {
1190 self.publish_package_with_owner(package_dir.as_ref(), owner_badge)
1191 }
1192
1193 fn resolve_suggested_config(&self, manifest: &impl BuildableManifest) -> ExecutionConfig {
1194 let config = match manifest.default_test_execution_config_type() {
1195 DefaultTestExecutionConfigType::Notarized => {
1196 ExecutionConfig::for_notarized_transaction(NetworkDefinition::simulator())
1197 }
1198 DefaultTestExecutionConfigType::System => {
1199 ExecutionConfig::for_system_transaction(NetworkDefinition::simulator())
1200 }
1201 DefaultTestExecutionConfigType::Test => ExecutionConfig::for_test_transaction(),
1202 };
1203 self.override_configured_execution_config_properties(config)
1204 }
1205
1206 fn override_configured_execution_config_properties(
1207 &self,
1208 mut config: ExecutionConfig,
1209 ) -> ExecutionConfig {
1210 if let Some(override_kernel_trace) = self.with_kernel_trace {
1211 config = config.with_kernel_trace(override_kernel_trace);
1212 }
1213 if let Some(override_cost_breakdown) = self.with_cost_breakdown {
1214 config = config.with_cost_breakdown(override_cost_breakdown);
1215 }
1216 config
1217 }
1218
1219 pub fn execute_manifest(
1220 &mut self,
1221 manifest: impl BuildableManifest,
1222 initial_proofs: impl IntoIterator<Item = NonFungibleGlobalId>,
1223 ) -> TransactionReceipt {
1224 let config = self.resolve_suggested_config(&manifest);
1225 self.execute_manifest_with_execution_config(manifest, initial_proofs, config)
1226 }
1227
1228 pub fn execute_manifest_with_execution_config(
1229 &mut self,
1230 manifest: impl BuildableManifest,
1231 initial_proofs: impl IntoIterator<Item = NonFungibleGlobalId>,
1232 execution_config: ExecutionConfig,
1233 ) -> TransactionReceipt {
1234 let executable = manifest
1235 .into_executable_with_proofs(
1236 self.next_transaction_nonce(),
1237 initial_proofs.into_iter().collect(),
1238 &self.transaction_validator,
1239 )
1240 .unwrap_or_else(|err| {
1241 panic!(
1242 "Could not convert manifest into executable transaction: {}",
1243 err
1244 )
1245 });
1246 self.execute_transaction(executable, execution_config)
1247 }
1248
1249 pub fn execute_manifest_with_costing_params(
1250 &mut self,
1251 manifest: impl BuildableManifest,
1252 initial_proofs: impl IntoIterator<Item = NonFungibleGlobalId>,
1253 costing_parameters: CostingParameters,
1254 ) -> TransactionReceipt {
1255 let mut config = self.resolve_suggested_config(&manifest);
1256 config.system_overrides = Some(SystemOverrides {
1257 costing_parameters: Some(costing_parameters),
1258 ..config.system_overrides.unwrap_or_default()
1259 });
1260 self.execute_manifest_with_execution_config(manifest, initial_proofs, config)
1261 }
1262
1263 pub fn execute_manifest_with_injected_error(
1264 &mut self,
1265 manifest: impl BuildableManifest,
1266 initial_proofs: impl IntoIterator<Item = NonFungibleGlobalId>,
1267 error_after_count: u64,
1268 ) -> TransactionReceipt {
1269 let execution_config = self.resolve_suggested_config(&manifest);
1270
1271 let executable = manifest
1272 .into_executable_with_proofs(
1273 self.next_transaction_nonce(),
1274 initial_proofs.into_iter().collect(),
1275 &self.transaction_validator,
1276 )
1277 .unwrap_or_else(|err| {
1278 panic!(
1279 "Could not convert manifest into executable transaction: {}",
1280 err
1281 )
1282 });
1283
1284 let vm_init = VmInit::load(&self.database, &self.vm_modules);
1285 let system_init = InjectCostingErrorInit {
1286 system_input: SystemInit::load(&self.database, execution_config, vm_init),
1287 error_after_count,
1288 };
1289 let kernel_init = KernelInit::load(&self.database, system_init);
1290
1291 let transaction_receipt = kernel_init.execute(&executable);
1292
1293 if let TransactionResult::Commit(commit) = &transaction_receipt.result {
1294 let database_updates = commit.state_updates.create_database_updates();
1295 self.database.commit(&database_updates);
1296 self.collected_events
1297 .push(commit.application_events.clone());
1298
1299 if self.with_receipt_substate_check {
1300 assert_receipt_substate_changes_can_be_typed(commit);
1301 }
1302 }
1303 transaction_receipt
1304 }
1305
1306 pub fn construct_unsigned_notarized_transaction_v1(
1307 &mut self,
1308 manifest: TransactionManifestV1,
1309 ) -> NotarizedTransactionV1 {
1310 let notary = Ed25519PrivateKey::from_u64(1337).unwrap();
1311 let current_epoch = self.get_current_epoch();
1312 let nonce = self.next_transaction_nonce();
1313 TransactionV1Builder::new()
1314 .header(TransactionHeaderV1 {
1315 network_id: NetworkDefinition::simulator().id,
1316 start_epoch_inclusive: current_epoch,
1317 end_epoch_exclusive: current_epoch.next().unwrap(),
1318 nonce,
1319 notary_public_key: notary.public_key().into(),
1320 notary_is_signatory: false,
1321 tip_percentage: 0,
1322 })
1323 .manifest(manifest)
1324 .notarize(¬ary)
1325 .build()
1326 }
1327
1328 pub fn default_notary(&self) -> Ed25519PrivateKey {
1329 Ed25519PrivateKey::from_u64(1337).unwrap()
1330 }
1331
1332 pub fn v2_transaction_builder(&mut self) -> TransactionV2Builder {
1334 let current_epoch = self.get_current_epoch();
1335 let nonce = self.next_transaction_nonce();
1336 TransactionV2Builder::new()
1337 .intent_header(IntentHeaderV2 {
1338 network_id: NetworkDefinition::simulator().id,
1339 start_epoch_inclusive: current_epoch,
1340 end_epoch_exclusive: current_epoch.next().unwrap(),
1341 min_proposer_timestamp_inclusive: None,
1342 max_proposer_timestamp_exclusive: None,
1343 intent_discriminator: nonce as u64,
1344 })
1345 .transaction_header(TransactionHeaderV2 {
1346 notary_public_key: self.default_notary().public_key().into(),
1347 notary_is_signatory: false,
1348 tip_basis_points: 0,
1349 })
1350 }
1351
1352 pub fn v2_partial_transaction_builder(&mut self) -> PartialTransactionV2Builder {
1354 let current_epoch = self.get_current_epoch();
1355 let nonce = self.next_transaction_nonce();
1356 PartialTransactionV2Builder::new().intent_header(IntentHeaderV2 {
1357 network_id: NetworkDefinition::simulator().id,
1358 start_epoch_inclusive: current_epoch,
1359 end_epoch_exclusive: current_epoch.next().unwrap(),
1360 min_proposer_timestamp_inclusive: None,
1361 max_proposer_timestamp_exclusive: None,
1362 intent_discriminator: nonce as u64,
1363 })
1364 }
1365
1366 pub fn execute_notarized_transaction(
1367 &mut self,
1368 transaction_source: impl ResolveAsRawNotarizedTransaction,
1369 ) -> TransactionReceipt {
1370 let raw_transaction = transaction_source.resolve_raw_notarized_transaction();
1371 let executable = raw_transaction
1372 .as_ref()
1373 .validate(&self.transaction_validator)
1374 .expect("Expected raw transaction to be valid")
1375 .create_executable();
1376 self.execute_transaction(
1377 executable,
1378 ExecutionConfig::for_notarized_transaction(NetworkDefinition::simulator()),
1379 )
1380 }
1381
1382 pub fn execute_system_transaction(
1385 &mut self,
1386 manifest: SystemTransactionManifestV1,
1387 initial_proofs: impl IntoIterator<Item = NonFungibleGlobalId>,
1388 ) -> TransactionReceipt {
1389 self.execute_manifest(manifest, initial_proofs)
1390 }
1391
1392 pub fn execute_test_transaction(
1393 &mut self,
1394 test_transaction: TestTransaction,
1395 ) -> TransactionReceipt {
1396 self.execute_transaction(test_transaction, ExecutionConfig::for_test_transaction())
1397 }
1398
1399 pub fn execute_transaction_no_commit(
1400 &mut self,
1401 executable_source: impl IntoExecutable,
1402 execution_config: ExecutionConfig,
1403 ) -> TransactionReceipt {
1404 let executable = executable_source
1405 .into_executable(&self.transaction_validator)
1406 .expect("Transaction should be convertible to executable");
1407
1408 let execution_config =
1409 self.override_configured_execution_config_properties(execution_config);
1410
1411 execute_transaction(
1412 &self.database,
1413 &self.vm_modules,
1414 &execution_config,
1415 executable,
1416 )
1417 }
1418
1419 pub fn execute_transaction(
1420 &mut self,
1421 executable_source: impl IntoExecutable,
1422 execution_config: ExecutionConfig,
1423 ) -> TransactionReceipt {
1424 let executable = executable_source
1425 .into_executable(&self.transaction_validator)
1426 .expect("Transaction should be convertible to executable");
1427
1428 let execution_config =
1429 self.override_configured_execution_config_properties(execution_config);
1430
1431 if executable
1432 .costing_parameters()
1433 .free_credit_in_xrd
1434 .is_positive()
1435 {
1436 self.xrd_free_credits_used = true;
1437 }
1438
1439 let transaction_receipt = execute_transaction(
1440 &self.database,
1441 &self.vm_modules,
1442 &execution_config,
1443 executable,
1444 );
1445
1446 if let TransactionResult::Commit(commit) = &transaction_receipt.result {
1447 let database_updates = commit.state_updates.create_database_updates();
1448 self.database.commit(&database_updates);
1449 self.collected_events
1450 .push(commit.application_events.clone());
1451
1452 if self.with_receipt_substate_check {
1453 assert_receipt_substate_changes_can_be_typed(commit);
1454 }
1455 }
1456 transaction_receipt
1457 }
1458
1459 pub fn preview(
1460 &mut self,
1461 preview_intent: PreviewIntentV1,
1462 network: &NetworkDefinition,
1463 ) -> Result<TransactionReceipt, PreviewError> {
1464 execute_preview(
1465 &self.database,
1466 &self.vm_modules,
1467 network,
1468 preview_intent,
1469 self.with_kernel_trace.unwrap_or(false),
1470 )
1471 }
1472
1473 pub fn preview_manifest(
1474 &mut self,
1475 manifest: TransactionManifestV1,
1476 signer_public_keys: Vec<PublicKey>,
1477 tip_percentage: u16,
1478 flags: PreviewFlags,
1479 ) -> TransactionReceipt {
1480 let epoch = self.get_current_epoch();
1481 execute_preview(
1482 &self.database,
1483 &self.vm_modules,
1484 &NetworkDefinition::simulator(),
1485 PreviewIntentV1 {
1486 intent: IntentV1 {
1487 header: TransactionHeaderV1 {
1488 network_id: NetworkDefinition::simulator().id,
1489 start_epoch_inclusive: epoch,
1490 end_epoch_exclusive: epoch.after(10).unwrap(),
1491 nonce: 0,
1492 notary_public_key: PublicKey::Secp256k1(Secp256k1PublicKey([0u8; 33])),
1493 notary_is_signatory: false,
1494 tip_percentage,
1495 },
1496 instructions: InstructionsV1::from(manifest.instructions),
1497 blobs: BlobsV1 {
1498 blobs: manifest.blobs.values().map(|x| BlobV1(x.clone())).collect(),
1499 },
1500 message: MessageV1::default(),
1501 },
1502 signer_public_keys,
1503 flags,
1504 },
1505 self.with_kernel_trace.unwrap_or(false),
1506 )
1507 .unwrap()
1508 }
1509
1510 pub fn preview_v2(
1511 &mut self,
1512 preview_transaction: PreviewTransactionV2,
1513 flags: PreviewFlags,
1514 ) -> TransactionReceipt {
1515 let validated = preview_transaction
1516 .prepare_and_validate(&self.transaction_validator)
1517 .expect("Preview transaction should be valid");
1518 let execution_config = if flags.disable_auth {
1519 ExecutionConfig::for_preview_no_auth(NetworkDefinition::simulator())
1520 } else {
1521 ExecutionConfig::for_preview(NetworkDefinition::simulator())
1522 };
1523 let execution_config =
1524 self.override_configured_execution_config_properties(execution_config);
1525 let executable = validated.create_executable(flags);
1526 self.execute_transaction_no_commit(executable, execution_config)
1527 }
1528
1529 pub fn call_function(
1543 &mut self,
1544 package_address: impl Resolve<ManifestPackageAddress>,
1545 blueprint_name: impl Into<String>,
1546 function_name: impl Into<String>,
1547 arguments: impl ResolvableArguments,
1548 ) -> TransactionReceipt {
1549 self.execute_manifest(
1550 ManifestBuilder::new()
1551 .lock_fee_from_faucet()
1552 .call_function(package_address, blueprint_name, function_name, arguments)
1553 .build(),
1554 vec![],
1555 )
1556 }
1557
1558 pub fn construct_new(
1572 &mut self,
1573 package_address: impl Resolve<ManifestPackageAddress>,
1574 blueprint_name: impl Into<String>,
1575 function_name: impl Into<String>,
1576 arguments: impl ResolvableArguments,
1577 ) -> ComponentAddress {
1578 self.call_function(package_address, blueprint_name, function_name, arguments)
1579 .expect_commit_success()
1580 .new_component_addresses()[0]
1581 }
1582
1583 pub fn call_method(
1597 &mut self,
1598 address: impl Resolve<ManifestGlobalAddress>,
1599 method_name: impl Into<String>,
1600 args: impl ResolvableArguments,
1601 ) -> TransactionReceipt {
1602 self.execute_manifest(
1603 ManifestBuilder::new()
1604 .lock_fee_from_faucet()
1605 .call_method(address, method_name, args)
1606 .build(),
1607 vec![],
1608 )
1609 }
1610
1611 fn create_fungible_resource_and_deposit(
1612 &mut self,
1613 owner_role: OwnerRole,
1614 resource_roles: FungibleResourceRoles,
1615 to: ComponentAddress,
1616 ) -> ResourceAddress {
1617 let manifest = ManifestBuilder::new()
1618 .lock_fee_from_faucet()
1619 .create_fungible_resource(
1620 owner_role,
1621 true,
1622 0,
1623 resource_roles,
1624 metadata!(),
1625 Some(5.into()),
1626 )
1627 .try_deposit_entire_worktop_or_abort(to, None)
1628 .build();
1629 let receipt = self.execute_manifest(manifest, vec![]);
1630 receipt.expect_commit(true).new_resource_addresses()[0]
1631 }
1632
1633 pub fn create_restricted_token(
1634 &mut self,
1635 account: ComponentAddress,
1636 ) -> (
1637 ResourceAddress,
1638 ResourceAddress,
1639 ResourceAddress,
1640 ResourceAddress,
1641 ResourceAddress,
1642 ResourceAddress,
1643 ResourceAddress,
1644 ResourceAddress,
1645 ) {
1646 let mint_auth = self.create_fungible_resource(dec!(1), 0, account);
1647 let burn_auth = self.create_fungible_resource(dec!(1), 0, account);
1648 let withdraw_auth = self.create_fungible_resource(dec!(1), 0, account);
1649 let recall_auth = self.create_fungible_resource(dec!(1), 0, account);
1650 let update_metadata_auth = self.create_fungible_resource(dec!(1), 0, account);
1651 let freeze_auth = self.create_fungible_resource(dec!(1), 0, account);
1652 let admin_auth = self.create_fungible_resource(dec!(1), 0, account);
1653
1654 let token_address = self.create_fungible_resource_and_deposit(
1655 OwnerRole::None,
1656 FungibleResourceRoles {
1657 mint_roles: mint_roles! {
1658 minter => rule!(require(mint_auth));
1659 minter_updater => rule!(require(admin_auth));
1660 },
1661 burn_roles: burn_roles! {
1662 burner => rule!(require(burn_auth));
1663 burner_updater => rule!(require(admin_auth));
1664 },
1665 freeze_roles: freeze_roles! {
1666 freezer => rule!(require(freeze_auth));
1667 freezer_updater => rule!(require(admin_auth));
1668 },
1669 recall_roles: recall_roles! {
1670 recaller => rule!(require(recall_auth));
1671 recaller_updater => rule!(require(admin_auth));
1672 },
1673 withdraw_roles: withdraw_roles! {
1674 withdrawer => rule!(require(withdraw_auth));
1675 withdrawer_updater => rule!(require(admin_auth));
1676 },
1677 deposit_roles: deposit_roles! {
1678 depositor => rule!(allow_all);
1679 depositor_updater => rule!(require(admin_auth));
1680 },
1681 },
1682 account,
1683 );
1684
1685 (
1686 token_address,
1687 mint_auth,
1688 burn_auth,
1689 withdraw_auth,
1690 recall_auth,
1691 update_metadata_auth,
1692 freeze_auth,
1693 admin_auth,
1694 )
1695 }
1696
1697 pub fn create_everything_allowed_non_fungible_resource(
1698 &mut self,
1699 owner_role: OwnerRole,
1700 ) -> ResourceAddress {
1701 let receipt = self.execute_manifest(
1702 ManifestBuilder::new()
1703 .lock_fee_from_faucet()
1704 .create_non_fungible_resource::<Vec<_>, ()>(
1705 owner_role,
1706 NonFungibleIdType::Integer,
1707 false,
1708 NonFungibleResourceRoles {
1709 mint_roles: mint_roles! {
1710 minter => rule!(allow_all);
1711 minter_updater => rule!(allow_all);
1712 },
1713 burn_roles: burn_roles! {
1714 burner => rule!(allow_all);
1715 burner_updater => rule!(allow_all);
1716 },
1717 freeze_roles: freeze_roles! {
1718 freezer => rule!(allow_all);
1719 freezer_updater => rule!(allow_all);
1720 },
1721 recall_roles: recall_roles! {
1722 recaller => rule!(allow_all);
1723 recaller_updater => rule!(allow_all);
1724 },
1725 withdraw_roles: withdraw_roles! {
1726 withdrawer => rule!(allow_all);
1727 withdrawer_updater => rule!(allow_all);
1728 },
1729 deposit_roles: deposit_roles! {
1730 depositor => rule!(allow_all);
1731 depositor_updater => rule!(allow_all);
1732 },
1733 non_fungible_data_update_roles: non_fungible_data_update_roles! {
1734 non_fungible_data_updater => rule!(allow_all);
1735 non_fungible_data_updater_updater => rule!(allow_all);
1736 },
1737 },
1738 metadata!(),
1739 None,
1740 )
1741 .build(),
1742 vec![],
1743 );
1744 receipt.expect_commit(true).new_resource_addresses()[0]
1745 }
1746
1747 pub fn create_freezeable_token(&mut self, account: ComponentAddress) -> ResourceAddress {
1748 self.create_fungible_resource_and_deposit(
1749 OwnerRole::None,
1750 FungibleResourceRoles {
1751 burn_roles: burn_roles! {
1752 burner => rule!(allow_all);
1753 burner_updater => rule!(deny_all);
1754 },
1755 recall_roles: recall_roles! {
1756 recaller => rule!(allow_all);
1757 recaller_updater => rule!(deny_all);
1758 },
1759 freeze_roles: freeze_roles! {
1760 freezer => rule!(allow_all);
1761 freezer_updater => rule!(deny_all);
1762 },
1763 ..Default::default()
1764 },
1765 account,
1766 )
1767 }
1768
1769 pub fn create_freezeable_non_fungible(&mut self, account: ComponentAddress) -> ResourceAddress {
1770 self.create_non_fungible_resource_with_roles(
1771 NonFungibleResourceRoles {
1772 burn_roles: burn_roles! {
1773 burner => rule!(allow_all);
1774 burner_updater => rule!(deny_all);
1775 },
1776 recall_roles: recall_roles! {
1777 recaller => rule!(allow_all);
1778 recaller_updater => rule!(deny_all);
1779 },
1780 freeze_roles: freeze_roles! {
1781 freezer => rule!(allow_all);
1782 freezer_updater => rule!(deny_all);
1783 },
1784 ..Default::default()
1785 },
1786 account,
1787 )
1788 }
1789
1790 pub fn create_recallable_token(&mut self, account: ComponentAddress) -> ResourceAddress {
1791 self.create_fungible_resource_and_deposit(
1792 OwnerRole::None,
1793 FungibleResourceRoles {
1794 recall_roles: recall_roles! {
1795 recaller => rule!(allow_all);
1796 recaller_updater => rule!(deny_all);
1797 },
1798 ..Default::default()
1799 },
1800 account,
1801 )
1802 }
1803
1804 pub fn create_restricted_burn_token(
1805 &mut self,
1806 account: ComponentAddress,
1807 ) -> (ResourceAddress, ResourceAddress) {
1808 let auth_resource_address = self.create_fungible_resource(dec!(1), 0, account);
1809
1810 let resource_address = self.create_fungible_resource_and_deposit(
1811 OwnerRole::None,
1812 FungibleResourceRoles {
1813 burn_roles: burn_roles! {
1814 burner => rule!(require(auth_resource_address));
1815 burner_updater => rule!(deny_all);
1816 },
1817 ..Default::default()
1818 },
1819 account,
1820 );
1821
1822 (auth_resource_address, resource_address)
1823 }
1824
1825 pub fn create_restricted_transfer_token(
1826 &mut self,
1827 account: ComponentAddress,
1828 ) -> (ResourceAddress, ResourceAddress) {
1829 let auth_resource_address = self.create_non_fungible_resource(account);
1830
1831 let resource_address = self.create_fungible_resource_and_deposit(
1832 OwnerRole::None,
1833 FungibleResourceRoles {
1834 withdraw_roles: withdraw_roles! {
1835 withdrawer => rule!(require(auth_resource_address));
1836 withdrawer_updater => rule!(deny_all);
1837 },
1838 ..Default::default()
1839 },
1840 account,
1841 );
1842
1843 (auth_resource_address, resource_address)
1844 }
1845
1846 pub fn create_non_fungible_resource(&mut self, account: ComponentAddress) -> ResourceAddress {
1847 self.create_non_fungible_resource_advanced(NonFungibleResourceRoles::default(), account, 3)
1848 }
1849 pub fn create_non_fungible_resource_with_roles(
1850 &mut self,
1851 resource_roles: NonFungibleResourceRoles,
1852 account: ComponentAddress,
1853 ) -> ResourceAddress {
1854 self.create_non_fungible_resource_advanced(resource_roles, account, 3)
1855 }
1856
1857 pub fn create_non_fungible_resource_advanced(
1858 &mut self,
1859 resource_roles: NonFungibleResourceRoles,
1860 account: ComponentAddress,
1861 n: usize,
1862 ) -> ResourceAddress {
1863 let mut entries = BTreeMap::new();
1864 for i in 1..n + 1 {
1865 entries.insert(
1866 NonFungibleLocalId::integer(i as u64),
1867 EmptyNonFungibleData {},
1868 );
1869 }
1870
1871 let manifest = ManifestBuilder::new()
1872 .lock_fee_from_faucet()
1873 .create_non_fungible_resource(
1874 OwnerRole::None,
1875 NonFungibleIdType::Integer,
1876 false,
1877 resource_roles,
1878 metadata!(),
1879 Some(entries),
1880 )
1881 .try_deposit_entire_worktop_or_abort(account, None)
1882 .build();
1883 let receipt = self.execute_manifest(manifest, vec![]);
1884 receipt.expect_commit(true).new_resource_addresses()[0]
1885 }
1886
1887 pub fn create_fungible_resource(
1888 &mut self,
1889 amount: Decimal,
1890 divisibility: u8,
1891 account: ComponentAddress,
1892 ) -> ResourceAddress {
1893 let manifest = ManifestBuilder::new()
1894 .lock_fee_from_faucet()
1895 .create_fungible_resource(
1896 OwnerRole::None,
1897 true,
1898 divisibility,
1899 FungibleResourceRoles::default(),
1900 metadata!(),
1901 Some(amount),
1902 )
1903 .try_deposit_entire_worktop_or_abort(account, None)
1904 .build();
1905 let receipt = self.execute_manifest(manifest, vec![]);
1906 receipt.expect_commit(true).new_resource_addresses()[0]
1907 }
1908
1909 pub fn create_mintable_burnable_fungible_resource(
1910 &mut self,
1911 account: ComponentAddress,
1912 ) -> (ResourceAddress, ResourceAddress) {
1913 let admin_auth = self.create_non_fungible_resource(account);
1914
1915 let manifest = ManifestBuilder::new()
1916 .lock_fee_from_faucet()
1917 .create_fungible_resource(
1918 OwnerRole::None,
1919 true,
1920 1u8,
1921 FungibleResourceRoles {
1922 mint_roles: mint_roles! {
1923 minter => rule!(require(admin_auth));
1924 minter_updater => rule!(deny_all);
1925 },
1926 burn_roles: burn_roles! {
1927 burner => rule!(require(admin_auth));
1928 burner_updater => rule!(deny_all);
1929 },
1930 ..Default::default()
1931 },
1932 metadata!(),
1933 None,
1934 )
1935 .try_deposit_entire_worktop_or_abort(account, None)
1936 .build();
1937 let receipt = self.execute_manifest(manifest, vec![]);
1938 let resource_address = receipt.expect_commit(true).new_resource_addresses()[0];
1939 (admin_auth, resource_address)
1940 }
1941
1942 pub fn create_freely_mintable_fungible_resource(
1943 &mut self,
1944 owner_role: OwnerRole,
1945 amount: Option<Decimal>,
1946 divisibility: u8,
1947 account: ComponentAddress,
1948 ) -> ResourceAddress {
1949 let manifest = ManifestBuilder::new()
1950 .lock_fee_from_faucet()
1951 .create_fungible_resource(
1952 owner_role,
1953 true,
1954 divisibility,
1955 FungibleResourceRoles {
1956 mint_roles: mint_roles! {
1957 minter => rule!(allow_all);
1958 minter_updater => rule!(deny_all);
1959 },
1960 ..Default::default()
1961 },
1962 metadata!(),
1963 amount,
1964 )
1965 .try_deposit_entire_worktop_or_abort(account, None)
1966 .build();
1967 let receipt = self.execute_manifest(manifest, vec![]);
1968 receipt.expect_commit(true).new_resource_addresses()[0]
1969 }
1970
1971 pub fn create_freely_mintable_and_burnable_fungible_resource(
1972 &mut self,
1973 owner_role: OwnerRole,
1974 amount: Option<Decimal>,
1975 divisibility: u8,
1976 account: ComponentAddress,
1977 ) -> ResourceAddress {
1978 let manifest = ManifestBuilder::new()
1979 .lock_fee_from_faucet()
1980 .create_fungible_resource(
1981 owner_role,
1982 true,
1983 divisibility,
1984 FungibleResourceRoles {
1985 mint_roles: mint_roles! {
1986 minter => rule!(allow_all);
1987 minter_updater => rule!(deny_all);
1988 },
1989 burn_roles: burn_roles! {
1990 burner => rule!(allow_all);
1991 burner_updater => rule!(deny_all);
1992 },
1993 ..Default::default()
1994 },
1995 metadata!(),
1996 amount,
1997 )
1998 .try_deposit_entire_worktop_or_abort(account, None)
1999 .build();
2000 let receipt = self.execute_manifest(manifest, vec![]);
2001 receipt.expect_commit(true).new_resource_addresses()[0]
2002 }
2003
2004 pub fn create_freely_mintable_and_burnable_non_fungible_resource<T, V>(
2005 &mut self,
2006 owner_role: OwnerRole,
2007 id_type: NonFungibleIdType,
2008 initial_supply: Option<T>,
2009 account: ComponentAddress,
2010 ) -> ResourceAddress
2011 where
2012 T: IntoIterator<Item = (NonFungibleLocalId, V)>,
2013 V: ManifestEncode + NonFungibleData,
2014 {
2015 let manifest = ManifestBuilder::new()
2016 .lock_fee_from_faucet()
2017 .create_non_fungible_resource(
2018 owner_role,
2019 id_type,
2020 true,
2021 NonFungibleResourceRoles {
2022 mint_roles: mint_roles! {
2023 minter => rule!(allow_all);
2024 minter_updater => rule!(deny_all);
2025 },
2026 burn_roles: burn_roles! {
2027 burner => rule!(allow_all);
2028 burner_updater => rule!(deny_all);
2029 },
2030 ..Default::default()
2031 },
2032 metadata!(),
2033 initial_supply,
2034 )
2035 .try_deposit_entire_worktop_or_abort(account, None)
2036 .build();
2037 let receipt = self.execute_manifest(manifest, vec![]);
2038 receipt.expect_commit(true).new_resource_addresses()[0]
2039 }
2040
2041 pub fn create_one_resource_pool(
2042 &mut self,
2043 resource_address: ResourceAddress,
2044 pool_manager_rule: AccessRule,
2045 ) -> (ComponentAddress, ResourceAddress) {
2046 let manifest = ManifestBuilder::new()
2047 .lock_fee_from_faucet()
2048 .call_function(
2049 POOL_PACKAGE,
2050 ONE_RESOURCE_POOL_BLUEPRINT_IDENT,
2051 ONE_RESOURCE_POOL_INSTANTIATE_IDENT,
2052 OneResourcePoolInstantiateManifestInput {
2053 resource_address: resource_address.into(),
2054 pool_manager_rule: pool_manager_rule.into(),
2055 owner_role: OwnerRole::None.into(),
2056 address_reservation: None,
2057 },
2058 )
2059 .build();
2060 let receipt = self.execute_manifest(manifest, vec![]);
2061 let commit_result = receipt.expect_commit_success();
2062
2063 (
2064 commit_result.new_component_addresses()[0],
2065 commit_result.new_resource_addresses()[0],
2066 )
2067 }
2068
2069 pub fn new_component<F>(
2070 &mut self,
2071 initial_proofs: BTreeSet<NonFungibleGlobalId>,
2072 handler: F,
2073 ) -> ComponentAddress
2074 where
2075 F: FnOnce(ManifestBuilder) -> ManifestBuilder,
2076 {
2077 let manifest = ManifestBuilder::new()
2078 .lock_fee_from_faucet()
2079 .then(handler)
2080 .build();
2081
2082 let receipt = self.execute_manifest(manifest, initial_proofs);
2083 receipt.expect_commit(true).new_component_addresses()[0]
2084 }
2085
2086 pub fn set_current_epoch(&mut self, epoch: Epoch) {
2087 let reader = SystemDatabaseReader::new(&self.database);
2088 let mut substate = reader
2089 .read_typed_object_field::<ConsensusManagerStateFieldPayload>(
2090 CONSENSUS_MANAGER.as_node_id(),
2091 ModuleId::Main,
2092 ConsensusManagerField::State.field_index(),
2093 )
2094 .unwrap()
2095 .fully_update_and_into_latest_version();
2096
2097 substate.epoch = epoch;
2098
2099 let mut writer = SystemDatabaseWriter::new(&mut self.database);
2100 writer
2101 .write_typed_object_field(
2102 CONSENSUS_MANAGER.as_node_id(),
2103 ModuleId::Main,
2104 ConsensusManagerField::State.field_index(),
2105 ConsensusManagerStateFieldPayload::from_content_source(substate),
2106 )
2107 .unwrap();
2108 }
2109
2110 pub fn get_current_epoch(&mut self) -> Epoch {
2111 let receipt = self.execute_system_transaction(
2112 ManifestBuilder::new_system_v1()
2113 .call_method(
2114 CONSENSUS_MANAGER,
2115 CONSENSUS_MANAGER_GET_CURRENT_EPOCH_IDENT,
2116 ConsensusManagerGetCurrentEpochInput,
2117 )
2118 .build(),
2119 btreeset![system_execution(SystemExecution::Validator)],
2120 );
2121 receipt.expect_commit(true).output(0)
2122 }
2123
2124 pub fn advance_to_round_at_timestamp(
2128 &mut self,
2129 round: Round,
2130 proposer_timestamp_ms: i64,
2131 ) -> TransactionReceipt {
2132 let expected_round_number = self.get_consensus_manager_state().round.number() + 1;
2133 self.execute_system_transaction(
2134 ManifestBuilder::new_system_v1()
2135 .call_method(
2136 CONSENSUS_MANAGER,
2137 CONSENSUS_MANAGER_NEXT_ROUND_IDENT,
2138 ConsensusManagerNextRoundInput {
2139 round,
2140 proposer_timestamp_ms,
2141 leader_proposal_history: LeaderProposalHistory {
2142 gap_round_leaders: (expected_round_number..round.number())
2143 .map(|_| 0)
2144 .collect(),
2145 current_leader: 0,
2146 is_fallback: false,
2147 },
2148 },
2149 )
2150 .build(),
2151 btreeset![system_execution(SystemExecution::Validator)],
2152 )
2153 }
2154
2155 pub fn advance_to_round(&mut self, round: Round) -> TransactionReceipt {
2157 let current_timestamp_ms = self.get_current_proposer_timestamp_ms();
2158 self.advance_to_round_at_timestamp(round, current_timestamp_ms)
2159 }
2160
2161 pub fn get_current_proposer_timestamp_ms(&mut self) -> i64 {
2164 let reader = SystemDatabaseReader::new(self.substate_db());
2165 reader
2166 .read_typed_object_field::<ConsensusManagerProposerMilliTimestampFieldPayload>(
2167 CONSENSUS_MANAGER.as_node_id(),
2168 ModuleId::Main,
2169 ConsensusManagerField::ProposerMilliTimestamp.field_index(),
2170 )
2171 .unwrap()
2172 .fully_update_and_into_latest_version()
2173 .epoch_milli
2174 }
2175
2176 pub fn get_consensus_manager_state(&mut self) -> ConsensusManagerSubstate {
2177 let reader = SystemDatabaseReader::new(self.substate_db());
2178 reader
2179 .read_typed_object_field::<ConsensusManagerStateFieldPayload>(
2180 CONSENSUS_MANAGER.as_node_id(),
2181 ModuleId::Main,
2182 ConsensusManagerField::State.field_index(),
2183 )
2184 .unwrap()
2185 .fully_update_and_into_latest_version()
2186 }
2187
2188 pub fn get_current_time(&mut self, precision: TimePrecision) -> Instant {
2189 let receipt = self.execute_system_transaction(
2190 ManifestBuilder::new_system_v1()
2191 .call_method(
2192 CONSENSUS_MANAGER,
2193 CONSENSUS_MANAGER_GET_CURRENT_TIME_IDENT,
2194 ConsensusManagerGetCurrentTimeInputV2 { precision },
2195 )
2196 .build(),
2197 btreeset![system_execution(SystemExecution::Validator)],
2198 );
2199 receipt.expect_commit(true).output(0)
2200 }
2201
2202 pub fn event_schema(
2203 &self,
2204 event_type_identifier: &EventTypeIdentifier,
2205 ) -> (LocalTypeId, VersionedScryptoSchema) {
2206 let (blueprint_id, name) = match event_type_identifier {
2207 EventTypeIdentifier(Emitter::Method(node_id, node_module), event_name) => {
2208 let blueprint_id = match node_module {
2209 ModuleId::Main => {
2210 let reader = SystemDatabaseReader::new(self.substate_db());
2211 let type_info = reader.get_type_info(node_id).unwrap();
2212 match type_info {
2213 TypeInfoSubstate::Object(ObjectInfo {
2214 blueprint_info: BlueprintInfo { blueprint_id, .. },
2215 ..
2216 }) => blueprint_id,
2217 _ => {
2218 panic!("No event schema.")
2219 }
2220 }
2221 }
2222 module => module.static_blueprint().unwrap(),
2223 };
2224 (blueprint_id, event_name.clone())
2225 }
2226 EventTypeIdentifier(Emitter::Function(blueprint_id), event_name) => {
2227 (blueprint_id.clone(), event_name.clone())
2228 }
2229 };
2230
2231 let system_reader = SystemDatabaseReader::new(self.substate_db());
2232 let definition = system_reader
2233 .get_blueprint_definition(&blueprint_id)
2234 .unwrap();
2235 let schema_pointer = definition
2236 .interface
2237 .get_event_payload_def(name.as_str())
2238 .unwrap();
2239
2240 match schema_pointer {
2241 BlueprintPayloadDef::Static(type_identifier) => {
2242 let reader = SystemDatabaseReader::new(self.substate_db());
2243 let schema = reader
2244 .get_schema(
2245 blueprint_id.package_address.as_node_id(),
2246 &type_identifier.0,
2247 )
2248 .unwrap();
2249 (type_identifier.1, schema.as_ref().clone())
2250 }
2251 BlueprintPayloadDef::Generic(_instance_index) => {
2252 todo!()
2253 }
2254 }
2255 }
2256
2257 pub fn event_name(&self, event_type_identifier: &EventTypeIdentifier) -> String {
2258 let (local_type_id, schema) = self.event_schema(event_type_identifier);
2259 schema
2260 .v1()
2261 .resolve_type_metadata(local_type_id)
2262 .unwrap()
2263 .get_name_string()
2264 .unwrap()
2265 }
2266
2267 pub fn is_event_name_equal<T: ScryptoDescribe>(
2268 &self,
2269 event_type_identifier: &EventTypeIdentifier,
2270 ) -> bool {
2271 let expected_type_name = {
2272 let (local_type_id, schema) =
2273 sbor::generate_full_schema_from_single_type::<T, ScryptoCustomSchema>();
2274 schema
2275 .v1()
2276 .resolve_type_metadata(local_type_id)
2277 .unwrap()
2278 .get_name_string()
2279 .unwrap()
2280 };
2281 let actual_type_name = self.event_name(event_type_identifier);
2282 expected_type_name == actual_type_name
2283 }
2284
2285 pub fn extract_events_of_type<T: ScryptoEvent>(&self, result: &CommitResult) -> Vec<T> {
2286 result
2287 .application_events
2288 .iter()
2289 .filter(|(id, _data)| self.is_event_name_equal::<T>(id))
2290 .map(|(_id, data)| scrypto_decode::<T>(data).unwrap())
2291 .collect::<Vec<_>>()
2292 }
2293
2294 pub fn check_db<A: ApplicationChecker + Default>(
2295 &self,
2296 ) -> Result<
2297 (SystemDatabaseCheckerResults, A::ApplicationCheckerResults),
2298 SystemDatabaseCheckError,
2299 > {
2300 let mut checker = SystemDatabaseChecker::<A>::default();
2301 checker.check_db(&self.database)
2302 }
2303
2304 pub fn check_events<A: ApplicationEventChecker>(
2305 &self,
2306 ) -> Result<A::ApplicationEventCheckerResults, SystemEventCheckerError> {
2307 let mut event_checker = SystemEventChecker::<A>::new();
2308 event_checker.check_all_events(&self.database, self.collected_events())
2309 }
2310
2311 pub fn check_database(&self) {
2312 let mut kernel_checker = KernelDatabaseChecker::new();
2313 kernel_checker
2314 .check_db(&self.database)
2315 .expect("Database should be consistent");
2316
2317 define_composite_checker! {
2319 CompositeApplicationDatabaseChecker,
2320 [
2321 ResourceDatabaseChecker,
2322 RoleAssignmentDatabaseChecker,
2323 PackageRoyaltyDatabaseChecker<F: Fn(&BlueprintId, &str) -> bool>,
2324 ComponentRoyaltyDatabaseChecker,
2325 ]
2326 }
2327 let db_results = {
2328 let reader = SystemDatabaseReader::new(&self.database);
2329 let mut checker = SystemDatabaseChecker::new(CompositeApplicationDatabaseChecker::new(
2330 Default::default(),
2331 Default::default(),
2332 PackageRoyaltyDatabaseChecker::new(|blueprint_id, func_name| {
2333 reader
2334 .get_blueprint_definition(blueprint_id)
2335 .map(|bp_def| bp_def.interface.functions.contains_key(func_name))
2336 .unwrap_or(false)
2337 }),
2338 Default::default(),
2339 ));
2340 checker
2341 .check_db(&self.database)
2342 .expect("Database should be consistent after running test")
2343 };
2344 println!("{:#?}", db_results);
2345
2346 if !db_results.1 .1.is_empty() {
2347 panic!("Role assignment violations: {:?}", db_results.1 .1);
2348 }
2349
2350 let event_results = SystemEventChecker::<ResourceEventChecker>::new()
2351 .check_all_events(&self.database, &self.collected_events)
2352 .expect("Events should be consistent");
2353 println!("{:#?}", event_results);
2354
2355 if !self.xrd_free_credits_used {
2358 ResourceReconciler::reconcile(&db_results.1 .0, &event_results)
2359 .expect("Resource reconciliation failed");
2360 }
2361 }
2362}
2363
2364impl<E: NativeVmExtension, D: TestDatabase> LedgerSimulator<E, StateTreeUpdatingDatabase<D>> {
2365 pub fn get_state_hash(&self) -> Hash {
2366 self.database.get_current_root_hash()
2367 }
2368
2369 pub fn assert_state_tree_matches_substate_store(&mut self) {
2370 self.database
2371 .validate_state_tree_matches_substate_store()
2372 .unwrap()
2373 }
2374}
2375
2376pub struct SubtreeVaults<'d, D> {
2377 database: &'d D,
2378}
2379
2380impl<'d, D: SubstateDatabase> SubtreeVaults<'d, D> {
2381 pub fn new(database: &'d D) -> Self {
2382 Self { database }
2383 }
2384
2385 pub fn get_all(&self, node_id: &NodeId) -> IndexMap<ResourceAddress, Vec<NodeId>> {
2386 let mut vault_finder = VaultFinder::new();
2387 let mut traverser = StateTreeTraverser::new(self.database, &mut vault_finder, 100);
2388 traverser.traverse_subtree(None, *node_id);
2389 vault_finder.to_vaults()
2390 }
2391
2392 pub fn sum_balance_changes(
2393 &self,
2394 node_id: &NodeId,
2395 vault_balance_changes: &IndexMap<NodeId, (ResourceAddress, BalanceChange)>,
2396 ) -> IndexMap<ResourceAddress, BalanceChange> {
2397 self.get_all(node_id)
2398 .into_iter()
2399 .filter_map(|(traversed_resource, vault_ids)| {
2400 vault_ids
2401 .into_iter()
2402 .filter_map(|vault_id| vault_balance_changes.get(&vault_id).cloned())
2403 .map(|(reported_resource, change)| {
2404 assert_eq!(reported_resource, traversed_resource);
2405 change
2406 })
2407 .reduce(|mut left, right| {
2408 left.add_assign(right);
2409 left
2410 })
2411 .map(|change| (traversed_resource, change))
2412 })
2413 .collect()
2414 }
2415}
2416
2417pub fn is_auth_error(e: &RuntimeError) -> bool {
2418 matches!(
2419 e,
2420 RuntimeError::SystemModuleError(SystemModuleError::AuthError(_))
2421 )
2422}
2423
2424pub fn is_costing_error(e: &RuntimeError) -> bool {
2425 matches!(
2426 e,
2427 RuntimeError::SystemModuleError(SystemModuleError::CostingError(_))
2428 )
2429}
2430
2431pub fn is_wasm_error(e: &RuntimeError) -> bool {
2432 matches!(e, RuntimeError::VmError(VmError::Wasm(..)))
2433}
2434pub fn wat2wasm(wat: &str) -> Vec<u8> {
2435 let wat = wat
2436 .replace("${memcpy}", include_str!("snippets/memcpy.wat"))
2437 .replace("${memmove}", include_str!("snippets/memmove.wat"))
2438 .replace("${memset}", include_str!("snippets/memset.wat"));
2439
2440 wat::parse_str(wat).expect("Failed to compiled WAT into WASM")
2441}
2442
2443pub fn single_function_package_definition(
2444 blueprint_name: &str,
2445 function_name: &str,
2446) -> PackageDefinition {
2447 PackageDefinition::new_single_function_test_definition(blueprint_name, function_name)
2448}
2449
2450#[derive(ScryptoSbor, ManifestSbor)]
2451pub struct EmptyNonFungibleData {}
2452
2453impl NonFungibleData for EmptyNonFungibleData {
2454 const MUTABLE_FIELDS: &'static [&'static str] = &[];
2455}
2456
2457pub struct TransactionParams {
2458 pub start_epoch_inclusive: Epoch,
2459 pub end_epoch_exclusive: Epoch,
2460}
2461
2462pub fn create_notarized_transaction(
2463 params: TransactionParams,
2464 manifest: TransactionManifestV1,
2465) -> NotarizedTransactionV1 {
2466 let sk1 = Secp256k1PrivateKey::from_u64(1).unwrap();
2468 let sk2 = Secp256k1PrivateKey::from_u64(2).unwrap();
2469 let sk_notary = Secp256k1PrivateKey::from_u64(3).unwrap();
2470
2471 TransactionBuilder::new()
2472 .header(TransactionHeaderV1 {
2473 network_id: NetworkDefinition::simulator().id,
2474 start_epoch_inclusive: params.start_epoch_inclusive,
2475 end_epoch_exclusive: params.end_epoch_exclusive,
2476 nonce: 5,
2477 notary_public_key: sk_notary.public_key().into(),
2478 notary_is_signatory: false,
2479 tip_percentage: 5,
2480 })
2481 .manifest(manifest)
2482 .sign(&sk1)
2483 .sign(&sk2)
2484 .notarize(&sk_notary)
2485 .build()
2486}
2487
2488pub fn create_notarized_transaction_advanced<S: Signer>(
2489 ledger: &mut DefaultLedgerSimulator,
2490 network: &NetworkDefinition,
2491 manifest: TransactionManifestV1,
2492 signers: Vec<&S>,
2493 notary: &S,
2494 notary_is_signatory: bool,
2495) -> NotarizedTransactionV1 {
2496 TransactionBuilder::new()
2497 .header(TransactionHeaderV1 {
2498 network_id: network.id,
2499 start_epoch_inclusive: Epoch::zero(),
2500 end_epoch_exclusive: Epoch::of(99),
2501 nonce: ledger.next_transaction_nonce(),
2502 notary_public_key: notary.public_key(),
2503 notary_is_signatory,
2504 tip_percentage: 0,
2505 })
2506 .manifest(manifest)
2507 .multi_sign(&signers)
2508 .notarize(notary)
2509 .build()
2510}
2511
2512pub fn assert_receipt_substate_changes_can_be_typed(commit_result: &CommitResult) {
2513 let substate_updates = commit_result
2514 .state_updates
2515 .clone()
2516 .into_flattened_substate_updates();
2517 for ((node_id, partition_num, substate_key), database_update) in substate_updates.into_iter() {
2518 let typed_substate_key =
2519 to_typed_substate_key(node_id.entity_type().unwrap(), partition_num, &substate_key)
2520 .expect("Substate key should be typeable");
2521 if !typed_substate_key.value_is_mappable() {
2522 continue;
2523 }
2524 match database_update {
2525 DatabaseUpdate::Set(raw_value) => {
2526 to_typed_substate_value(&typed_substate_key, &raw_value)
2528 .expect("Substate value should be typeable");
2529 }
2530 DatabaseUpdate::Delete => {}
2531 }
2532 }
2533}
2534
2535pub fn assert_receipt_events_can_be_typed(commit_result: &CommitResult) {
2536 for (event_type_identifier, event_data) in &commit_result.application_events {
2537 match event_type_identifier.0 {
2538 Emitter::Function(BlueprintId {
2539 package_address, ..
2540 }) if ![
2541 PACKAGE_PACKAGE,
2542 RESOURCE_PACKAGE,
2543 ACCOUNT_PACKAGE,
2544 IDENTITY_PACKAGE,
2545 CONSENSUS_MANAGER_PACKAGE,
2546 ACCESS_CONTROLLER_PACKAGE,
2547 POOL_PACKAGE,
2548 TRANSACTION_PROCESSOR_PACKAGE,
2549 METADATA_MODULE_PACKAGE,
2550 ROYALTY_MODULE_PACKAGE,
2551 ROLE_ASSIGNMENT_MODULE_PACKAGE,
2552 TEST_UTILS_PACKAGE,
2553 GENESIS_HELPER_PACKAGE,
2554 FAUCET_PACKAGE,
2555 TRANSACTION_TRACKER_PACKAGE,
2556 ]
2557 .contains(&package_address) =>
2558 {
2559 continue
2560 }
2561 Emitter::Method(node_id, ..)
2562 if node_id.entity_type().is_some_and(|item| {
2563 matches!(
2564 item,
2565 EntityType::GlobalGenericComponent | EntityType::InternalGenericComponent
2566 )
2567 }) =>
2568 {
2569 continue
2570 }
2571 _ => {}
2572 };
2573 let _ = to_typed_native_event(event_type_identifier, event_data).unwrap();
2574 }
2575}
2576
2577pub enum PackagePublishingSource {
2578 CompileAndPublishFromSource(PathBuf, CompileProfile),
2579 PublishExisting(Vec<u8>, PackageDefinition),
2580}
2581
2582impl From<String> for PackagePublishingSource {
2583 fn from(value: String) -> Self {
2584 Self::CompileAndPublishFromSource(value.into(), CompileProfile::FastWithTraceLogs)
2585 }
2586}
2587
2588impl<'g> From<&'g str> for PackagePublishingSource {
2589 fn from(value: &'g str) -> Self {
2590 Self::CompileAndPublishFromSource(value.into(), CompileProfile::FastWithTraceLogs)
2591 }
2592}
2593
2594impl From<PathBuf> for PackagePublishingSource {
2595 fn from(value: PathBuf) -> Self {
2596 Self::CompileAndPublishFromSource(value, CompileProfile::FastWithTraceLogs)
2597 }
2598}
2599
2600impl<'g> From<&'g Path> for PackagePublishingSource {
2601 fn from(value: &'g Path) -> Self {
2602 Self::CompileAndPublishFromSource(value.into(), CompileProfile::FastWithTraceLogs)
2603 }
2604}
2605
2606impl From<(Vec<u8>, PackageDefinition)> for PackagePublishingSource {
2607 fn from(value: (Vec<u8>, PackageDefinition)) -> Self {
2608 Self::PublishExisting(value.0, value.1)
2609 }
2610}
2611
2612impl PackagePublishingSource {
2613 pub fn code_and_definition(self) -> (Vec<u8>, PackageDefinition) {
2614 match self {
2615 Self::CompileAndPublishFromSource(path, profile) => Compile::compile(path, profile),
2616 Self::PublishExisting(code, definition) => (code, definition),
2617 }
2618 }
2619}