use crate::errors::*;
use crate::internal_prelude::*;
use crate::kernel::kernel::KernelInit;
use crate::system::system_callback::*;
use crate::transaction::*;
use crate::vm::*;
use radix_common::constants::*;
use radix_engine_interface::blueprints::transaction_processor::InstructionOutput;
use radix_substate_store_interface::interface::*;
use radix_transactions::model::*;
#[derive(Debug, Copy, Clone, ScryptoSbor, PartialEq, Eq)]
pub struct CostingParameters {
pub execution_cost_unit_price: Decimal,
pub execution_cost_unit_limit: u32,
pub execution_cost_unit_loan: u32,
pub finalization_cost_unit_price: Decimal,
pub finalization_cost_unit_limit: u32,
pub usd_price: Decimal,
pub state_storage_price: Decimal,
pub archive_storage_price: Decimal,
}
impl CostingParameters {
pub fn latest() -> Self {
Self::babylon_genesis()
}
#[cfg(not(feature = "coverage"))]
pub fn babylon_genesis() -> Self {
Self {
execution_cost_unit_price: EXECUTION_COST_UNIT_PRICE_IN_XRD.try_into().unwrap(),
execution_cost_unit_limit: EXECUTION_COST_UNIT_LIMIT,
execution_cost_unit_loan: EXECUTION_COST_UNIT_LOAN,
finalization_cost_unit_price: FINALIZATION_COST_UNIT_PRICE_IN_XRD.try_into().unwrap(),
finalization_cost_unit_limit: FINALIZATION_COST_UNIT_LIMIT,
usd_price: USD_PRICE_IN_XRD.try_into().unwrap(),
state_storage_price: STATE_STORAGE_PRICE_IN_XRD.try_into().unwrap(),
archive_storage_price: ARCHIVE_STORAGE_PRICE_IN_XRD.try_into().unwrap(),
}
}
#[cfg(feature = "coverage")]
pub fn babylon_genesis() -> Self {
Self {
execution_cost_unit_price: Decimal::zero(),
execution_cost_unit_limit: u32::MAX,
execution_cost_unit_loan: u32::MAX,
finalization_cost_unit_price: Decimal::zero(),
finalization_cost_unit_limit: u32::MAX,
usd_price: USD_PRICE_IN_XRD.try_into().unwrap(),
state_storage_price: Decimal::zero(),
archive_storage_price: Decimal::zero(),
}
}
pub fn with_execution_cost_unit_loan(mut self, loan_units: u32) -> Self {
self.execution_cost_unit_loan = loan_units;
self
}
pub fn with_execution_cost_unit_limit(mut self, limit: u32) -> Self {
self.execution_cost_unit_limit = limit;
self
}
pub fn with_finalization_cost_unit_limit(mut self, limit: u32) -> Self {
self.finalization_cost_unit_limit = limit;
self
}
}
#[derive(Debug, Copy, Clone, ScryptoSbor, PartialEq, Eq)]
pub struct LimitParameters {
pub max_call_depth: usize,
pub max_heap_substate_total_bytes: usize,
pub max_track_substate_total_bytes: usize,
pub max_substate_key_size: usize,
pub max_substate_value_size: usize,
pub max_invoke_input_size: usize,
pub max_event_size: usize,
pub max_log_size: usize,
pub max_panic_message_size: usize,
pub max_number_of_logs: usize,
pub max_number_of_events: usize,
}
impl LimitParameters {
pub fn babylon_genesis() -> Self {
Self {
max_call_depth: MAX_CALL_DEPTH,
max_heap_substate_total_bytes: MAX_HEAP_SUBSTATE_TOTAL_BYTES,
max_track_substate_total_bytes: MAX_TRACK_SUBSTATE_TOTAL_BYTES,
max_substate_key_size: MAX_SUBSTATE_KEY_SIZE,
max_substate_value_size: MAX_SUBSTATE_VALUE_SIZE,
max_invoke_input_size: MAX_INVOKE_PAYLOAD_SIZE,
max_event_size: MAX_EVENT_SIZE,
max_log_size: MAX_LOG_SIZE,
max_panic_message_size: MAX_PANIC_MESSAGE_SIZE,
max_number_of_logs: MAX_NUMBER_OF_LOGS,
max_number_of_events: MAX_NUMBER_OF_EVENTS,
}
}
pub fn for_genesis_transaction() -> Self {
Self {
max_heap_substate_total_bytes: 512 * 1024 * 1024,
max_track_substate_total_bytes: 512 * 1024 * 1024,
max_number_of_events: 1024 * 1024,
..Self::babylon_genesis()
}
}
}
#[derive(Debug, Clone)]
pub struct SystemOverrides {
pub disable_costing: bool,
pub disable_limits: bool,
pub disable_auth: bool,
pub abort_when_loan_repaid: bool,
pub network_definition: Option<NetworkDefinition>,
pub costing_parameters: Option<CostingParameters>,
pub limit_parameters: Option<LimitParameters>,
}
impl SystemOverrides {
const fn internal_default(network_definition: Option<NetworkDefinition>) -> Self {
Self {
disable_costing: false,
disable_limits: false,
disable_auth: false,
abort_when_loan_repaid: false,
network_definition,
costing_parameters: None,
limit_parameters: None,
}
}
pub const fn default_with_no_network() -> Self {
Self::internal_default(None)
}
pub const fn with_network(network_definition: NetworkDefinition) -> Self {
Self::internal_default(Some(network_definition))
}
pub const fn set_costing_parameters(
mut self,
costing_parameters: Option<CostingParameters>,
) -> Self {
self.costing_parameters = costing_parameters;
self
}
pub fn set_abort_when_loan_repaid(mut self) -> Self {
self.abort_when_loan_repaid = true;
self
}
}
impl Default for SystemOverrides {
fn default() -> Self {
Self::default_with_no_network()
}
}
#[derive(Debug, Clone)]
pub struct ExecutionConfig {
pub enable_kernel_trace: bool,
pub enable_cost_breakdown: bool,
pub execution_trace: Option<usize>,
pub enable_debug_information: bool,
pub system_overrides: Option<SystemOverrides>,
}
impl ExecutionConfig {
const fn default_with_no_network() -> Self {
Self {
enable_kernel_trace: false,
enable_cost_breakdown: false,
execution_trace: None,
system_overrides: None,
enable_debug_information: false,
}
}
fn default_with_network(network_definition: NetworkDefinition) -> Self {
Self {
system_overrides: Some(SystemOverrides::with_network(network_definition)),
..Self::default_with_no_network()
}
}
pub fn for_genesis_transaction(network_definition: NetworkDefinition) -> Self {
Self::for_auth_disabled_system_transaction(network_definition)
}
pub fn for_auth_disabled_system_transaction(network_definition: NetworkDefinition) -> Self {
Self {
system_overrides: Some(SystemOverrides {
disable_costing: true,
disable_limits: true,
disable_auth: true,
network_definition: Some(network_definition),
..Default::default()
}),
..Self::default_with_no_network()
}
}
pub fn for_system_transaction(network_definition: NetworkDefinition) -> Self {
Self {
system_overrides: Some(SystemOverrides {
disable_costing: true,
disable_limits: true,
network_definition: Some(network_definition),
..Default::default()
}),
..Self::default_with_no_network()
}
}
pub fn for_validator_transaction(network_definition: NetworkDefinition) -> Self {
Self {
..Self::default_with_network(network_definition)
}
}
pub fn for_notarized_transaction(network_definition: NetworkDefinition) -> Self {
Self {
..Self::default_with_network(network_definition)
}
}
pub fn for_notarized_transaction_rejection_check(
network_definition: NetworkDefinition,
) -> Self {
Self::default_with_network(network_definition)
.update_system_overrides(|overrides| overrides.set_abort_when_loan_repaid())
}
pub fn update_system_overrides(
mut self,
update: impl FnOnce(SystemOverrides) -> SystemOverrides,
) -> Self {
self.system_overrides = Some(update(self.system_overrides.unwrap_or_default()));
self
}
pub fn for_test_transaction() -> Self {
Self {
enable_cost_breakdown: true,
..Self::default_with_network(NetworkDefinition::simulator())
}
}
pub fn for_debug_transaction() -> Self {
Self {
enable_debug_information: true,
..Self::for_test_transaction()
}
}
pub fn for_preview(network_definition: NetworkDefinition) -> Self {
Self {
enable_cost_breakdown: true,
execution_trace: Some(MAX_EXECUTION_TRACE_DEPTH),
..Self::default_with_network(network_definition)
}
}
pub fn for_preview_no_auth(network_definition: NetworkDefinition) -> Self {
Self {
enable_cost_breakdown: true,
execution_trace: Some(MAX_EXECUTION_TRACE_DEPTH),
system_overrides: Some(SystemOverrides {
disable_auth: true,
network_definition: Some(network_definition),
..Default::default()
}),
..Self::default_with_no_network()
}
}
pub fn with_kernel_trace(mut self, enabled: bool) -> Self {
self.enable_kernel_trace = enabled;
self
}
pub fn with_execution_trace(mut self, depth: Option<usize>) -> Self {
self.execution_trace = depth;
self
}
pub fn with_cost_breakdown(mut self, enabled: bool) -> Self {
self.enable_cost_breakdown = enabled;
self
}
}
pub fn execute_transaction<V: VmInitialize>(
substate_db: &impl SubstateDatabase,
vm_modules: &V,
execution_config: &ExecutionConfig,
executable: impl AsRef<ExecutableTransaction>,
) -> TransactionReceipt {
let vm_init = VmInit::load(substate_db, vm_modules);
let system_init = SystemInit::load(substate_db, execution_config.clone(), vm_init);
KernelInit::load(substate_db, system_init).execute(executable.as_ref())
}
pub fn execute_and_commit_transaction<V: VmInitialize>(
substate_db: &mut (impl SubstateDatabase + CommittableSubstateDatabase),
vm_modules: &V,
execution_config: &ExecutionConfig,
executable: impl AsRef<ExecutableTransaction>,
) -> TransactionReceipt {
let receipt = execute_transaction(substate_db, vm_modules, execution_config, executable);
if let TransactionResult::Commit(commit) = &receipt.result {
substate_db.commit(&commit.state_updates.create_database_updates());
}
receipt
}
pub enum TransactionResultType {
Commit(Result<Vec<InstructionOutput>, RuntimeError>),
Reject(RejectionReason),
Abort(AbortReason),
}