radix_engine/transaction/
transaction_executor.rs1use crate::errors::*;
2use crate::internal_prelude::*;
3use crate::kernel::kernel::KernelInit;
4use crate::system::system_callback::*;
5use crate::transaction::*;
6use crate::vm::*;
7use radix_common::constants::*;
8use radix_engine_interface::blueprints::transaction_processor::InstructionOutput;
9use radix_substate_store_interface::interface::*;
10use radix_transactions::model::*;
11
12#[derive(Debug, Copy, Clone, ScryptoSbor, PartialEq, Eq)]
14pub struct CostingParameters {
15 pub execution_cost_unit_price: Decimal,
17 pub execution_cost_unit_limit: u32,
19 pub execution_cost_unit_loan: u32,
21
22 pub finalization_cost_unit_price: Decimal,
24 pub finalization_cost_unit_limit: u32,
26
27 pub usd_price: Decimal,
29 pub state_storage_price: Decimal,
31 pub archive_storage_price: Decimal,
33}
34
35impl CostingParameters {
36 pub fn latest() -> Self {
37 Self::babylon_genesis()
38 }
39
40 #[cfg(not(feature = "coverage"))]
41 pub fn babylon_genesis() -> Self {
42 Self {
43 execution_cost_unit_price: EXECUTION_COST_UNIT_PRICE_IN_XRD.try_into().unwrap(),
44 execution_cost_unit_limit: EXECUTION_COST_UNIT_LIMIT,
45 execution_cost_unit_loan: EXECUTION_COST_UNIT_LOAN,
46 finalization_cost_unit_price: FINALIZATION_COST_UNIT_PRICE_IN_XRD.try_into().unwrap(),
47 finalization_cost_unit_limit: FINALIZATION_COST_UNIT_LIMIT,
48 usd_price: USD_PRICE_IN_XRD.try_into().unwrap(),
49 state_storage_price: STATE_STORAGE_PRICE_IN_XRD.try_into().unwrap(),
50 archive_storage_price: ARCHIVE_STORAGE_PRICE_IN_XRD.try_into().unwrap(),
51 }
52 }
53 #[cfg(feature = "coverage")]
54 pub fn babylon_genesis() -> Self {
55 Self {
56 execution_cost_unit_price: Decimal::zero(),
57 execution_cost_unit_limit: u32::MAX,
58 execution_cost_unit_loan: u32::MAX,
59 finalization_cost_unit_price: Decimal::zero(),
60 finalization_cost_unit_limit: u32::MAX,
61 usd_price: USD_PRICE_IN_XRD.try_into().unwrap(),
62 state_storage_price: Decimal::zero(),
63 archive_storage_price: Decimal::zero(),
64 }
65 }
66
67 pub fn with_execution_cost_unit_loan(mut self, loan_units: u32) -> Self {
68 self.execution_cost_unit_loan = loan_units;
69 self
70 }
71
72 pub fn with_execution_cost_unit_limit(mut self, limit: u32) -> Self {
73 self.execution_cost_unit_limit = limit;
74 self
75 }
76
77 pub fn with_finalization_cost_unit_limit(mut self, limit: u32) -> Self {
78 self.finalization_cost_unit_limit = limit;
79 self
80 }
81}
82
83#[derive(Debug, Copy, Clone, ScryptoSbor, PartialEq, Eq)]
84pub struct LimitParameters {
85 pub max_call_depth: usize,
86 pub max_heap_substate_total_bytes: usize,
87 pub max_track_substate_total_bytes: usize,
88 pub max_substate_key_size: usize,
89 pub max_substate_value_size: usize,
90 pub max_invoke_input_size: usize,
91 pub max_event_size: usize,
92 pub max_log_size: usize,
93 pub max_panic_message_size: usize,
94 pub max_number_of_logs: usize,
95 pub max_number_of_events: usize,
96}
97
98impl LimitParameters {
99 pub fn babylon_genesis() -> Self {
100 Self {
101 max_call_depth: MAX_CALL_DEPTH,
102 max_heap_substate_total_bytes: MAX_HEAP_SUBSTATE_TOTAL_BYTES,
103 max_track_substate_total_bytes: MAX_TRACK_SUBSTATE_TOTAL_BYTES,
104 max_substate_key_size: MAX_SUBSTATE_KEY_SIZE,
105 max_substate_value_size: MAX_SUBSTATE_VALUE_SIZE,
106 max_invoke_input_size: MAX_INVOKE_PAYLOAD_SIZE,
107 max_event_size: MAX_EVENT_SIZE,
108 max_log_size: MAX_LOG_SIZE,
109 max_panic_message_size: MAX_PANIC_MESSAGE_SIZE,
110 max_number_of_logs: MAX_NUMBER_OF_LOGS,
111 max_number_of_events: MAX_NUMBER_OF_EVENTS,
112 }
113 }
114
115 pub fn for_genesis_transaction() -> Self {
116 Self {
117 max_heap_substate_total_bytes: 512 * 1024 * 1024,
118 max_track_substate_total_bytes: 512 * 1024 * 1024,
119 max_number_of_events: 1024 * 1024,
120 ..Self::babylon_genesis()
121 }
122 }
123}
124
125#[derive(Debug, Clone)]
126pub struct SystemOverrides {
127 pub disable_costing: bool,
128 pub disable_limits: bool,
129 pub disable_auth: bool,
130 pub abort_when_loan_repaid: bool,
133 pub network_definition: Option<NetworkDefinition>,
136 pub costing_parameters: Option<CostingParameters>,
137 pub limit_parameters: Option<LimitParameters>,
138}
139
140impl SystemOverrides {
141 const fn internal_default(network_definition: Option<NetworkDefinition>) -> Self {
142 Self {
143 disable_costing: false,
144 disable_limits: false,
145 disable_auth: false,
146 abort_when_loan_repaid: false,
147 network_definition,
148 costing_parameters: None,
149 limit_parameters: None,
150 }
151 }
152
153 pub const fn default_with_no_network() -> Self {
154 Self::internal_default(None)
155 }
156
157 pub const fn with_network(network_definition: NetworkDefinition) -> Self {
158 Self::internal_default(Some(network_definition))
159 }
160
161 pub const fn set_costing_parameters(
162 mut self,
163 costing_parameters: Option<CostingParameters>,
164 ) -> Self {
165 self.costing_parameters = costing_parameters;
166 self
167 }
168
169 pub fn set_abort_when_loan_repaid(mut self) -> Self {
170 self.abort_when_loan_repaid = true;
171 self
172 }
173}
174
175impl Default for SystemOverrides {
176 fn default() -> Self {
177 Self::default_with_no_network()
178 }
179}
180
181#[derive(Debug, Clone)]
182pub struct ExecutionConfig {
183 pub enable_kernel_trace: bool,
185 pub enable_cost_breakdown: bool,
186 pub execution_trace: Option<usize>,
187 pub enable_debug_information: bool,
188
189 pub system_overrides: Option<SystemOverrides>,
190}
191
192impl ExecutionConfig {
193 const fn default_with_no_network() -> Self {
196 Self {
197 enable_kernel_trace: false,
198 enable_cost_breakdown: false,
199 execution_trace: None,
200 system_overrides: None,
201 enable_debug_information: false,
202 }
203 }
204
205 fn default_with_network(network_definition: NetworkDefinition) -> Self {
208 Self {
209 system_overrides: Some(SystemOverrides::with_network(network_definition)),
210 ..Self::default_with_no_network()
211 }
212 }
213
214 pub fn for_genesis_transaction(network_definition: NetworkDefinition) -> Self {
215 Self::for_auth_disabled_system_transaction(network_definition)
216 }
217
218 pub fn for_auth_disabled_system_transaction(network_definition: NetworkDefinition) -> Self {
219 Self {
220 system_overrides: Some(SystemOverrides {
221 disable_costing: true,
222 disable_limits: true,
223 disable_auth: true,
224 network_definition: Some(network_definition),
225 ..Default::default()
226 }),
227 ..Self::default_with_no_network()
228 }
229 }
230
231 pub fn for_system_transaction(network_definition: NetworkDefinition) -> Self {
232 Self {
233 system_overrides: Some(SystemOverrides {
234 disable_costing: true,
235 disable_limits: true,
236 network_definition: Some(network_definition),
237 ..Default::default()
238 }),
239 ..Self::default_with_no_network()
240 }
241 }
242
243 pub fn for_validator_transaction(network_definition: NetworkDefinition) -> Self {
244 Self {
245 ..Self::default_with_network(network_definition)
246 }
247 }
248
249 pub fn for_notarized_transaction(network_definition: NetworkDefinition) -> Self {
250 Self {
251 ..Self::default_with_network(network_definition)
252 }
253 }
254
255 pub fn for_notarized_transaction_rejection_check(
256 network_definition: NetworkDefinition,
257 ) -> Self {
258 Self::default_with_network(network_definition)
259 .update_system_overrides(|overrides| overrides.set_abort_when_loan_repaid())
260 }
261
262 pub fn update_system_overrides(
263 mut self,
264 update: impl FnOnce(SystemOverrides) -> SystemOverrides,
265 ) -> Self {
266 self.system_overrides = Some(update(self.system_overrides.unwrap_or_default()));
267 self
268 }
269
270 pub fn for_test_transaction() -> Self {
271 Self {
272 enable_cost_breakdown: true,
273 ..Self::default_with_network(NetworkDefinition::simulator())
274 }
275 }
276
277 pub fn for_debug_transaction() -> Self {
278 Self {
279 enable_debug_information: true,
280 ..Self::for_test_transaction()
281 }
282 }
283
284 pub fn for_preview(network_definition: NetworkDefinition) -> Self {
285 Self {
286 enable_cost_breakdown: true,
287 execution_trace: Some(MAX_EXECUTION_TRACE_DEPTH),
288 ..Self::default_with_network(network_definition)
289 }
290 }
291
292 pub fn for_preview_no_auth(network_definition: NetworkDefinition) -> Self {
293 Self {
294 enable_cost_breakdown: true,
295 execution_trace: Some(MAX_EXECUTION_TRACE_DEPTH),
296 system_overrides: Some(SystemOverrides {
297 disable_auth: true,
298 network_definition: Some(network_definition),
299 ..Default::default()
300 }),
301 ..Self::default_with_no_network()
302 }
303 }
304
305 pub fn with_kernel_trace(mut self, enabled: bool) -> Self {
306 self.enable_kernel_trace = enabled;
307 self
308 }
309
310 pub fn with_execution_trace(mut self, depth: Option<usize>) -> Self {
311 self.execution_trace = depth;
312 self
313 }
314
315 pub fn with_cost_breakdown(mut self, enabled: bool) -> Self {
316 self.enable_cost_breakdown = enabled;
317 self
318 }
319}
320
321pub fn execute_transaction<'v, V: VmInitialize>(
322 substate_db: &impl SubstateDatabase,
323 vm_modules: &'v V,
324 execution_config: &ExecutionConfig,
325 executable: impl AsRef<ExecutableTransaction>,
326) -> TransactionReceipt {
327 let vm_init = VmInit::load(substate_db, vm_modules);
328 let system_init = SystemInit::load(substate_db, execution_config.clone(), vm_init);
329 KernelInit::load(substate_db, system_init).execute(executable.as_ref())
330}
331
332pub fn execute_and_commit_transaction<'s, V: VmInitialize>(
333 substate_db: &mut (impl SubstateDatabase + CommittableSubstateDatabase),
334 vm_modules: &'s V,
335 execution_config: &ExecutionConfig,
336 executable: impl AsRef<ExecutableTransaction>,
337) -> TransactionReceipt {
338 let receipt = execute_transaction(substate_db, vm_modules, execution_config, executable);
339 if let TransactionResult::Commit(commit) = &receipt.result {
340 substate_db.commit(&commit.state_updates.create_database_updates());
341 }
342 receipt
343}
344
345pub enum TransactionResultType {
346 Commit(Result<Vec<InstructionOutput>, RuntimeError>),
347 Reject(RejectionReason),
348 Abort(AbortReason),
349}