1pub mod install;
2pub(crate) mod system;
3
4use std::{
5 collections::{BTreeSet, VecDeque},
6 sync::Arc,
7};
8
9use bytes::Bytes;
10use casper_execution_engine::{
11 engine_state::{BlockInfo, Error as EngineError, ExecutableItem, ExecutionEngineV1},
12 execution::ExecError,
13};
14use casper_executor_wasm_common::{
15 chain_utils,
16 error::{CallError, TrapCode},
17 flags::ReturnFlags,
18};
19use casper_executor_wasm_host::context::Context;
20use casper_executor_wasm_interface::{
21 executor::{
22 ExecuteError, ExecuteRequest, ExecuteRequestBuilder, ExecuteResult,
23 ExecuteWithProviderError, ExecuteWithProviderResult, ExecutionKind, Executor,
24 },
25 ConfigBuilder, GasUsage, VMError, WasmInstance,
26};
27use casper_executor_wasmer_backend::WasmerEngine;
28use casper_storage::{
29 global_state::{
30 error::Error as GlobalStateError,
31 state::{CommitProvider, StateProvider},
32 GlobalStateReader,
33 },
34 TrackingCopy,
35};
36use casper_types::{
37 account::AccountHash,
38 addressable_entity::{ActionThresholds, AssociatedKeys},
39 bytesrepr, AddressableEntity, ByteCode, ByteCodeAddr, ByteCodeHash, ByteCodeKind,
40 ContractRuntimeTag, Digest, EntityAddr, EntityKind, Gas, Groups, InitiatorAddr, Key,
41 MessageLimits, Package, PackageHash, PackageStatus, Phase, ProtocolVersion, StorageCosts,
42 StoredValue, TransactionInvocationTarget, URef, WasmV2Config, U512,
43};
44use either::Either;
45use install::{InstallContractError, InstallContractRequest, InstallContractResult};
46use parking_lot::RwLock;
47use system::{MintArgs, MintTransferArgs};
48use tracing::{error, warn};
49
50const DEFAULT_WASM_ENTRY_POINT: &str = "call";
51
52const DEFAULT_MINT_TRANSFER_GAS_COST: u64 = 1; #[derive(Copy, Clone, Debug)]
55pub enum ExecutorKind {
56 Compiled,
60}
61
62#[derive(Copy, Clone, Debug)]
63pub struct ExecutorConfig {
64 memory_limit: u32,
65 executor_kind: ExecutorKind,
66 wasm_config: WasmV2Config,
67 storage_costs: StorageCosts,
68 message_limits: MessageLimits,
69}
70
71impl ExecutorConfigBuilder {
72 pub fn new() -> ExecutorConfigBuilder {
73 ExecutorConfigBuilder::default()
74 }
75}
76
77#[derive(Default)]
78pub struct ExecutorConfigBuilder {
79 memory_limit: Option<u32>,
80 executor_kind: Option<ExecutorKind>,
81 wasm_config: Option<WasmV2Config>,
82 storage_costs: Option<StorageCosts>,
83 message_limits: Option<MessageLimits>,
84}
85
86impl ExecutorConfigBuilder {
87 pub fn with_memory_limit(mut self, memory_limit: u32) -> Self {
89 self.memory_limit = Some(memory_limit);
90 self
91 }
92
93 pub fn with_executor_kind(mut self, executor_kind: ExecutorKind) -> Self {
95 self.executor_kind = Some(executor_kind);
96 self
97 }
98
99 pub fn with_wasm_config(mut self, wasm_config: WasmV2Config) -> Self {
101 self.wasm_config = Some(wasm_config);
102 self
103 }
104
105 pub fn with_storage_costs(mut self, storage_costs: StorageCosts) -> Self {
107 self.storage_costs = Some(storage_costs);
108 self
109 }
110
111 pub fn with_message_limits(mut self, message_limits: MessageLimits) -> Self {
113 self.message_limits = Some(message_limits);
114 self
115 }
116
117 pub fn build(self) -> Result<ExecutorConfig, &'static str> {
119 let memory_limit = self.memory_limit.ok_or("Memory limit is not set")?;
120 let executor_kind = self.executor_kind.ok_or("Executor kind is not set")?;
121 let wasm_config = self.wasm_config.ok_or("Wasm config is not set")?;
122 let storage_costs = self.storage_costs.ok_or("Storage costs are not set")?;
123 let message_limits = self.message_limits.ok_or("Message limits are not set")?;
124
125 Ok(ExecutorConfig {
126 memory_limit,
127 executor_kind,
128 wasm_config,
129 storage_costs,
130 message_limits,
131 })
132 }
133}
134
135#[derive(Clone)]
136pub struct ExecutorV2 {
137 config: ExecutorConfig,
138 compiled_wasm_engine: Arc<WasmerEngine>,
139 execution_stack: Arc<RwLock<VecDeque<ExecutionKind>>>,
140 execution_engine_v1: Arc<ExecutionEngineV1>,
141}
142
143impl ExecutorV2 {
144 pub fn install_contract<R>(
145 &self,
146 state_root_hash: Digest,
147 state_provider: &R,
148 install_request: InstallContractRequest,
149 ) -> Result<InstallContractResult, InstallContractError>
150 where
151 R: StateProvider + CommitProvider,
152 <R as StateProvider>::Reader: 'static,
153 {
154 let mut tracking_copy = match state_provider.checkout(state_root_hash) {
155 Ok(Some(tracking_copy)) => {
156 TrackingCopy::new(tracking_copy, 1, state_provider.enable_entity())
157 }
158 Ok(None) => {
159 return Err(InstallContractError::GlobalState(
160 GlobalStateError::RootNotFound,
161 ))
162 }
163 Err(error) => return Err(error.into()),
164 };
165
166 let InstallContractRequest {
167 initiator,
168 gas_limit,
169 wasm_bytes,
170 entry_point,
171 input,
172 transferred_value,
173 address_generator,
174 transaction_hash,
175 chain_name,
176 block_time,
177 seed,
178 state_hash,
179 parent_block_hash,
180 block_height,
181 } = install_request;
182
183 let bytecode_hash = chain_utils::compute_wasm_bytecode_hash(&wasm_bytes);
184
185 let caller_key = Key::Account(initiator);
186 let _source_purse = get_purse_for_entity(&mut tracking_copy, caller_key);
187
188 let smart_contract_addr: [u8; 32] = chain_utils::compute_predictable_address(
190 chain_name.as_bytes(),
191 initiator.value(),
192 bytecode_hash,
193 seed,
194 );
195
196 let mut smart_contract = Package::new(
197 Default::default(),
198 Default::default(),
199 Groups::default(),
200 PackageStatus::Unlocked,
201 );
202
203 let protocol_version = ProtocolVersion::V2_0_0;
204
205 let protocol_version_major = protocol_version.value().major;
206 let next_version = smart_contract.next_entity_version_for(protocol_version_major);
207 let entity_hash =
208 chain_utils::compute_next_contract_hash_version(smart_contract_addr, next_version);
209 let entity_version_key = smart_contract.insert_entity_version(
210 protocol_version_major,
211 EntityAddr::SmartContract(entity_hash),
212 );
213 debug_assert_eq!(entity_version_key.entity_version(), next_version);
214
215 let smart_contract_addr = chain_utils::compute_predictable_address(
216 chain_name.as_bytes(),
217 initiator.value(),
218 bytecode_hash,
219 seed,
220 );
221
222 tracking_copy.write(
223 Key::SmartContract(smart_contract_addr),
224 StoredValue::SmartContract(smart_contract),
225 );
226
227 let bytecode = ByteCode::new(ByteCodeKind::V2CasperWasm, wasm_bytes.clone().into());
230 let bytecode_addr = ByteCodeAddr::V2CasperWasm(bytecode_hash);
231
232 tracking_copy.write(
233 Key::ByteCode(bytecode_addr),
234 StoredValue::ByteCode(bytecode),
235 );
236
237 let addressable_entity_key = Key::AddressableEntity(EntityAddr::SmartContract(entity_hash));
239
240 let main_purse: URef = match system::mint_mint(
242 &mut tracking_copy,
243 transaction_hash,
244 Arc::clone(&address_generator),
245 MintArgs {
246 initial_balance: U512::zero(),
247 },
248 ) {
249 Ok(uref) => uref,
250 Err(mint_error) => {
251 error!(?mint_error, "Failed to create a purse");
252 return Err(InstallContractError::SystemContract(
253 CallError::CalleeTrapped(TrapCode::UnreachableCodeReached),
254 ));
255 }
256 };
257
258 let addressable_entity = AddressableEntity::new(
259 PackageHash::new(smart_contract_addr),
260 ByteCodeHash::new(bytecode_hash),
261 ProtocolVersion::V2_0_0,
262 main_purse,
263 AssociatedKeys::default(),
264 ActionThresholds::default(),
265 EntityKind::SmartContract(ContractRuntimeTag::VmCasperV2),
266 );
267
268 tracking_copy.write(
269 addressable_entity_key,
270 StoredValue::AddressableEntity(addressable_entity),
271 );
272
273 let ctor_gas_usage = match entry_point {
274 Some(entry_point_name) => {
275 let input = input.unwrap_or_default();
276 let execute_request = ExecuteRequestBuilder::default()
277 .with_initiator(initiator)
278 .with_caller_key(caller_key)
279 .with_target(ExecutionKind::Stored {
280 address: smart_contract_addr,
281 entry_point: entry_point_name,
282 })
283 .with_gas_limit(gas_limit)
284 .with_input(input)
285 .with_transferred_value(transferred_value)
286 .with_transaction_hash(transaction_hash)
287 .with_shared_address_generator(address_generator)
288 .with_chain_name(chain_name)
289 .with_block_time(block_time)
290 .with_state_hash(state_hash)
291 .with_parent_block_hash(parent_block_hash)
292 .with_block_height(block_height)
293 .build()
294 .expect("should build");
295
296 let forked_tc = tracking_copy.fork2();
297
298 match Self::execute_with_tracking_copy(self, forked_tc, execute_request) {
299 Ok(ExecuteResult {
300 host_error,
301 output,
302 gas_usage,
303 effects,
304 cache,
305 messages,
306 }) => {
307 if let Some(host_error) = host_error {
308 return Err(InstallContractError::Constructor { host_error });
309 }
310
311 tracking_copy.apply_changes(effects, cache, messages);
312
313 if let Some(output) = output {
314 warn!(?output, "unexpected output from constructor");
315 }
316
317 gas_usage
318 }
319 Err(error) => {
320 error!(%error, "unable to execute constructor");
321 return Err(InstallContractError::Execute(error));
322 }
323 }
324 }
325 None => {
326 GasUsage::new(gas_limit, gas_limit)
329 }
330 };
331
332 let effects = tracking_copy.effects();
333
334 match state_provider.commit_effects(state_root_hash, effects.clone()) {
335 Ok(post_state_hash) => Ok(InstallContractResult {
336 smart_contract_addr,
337 gas_usage: ctor_gas_usage,
338 effects,
339 post_state_hash,
340 }),
341 Err(error) => Err(InstallContractError::GlobalState(error)),
342 }
343 }
344
345 fn execute_with_tracking_copy<R: GlobalStateReader + 'static>(
346 &self,
347 mut tracking_copy: TrackingCopy<R>,
348 execute_request: ExecuteRequest,
349 ) -> Result<ExecuteResult, ExecuteError> {
350 let ExecuteRequest {
351 initiator,
352 caller_key,
353 gas_limit,
354 execution_kind,
355 input,
356 transferred_value,
357 transaction_hash,
358 address_generator,
359 chain_name,
360 block_time,
361 state_hash,
362 parent_block_hash,
363 block_height,
364 } = execute_request;
365
366 let source_purse = get_purse_for_entity(&mut tracking_copy, caller_key);
369
370 let (wasm_bytes, export_or_selector): (_, Either<&str, u32>) = match &execution_kind {
371 ExecutionKind::SessionBytes(wasm_bytes) => {
372 (wasm_bytes.clone(), Either::Left(DEFAULT_WASM_ENTRY_POINT))
374 }
375 ExecutionKind::Stored {
376 address: smart_contract_addr,
377 entry_point,
378 } => {
379 let smart_contract_key = Key::SmartContract(*smart_contract_addr);
380 let legacy_key = Key::Hash(*smart_contract_addr);
381
382 let mut contract = tracking_copy
383 .read_first(&[&legacy_key, &smart_contract_key])
384 .expect("should read contract");
385
386 if let Some(StoredValue::SmartContract(smart_contract_package)) = &contract {
392 let contract_hash = smart_contract_package
393 .versions()
394 .latest()
395 .expect("should have last entry");
396 let entity_addr = EntityAddr::SmartContract(contract_hash.value());
397 let latest_version_key = Key::AddressableEntity(entity_addr);
398 assert_ne!(&entity_addr.value(), smart_contract_addr);
399 let new_contract = tracking_copy
400 .read(&latest_version_key)
401 .expect("should read latest version");
402 contract = new_contract;
403 };
404
405 match contract {
406 Some(StoredValue::AddressableEntity(addressable_entity)) => {
407 let wasm_key = match addressable_entity.kind() {
408 EntityKind::System(_) => todo!(),
409 EntityKind::Account(_) => todo!(),
410 EntityKind::SmartContract(ContractRuntimeTag::VmCasperV1) => {
411 let block_info = BlockInfo::new(
415 state_hash,
416 block_time,
417 parent_block_hash,
418 block_height,
419 self.execution_engine_v1.config().protocol_version(),
420 );
421
422 let entity_addr = EntityAddr::SmartContract(*smart_contract_addr);
423
424 return self.execute_legacy_wasm_byte_code(
425 initiator,
426 &entity_addr,
427 entry_point.clone(),
428 &input,
429 &mut tracking_copy,
430 block_info,
431 transaction_hash,
432 gas_limit,
433 );
434 }
435 EntityKind::SmartContract(ContractRuntimeTag::VmCasperV2) => {
436 Key::ByteCode(ByteCodeAddr::V2CasperWasm(
437 addressable_entity.byte_code_addr(),
438 ))
439 }
440 };
441
442 let wasm_bytes = tracking_copy
446 .read(&wasm_key)
447 .expect("should read wasm")
448 .expect("should have wasm bytes")
449 .into_byte_code()
450 .expect("should be byte code")
451 .take_bytes();
452
453 if transferred_value != 0 {
454 let args = {
455 let maybe_to = None;
456 let source = source_purse;
457 let target = addressable_entity.main_purse();
458 let amount = transferred_value;
459 let id = None;
460 MintTransferArgs {
461 maybe_to,
462 source,
463 target,
464 amount: amount.into(),
465 id,
466 }
467 };
468
469 match system::mint_transfer(
470 &mut tracking_copy,
471 transaction_hash,
472 Arc::clone(&address_generator),
473 args,
474 ) {
475 Ok(()) => {
476 }
478 Err(error) => {
479 return Ok(ExecuteResult {
480 host_error: Some(error),
481 output: None,
482 gas_usage: GasUsage::new(
483 gas_limit,
484 gas_limit - DEFAULT_MINT_TRANSFER_GAS_COST,
485 ),
486 effects: tracking_copy.effects(),
487 cache: tracking_copy.cache(),
488 messages: tracking_copy.messages(),
489 });
490 }
491 }
492 }
493
494 (Bytes::from(wasm_bytes), Either::Left(entry_point.as_str()))
495 }
496 Some(StoredValue::Contract(_legacy_contract)) => {
497 let block_info = BlockInfo::new(
498 state_hash,
499 block_time,
500 parent_block_hash,
501 block_height,
502 self.execution_engine_v1.config().protocol_version(),
503 );
504
505 let entity_addr = EntityAddr::SmartContract(*smart_contract_addr);
506
507 return self.execute_legacy_wasm_byte_code(
508 initiator,
509 &entity_addr,
510 entry_point.clone(),
511 &input,
512 &mut tracking_copy,
513 block_info,
514 transaction_hash,
515 gas_limit,
516 );
517 }
518 Some(stored_value) => {
519 todo!(
520 "Unexpected {stored_value:?} under key {:?}",
521 &execution_kind
522 );
523 }
524 None => {
525 panic!("No code found in {smart_contract_key:?}");
526 }
527 }
528 }
529 };
530
531 let vm = Arc::clone(&self.compiled_wasm_engine);
532
533 let mut initial_tracking_copy = tracking_copy.fork2();
534
535 let callee_key = match &execution_kind {
537 ExecutionKind::Stored {
538 address: smart_contract_addr,
539 ..
540 } => Key::SmartContract(*smart_contract_addr),
541 ExecutionKind::SessionBytes(_wasm_bytes) => Key::Account(initiator),
542 };
543
544 let context = Context {
545 initiator,
546 config: self.config.wasm_config,
547 storage_costs: self.config.storage_costs,
548 caller: caller_key,
549 callee: callee_key,
550 transferred_value,
551 tracking_copy,
552 executor: self.clone(),
553 address_generator: Arc::clone(&address_generator),
554 transaction_hash,
555 chain_name,
556 input,
557 block_time,
558 message_limits: self.config.message_limits,
559 };
560
561 let wasm_instance_config = ConfigBuilder::new()
562 .with_gas_limit(gas_limit)
563 .with_memory_limit(self.config.memory_limit)
564 .build();
565
566 let mut instance = vm.instantiate(wasm_bytes, context, wasm_instance_config)?;
567
568 self.push_execution_stack(execution_kind.clone());
569 let (vm_result, gas_usage) = match export_or_selector {
570 Either::Left(export_name) => instance.call_export(export_name),
571 Either::Right(_entry_point) => todo!("Restore selectors"), };
574
575 let top_execution_kind = self
576 .pop_execution_stack()
577 .expect("should have execution kind"); debug_assert_eq!(&top_execution_kind, &execution_kind);
579
580 let context = instance.teardown();
581
582 let Context {
583 tracking_copy: final_tracking_copy,
584 ..
585 } = context;
586
587 match vm_result {
588 Ok(()) => Ok(ExecuteResult {
589 host_error: None,
590 output: None,
591 gas_usage,
592 effects: final_tracking_copy.effects(),
593 cache: final_tracking_copy.cache(),
594 messages: final_tracking_copy.messages(),
595 }),
596 Err(VMError::Return { flags, data }) => {
597 let host_error = if flags.contains(ReturnFlags::REVERT) {
598 Some(CallError::CalleeReverted)
600 } else {
601 initial_tracking_copy.apply_changes(
603 final_tracking_copy.effects(),
604 final_tracking_copy.cache(),
605 final_tracking_copy.messages(),
606 );
607
608 None
609 };
610
611 Ok(ExecuteResult {
612 host_error,
613 output: data,
614 gas_usage,
615 effects: initial_tracking_copy.effects(),
616 cache: initial_tracking_copy.cache(),
617 messages: initial_tracking_copy.messages(),
618 })
619 }
620 Err(VMError::OutOfGas) => Ok(ExecuteResult {
621 host_error: Some(CallError::CalleeGasDepleted),
622 output: None,
623 gas_usage,
624 effects: final_tracking_copy.effects(),
625 cache: final_tracking_copy.cache(),
626 messages: final_tracking_copy.messages(),
627 }),
628 Err(VMError::Trap(trap_code)) => Ok(ExecuteResult {
629 host_error: Some(CallError::CalleeTrapped(trap_code)),
630 output: None,
631 gas_usage,
632 effects: initial_tracking_copy.effects(),
633 cache: initial_tracking_copy.cache(),
634 messages: initial_tracking_copy.messages(),
635 }),
636 Err(VMError::Export(export_error)) => {
637 error!(?export_error, "export error");
638 Ok(ExecuteResult {
639 host_error: Some(CallError::NotCallable),
640 output: None,
641 gas_usage,
642 effects: initial_tracking_copy.effects(),
643 cache: initial_tracking_copy.cache(),
644 messages: initial_tracking_copy.messages(),
645 })
646 }
647 Err(VMError::Internal(host_error)) => {
648 error!(?host_error, "host error");
649 Ok(ExecuteResult {
650 host_error: Some(CallError::InternalHost),
651 output: None,
652 gas_usage,
653 effects: initial_tracking_copy.effects(),
654 cache: initial_tracking_copy.cache(),
655 messages: initial_tracking_copy.messages(),
656 })
657 }
658 }
659 }
660
661 #[allow(clippy::too_many_arguments)]
662 fn execute_legacy_wasm_byte_code<R>(
663 &self,
664 initiator: AccountHash,
665 entity_addr: &EntityAddr,
666 entry_point: String,
667 input: &Bytes,
668 tracking_copy: &mut TrackingCopy<R>,
669 block_info: BlockInfo,
670 transaction_hash: casper_types::TransactionHash,
671 gas_limit: u64,
672 ) -> Result<ExecuteResult, ExecuteError>
673 where
674 R: GlobalStateReader + 'static,
675 {
676 let authorization_keys = BTreeSet::from_iter([initiator]);
677 let initiator_addr = InitiatorAddr::AccountHash(initiator);
678 let executable_item =
679 ExecutableItem::Invocation(TransactionInvocationTarget::ByHash(entity_addr.value()));
680 let entry_point = entry_point.clone();
681 let args = bytesrepr::deserialize_from_slice(input).expect("should deserialize");
682 let phase = Phase::Session;
683
684 let wasm_v1_result = {
685 let forked_tc = tracking_copy.fork2();
686 self.execution_engine_v1.execute_with_tracking_copy(
687 forked_tc,
688 block_info,
689 transaction_hash,
690 Gas::from(gas_limit),
691 initiator_addr,
692 executable_item,
693 entry_point,
694 args,
695 authorization_keys,
696 phase,
697 )
698 };
699
700 let effects = wasm_v1_result.effects();
701 let messages = wasm_v1_result.messages();
702
703 match wasm_v1_result.cache() {
704 Some(cache) => {
705 tracking_copy.apply_changes(effects.clone(), cache.clone(), messages.clone());
706 }
707 None => {
708 debug_assert!(
709 effects.is_empty(),
710 "effects should be empty if there is no cache"
711 );
712 }
713 }
714
715 let gas_consumed = wasm_v1_result
716 .consumed()
717 .value()
718 .try_into()
719 .expect("Should convert consumed gas to u64");
720
721 let mut output = wasm_v1_result
722 .ret()
723 .map(|ret| bytesrepr::serialize(ret).unwrap())
724 .map(Bytes::from);
725
726 let host_error = match wasm_v1_result.error() {
727 Some(EngineError::Exec(ExecError::GasLimit)) => Some(CallError::CalleeGasDepleted),
728 Some(EngineError::Exec(ExecError::Revert(revert_code))) => {
729 assert!(output.is_none(), "output should be None"); let revert_code: u32 = (*revert_code).into();
731 output = Some(revert_code.to_le_bytes().to_vec().into()); Some(CallError::CalleeReverted)
733 }
734 Some(_) => Some(CallError::CalleeTrapped(TrapCode::UnreachableCodeReached)),
735 None => None,
736 };
737
738 let remaining_points = gas_limit.checked_sub(gas_consumed).unwrap();
747
748 let fork2 = tracking_copy.fork2();
749 Ok(ExecuteResult {
750 host_error,
751 output,
752 gas_usage: GasUsage::new(gas_limit, remaining_points),
753 effects: fork2.effects(),
754 cache: fork2.cache(),
755 messages: fork2.messages(),
756 })
757 }
758
759 pub fn execute_with_provider<R>(
760 &self,
761 state_root_hash: Digest,
762 state_provider: &R,
763 execute_request: ExecuteRequest,
764 ) -> Result<ExecuteWithProviderResult, ExecuteWithProviderError>
765 where
766 R: StateProvider + CommitProvider,
767 <R as StateProvider>::Reader: 'static,
768 {
769 let tracking_copy = match state_provider.checkout(state_root_hash) {
770 Ok(Some(tracking_copy)) => tracking_copy,
771 Ok(None) => {
772 return Err(ExecuteWithProviderError::GlobalState(
773 GlobalStateError::RootNotFound,
774 ))
775 }
776 Err(global_state_error) => return Err(global_state_error.into()),
777 };
778
779 let tracking_copy = TrackingCopy::new(tracking_copy, 1, state_provider.enable_entity());
780
781 match self.execute_with_tracking_copy(tracking_copy, execute_request) {
782 Ok(ExecuteResult {
783 host_error,
784 output,
785 gas_usage,
786 effects,
787 cache: _,
788 messages,
789 }) => match state_provider.commit_effects(state_root_hash, effects.clone()) {
790 Ok(post_state_hash) => Ok(ExecuteWithProviderResult::new(
791 host_error,
792 output,
793 gas_usage,
794 effects,
795 post_state_hash,
796 messages,
797 )),
798 Err(error) => Err(error.into()),
799 },
800 Err(error) => Err(ExecuteWithProviderError::Execute(error)),
801 }
802 }
803}
804
805impl ExecutorV2 {
806 pub fn new(config: ExecutorConfig, execution_engine_v1: Arc<ExecutionEngineV1>) -> Self {
808 let wasm_engine = match config.executor_kind {
809 ExecutorKind::Compiled => WasmerEngine::new(),
810 };
811 ExecutorV2 {
812 config,
813 compiled_wasm_engine: Arc::new(wasm_engine),
814 execution_stack: Default::default(),
815 execution_engine_v1,
816 }
817 }
818
819 pub(crate) fn push_execution_stack(&self, execution_kind: ExecutionKind) {
821 let mut execution_stack = self.execution_stack.write();
822 execution_stack.push_back(execution_kind);
823 }
824
825 pub(crate) fn pop_execution_stack(&self) -> Option<ExecutionKind> {
827 let mut execution_stack = self.execution_stack.write();
828 execution_stack.pop_back()
829 }
830}
831
832impl Executor for ExecutorV2 {
833 fn execute<R: GlobalStateReader + 'static>(
841 &self,
842 tracking_copy: TrackingCopy<R>,
843 execute_request: ExecuteRequest,
844 ) -> Result<ExecuteResult, ExecuteError> {
845 self.execute_with_tracking_copy(tracking_copy, execute_request)
846 }
847}
848
849fn get_purse_for_entity<R: GlobalStateReader>(
850 tracking_copy: &mut TrackingCopy<R>,
851 entity_key: Key,
852) -> casper_types::URef {
853 let stored_value = tracking_copy
854 .read(&entity_key)
855 .expect("should read account")
856 .expect("should have account");
857 match stored_value {
858 StoredValue::CLValue(addressable_entity_key) => {
859 let key = addressable_entity_key
860 .into_t::<Key>()
861 .expect("should be key");
862 let stored_value = tracking_copy
863 .read(&key)
864 .expect("should read account")
865 .expect("should have account");
866
867 let addressable_entity = stored_value
868 .into_addressable_entity()
869 .expect("should be addressable entity");
870
871 addressable_entity.main_purse()
872 }
873 StoredValue::Account(account) => account.main_purse(),
874 StoredValue::SmartContract(smart_contract_package) => {
875 let contract_hash = smart_contract_package
876 .versions()
877 .latest()
878 .expect("should have last entry");
879 let entity_addr = EntityAddr::SmartContract(contract_hash.value());
880 let latest_version_key = Key::AddressableEntity(entity_addr);
881 let new_contract = tracking_copy
882 .read(&latest_version_key)
883 .expect("should read latest version");
884 let addressable_entity = new_contract
885 .expect("should have addressable entity")
886 .into_addressable_entity()
887 .expect("should be addressable entity");
888 addressable_entity.main_purse()
889 }
890 other => panic!("should be account or contract received {other:?}"),
891 }
892}