casper_executor_wasm_interface/
executor.rs1use std::sync::Arc;
2
3use borsh::BorshSerialize;
4use bytes::Bytes;
5use casper_storage::{
6 global_state::{error::Error as GlobalStateError, GlobalStateReader},
7 tracking_copy::TrackingCopyCache,
8 AddressGenerator, TrackingCopy,
9};
10use casper_types::{
11 account::AccountHash, contract_messages::Messages, execution::Effects, BlockHash, BlockTime,
12 Digest, HashAddr, Key, TransactionHash,
13};
14use parking_lot::RwLock;
15use thiserror::Error;
16
17use crate::{CallError, GasUsage, InternalHostError, WasmPreparationError};
18
19pub struct ExecuteRequest {
21 pub initiator: AccountHash,
23 pub caller_key: Key,
27 pub gas_limit: u64,
29 pub execution_kind: ExecutionKind,
31 pub input: Bytes,
33 pub transferred_value: u64,
35 pub transaction_hash: TransactionHash,
37 pub address_generator: Arc<RwLock<AddressGenerator>>,
42 pub chain_name: Arc<str>,
46 pub block_time: BlockTime,
48 pub state_hash: Digest,
50 pub parent_block_hash: BlockHash,
52 pub block_height: u64,
54}
55
56#[derive(Default)]
58pub struct ExecuteRequestBuilder {
59 initiator: Option<AccountHash>,
60 caller_key: Option<Key>,
61 gas_limit: Option<u64>,
62 target: Option<ExecutionKind>,
63 input: Option<Bytes>,
64 value: Option<u64>,
65 transaction_hash: Option<TransactionHash>,
66 address_generator: Option<Arc<RwLock<AddressGenerator>>>,
67 chain_name: Option<Arc<str>>,
68 block_time: Option<BlockTime>,
69 state_hash: Option<Digest>,
70 parent_block_hash: Option<BlockHash>,
71 block_height: Option<u64>,
72}
73
74impl ExecuteRequestBuilder {
75 #[must_use]
77 pub fn with_initiator(mut self, initiator: AccountHash) -> Self {
78 self.initiator = Some(initiator);
79 self
80 }
81
82 #[must_use]
84 pub fn with_caller_key(mut self, caller_key: Key) -> Self {
85 self.caller_key = Some(caller_key);
86 self
87 }
88
89 #[must_use]
91 pub fn with_gas_limit(mut self, gas_limit: u64) -> Self {
92 self.gas_limit = Some(gas_limit);
93 self
94 }
95
96 #[must_use]
98 pub fn with_target(mut self, target: ExecutionKind) -> Self {
99 self.target = Some(target);
100 self
101 }
102
103 #[must_use]
105 pub fn with_input(mut self, input: Bytes) -> Self {
106 self.input = Some(input);
107 self
108 }
109
110 #[must_use]
112 pub fn with_serialized_input<T: BorshSerialize>(self, input: T) -> Self {
113 let input = borsh::to_vec(&input)
114 .map(Bytes::from)
115 .expect("should serialize input");
116 self.with_input(input)
117 }
118
119 #[must_use]
121 pub fn with_transferred_value(mut self, value: u64) -> Self {
122 self.value = Some(value);
123 self
124 }
125
126 #[must_use]
128 pub fn with_transaction_hash(mut self, transaction_hash: TransactionHash) -> Self {
129 self.transaction_hash = Some(transaction_hash);
130 self
131 }
132
133 #[must_use]
138 pub fn with_address_generator(mut self, address_generator: AddressGenerator) -> Self {
139 self.address_generator = Some(Arc::new(RwLock::new(address_generator)));
140 self
141 }
142
143 #[must_use]
148 pub fn with_shared_address_generator(
149 mut self,
150 address_generator: Arc<RwLock<AddressGenerator>>,
151 ) -> Self {
152 self.address_generator = Some(address_generator);
153 self
154 }
155
156 #[must_use]
158 pub fn with_chain_name<T: Into<Arc<str>>>(mut self, chain_name: T) -> Self {
159 self.chain_name = Some(chain_name.into());
160 self
161 }
162
163 #[must_use]
165 pub fn with_block_time(mut self, block_time: BlockTime) -> Self {
166 self.block_time = Some(block_time);
167 self
168 }
169
170 #[must_use]
172 pub fn with_state_hash(mut self, state_hash: Digest) -> Self {
173 self.state_hash = Some(state_hash);
174 self
175 }
176
177 #[must_use]
179 pub fn with_parent_block_hash(mut self, parent_block_hash: BlockHash) -> Self {
180 self.parent_block_hash = Some(parent_block_hash);
181 self
182 }
183
184 #[must_use]
186 pub fn with_block_height(mut self, block_height: u64) -> Self {
187 self.block_height = Some(block_height);
188 self
189 }
190
191 pub fn build(self) -> Result<ExecuteRequest, &'static str> {
193 let initiator = self.initiator.ok_or("Initiator is not set")?;
194 let caller_key = self.caller_key.ok_or("Caller is not set")?;
195 let gas_limit = self.gas_limit.ok_or("Gas limit is not set")?;
196 let execution_kind = self.target.ok_or("Target is not set")?;
197 let input = self.input.ok_or("Input is not set")?;
198 let transferred_value = self.value.ok_or("Value is not set")?;
199 let transaction_hash = self.transaction_hash.ok_or("Transaction hash is not set")?;
200 let address_generator = self
201 .address_generator
202 .ok_or("Address generator is not set")?;
203 let chain_name = self.chain_name.ok_or("Chain name is not set")?;
204 let block_time = self.block_time.ok_or("Block time is not set")?;
205 let state_hash = self.state_hash.ok_or("State hash is not set")?;
206 let parent_block_hash = self
207 .parent_block_hash
208 .ok_or("Parent block hash is not set")?;
209 let block_height = self.block_height.ok_or("Block height is not set")?;
210 Ok(ExecuteRequest {
211 initiator,
212 caller_key,
213 gas_limit,
214 execution_kind,
215 input,
216 transferred_value,
217 transaction_hash,
218 address_generator,
219 chain_name,
220 block_time,
221 state_hash,
222 parent_block_hash,
223 block_height,
224 })
225 }
226}
227
228#[derive(Debug)]
230pub struct ExecuteResult {
231 pub host_error: Option<CallError>,
233 pub output: Option<Bytes>,
235 pub gas_usage: GasUsage,
237 pub effects: Effects,
239 pub cache: TrackingCopyCache,
241 pub messages: Messages,
243}
244
245impl ExecuteResult {
246 pub fn effects(&self) -> &Effects {
248 &self.effects
249 }
250
251 pub fn into_effects(self) -> Effects {
252 self.effects
253 }
254
255 pub fn host_error(&self) -> Option<&CallError> {
256 self.host_error.as_ref()
257 }
258
259 pub fn output(&self) -> Option<&Bytes> {
260 self.output.as_ref()
261 }
262
263 pub fn gas_usage(&self) -> &GasUsage {
264 &self.gas_usage
265 }
266}
267
268#[derive(Debug)]
270pub struct ExecuteWithProviderResult {
271 pub host_error: Option<CallError>,
273 output: Option<Bytes>,
275 gas_usage: GasUsage,
277 effects: Effects,
279 post_state_hash: Digest,
281 messages: Messages,
283}
284
285impl ExecuteWithProviderResult {
286 #[must_use]
287 pub fn new(
288 host_error: Option<CallError>,
289 output: Option<Bytes>,
290 gas_usage: GasUsage,
291 effects: Effects,
292 post_state_hash: Digest,
293 messages: Messages,
294 ) -> Self {
295 Self {
296 host_error,
297 output,
298 gas_usage,
299 effects,
300 post_state_hash,
301 messages,
302 }
303 }
304
305 pub fn output(&self) -> Option<&Bytes> {
306 self.output.as_ref()
307 }
308
309 pub fn gas_usage(&self) -> &GasUsage {
310 &self.gas_usage
311 }
312
313 pub fn effects(&self) -> &Effects {
314 &self.effects
315 }
316
317 #[must_use]
318 pub fn post_state_hash(&self) -> Digest {
319 self.post_state_hash
320 }
321
322 pub fn messages(&self) -> &Messages {
323 &self.messages
324 }
325}
326
327#[derive(Debug, Clone, PartialEq, Eq)]
329pub enum ExecutionKind {
330 SessionBytes(Bytes),
332 Stored {
334 address: HashAddr,
336 entry_point: String,
338 },
339}
340
341#[derive(Debug, Error)]
346pub enum ExecuteError {
347 #[error("Wasm error error: {0}")]
351 WasmPreparation(#[from] WasmPreparationError),
352 #[error("Internal host error: {0}")]
354 InternalHost(#[from] InternalHostError),
355 #[error("Code not found")]
356 CodeNotFound(HashAddr),
357}
358
359#[derive(Debug, Error)]
360pub enum ExecuteWithProviderError {
361 #[error("Global state error: {0}")]
363 GlobalState(#[from] GlobalStateError),
364 #[error(transparent)]
365 Execute(#[from] ExecuteError),
366}
367
368pub trait Executor: Clone + Send {
376 fn execute<R: GlobalStateReader + 'static>(
377 &self,
378 tracking_copy: TrackingCopy<R>,
379 execute_request: ExecuteRequest,
380 ) -> Result<ExecuteResult, ExecuteError>;
381}