cfx_executor/stack/
resumable.rs

1use super::{Executable, FrameResult, FrameReturn};
2use cfx_vm_types::{
3    ContractCreateResult, MessageCallResult, ResumeCall, ResumeCreate,
4};
5
6/// `Resumable` is a trait representing objects for resuming the execution of a
7/// frame, which is suspended due to the invocation of another frame. The caller
8/// frame is resumed when the callee frame returns.
9pub trait Resumable: Send {
10    fn resume(self: Box<Self>, result: FrameResult) -> Box<dyn Executable>;
11}
12
13impl Resumable for Box<dyn ResumeCall> {
14    fn resume(self: Box<Self>, result: FrameResult) -> Box<dyn Executable> {
15        let result = into_message_call_result(result);
16        Box::new(self.resume_call(result))
17    }
18}
19
20impl Resumable for Box<dyn ResumeCreate> {
21    fn resume(self: Box<Self>, result: FrameResult) -> Box<dyn Executable> {
22        let result = into_contract_create_result(result);
23        Box::new(self.resume_create(result))
24    }
25}
26
27/// Converts the execution result of a frame into the format expected by the VM.
28fn into_message_call_result(result: FrameResult) -> MessageCallResult {
29    match result {
30        Ok(FrameReturn {
31            gas_left,
32            return_data,
33            apply_state: true,
34            ..
35        }) => MessageCallResult::Success(gas_left, return_data),
36        Ok(FrameReturn {
37            gas_left,
38            return_data,
39            apply_state: false,
40            ..
41        }) => MessageCallResult::Reverted(gas_left, return_data),
42        Err(err) => MessageCallResult::Failed(err),
43    }
44}
45
46/// Converts the execution result of a frame into the format expected by the VM.
47fn into_contract_create_result(result: FrameResult) -> ContractCreateResult {
48    match result {
49        Ok(FrameReturn {
50            gas_left,
51            apply_state: true,
52            create_address,
53            ..
54        }) => {
55            // Move the change of contracts_created in substate to
56            // process_return.
57            let address = create_address
58                .expect("ExecutiveResult for Create executive should be some.");
59            ContractCreateResult::Created(address, gas_left)
60        }
61        Ok(FrameReturn {
62            gas_left,
63            apply_state: false,
64            return_data,
65            ..
66        }) => ContractCreateResult::Reverted(gas_left, return_data),
67        Err(err) => ContractCreateResult::Failed(err),
68    }
69}