Skip to content

Commit

Permalink
fix: various inspector fixes (#69)
Browse files Browse the repository at this point in the history
* chore: remove unused `Inspector::initialize`

* feat: allow `Inspector::call_end` to alter result

* fix: call inspector before/after every call

* chore: fmt

* ci: fix lint check

* fix: adjust binaries to new `call_end`

* feat: allow `Inspector::create_end` to alter res

* Update .github/workflows/ci.yml

* Update crates/revm/src/specification.rs
  • Loading branch information
onbjerg committed Mar 7, 2022
1 parent 1398d16 commit 0f6c09f
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 108 deletions.
22 changes: 13 additions & 9 deletions bins/revme/src/debugger/ctrl/ctrl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,14 +221,16 @@ impl<DB: Database> Inspector<DB> for Controller {
&mut self,
_data: &mut EVMData<'_, DB>,
_inputs: &CallInputs,
_remaining_gas: Gas,
_ret: Return,
_out: &Bytes,
remaining_gas: Gas,
ret: Return,
out: Bytes,
_is_static: bool,
) {
) -> (Return, Gas, Bytes) {
if let StateMachine::StepOut = self.state_interp {
self.state_interp = StateMachine::TriggerStep
}

(ret, remaining_gas, out)
}

fn create(
Expand All @@ -243,14 +245,16 @@ impl<DB: Database> Inspector<DB> for Controller {
&mut self,
_data: &mut EVMData<'_, DB>,
_inputs: &CreateInputs,
_ret: Return,
_address: Option<H160>,
_remaining_gas: Gas,
_out: &Bytes,
) {
ret: Return,
address: Option<H160>,
remaining_gas: Gas,
out: Bytes,
) -> (Return, Option<H160>, Gas, Bytes) {
if let StateMachine::StepOut = self.state_interp {
self.state_interp = StateMachine::TriggerStep
}

(ret, address, remaining_gas, out)
}

fn selfdestruct(&mut self) {}
Expand Down
22 changes: 0 additions & 22 deletions bins/revme/src/statetest/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,6 @@ impl<DB: Database> Inspector<DB> for CustomPrintTracer {
(Return::Continue, Gas::new(0), Bytes::new())
}

fn call_end(
&mut self,
_data: &mut EVMData<'_, DB>,
_inputs: &CallInputs,
_remaining_gas: Gas,
_ret: Return,
_out: &Bytes,
_is_static: bool,
) {
}

fn create(
&mut self,
_data: &mut EVMData<'_, DB>,
Expand All @@ -126,17 +115,6 @@ impl<DB: Database> Inspector<DB> for CustomPrintTracer {
(Return::Continue, None, Gas::new(0), Bytes::new())
}

fn create_end(
&mut self,
_data: &mut EVMData<'_, DB>,
_inputs: &CreateInputs,
_ret: Return,
_address: Option<H160>,
_remaining_gas: Gas,
_out: &Bytes,
) {
}

fn selfdestruct(&mut self) {
//, address: H160, target: H160) {
println!("SELFDESTRUCT on "); //{:?} target: {:?}", address, target);
Expand Down
103 changes: 57 additions & 46 deletions crates/revm/src/evm_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,35 +293,44 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB,
&mut self,
inputs: &CreateInputs,
) -> (Return, Option<H160>, Gas, Bytes) {
// Call inspector
if INSPECT {
let (ret, address, gas, out) = self.inspector.create(&mut self.data, inputs);
if ret != Return::Continue {
return (ret, address, gas, out);
}
}

let gas = Gas::new(inputs.gas_limit);
self.load_account(inputs.caller);

// check depth of calls
// Check depth of calls
if self.data.subroutine.depth() > interpreter::CALL_STACK_LIMIT {
return (Return::CallTooDeep, None, gas, Bytes::new());
}
// check balance of caller and value. Do this before increasing nonce
// Check balance of caller and value. Do this before increasing nonce
if self.balance(inputs.caller).0 < inputs.value {
return (Return::OutOfFund, None, gas, Bytes::new());
}

// inc nonce of caller
// Increase nonce of caller
let old_nonce = self.data.subroutine.inc_nonce(inputs.caller);
// create address

// Create address
let code_hash = H256::from_slice(Keccak256::digest(&inputs.init_code).as_slice());
let created_address = match inputs.scheme {
CreateScheme::Create => create_address(inputs.caller, old_nonce),
CreateScheme::Create2 { salt } => create2_address(inputs.caller, code_hash, salt),
};
let ret = Some(created_address);

// load account so that it will be hot
// Load account so that it will be hot
self.load_account(created_address);

// enter into subroutine
// Enter subroutine
let checkpoint = self.data.subroutine.create_checkpoint();

// create contract account and check for collision
// Create contract account and check for collision
if !self.data.subroutine.new_contract_acc(
created_address,
self.precompiles.contains(&created_address),
Expand All @@ -331,7 +340,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB,
return (Return::CreateCollision, ret, gas, Bytes::new());
}

// transfer value to contract address
// Transfer value to contract address
if let Err(e) = self.data.subroutine.transfer(
inputs.caller,
created_address,
Expand All @@ -341,11 +350,13 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB,
self.data.subroutine.checkpoint_revert(checkpoint);
return (e, ret, gas, Bytes::new());
}
// inc nonce of contract

// Increase nonce of the contract
if SPEC::enabled(ISTANBUL) {
self.data.subroutine.inc_nonce(created_address);
}
// create new interp and execute init function

// Create new interpreter and execute initcode
let contract = Contract::new::<SPEC>(
Bytes::new(),
inputs.init_code.clone(),
Expand All @@ -360,8 +371,9 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB,
.initialize_interp(&mut interp, &mut self.data, false); // TODO fix is_static
}
let exit_reason = interp.run::<Self, SPEC>(self);

// Host error if present on execution\
let ret = match exit_reason {
let (ret, address, gas, out) = match exit_reason {
return_ok!() => {
let b = Bytes::new();
// if ok, check contract creation limit and calculate gas deduction on output len.
Expand Down Expand Up @@ -407,31 +419,47 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB,
(exit_reason, ret, interp.gas, interp.return_value())
}
};
ret

if INSPECT {
self.inspector
.create_end(&mut self.data, inputs, ret, address, gas, out)
} else {
(ret, address, gas, out)
}
}

#[allow(clippy::too_many_arguments)]
fn call_inner<SPEC: Spec>(&mut self, inputs: &CallInputs) -> (Return, Gas, Bytes) {
// Call the inspector
if INSPECT {
let (ret, gas, out) = self
.inspector
.call(&mut self.data, inputs, SPEC::IS_STATIC_CALL);
if ret != Return::Continue {
return (ret, gas, out);
}
}

let mut gas = Gas::new(inputs.gas_limit);
// Load account and get code. Account is now hot.
let (code, _) = self.code(inputs.contract);

// check depth
// Check depth
if self.data.subroutine.depth() > interpreter::CALL_STACK_LIMIT {
return (Return::CallTooDeep, gas, Bytes::new());
}

// Create subroutine checkpoint
let checkpoint = self.data.subroutine.create_checkpoint();
// touch address. For "EIP-158 State Clear" this will erase empty accounts.

// Touch address. For "EIP-158 State Clear", this will erase empty accounts.
if inputs.transfer.value.is_zero() {
self.load_account(inputs.context.address);
self.data
.subroutine
.balance_add(inputs.context.address, U256::zero()); // touch the acc
.balance_add(inputs.context.address, U256::zero());
}

// transfer value from caller to called account;
// Transfer value from caller to called account
match self.data.subroutine.transfer(
inputs.transfer.source,
inputs.transfer.target,
Expand All @@ -445,8 +473,8 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB,
Ok((_source_is_cold, _target_is_cold)) => {}
}

// call precompiles
if let Some(precompile) = self.precompiles.get(&inputs.contract) {
// Call precompiles
let (ret, gas, out) = if let Some(precompile) = self.precompiles.get(&inputs.contract) {
let out = match precompile {
Precompile::Standard(fun) => fun(inputs.input.as_ref(), inputs.gas_limit),
Precompile::Custom(fun) => fun(inputs.input.as_ref(), inputs.gas_limit),
Expand Down Expand Up @@ -474,7 +502,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB,
}
}
} else {
// create interp and execute subcall
// Create interpreter and execute subcall
let contract =
Contract::new_with_context::<SPEC>(inputs.input.clone(), code, &inputs.context);
let mut interp =
Expand All @@ -491,6 +519,13 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB,
}

(exit_reason, interp.gas, interp.return_value())
};

if INSPECT {
self.inspector
.call_end(&mut self.data, inputs, gas, ret, out, SPEC::IS_STATIC_CALL)
} else {
(ret, gas, out)
}
}
}
Expand Down Expand Up @@ -581,35 +616,11 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host
}

fn create<SPEC: Spec>(&mut self, inputs: &CreateInputs) -> (Return, Option<H160>, Gas, Bytes) {
if INSPECT {
let (ret, address, gas, out) = self.inspector.create(&mut self.data, inputs);
if ret != Return::Continue {
return (ret, address, gas, out);
}
}
let (ret, address, gas, out) = self.create_inner::<SPEC>(inputs);
if INSPECT {
self.inspector
.create_end(&mut self.data, inputs, ret, address, gas, &out);
}
(ret, address, gas, out)
self.create_inner::<SPEC>(inputs)
}

fn call<SPEC: Spec>(&mut self, inputs: &CallInputs) -> (Return, Gas, Bytes) {
if INSPECT {
let (ret, gas, out) = self
.inspector
.call(&mut self.data, inputs, SPEC::IS_STATIC_CALL);
if ret != Return::Continue {
return (ret, gas, out);
}
}
let (ret, gas, out) = self.call_inner::<SPEC>(inputs);
if INSPECT {
self.inspector
.call_end(&mut self.data, inputs, gas, ret, &out, SPEC::IS_STATIC_CALL);
}
(ret, gas, out)
self.call_inner::<SPEC>(inputs)
}
}

Expand Down
Loading

0 comments on commit 0f6c09f

Please sign in to comment.