casper_execution_engine/engine_state/
mod.rs1pub mod engine_config;
3mod error;
4pub(crate) mod execution_kind;
5mod wasm_v1;
6
7use std::{cell::RefCell, collections::BTreeSet, rc::Rc};
8
9use casper_types::{
10 account::AccountHash, Gas, InitiatorAddr, Key, Phase, RuntimeArgs, StoredValue, TransactionHash,
11};
12
13use casper_storage::{
14 global_state::{
15 error::Error as GlobalStateError,
16 state::{StateProvider, StateReader},
17 },
18 tracking_copy::{TrackingCopyEntityExt, TrackingCopyError},
19 TrackingCopy,
20};
21
22use crate::{execution::Executor, runtime::RuntimeStack};
23pub use engine_config::{
24 EngineConfig, EngineConfigBuilder, DEFAULT_MAX_QUERY_DEPTH,
25 DEFAULT_MAX_RUNTIME_CALL_STACK_HEIGHT,
26};
27pub use error::Error;
28use execution_kind::ExecutionKind;
29pub use wasm_v1::{
30 BlockInfo, ExecutableItem, InvalidRequest, SessionDataDeploy, SessionDataV1, SessionInputData,
31 WasmV1Request, WasmV1Result,
32};
33
34pub const WASMLESS_TRANSFER_FIXED_GAS_PRICE: u8 = 1;
37
38#[derive(Debug, Clone, Default)]
40pub struct ExecutionEngineV1 {
41 config: EngineConfig,
42}
43
44impl ExecutionEngineV1 {
45 pub fn new(config: EngineConfig) -> ExecutionEngineV1 {
47 ExecutionEngineV1 { config }
48 }
49
50 pub fn config(&self) -> &EngineConfig {
52 &self.config
53 }
54
55 pub fn execute(
57 &self,
58 state_provider: &impl StateProvider,
59 wasm_v1_request: WasmV1Request,
60 ) -> WasmV1Result {
61 let WasmV1Request {
62 block_info,
63 transaction_hash,
64 gas_limit,
65 initiator_addr,
66 executable_item,
67 entry_point,
68 args,
69 authorization_keys,
70 phase,
71 } = wasm_v1_request;
72 let account_hash = initiator_addr.account_hash();
79 let protocol_version = self.config.protocol_version();
80 let state_hash = block_info.state_hash;
81 let tc = match state_provider.tracking_copy(state_hash) {
82 Ok(Some(tracking_copy)) => Rc::new(RefCell::new(tracking_copy)),
83 Ok(None) => return WasmV1Result::root_not_found(gas_limit, state_hash),
84 Err(gse) => {
85 return WasmV1Result::precondition_failure(
86 gas_limit,
87 Error::TrackingCopy(TrackingCopyError::Storage(gse)),
88 )
89 }
90 };
91 let (runtime_footprint, entity_addr) = {
92 match tc.borrow_mut().authorized_runtime_footprint_by_account(
93 protocol_version,
94 account_hash,
95 &authorization_keys,
96 &self.config().administrative_accounts,
97 ) {
98 Ok((runtime_footprint, entity_hash)) => (runtime_footprint, entity_hash),
99 Err(tce) => {
100 return WasmV1Result::precondition_failure(gas_limit, Error::TrackingCopy(tce))
101 }
102 }
103 };
104 let mut named_keys = runtime_footprint.named_keys().clone();
105 let execution_kind = match ExecutionKind::new(&named_keys, &executable_item, entry_point) {
106 Ok(execution_kind) => execution_kind,
107 Err(ese) => return WasmV1Result::precondition_failure(gas_limit, ese),
108 };
109 let access_rights = runtime_footprint.extract_access_rights(entity_addr.value());
110 Executor::new(self.config().clone()).exec(
111 execution_kind,
112 args,
113 entity_addr,
114 Rc::new(RefCell::new(runtime_footprint)),
115 &mut named_keys,
116 access_rights,
117 authorization_keys,
118 account_hash,
119 block_info,
120 transaction_hash,
121 gas_limit,
122 Rc::clone(&tc),
123 phase,
124 RuntimeStack::from_account_hash(
125 account_hash,
126 self.config.max_runtime_call_stack_height() as usize,
127 ),
128 )
129 }
130
131 #[allow(clippy::too_many_arguments)]
133 pub fn execute_with_tracking_copy<R>(
134 &self,
135 tracking_copy: TrackingCopy<R>,
136 block_info: BlockInfo,
137 transaction_hash: TransactionHash,
138 gas_limit: Gas,
139 initiator_addr: InitiatorAddr,
140 executable_item: ExecutableItem,
141 entry_point: String,
142 args: RuntimeArgs,
143 authorization_keys: BTreeSet<AccountHash>,
144 phase: Phase,
145 ) -> WasmV1Result
146 where
147 R: StateReader<Key, StoredValue, Error = GlobalStateError>,
148 {
149 let account_hash = initiator_addr.account_hash();
156 let protocol_version = self.config.protocol_version();
157 let tc = Rc::new(RefCell::new(tracking_copy));
158 let (runtime_footprint, entity_addr) = {
159 match tc.borrow_mut().authorized_runtime_footprint_by_account(
160 protocol_version,
161 account_hash,
162 &authorization_keys,
163 &self.config().administrative_accounts,
164 ) {
165 Ok((addressable_entity, entity_hash)) => (addressable_entity, entity_hash),
166 Err(tce) => {
167 return WasmV1Result::precondition_failure(gas_limit, Error::TrackingCopy(tce))
168 }
169 }
170 };
171 let mut named_keys = runtime_footprint.named_keys().clone();
172 let execution_kind = match ExecutionKind::new(&named_keys, &executable_item, entry_point) {
173 Ok(execution_kind) => execution_kind,
174 Err(ese) => return WasmV1Result::precondition_failure(gas_limit, ese),
175 };
176 let access_rights = runtime_footprint.extract_access_rights(entity_addr.value());
177 Executor::new(self.config().clone()).exec(
178 execution_kind,
179 args,
180 entity_addr,
181 Rc::new(RefCell::new(runtime_footprint)),
182 &mut named_keys,
183 access_rights,
184 authorization_keys,
185 account_hash,
186 block_info,
187 transaction_hash,
188 gas_limit,
189 Rc::clone(&tc),
190 phase,
191 RuntimeStack::from_account_hash(
192 account_hash,
193 self.config.max_runtime_call_stack_height() as usize,
194 ),
195 )
196 }
197}