Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: various inspector fixes #69

Merged
merged 9 commits into from
Mar 7, 2022
Merged
Show file tree
Hide file tree
Changes from 8 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
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