feat: add TraceError enum (#1814)
This commit is contained in:
parent
715cd5b0a6
commit
2418098d8c
|
@ -1,6 +1,10 @@
|
||||||
//! Types for the Parity Transaction-Trace Filtering API
|
//! Types for the Parity Transaction-Trace Filtering API
|
||||||
use crate::types::{Address, BlockNumber, Bytes, H160, H256, U256};
|
use crate::types::{Address, BlockNumber, Bytes, H160, H256, U256};
|
||||||
|
use bytes::{Buf, BufMut};
|
||||||
|
use open_fastrlp::DecodeError;
|
||||||
|
use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
/// Trace filter
|
/// Trace filter
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize)]
|
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize)]
|
||||||
|
@ -102,7 +106,7 @@ pub struct Trace {
|
||||||
/// Action Type
|
/// Action Type
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub action_type: ActionType,
|
pub action_type: ActionType,
|
||||||
/// Error
|
/// Error, See also [`TraceError`]
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub error: Option<String>,
|
pub error: Option<String>,
|
||||||
}
|
}
|
||||||
|
@ -273,6 +277,124 @@ pub enum RewardType {
|
||||||
External,
|
External,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trace evm errors.
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum TraceError {
|
||||||
|
/// `OutOfGas` is returned when transaction execution runs out of gas.
|
||||||
|
OutOfGas = 0,
|
||||||
|
/// `BadJumpDestination` is returned when execution tried to move
|
||||||
|
/// to position that wasn't marked with JUMPDEST instruction
|
||||||
|
BadJumpDestination = 1,
|
||||||
|
/// `BadInstructions` is returned when given instruction is not supported
|
||||||
|
BadInstruction = 2,
|
||||||
|
/// `StackUnderflow` when there is not enough stack elements to execute instruction
|
||||||
|
StackUnderflow = 3,
|
||||||
|
/// When execution would exceed defined Stack Limit
|
||||||
|
OutOfStack = 4,
|
||||||
|
/// Returned on evm internal error. Should never be ignored during development.
|
||||||
|
/// Likely to cause consensus issues.
|
||||||
|
Internal = 5,
|
||||||
|
/// When builtin contract failed on input data
|
||||||
|
BuiltIn = 6,
|
||||||
|
/// When execution tries to modify the state in static context
|
||||||
|
MutableCallInStaticContext = 7,
|
||||||
|
/// Wasm error
|
||||||
|
Wasm = 8,
|
||||||
|
/// Contract tried to access past the return data buffer.
|
||||||
|
OutOfBounds = 9,
|
||||||
|
/// Execution has been reverted with REVERT instruction.
|
||||||
|
Reverted = 10,
|
||||||
|
/// When there is not enough subroutine stack elements to return from
|
||||||
|
SubStackUnderflow = 11,
|
||||||
|
/// When execution would exceed defined subroutine Stack Limit
|
||||||
|
OutOfSubStack = 12,
|
||||||
|
/// When the code walks into a subroutine, that is not allowed
|
||||||
|
InvalidSubEntry = 13,
|
||||||
|
/// When invalid code was attempted to deploy
|
||||||
|
InvalidCode = 14,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TraceError {
|
||||||
|
/// Converts the given byte into the corresponding error variant.
|
||||||
|
pub fn from_u8(val: u8) -> Result<Self, u8> {
|
||||||
|
let val = match val {
|
||||||
|
0 => TraceError::OutOfGas,
|
||||||
|
1 => TraceError::BadJumpDestination,
|
||||||
|
2 => TraceError::BadInstruction,
|
||||||
|
3 => TraceError::StackUnderflow,
|
||||||
|
4 => TraceError::OutOfStack,
|
||||||
|
5 => TraceError::Internal,
|
||||||
|
6 => TraceError::BuiltIn,
|
||||||
|
7 => TraceError::MutableCallInStaticContext,
|
||||||
|
8 => TraceError::Wasm,
|
||||||
|
9 => TraceError::OutOfBounds,
|
||||||
|
10 => TraceError::Reverted,
|
||||||
|
11 => TraceError::SubStackUnderflow,
|
||||||
|
12 => TraceError::OutOfSubStack,
|
||||||
|
13 => TraceError::InvalidSubEntry,
|
||||||
|
14 => TraceError::InvalidCode,
|
||||||
|
_ => return Err(val),
|
||||||
|
};
|
||||||
|
Ok(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for TraceError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let message = match *self {
|
||||||
|
TraceError::OutOfGas => "Out of gas",
|
||||||
|
TraceError::BadJumpDestination => "Bad jump destination",
|
||||||
|
TraceError::BadInstruction => "Bad instruction",
|
||||||
|
TraceError::StackUnderflow => "Stack underflow",
|
||||||
|
TraceError::OutOfStack => "Out of stack",
|
||||||
|
TraceError::SubStackUnderflow => "Subroutine stack underflow",
|
||||||
|
TraceError::OutOfSubStack => "Subroutine stack overflow",
|
||||||
|
TraceError::BuiltIn => "Built-in failed",
|
||||||
|
TraceError::InvalidSubEntry => "Invalid subroutine entry",
|
||||||
|
TraceError::InvalidCode => "Invalid code",
|
||||||
|
TraceError::Wasm => "Wasm runtime error",
|
||||||
|
TraceError::Internal => "Internal error",
|
||||||
|
TraceError::MutableCallInStaticContext => "Mutable Call In Static Context",
|
||||||
|
TraceError::OutOfBounds => "Out of bounds",
|
||||||
|
TraceError::Reverted => "Reverted",
|
||||||
|
};
|
||||||
|
message.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl open_fastrlp::Encodable for TraceError {
|
||||||
|
fn encode(&self, out: &mut dyn BufMut) {
|
||||||
|
out.put_u8((*self) as u8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encodable for TraceError {
|
||||||
|
fn rlp_append(&self, s: &mut RlpStream) {
|
||||||
|
let val = (*self) as u8;
|
||||||
|
s.append_internal(&val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable for TraceError {
|
||||||
|
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
|
||||||
|
let value: u8 = rlp.as_val()?;
|
||||||
|
Self::from_u8(value).map_err(|_| DecoderError::Custom("Invalid error code"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl open_fastrlp::Decodable for TraceError {
|
||||||
|
fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
|
||||||
|
if buf.is_empty() {
|
||||||
|
return Err(DecodeError::InputTooShort)
|
||||||
|
}
|
||||||
|
let val = buf[0];
|
||||||
|
let val = Self::from_u8(val).map_err(|_| DecodeError::Custom("Invalid error code"))?;
|
||||||
|
buf.advance(1);
|
||||||
|
Ok(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
Loading…
Reference in New Issue