ceres_executor/
result.rs

1//! Ceres executor result
2use crate::{
3    trap::{Trap, TrapCode},
4    Value,
5};
6use ceres_std::{fmt, format, String, Vec};
7use parity_scale_codec::{Decode, Encode};
8
9bitflags::bitflags! {
10    /// Flags used by a contract to customize exit behaviour.
11    #[derive(Encode, Decode, Default)]
12    pub struct ReturnFlags: u32 {
13        /// If this bit is set all changes made by the contract execution are rolled back.
14        const REVERT = 0x0000_0001;
15    }
16}
17
18/// Successful Return data
19#[derive(PartialEq, Eq, Debug, Clone, Default, Encode, Decode)]
20pub struct ReturnData {
21    /// Flags passed along by `seal_return`. Empty when `seal_return` was never called.
22    pub flags: ReturnFlags,
23    /// Buffer passed along by `seal_return`. Empty when `seal_return` was never called.
24    pub data: Vec<u8>,
25}
26
27#[repr(i32)]
28#[derive(Debug, PartialEq, Eq, Clone, Copy)]
29pub enum ReturnCode {
30    /// API call successful.
31    Success = 0,
32    /// The called function trapped and has its state changes reverted.
33    /// In this case no output buffer is returned.
34    CalleeTrapped = 1,
35    /// The called function ran to completion but decided to revert its state.
36    /// An output buffer is returned when one was supplied.
37    CalleeReverted = 2,
38    /// The passed key does not exist in storage.
39    KeyNotFound = 3,
40    /// Transfer failed because it would have brought the sender's total balance below the
41    /// subsistence threshold.
42    BelowSubsistenceThreshold = 4,
43    /// Transfer failed for other reasons. Most probably reserved or locked balance of the
44    /// sender prevents the transfer.
45    TransferFailed = 5,
46    /// The newly created contract is below the subsistence threshold after executing
47    /// its constructor.
48    NewContractNotFunded = 6,
49    /// No code could be found at the supplied code hash.
50    CodeNotFound = 7,
51    /// The contract that was called is either no contract at all (a plain account)
52    /// or is a tombstone.
53    NotCallable = 8,
54    /// The call to `seal_debug_message` had no effect because debug message
55    /// recording was disabled.
56    LoggingDisabled = 9,
57    /// Unexpected return code
58    UnExpectedReturnCode = 10,
59}
60
61impl From<i32> for ReturnCode {
62    fn from(n: i32) -> ReturnCode {
63        match n {
64            0 => ReturnCode::Success,
65            1 => ReturnCode::CalleeTrapped,
66            2 => ReturnCode::CalleeReverted,
67            3 => ReturnCode::KeyNotFound,
68            4 => ReturnCode::BelowSubsistenceThreshold,
69            5 => ReturnCode::TransferFailed,
70            6 => ReturnCode::NewContractNotFunded,
71            7 => ReturnCode::CodeNotFound,
72            8 => ReturnCode::NotCallable,
73            9 => ReturnCode::LoggingDisabled,
74            _ => ReturnCode::UnExpectedReturnCode,
75        }
76    }
77}
78
79/// Ceres executor errors
80#[derive(Debug, Eq, PartialEq, Clone)]
81pub enum Error {
82    InitMemoryFailed,
83    /// Memory outof bounds
84    OutOfBounds,
85    InitModuleFailed,
86    ExecuteFailed(ReturnCode),
87    UnkownError,
88    Trap(Trap),
89    GetFunctionNameFailed,
90    CreateWasmtimeConfigFailed,
91    GetExternalFailed(String),
92    DecodeRuntimeValueFailed,
93    OutputBufferTooSmall,
94    WrongArugmentLength,
95    SetStorageFailed,
96    Return(ReturnData),
97    /// Topics
98    TooManyTopics,
99    DuplicateTopics,
100    TopicValueTooLarge,
101    /// Gas
102    OutOfGas,
103    /// Custom Error
104    Custom(&'static str),
105    /// Unexpected return value
106    UnExpectedReturnValue,
107    ParseWasmModuleFailed,
108    ExecutorNotInited,
109    CodeNotFound,
110    ExitedAllFrames,
111    CalcuateMemoryLimitFailed,
112    InitExecutorFailed,
113    DecodeBucketFailed([u8; 32]),
114    MemoryNotFound,
115    SerializationError(String),
116    StateNotFound,
117    CodeHashNotFound,
118    DecodeContractFailed,
119    FlushDataFailed,
120}
121
122impl From<parity_wasm::SerializationError> for Error {
123    fn from(e: parity_wasm::SerializationError) -> Error {
124        Error::SerializationError(format!("{}", e))
125    }
126}
127
128impl From<&'static str> for Error {
129    fn from(e: &'static str) -> Error {
130        Error::Custom(e)
131    }
132}
133
134#[cfg(feature = "wasmtime")]
135impl std::error::Error for Error {}
136
137impl fmt::Display for Error {
138    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139        write!(f, "{:?}", self)
140    }
141}
142
143/// Ceres executor result
144pub type Result<T> = core::result::Result<T, Error>;
145
146/// Wasm function execution result
147#[derive(Clone, Default)]
148pub struct ExecResult {
149    pub data: ReturnData,
150    pub value: Value,
151}
152
153impl ExecResult {
154    /// from execution result
155    pub fn from_res(v: Result<Value>) -> Result<ExecResult> {
156        Ok(match v {
157            Ok(value) => ExecResult {
158                value,
159                ..Default::default()
160            },
161            Err(Error::Trap(Trap {
162                code: TrapCode::HostError(e),
163                trace: _,
164            })) => Self::from_res(Err(*e))?,
165            Err(Error::Return(data)) => {
166                if data.flags.contains(ReturnFlags::REVERT) {
167                    return Err(Error::ExecuteFailed(ReturnCode::CalleeReverted));
168                }
169                ExecResult {
170                    data,
171                    ..Default::default()
172                }
173            }
174            Err(e) => return Err(e),
175        })
176    }
177}