scrypto_test/ledger_simulator/
ledger_simulator.rs

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    // General options
53    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    /// Overrides the kernel trace setting to `true` for all executed transactions.
95    pub fn with_kernel_trace(mut self) -> Self {
96        self.with_kernel_trace = Some(true);
97        self
98    }
99
100    /// Overrides the kernel trace setting to `false` for all executed transactions.
101    pub fn without_kernel_trace(mut self) -> Self {
102        self.with_kernel_trace = Some(false);
103        self
104    }
105
106    /// Overrides the cost breakdown setting to `true` for all executed transactions.
107    pub fn with_cost_breakdown(mut self) -> Self {
108        self.with_cost_breakdown = Some(true);
109        self
110    }
111
112    /// Overrides the cost breakdown setting to `false` for all executed transactions.
113    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    /// Note - this overwrites / is overwritten by any other protocol overrides.
157    /// Use [`Self::with_custom_protocol`] for full control.
158    ///
159    /// If you previously just used `CustomGenesis::test_default` in order to get round
160    /// change tests to pass, this is no longer necessary.
161    #[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    /// Note - this overwrites / is overwritten by any other protocol overrides.
180    /// Use [`Self::with_custom_protocol`] for full control.
181    #[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    /// NOTE: The epoch change isn't available if the protocol builder does not run genesis.
208    pub fn build_and_get_post_genesis_epoch_change(
209        self,
210    ) -> (LedgerSimulator<E, D>, Option<EpochChangeEvent>) {
211        //---------- Override configs for resource tracker ---------------
212        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        //----------------------------------------------------------------
225        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        // Protocol Updates
262        self.protocol_executor.commit_each_protocol_update_advanced(
263            &mut substate_db,
264            &mut hooks,
265            &vm_modules,
266        );
267
268        // Note that 0 is not a valid private key
269        let next_private_key = 100;
270
271        // Starting from non-zero considering that bootstrap might have used a few.
272        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    /// Events collected from all the committed transactions
306    collected_events: Vec<Vec<(EventTypeIdentifier, Vec<u8>)>>,
307    /// Track whether any of the committed transaction has used free credit
308    xrd_free_credits_used: bool,
309
310    /// Override whether to enable kernel tracing
311    with_kernel_trace: Option<bool>,
312    /// Override whether to enable the cost breakdown
313    with_cost_breakdown: Option<bool>,
314    /// Whether to enable receipt substate type checking
315    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    /// This should only be needed if you manually apply protocol
395    /// updates to the underlying database after the LedgerSimulator
396    /// has been built.
397    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        // TODO: Remove .collect() by using SystemDatabaseReader in ledger
675        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    /// Publishes a package at a specified address.
1054    ///
1055    /// This is for testing only. On real networks, this operation is not allowed to users.
1056    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    // Doesn't need to be here - kept for backward compatibility
1157    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    // Doesn't need to be here - kept for backward compatibility
1162    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    // Doesn't need to be here - kept for backward compatibility
1185    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(&notary)
1325            .build()
1326    }
1327
1328    pub fn default_notary(&self) -> Ed25519PrivateKey {
1329        Ed25519PrivateKey::from_u64(1337).unwrap()
1330    }
1331
1332    /// Includes default headers
1333    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    /// Includes default headers
1353    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    /// The system manifest can be created with `ManifestBuilder::new_system_v1()`.
1383    /// Preallocated addresses can be created with manifest_builder.preallocate_address()
1384    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    /// Calls a package blueprint function with the given arguments, paying the fee from the faucet.
1530    ///
1531    /// The arguments should be one of:
1532    /// * A tuple, such as `()`, `(x,)` or `(x, y, z)`
1533    ///   * IMPORTANT: If calling with a single argument, you must include a trailing comma
1534    ///     in the tuple declaration. This ensures that the rust compiler knows it's a singleton tuple,
1535    ///     rather than just some brackets around the inner value.
1536    /// * A struct which implements `ManifestEncode` representing the arguments
1537    /// * `manifest_args!(x, y, z)`
1538    ///
1539    /// Notes:
1540    /// * Buckets and signatures are not supported - instead use `execute_manifest_ignoring_fee` and `ManifestBuilder` directly.
1541    /// * Call `.expect_commit_success()` on the receipt to get access to receipt details.
1542    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    /// Calls a package blueprint function with the given arguments, and assumes it constructs a single component successfully.
1559    /// It returns the address of the first created component.
1560    ///
1561    /// The arguments should be one of:
1562    /// * A tuple, such as `()`, `(x,)` or `(x, y, z)`
1563    ///   * IMPORTANT: If calling with a single argument, you must include a trailing comma
1564    ///     in the tuple declaration. This ensures that the rust compiler knows it's a singleton tuple,
1565    ///     rather than just some brackets around the inner value.
1566    /// * A struct which implements `ManifestEncode` representing the arguments
1567    /// * `manifest_args!(x, y, z)`
1568    ///
1569    /// Notes:
1570    /// * Buckets and signatures are not supported - instead use `execute_manifest_ignoring_fee` and `ManifestBuilder` directly.
1571    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    /// Calls a component method with the given arguments, paying the fee from the faucet.
1584    ///
1585    /// The arguments should be one of:
1586    /// * A tuple, such as `()`, `(x,)` or `(x, y, z)`
1587    ///   * IMPORTANT: If calling with a single argument, you must include a trailing comma
1588    ///     in the tuple declaration. This ensures that the rust compiler knows it's a singleton tuple,
1589    ///     rather than just some brackets around the inner value.
1590    /// * A struct which implements `ManifestEncode` representing the arguments
1591    /// * `manifest_args!(x, y, z)`
1592    ///
1593    /// Notes:
1594    /// * Buckets and signatures are not supported - instead use `execute_manifest_ignoring_fee` and `ManifestBuilder` directly.
1595    /// * Call `.expect_commit_success()` on the receipt to get access to receipt details.
1596    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    /// Executes a "start round number `round` at timestamp `timestamp_ms`" system transaction, as
2125    /// if it was proposed by the first validator from the validator set, after `round - 1` missed
2126    /// rounds by that validator.
2127    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    /// Performs an [`advance_to_round_at_timestamp()`] with an unchanged timestamp.
2156    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    /// Reads out the substate holding the "epoch milli" timestamp reported by the proposer on the
2162    /// most recent round change.
2163    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        // Defining a composite checker of all of the application db checkers we have.
2318        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 free credits (xrd from thin air) have been used then reconciliation will fail
2356        // due to missing mint events
2357        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    // create key pairs
2467    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                // Check that typed value mapping works
2527                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}