Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ default = ["std"]
with-codec = ["codec", "evm-core/with-codec", "evm-runtime/with-codec"]
with-serde = ["serde", "serde_bytes", "evm-core/with-serde", "evm-runtime/with-serde"]
std = ["evm-core/std", "evm-runtime/std", "sha3/std", "serde/std", "codec/std", "log/std"]
tracing = ["evm-runtime/tracing"]
tracing = ["evm-runtime/tracing", "evm-core/tracing"]
#[workspace]
#members = [
# "core",
Expand Down
1 change: 1 addition & 0 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ default = ["std"]
with-codec = ["codec"]
with-serde = ["serde", "serde_bytes", "impl-serde"]
std = ["log/std", "codec/std", "serde/std"]
tracing = []
14 changes: 14 additions & 0 deletions runtime/src/context.rs → core/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,17 @@ pub struct Context {
/// Apparent value of the EVM.
pub apparent_value: U256,
}


/// Transfer from source to target, with given value.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "with-codec", derive(codec::Encode, codec::Decode))]
#[cfg_attr(feature = "with-serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Transfer {
/// Source address.
pub source: H160,
/// Target address.
pub target: H160,
/// Transfer value.
pub value: U256,
}
93 changes: 59 additions & 34 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,45 @@ mod error;
mod eval;
mod utils;
mod primitive_types;
mod context;
#[cfg(feature = "tracing")]
mod tracing;

pub use crate::memory::Memory;
pub use crate::stack::Stack;
pub use crate::valids::Valids;
pub use crate::opcode::Opcode;
pub use crate::error::{Trap, Capture, ExitReason, ExitSucceed, ExitError, ExitRevert, ExitFatal};
pub use crate::primitive_types::{H160, H256, U256, U512};
pub use crate::context::{Context, CreateScheme, CallScheme, Transfer};

use alloc::vec::Vec;
use crate::eval::{eval, Control};

#[cfg(feature = "tracing")]
pub use crate::tracing::*;

#[cfg(feature = "tracing")]
extern "C" {fn sol_send_trace_message(val: *const u8) -> u64;}


#[macro_export]
#[cfg(feature = "tracing")]
macro_rules! event {
($x:expr) => {
let ptr = &$x as *const _ as *const u8;
unsafe {
sol_send_trace_message(ptr);
}
};
}

#[macro_export]
#[cfg(not(feature = "tracing"))]
macro_rules! event {
($x:expr) => {}
}

/// Core execution layer for EVM.
#[cfg_attr(feature = "with-codec", derive(codec::Encode, codec::Decode))]
#[cfg_attr(feature = "with-serde", derive(serde::Serialize, serde::Deserialize))]
Expand Down Expand Up @@ -126,7 +154,11 @@ impl Machine {
}

/// Loop stepping the machine, until it stops.
pub fn run<F>(&mut self, max_steps: u64, mut pre_validate: F) -> (u64, Capture<ExitReason, Trap>)
pub fn run<F>(&mut self,
max_steps: u64,
mut pre_validate: F,
_context : &Context
) -> (u64, Capture<ExitReason, Trap>)
where F: FnMut(Opcode, &Stack) -> Result<(), ExitError>
{
for step in 0..max_steps {
Expand All @@ -143,61 +175,54 @@ impl Machine {
}
};

event!(Event::Step(
StepTrace {
context: _context,
opcode,
position: &self.position,
stack: &self.stack,
memory: &self.memory,
}
));

if let Err(error) = pre_validate(opcode, &self.stack()) {
let reason = ExitReason::from(error);
self.exit(reason);
return (step, Capture::Exit(reason));
}

match eval(self, opcode, position) {
let result = match eval(self, opcode, position) {
Control::Continue(p) => {
self.position = Ok(position + p);
Ok(())
},
Control::Exit(reason) => {
self.exit(reason);
return (step, Capture::Exit(reason))
Err(Capture::Exit(reason))
},
Control::Jump(p) => {
self.position = Ok(p);
Ok(())
},
Control::Trap(opcode) => {
self.position = Ok(position + 1);
return (step, Capture::Trap(opcode));
Err(Capture::Trap(opcode))
},
};

event!(Event::StepResult (StepResultTrace{
result: &result,
return_value: &self.return_value(),
stack: &self.stack,
memory: &self.memory
}));

if let Err(capture) = result {
return (step, capture)
}
}

(max_steps, Capture::Exit(ExitReason::StepLimitReached))
}

/// Step the machine, executing one opcode. It then returns.
pub fn step(&mut self) -> Result<(), Capture<ExitReason, Trap>> {
let position = *self.position.as_ref().map_err(|reason| Capture::Exit(reason.clone()))?;

let opcode = if let Some(opcode) = self.code.get(position).map(|v| Opcode(*v)) {
opcode
} else {
self.position = Err(ExitSucceed::Stopped.into());
return Err(Capture::Exit(ExitSucceed::Stopped.into()))
};

match eval(self, opcode, position) {
Control::Continue(p) => {
self.position = Ok(position + p);
Ok(())
},
Control::Exit(e) => {
self.position = Err(e.clone());
Err(Capture::Exit(e))
},
Control::Jump(p) => {
self.position = Ok(p);
Ok(())
},
Control::Trap(opcode) => {
self.position = Ok(position + 1);
Err(Capture::Trap(opcode))
},
}
}
}
13 changes: 10 additions & 3 deletions core/src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ impl Memory {
}
}

pub fn from(data: &[u8], len: usize, limit: usize) -> Self {
Self {
data: Vec::from(data),
effective_len: len,
limit,
}
}
/// Memory limit.
#[must_use]
pub const fn limit(&self) -> usize {
Expand All @@ -50,9 +57,9 @@ impl Memory {
self.len() == 0
}

pub fn data(&self) -> &[u8] {
&self.data
}
pub fn data(&self) -> &[u8] { &self.data }

pub fn data_vec(&self) -> &Vec<u8> { &self.data }

/// Resize the memory, making it cover the memory region of `offset..(offset
/// + len)`, with 32 bytes as the step. If the length is zero, this function
Expand Down
11 changes: 11 additions & 0 deletions core/src/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ impl Stack {
}
}

pub fn from(data: &[U256], limit: usize) -> Self {
Self {
data: Vec::from(data),
limit,
}
}
/// Stack limit.
#[must_use]
pub const fn limit(&self) -> usize {
Expand Down Expand Up @@ -168,4 +174,9 @@ impl Stack {

Ok(())
}

pub fn data_vec(&self) -> &Vec<U256> {
&self.data
}

}
144 changes: 144 additions & 0 deletions core/src/tracing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
use crate::{H160, H256, U256, Context, Opcode, Stack, Memory, Capture, ExitReason, Trap, CreateScheme, Transfer};
use alloc::vec::Vec;


#[derive(Debug, Clone)]
pub struct CallTrace<'a>{
/// Called code address
pub code_address: H160,
/// Transfer parameters
pub transfer: &'a Option<Transfer>,
/// Input data provided to the call
pub input: &'a Vec<u8>,
/// Target gas
pub target_gas: Option<u64>,
/// Static call flag
pub is_static: bool,
/// Runtime context
pub context: &'a Context,
}

#[derive(Debug, Clone)]
pub struct CreateTrace<'a>{
/// Creator address
pub caller: H160,
/// Address of the created account
pub address: H160,
/// Scheme
pub scheme: CreateScheme,
/// Value the created account is endowed with
pub value: U256,
/// Init code
pub init_code: &'a Vec<u8>,
/// Target Gas
pub target_gas: Option<u64>,
}

#[derive(Debug, Clone)]
pub struct SuicideTrace{
/// Suicided address
pub address: H160,
/// Suicided contract heir
pub target: H160,
/// Balance before suicide
pub balance: U256,
}

#[derive(Debug, Clone)]
pub struct ExitTrace<'a>{
pub reason: &'a ExitReason,
pub return_value: &'a Vec<u8>,
}


#[derive(Debug, Clone)]
pub struct TransactCallTrace<'a>{
/// Caller account address
pub caller: H160,
/// Destination account address
pub address: H160,
/// Value transferred to the destination account
pub value: U256,
/// Input data provided to the call
pub data: &'a Vec<u8>,
/// Gas Limit
pub gas_limit: U256,
}

#[derive(Debug, Clone)]
pub struct TransactCreateTrace<'a>{
/// Creator address
pub caller: H160,
/// Value the created account is endowed with
pub value: U256,
/// Init code
pub init_code: &'a Vec<u8>,
/// Gas limit
pub gas_limit: U256,
/// Address of the created account
pub address: H160,
}

#[derive(Debug, Clone)]
pub struct TransactCreate2Trace<'a>{
/// Creator address
pub caller: H160,
/// Value the created account is endowed with
pub value: U256,
/// Init code
pub init_code: &'a Vec<u8>,
/// Salt
pub salt: H256,
/// Gas limit
pub gas_limit: U256,
/// Address of the created account
pub address: H160,
}

#[derive(Debug, Clone)]
pub struct StepTrace<'a>{
pub context: &'a Context,
pub opcode: Opcode,
pub position: &'a Result<usize, ExitReason>,
pub stack: &'a Stack,
pub memory: &'a Memory,
}

#[derive(Debug, Clone)]
pub struct StepResultTrace<'a>{
pub result: &'a Result<(), Capture<ExitReason, Trap>>,
pub return_value: &'a Vec<u8>,
pub stack: &'a Stack,
pub memory: &'a Memory,
}

#[derive(Debug, Clone)]
pub struct SLoadTrace{
pub address: H160,
pub index: U256,
pub value: U256
}

#[derive(Debug, Clone)]
pub struct SStoreTrace {
pub address: H160,
pub index: U256,
pub value: U256
}

/// Trace event
#[derive(Debug, Clone)]
// #[allow(dead_code)]
pub enum Event<'a>{
Call(CallTrace<'a>) ,
Create(CreateTrace<'a>) ,
Suicide(SuicideTrace) ,
Exit(ExitTrace<'a>) ,
TransactCall(TransactCallTrace<'a>) ,
TransactCreate(TransactCreateTrace<'a>) ,
TransactCreate2(TransactCreate2Trace<'a>) ,
Step(StepTrace<'a>) ,
StepResult(StepResultTrace<'a>),
SLoad(SLoadTrace),
SStore(SStoreTrace),
}
7 changes: 2 additions & 5 deletions runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,11 @@ sha3 = { version = "0.8", default-features = false }
codec = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive", "full"], optional = true }
serde = { version = "1.0", default-features = false, features = ["derive"], optional = true }
serde_bytes = { version = "0.11.5", optional = true }
environmental = { version = "1.1.2", default-features = false, optional = true}
borsh = { version = "0.9" }

[features]
default = ["std"]
with-codec = ["codec"]
with-serde = ["serde", "serde_bytes"]
std = ["evm-core/std", "sha3/std", "environmental/std"]
tracing = [
"environmental"
]
std = ["evm-core/std", "sha3/std"]
tracing = ["evm-core/tracing"]
Loading