diff --git a/radix-engine/src/kernel/kernel.rs b/radix-engine/src/kernel/kernel.rs index c1ac6c79aa..e1a5139d1d 100644 --- a/radix-engine/src/kernel/kernel.rs +++ b/radix-engine/src/kernel/kernel.rs @@ -149,7 +149,7 @@ impl<'h, S: SubstateDatabase> BootLoader<'h, S> { kernel_boot.always_visible_global_nodes(), ); - let (mut system, call_frame_inits) = match system_init_result { + let (mut system, call_frame_inits, num_of_intent_statuses) = match system_init_result { Ok(success) => success, Err(receipt) => return receipt, }; @@ -177,7 +177,9 @@ impl<'h, S: SubstateDatabase> BootLoader<'h, S> { // Finalize state updates based on what has occurred let commit_info = kernel.substate_io.store.get_commit_info(); - kernel.callback.finalize(commit_info)?; + kernel + .callback + .finalize(commit_info, num_of_intent_statuses)?; Ok(output) }() diff --git a/radix-engine/src/kernel/kernel_callback_api.rs b/radix-engine/src/kernel/kernel_callback_api.rs index 857bcb4c0d..a445fcd791 100644 --- a/radix-engine/src/kernel/kernel_callback_api.rs +++ b/radix-engine/src/kernel/kernel_callback_api.rs @@ -166,7 +166,7 @@ pub trait KernelTransactionExecutor: KernelCallbackObject { executable: &Self::Executable, init: Self::Init, always_visible_global_nodes: &'static IndexSet, - ) -> Result<(Self, Vec>), Self::Receipt>; + ) -> Result<(Self, Vec>, usize), Self::Receipt>; /// Start execution fn execute>( @@ -175,7 +175,11 @@ pub trait KernelTransactionExecutor: KernelCallbackObject { ) -> Result; /// Finish execution - fn finalize(&mut self, store_commit_info: StoreCommitInfo) -> Result<(), RuntimeError>; + fn finalize( + &mut self, + store_commit_info: StoreCommitInfo, + num_of_intent_statuses: usize, + ) -> Result<(), RuntimeError>; /// Create final receipt fn create_receipt( diff --git a/radix-engine/src/system/system_callback.rs b/radix-engine/src/system/system_callback.rs index 0f6f0d02c8..9a22b67623 100644 --- a/radix-engine/src/system/system_callback.rs +++ b/radix-engine/src/system/system_callback.rs @@ -1503,7 +1503,7 @@ impl KernelTransactionExecutor for System { executable: &ExecutableTransaction, init_input: Self::Init, always_visible_global_nodes: &'static IndexSet, - ) -> Result<(Self, Vec>), Self::Receipt> { + ) -> Result<(Self, Vec>, usize), Self::Receipt> { // Dump executable #[cfg(not(feature = "alloc"))] if init_input.self_init.enable_kernel_trace { @@ -1541,6 +1541,7 @@ impl KernelTransactionExecutor for System { } } + let mut num_of_intent_statuses = 0; for hash_nullification in executable.intent_hash_nullifications() { let intent_hash_validation_result = match hash_nullification { IntentHashNullification::TransactionIntent { @@ -1580,6 +1581,8 @@ impl KernelTransactionExecutor for System { // Transaction intent nullification is historically not costed. } IntentHashNullification::Subintent { .. } => { + num_of_intent_statuses += 1; + if let Some(costing) = modules.costing_mut() { return costing .apply_deferred_execution_cost( @@ -1626,7 +1629,7 @@ impl KernelTransactionExecutor for System { }, ); - Ok((system, call_frame_inits)) + Ok((system, call_frame_inits, num_of_intent_statuses)) } fn execute( @@ -1658,7 +1661,11 @@ impl KernelTransactionExecutor for System { Ok(output) } - fn finalize(&mut self, info: StoreCommitInfo) -> Result<(), RuntimeError> { + fn finalize( + &mut self, + info: StoreCommitInfo, + num_of_intent_statuses: usize, + ) -> Result<(), RuntimeError> { self.modules.on_teardown()?; // Note that if a transactions fails during this phase, the costing is @@ -1680,6 +1687,11 @@ impl KernelTransactionExecutor for System { logs: &self.modules.logs().clone(), }) .map_err(|e| RuntimeError::FinalizationCostingError(e))?; + self.modules + .apply_finalization_cost(FinalizationCostingEntry::CommitIntentStatus { + num_of_intent_statuses, + }) + .map_err(|e| RuntimeError::FinalizationCostingError(e))?; /* state storage costs */ for store_commit in &info { diff --git a/radix-engine/src/system/system_modules/costing/costing_entry.rs b/radix-engine/src/system/system_modules/costing/costing_entry.rs index 44a7e24ed4..23d15e1df6 100644 --- a/radix-engine/src/system/system_modules/costing/costing_entry.rs +++ b/radix-engine/src/system/system_modules/costing/costing_entry.rs @@ -140,6 +140,7 @@ pub enum FinalizationCostingEntry<'a> { CommitStateUpdates { store_commit: &'a StoreCommit }, CommitEvents { events: &'a Vec }, CommitLogs { logs: &'a Vec<(Level, String)> }, + CommitIntentStatus { num_of_intent_statuses: usize }, } impl<'a> ExecutionCostingEntry<'a> { @@ -222,6 +223,10 @@ impl<'a> FinalizationCostingEntry<'a> { } FinalizationCostingEntry::CommitEvents { events } => ft.commit_events_cost(events), FinalizationCostingEntry::CommitLogs { logs } => ft.commit_logs_cost(logs), + + FinalizationCostingEntry::CommitIntentStatus { + num_of_intent_statuses, + } => ft.commit_intent_status(*num_of_intent_statuses), } } } diff --git a/radix-engine/src/system/system_modules/costing/fee_table.rs b/radix-engine/src/system/system_modules/costing/fee_table.rs index 88600e8265..728c0c3331 100644 --- a/radix-engine/src/system/system_modules/costing/fee_table.rs +++ b/radix-engine/src/system/system_modules/costing/fee_table.rs @@ -562,6 +562,12 @@ impl FeeTable { } sum } + + #[inline] + pub fn commit_intent_status(&self, num_of_intent_statuses: usize) -> u32 { + // Equivalent to a substate insertion + mul(cast(num_of_intent_statuses), 100_000) + } } #[inline] diff --git a/scrypto-test/src/ledger_simulator/inject_costing_err.rs b/scrypto-test/src/ledger_simulator/inject_costing_err.rs index ab73842eff..a0c263e0a8 100644 --- a/scrypto-test/src/ledger_simulator/inject_costing_err.rs +++ b/scrypto-test/src/ledger_simulator/inject_costing_err.rs @@ -72,8 +72,8 @@ impl< executable: &ExecutableTransaction, init_input: Self::Init, always_visible_global_nodes: &'static IndexSet, - ) -> Result<(Self, Vec>), Self::Receipt> { - let (mut system, call_frame_inits) = E::init( + ) -> Result<(Self, Vec>, usize), Self::Receipt> { + let (mut system, call_frame_inits, num_of_intent_statuses) = E::init( store, executable, init_input.system_input, @@ -91,6 +91,7 @@ impl< wrapped: system, }, call_frame_inits, + num_of_intent_statuses, )) } @@ -102,9 +103,14 @@ impl< E::execute(&mut api, executable) } - fn finalize(&mut self, store_commit_info: StoreCommitInfo) -> Result<(), RuntimeError> { + fn finalize( + &mut self, + store_commit_info: StoreCommitInfo, + num_of_intent_statuses: usize, + ) -> Result<(), RuntimeError> { self.maybe_err()?; - self.wrapped.finalize(store_commit_info) + self.wrapped + .finalize(store_commit_info, num_of_intent_statuses) } fn create_receipt(