1use actor_system_error::actor_system_error;
20use gear_core::{
21 buffer::PanicBuffer,
22 env::MessageWaitedType,
23 gas::{ChargeError, CounterType},
24 ids::ActorId,
25};
26use gear_core_errors::ExtError as FallibleExtError;
27use parity_scale_codec::{Decode, Encode};
28
29actor_system_error! {
30 pub type TerminationReason = ActorSystemError<ActorTerminationReason, SystemTerminationReason>;
31}
32
33#[derive(Debug, Clone, Eq, PartialEq, derive_more::From)]
34pub enum UndefinedTerminationReason {
35 Actor(ActorTerminationReason),
36 System(SystemTerminationReason),
37 ProcessAccessErrorResourcesExceed,
39}
40
41impl UndefinedTerminationReason {
42 pub fn define(self, current_counter: CounterType) -> TerminationReason {
43 match self {
44 Self::Actor(r) => r.into(),
45 Self::System(r) => r.into(),
46 Self::ProcessAccessErrorResourcesExceed => {
47 ActorTerminationReason::from(current_counter).into()
48 }
49 }
50 }
51}
52
53impl From<ChargeError> for UndefinedTerminationReason {
54 fn from(err: ChargeError) -> Self {
55 match err {
56 ChargeError::GasLimitExceeded => {
57 ActorTerminationReason::Trap(TrapExplanation::GasLimitExceeded).into()
58 }
59 ChargeError::GasAllowanceExceeded => {
60 ActorTerminationReason::GasAllowanceExceeded.into()
61 }
62 }
63 }
64}
65
66impl From<TrapExplanation> for UndefinedTerminationReason {
67 fn from(trap: TrapExplanation) -> Self {
68 ActorTerminationReason::Trap(trap).into()
69 }
70}
71
72impl<E: BackendSyscallError> From<E> for UndefinedTerminationReason {
73 fn from(err: E) -> Self {
74 err.into_termination_reason()
75 }
76}
77
78#[derive(Decode, Encode, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, derive_more::From)]
79pub enum ActorTerminationReason {
80 Exit(ActorId),
81 Leave,
82 Success,
83 Wait(Option<u32>, MessageWaitedType),
84 GasAllowanceExceeded,
85 Trap(TrapExplanation),
86}
87
88impl From<CounterType> for ActorTerminationReason {
89 fn from(counter_type: CounterType) -> Self {
90 match counter_type {
91 CounterType::GasLimit => Self::Trap(TrapExplanation::GasLimitExceeded),
92 CounterType::GasAllowance => Self::GasAllowanceExceeded,
93 }
94 }
95}
96
97#[derive(Debug, Clone, Eq, PartialEq, derive_more::Display)]
103pub struct SystemTerminationReason;
104
105#[derive(
107 Decode,
108 Encode,
109 Debug,
110 Clone,
111 Eq,
112 PartialEq,
113 PartialOrd,
114 Ord,
115 derive_more::Display,
116 derive_more::From,
117)]
118pub enum UnrecoverableExecutionError {
119 #[display("Invalid debug string passed in `gr_debug` syscall")]
120 InvalidDebugString,
121 #[display("Not enough gas for operation")]
122 NotEnoughGas,
123 #[display("Cannot take data in payload range from message with size")]
124 ReadWrongRange,
125 #[display("Unsupported version of environment variables encountered")]
126 UnsupportedEnvVarsVersion,
127 #[display("Length is overflowed to read panic payload")]
128 PanicBufferIsTooBig,
129}
130
131#[derive(
133 Decode,
134 Encode,
135 Debug,
136 Clone,
137 Eq,
138 PartialEq,
139 PartialOrd,
140 Ord,
141 derive_more::Display,
142 derive_more::From,
143)]
144pub enum UnrecoverableMemoryError {
145 #[display("Trying to access memory outside wasm program memory")]
147 AccessOutOfBounds,
148 #[display("Trying to allocate more memory in block-chain runtime than allowed")]
150 RuntimeAllocOutOfBounds,
151}
152
153#[derive(
155 Decode,
156 Encode,
157 Debug,
158 Clone,
159 Eq,
160 PartialEq,
161 PartialOrd,
162 Ord,
163 derive_more::Display,
164 derive_more::From,
165)]
166pub enum UnrecoverableWaitError {
167 #[display("Waiting duration cannot be zero")]
169 ZeroDuration,
170 #[display("`wait()` is not allowed after reply sent")]
172 WaitAfterReply,
173}
174
175#[derive(
176 Decode,
177 Encode,
178 Debug,
179 Clone,
180 Eq,
181 PartialEq,
182 PartialOrd,
183 Ord,
184 derive_more::Display,
185 derive_more::From,
186)]
187pub enum UnrecoverableExtError {
188 #[display("Execution error: {_0}")]
189 Execution(UnrecoverableExecutionError),
190 #[display("Memory error: {_0}")]
191 Memory(UnrecoverableMemoryError),
192 #[display("Waiting error: {_0}")]
193 Wait(UnrecoverableWaitError),
194}
195
196#[derive(
197 Decode,
198 Encode,
199 Debug,
200 Clone,
201 PartialEq,
202 Eq,
203 PartialOrd,
204 Ord,
205 derive_more::Display,
206 derive_more::From,
207)]
208pub enum TrapExplanation {
209 #[display("Not enough gas to continue execution")]
211 GasLimitExceeded,
212 #[display("Unable to call a forbidden function")]
214 ForbiddenFunction,
215 #[display("Trying to allocate more wasm program memory than allowed")]
218 ProgramAllocOutOfBounds,
219 #[display("Syscall unrecoverable error: {_0}")]
220 UnrecoverableExt(UnrecoverableExtError),
221 #[display("Panic occurred: {_0}")]
222 Panic(PanicBuffer),
223 #[display("Stack limit exceeded")]
224 StackLimitExceeded,
225 #[display("Reason is unknown. Possibly `unreachable` instruction is occurred")]
226 Unknown,
227}
228
229#[derive(Debug, Clone)]
231pub enum RunFallibleError {
232 UndefinedTerminationReason(UndefinedTerminationReason),
233 FallibleExt(FallibleExtError),
234}
235
236impl<E> From<E> for RunFallibleError
237where
238 E: BackendSyscallError,
239{
240 fn from(err: E) -> Self {
241 err.into_run_fallible_error()
242 }
243}
244
245pub trait BackendSyscallError: Sized {
248 fn into_termination_reason(self) -> UndefinedTerminationReason;
249
250 fn into_run_fallible_error(self) -> RunFallibleError;
251}
252
253pub trait BackendAllocSyscallError: Sized {
258 type ExtError: BackendSyscallError;
259
260 fn into_backend_error(self) -> Result<Self::ExtError, Self>;
261}