Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
[revm] Full rename to Interepter
  • Loading branch information
rakita committed Feb 20, 2022
commit 8d7e7ee7101230ea17ca822550b38a20edb65e2b
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# revm - Revolutionary Machine

Is **Rust Ethereum Virtual Machine** with great name that is focused on **speed** and **simplicity**. It gets ispiration from `SputnikVM` (got opcodes/machine from here), `OpenEthereum` and `Geth` with a help from [wolflo/evm-opcodes](https://github.com/wolflo/evm-opcodes).
Is **Rust Ethereum Virtual Machine** with great name that is focused on **speed** and **simplicity**. It gets ispiration from `SputnikVM` (got opcodes/interp from here), `OpenEthereum` and `Geth` with a help from [wolflo/evm-opcodes](https://github.com/wolflo/evm-opcodes).

It is fast and flexible implementation of EVM with simple interface and embeded Host, there are multiple things done on Host part from const EVM Spec to optimistic changelogs for subroutines to merging `eip2929` in EVM state so that it can be accesses only once that are improving the speed of execution. There are still some improvements on Interepter part that needs to be done so that we can be comparable with evmone, for more info track [this issue](https://github.com/bluealloy/revm/issues/7).

Expand Down
58 changes: 27 additions & 31 deletions bins/revme/src/debugger/ctrl/ctrl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,15 @@ pub enum StateMachine {
}

pub struct Controller {
state_machine: StateMachine,
state_interp: StateMachine,
history_path: Option<PathBuf>,
//call_stack: Vec<>,
}

impl Controller {
pub fn new(history_path: Option<PathBuf>) -> Self {
Self {
state_machine: StateMachine::TriggerStep,
state_interp: StateMachine::TriggerStep,
history_path,
}
}
Expand All @@ -108,73 +108,69 @@ impl Controller {
impl<DB: Database> Inspector<DB> for Controller {
fn step(
&mut self,
machine: &mut revm::Interpreter,
interp: &mut revm::Interpreter,
data: &mut EVMData<'_, DB>,
_is_static: bool,
) -> Return {
loop {
match Ctrl::next(self.state_machine, &self.history_path) {
match Ctrl::next(self.state_interp, &self.history_path) {
Ctrl::Help => {
println!(
"available controls: \nstep\nexit\nprint all\nstack pop\nstack push 10\n"
)
}
Ctrl::Exit => {
self.state_machine = StateMachine::Exit;
self.state_interp = StateMachine::Exit;
break;
}
Ctrl::Step => {
self.state_machine = StateMachine::TriggerStep;
self.state_interp = StateMachine::TriggerStep;
break;
}
//Ctrl::StepIn => {}
//Ctrl::StepOut => {
// self.state_machine = StateMachine::StepOut;
// self.state_interp = StateMachine::StepOut;
//}
Ctrl::Print(print) => match print {
CtrlPrint::All => {
let opcode = machine
let opcode = interp
.contract
.code
.get(machine.program_counter())
.get(interp.program_counter())
.cloned()
.unwrap();
let gas_spend = machine.gas().spend();
let gas_remaining = machine.gas().remaining();
let gas_spend = interp.gas().spend();
let gas_remaining = interp.gas().remaining();
println!(
"call_depth:{} PC:{} Opcode: {:#x} {:?} gas(spend,remaining):({},{})\n\
Stack:{}",
machine.call_depth,
machine.program_counter(),
interp.call_depth,
interp.program_counter(),
opcode,
OPCODE_JUMPMAP[opcode as usize].unwrap_or("Invalid"),
gas_spend,
gas_remaining,
machine.stack(),
interp.stack(),
);
}
CtrlPrint::Opcode => {
let opcode = *machine
.contract
.code
.get(machine.program_counter())
.unwrap();
let opcode = *interp.contract.code.get(interp.program_counter()).unwrap();
println!(
"PC:{} OpCode: {:#x} {:?}",
machine.program_counter(),
interp.program_counter(),
opcode,
OPCODE_JUMPMAP[opcode as usize]
)
}
CtrlPrint::Stack => {
println!("PC:{} stack:{}", machine.program_counter(), machine.stack())
println!("PC:{} stack:{}", interp.program_counter(), interp.stack())
}
CtrlPrint::Memory => {
println!("memory:{}", hex::encode(&machine.memory.data()))
println!("memory:{}", hex::encode(&interp.memory.data()))
}
},
Ctrl::Continue => {
self.state_machine = StateMachine::TriggerBreakpoint;
self.state_interp = StateMachine::TriggerBreakpoint;
break;
}
Ctrl::Restart => {
Expand All @@ -190,10 +186,10 @@ impl<DB: Database> Inspector<DB> for Controller {
}
Ctrl::AccountPrintOriginal(_address) => (),
Ctrl::StackPop => {
println!("pop:{:?}", machine.stack.pop());
println!("pop:{:?}", interp.stack.pop());
}
Ctrl::StackPush(value) => match machine.stack.push(value) {
Ok(()) => println!("stack:{}", machine.stack()),
Ctrl::StackPush(value) => match interp.stack.push(value) {
Ok(()) => println!("stack:{}", interp.stack()),
Err(e) => println!("push error:{:?}", e),
},
Ctrl::None => break,
Expand All @@ -202,7 +198,7 @@ impl<DB: Database> Inspector<DB> for Controller {
Return::Continue
}

fn step_end(&mut self, _eval: revm::Return, _machine: &mut revm::Interpreter) -> Return {
fn step_end(&mut self, _eval: revm::Return, _interp: &mut revm::Interpreter) -> Return {
Return::Continue
}

Expand Down Expand Up @@ -232,8 +228,8 @@ impl<DB: Database> Inspector<DB> for Controller {
_out: &Bytes,
_is_static: bool,
) {
if let StateMachine::StepOut = self.state_machine {
self.state_machine = StateMachine::TriggerStep
if let StateMachine::StepOut = self.state_interp {
self.state_interp = StateMachine::TriggerStep
}
}

Expand Down Expand Up @@ -262,8 +258,8 @@ impl<DB: Database> Inspector<DB> for Controller {
_remaining_gas: u64,
_out: &Bytes,
) {
if let StateMachine::StepOut = self.state_machine {
self.state_machine = StateMachine::TriggerStep
if let StateMachine::StepOut = self.state_interp {
self.state_interp = StateMachine::TriggerStep
}
}

Expand Down
36 changes: 18 additions & 18 deletions bins/revme/src/statetest/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use revm::{opcode, spec_opcode_gas, Database, EVMData, Gas, Return};
#[derive(Clone)]
pub struct CustomPrintTracer {
/// We now batch continual gas_block in one go, that means we need to reduce it ifwe want to get
/// correct gas remaining. Check revm/machine/contract/analize for more information
/// correct gas remaining. Check revm/interp/contract/analize for more information
reduced_gas_block: u64,
full_gas_block: u64,
}
Expand All @@ -21,27 +21,27 @@ impl CustomPrintTracer {
}

impl<DB: Database> Inspector<DB> for CustomPrintTracer {
fn initialize_machine(
fn initialize_interp(
&mut self,
machine: &mut revm::Interpreter,
interp: &mut revm::Interpreter,
_data: &mut EVMData<'_, DB>,
_is_static: bool,
) -> Return {
self.full_gas_block = machine.contract.first_gas_block();
self.full_gas_block = interp.contract.first_gas_block();
Return::Continue
}

// get opcode by calling `machine.contract.opcode(machine.program_counter())`.
// all other information can be obtained from machine.
// get opcode by calling `interp.contract.opcode(interp.program_counter())`.
// all other information can be obtained from interp.
fn step(
&mut self,
machine: &mut revm::Interpreter,
interp: &mut revm::Interpreter,
data: &mut EVMData<'_, DB>,
_is_static: bool,
) -> Return {
// Safety: casting. In analazis we are making this clame true that program counter will always
// point to bytecode of the contract.
let opcode = unsafe { *machine.program_counter };
let opcode = unsafe { *interp.program_counter };
let opcode_str = opcode::OPCODE_JUMPMAP[opcode as usize];

// calculate gas_block
Expand All @@ -50,21 +50,21 @@ impl<DB: Database> Inspector<DB> for CustomPrintTracer {

println!(
"depth:{}, PC:{}, gas:{:#x}({}), OPCODE: {:?}({:?}) refund:{:#x}({}) Stack:{:?}, Data:",
machine.call_depth,
machine.program_counter(),
machine.gas.remaining()+self.full_gas_block-self.reduced_gas_block,
machine.gas.remaining()+self.full_gas_block-self.reduced_gas_block,
interp.call_depth,
interp.program_counter(),
interp.gas.remaining()+self.full_gas_block-self.reduced_gas_block,
interp.gas.remaining()+self.full_gas_block-self.reduced_gas_block,
opcode_str.unwrap(),
opcode,
machine.gas.refunded(),
machine.gas.refunded(),
machine.stack.data(),
//hex::encode(machine.memory.data()),
interp.gas.refunded(),
interp.gas.refunded(),
interp.stack.data(),
//hex::encode(interp.memory.data()),
);

if info.gas_block_end {
self.reduced_gas_block = 0;
self.full_gas_block = machine.contract.gas_block(machine.program_counter());
self.full_gas_block = interp.contract.gas_block(interp.program_counter());
} else {
self.reduced_gas_block += info.gas;
}
Expand All @@ -76,7 +76,7 @@ impl<DB: Database> Inspector<DB> for CustomPrintTracer {
// println!("ACCOUNT LOADED:{:?}", address);
// }

fn step_end(&mut self, _eval: revm::Return, _machine: &mut revm::Interpreter) -> Return {
fn step_end(&mut self, _eval: revm::Return, _interp: &mut revm::Interpreter) -> Return {
Return::Continue
}

Expand Down
2 changes: 1 addition & 1 deletion crates/revm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Optimization thread: https://github.com/bluealloy/revm/issues/7
# v0.5.0
date: 17.11.2021

A lot of optimization on machine(interpreter) part, it is now at least 3x faster. On interface side, Error enum was renamed to Return and it is simplified. Additionally if needed gas measuring can be removed with rust feature.
A lot of optimization on machine(Interpreter) part, it is now at least 3x faster. On interface side, Error enum was renamed to Return and it is simplified. Additionally if needed gas measuring can be removed with rust feature.

Changes:
* push instruction optimized.
Expand Down
2 changes: 1 addition & 1 deletion crates/revm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
authors = ["Dragan Rakita <dragan0rakita@gmail.com>"]
description = "REVM - Rust Ethereum virtual machine"
description = "REVM - Rust Ethereum virtual interp"
edition = "2018"
keywords = ["no_std", "ethereum", "evm"]
license = "MIT"
Expand Down
8 changes: 4 additions & 4 deletions crates/revm/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# revm - Revolutionary Machine

Is **Rust Ethereum Virtual Machine** with great name that is focused on **speed** and **simplicity**. It gets ispiration from `SputnikVM` (got opcodes/machine from here), `OpenEthereum` and `Geth` with a help from [wolflo/evm-opcodes](https://github.com/wolflo/evm-opcodes). This is probably one of the fastest implementation of EVM, from const EVM Spec to optimistic changelogs for subroutines to merging `eip2929` in EVM state so that it can be accesses only once are some of the things that are improving the speed of execution.
Is **Rust Ethereum Virtual Machine** with great name that is focused on **speed** and **simplicity**. It gets ispiration from `SputnikVM` (got opcodes/interp from here), `OpenEthereum` and `Geth` with a help from [wolflo/evm-opcodes](https://github.com/wolflo/evm-opcodes). This is probably one of the fastest implementation of EVM, from const EVM Spec to optimistic changelogs for subroutines to merging `eip2929` in EVM state so that it can be accesses only once are some of the things that are improving the speed of execution.

Here is list of things that i would like to use as guide in this project:
- **EVM compatibility and stability** - this goes without saying but it is nice to put it here. In blockchain industry, stability is most desired attribute of any system.
Expand Down Expand Up @@ -73,9 +73,9 @@ I just started this project as a hobby to kill some time. Presenty it has good s
The structure of the project is getting crystallized and we can see few parts that are worthy to write about:
- `Spec` contains a specification of Ethereum standard. It is made as a trait so that it can be optimized away by the compiler
- `instructions` have one main function `eval` and takes `Machine`, `EVM Host`, `Spec` and `opcode` and depending on opcode it does calculation or for various opcodes it call `Host` for subroutine handling. This is where execution happens and where we cancluate gas consumption.
- `machine` contains memory and execution stack of smart contracts. It calls opcode for execution and contains `step` function. It reads the contract, extracts opcodes and handles memory.
- `subroutine` for various calls/creates we need to have separate `machine` and separate accessed locations. This is place where all of this is done, additionaly, it contains all caches of accessed accounts/slots/code. EIP2929 related access is integrated into state memory. Getting inside new call `subroutine` creates checkpoint that contain needed information that can revert state if subcall reverts or needs to be discardet. Changeset is made so it is optimistic that means that we dont do any work if call is finished successfully and only do something when it fials.
- `EVMImpl`- Is main entry to the lib,it implements `Host` and connects `subroutine` and `machine` and does `subroutine checkpoint` switches.
- `interp` contains memory and execution stack of smart contracts. It calls opcode for execution and contains `step` function. It reads the contract, extracts opcodes and handles memory.
- `subroutine` for various calls/creates we need to have separate `interp` and separate accessed locations. This is place where all of this is done, additionaly, it contains all caches of accessed accounts/slots/code. EIP2929 related access is integrated into state memory. Getting inside new call `subroutine` creates checkpoint that contain needed information that can revert state if subcall reverts or needs to be discardet. Changeset is made so it is optimistic that means that we dont do any work if call is finished successfully and only do something when it fials.
- `EVMImpl`- Is main entry to the lib,it implements `Host` and connects `subroutine` and `interp` and does `subroutine checkpoint` switches.


### Subroutine
Expand Down
Loading