// Copyright 2015-2020 Parity Technologies (UK) Ltd. // This file is part of OpenEthereum. // OpenEthereum is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // OpenEthereum is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . //! Interface for Evm externalities. use bytes::Bytes; use call_type::CallType; use env_info::EnvInfo; use error::{Result, TrapKind}; use ethereum_types::{Address, H256, U256}; use return_data::ReturnData; use schedule::Schedule; use std::sync::Arc; #[derive(Debug)] /// Result of externalities create function. pub enum ContractCreateResult { /// Returned when creation was successfull. /// Contains an address of newly created contract and gas left. Created(Address, U256), /// Returned when contract creation failed. /// VM doesn't have to know the reason. Failed, /// Reverted with REVERT. Reverted(U256, ReturnData), } #[derive(Debug)] /// Result of externalities call function. pub enum MessageCallResult { /// Returned when message call was successfull. /// Contains gas left and output data. Success(U256, ReturnData), /// Returned when message call failed. /// VM doesn't have to know the reason. Failed, /// Returned when message call was reverted. /// Contains gas left and output data. Reverted(U256, ReturnData), } /// Specifies how an address is calculated for a new contract. #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub enum CreateContractAddress { /// Address is calculated from sender and nonce. pWASM `create` scheme. FromSenderAndNonce, /// Address is calculated from sender, salt and code hash. pWASM `create2` scheme and EIP-1014 CREATE2 scheme. FromSenderSaltAndCodeHash(H256), /// Address is calculated from code hash and sender. Used by pwasm create ext. FromSenderAndCodeHash, } /// Externalities interface for EVMs pub trait Ext { /// Returns the storage value for a given key if reversion happens on the current transaction. fn initial_storage_at(&self, key: &H256) -> Result; /// Returns a value for given key. fn storage_at(&self, key: &H256) -> Result; /// Stores a value for given key. fn set_storage(&mut self, key: H256, value: H256) -> Result<()>; /// Determine whether an account exists. fn exists(&self, address: &Address) -> Result; /// Determine whether an account exists and is not null (zero balance/nonce, no code). fn exists_and_not_null(&self, address: &Address) -> Result; /// Balance of the origin account. fn origin_balance(&self) -> Result; /// Returns address balance. fn balance(&self, address: &Address) -> Result; /// Returns the hash of one of the 256 most recent complete blocks. fn blockhash(&mut self, number: &U256) -> H256; /// Creates new contract. /// /// Returns gas_left and contract address if contract creation was successful. fn create( &mut self, gas: &U256, value: &U256, code: &[u8], address: CreateContractAddress, trap: bool, ) -> ::std::result::Result; /// Returns the address that will be created in the create call fn calc_address(&self, code: &[u8], address: CreateContractAddress) -> Option
; /// Message call. /// /// Returns Err, if we run out of gas. /// Otherwise returns call_result which contains gas left /// and true if subcall was successfull. fn call( &mut self, gas: &U256, sender_address: &Address, receive_address: &Address, value: Option, data: &[u8], code_address: &Address, call_type: CallType, trap: bool, ) -> ::std::result::Result; /// Returns code at given address fn extcode(&self, address: &Address) -> Result>>; /// Returns code hash at given address fn extcodehash(&self, address: &Address) -> Result>; /// Returns code size at given address fn extcodesize(&self, address: &Address) -> Result>; /// Creates log entry with given topics and data fn log(&mut self, topics: Vec, data: &[u8]) -> Result<()>; /// Should be called when transaction calls `RETURN` opcode. /// Returns gas_left if cost of returning the data is not too high. fn ret(self, gas: &U256, data: &ReturnData, apply_state: bool) -> Result; /// Should be called when contract commits suicide. /// Address to which funds should be refunded. fn suicide(&mut self, refund_address: &Address) -> Result<()>; /// Returns schedule. fn schedule(&self) -> &Schedule; /// Returns environment info. fn env_info(&self) -> &EnvInfo; /// Returns the chain ID of the blockchain fn chain_id(&self) -> u64; /// Returns current depth of execution. /// /// If contract A calls contract B, and contract B calls C, /// then A depth is 0, B is 1, C is 2 and so on. fn depth(&self) -> usize; /// Increments sstore refunds counter. fn add_sstore_refund(&mut self, value: usize); /// Decrements sstore refunds counter. fn sub_sstore_refund(&mut self, value: usize); /// Decide if any more operations should be traced. Passthrough for the VM trace. fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8, _current_gas: U256) -> bool { false } /// Prepare to trace an operation. Passthrough for the VM trace. /// For each call of `trace_prepare_execute` either `trace_failed` or `trace_executed` MUST be called. fn trace_prepare_execute( &mut self, _pc: usize, _instruction: u8, _gas_cost: U256, _mem_written: Option<(usize, usize)>, _store_written: Option<(U256, U256)>, ) { } /// Trace the execution failure of a single instruction. fn trace_failed(&mut self) {} /// Trace the finalised execution of a single instruction. fn trace_executed(&mut self, _gas_used: U256, _stack_push: &[U256], _mem: &[u8]) {} /// Check if running in static context. fn is_static(&self) -> bool; /// Returns if the list is enabled fn al_is_enabled(&self) -> bool; /// Checks if contains an storage key fn al_contains_storage_key(&self, address: &Address, key: &H256) -> bool; /// Inserts an storage key into the list fn al_insert_storage_key(&mut self, address: Address, key: H256); /// Checks if contains an address fn al_contains_address(&self, address: &Address) -> bool; /// Inserts an address into the list fn al_insert_address(&mut self, address: Address); }