cfx_executor/stack/
executable.rs1use super::{FrameLocal, Resumable};
2use crate::{
3 builtin::BuiltinExec, context::Context, executive_observer::TracerTrait,
4 internal_contract::InternalContractExec,
5};
6use cfx_statedb::Result as DbResult;
7use cfx_types::{AddressSpaceUtil, U256};
8use cfx_vm_interpreter::{FinalizationResult, Finalize};
9use cfx_vm_types::{
10 self as vm, separate_out_db_error, ActionParams, Exec, GasLeft, ReturnData,
11 TrapError, TrapResult,
12};
13
14pub trait Executable: Send {
26 fn execute(
27 self: Box<Self>, context: Context,
28 ) -> DbResult<ExecutableOutcome>;
29}
30
31pub enum ExecutableOutcome {
36 Return(vm::Result<FinalizationResult>),
38 Invoke(ActionParams, Box<dyn Resumable>),
41}
42use ExecutableOutcome::*;
43
44pub fn make_executable<'a>(
48 frame_local: &FrameLocal<'a>, params: ActionParams,
49 tracer: &mut dyn TracerTrait,
50) -> Box<dyn 'a + Executable> {
51 let is_create = frame_local.create_address.is_some();
52 let code_address = params.code_address.with_space(params.space);
53 let internal_contract_map = frame_local.machine.internal_contracts();
54
55 if let Some(builtin) = frame_local
57 .machine
58 .builtin(&code_address, frame_local.env.number)
59 {
60 trace!("CallBuiltin");
61 return Box::new(BuiltinExec { builtin, params });
62 }
63
64 if let Some(internal) =
65 internal_contract_map.contract(&code_address, &frame_local.spec)
66 {
67 trace!(
68 "CallInternalContract: address={:?} data={:?}",
69 code_address,
70 params.data
71 );
72 return Box::new(InternalContractExec { internal, params });
73 }
74
75 if is_create || params.code.is_some() {
76 trace!("CallCreate");
77
78 tracer.initialize_interp(params.gas.clone());
80
81 let factory = frame_local.machine.vm_factory_ref();
82 Box::new(factory.create(params, frame_local.spec, frame_local.depth))
83 } else {
84 trace!("Transfer");
85 Box::new(NoopExec { gas: params.gas })
86 }
87}
88
89impl Executable for Box<dyn Exec> {
90 fn execute(
91 self: Box<Self>, mut context: Context,
92 ) -> DbResult<ExecutableOutcome> {
93 Ok(match self.exec(&mut context) {
94 TrapResult::Return(result) => {
95 let result = separate_out_db_error(result)?;
96 if matches!(result, Ok(GasLeft::Known(_))) {
101 context.insert_create_address_to_substate();
102 }
103 Return(result.finalize(context))
104 }
105 TrapResult::SubCallCreate(TrapError::Call(params, resume)) => {
106 Invoke(params, Box::new(resume))
107 }
108 TrapResult::SubCallCreate(TrapError::Create(params, resume)) => {
109 Invoke(params, Box::new(resume))
110 }
111 })
112 }
113}
114
115pub struct NoopExec {
116 pub gas: U256,
117}
118
119impl Executable for NoopExec {
120 fn execute(self: Box<Self>, _: Context) -> DbResult<ExecutableOutcome> {
121 let result = FinalizationResult {
122 gas_left: self.gas,
123 apply_state: true,
124 return_data: ReturnData::empty(),
125 };
126 Ok(Return(Ok(result)))
127 }
128}