Documentation
¶
Index ¶
- Constants
- Variables
- func NewDest() destinations
- func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error)
- func WriteLogs(writer io.Writer, logs []*types.Log)
- func WriteTrace(writer io.Writer, logs []StructLog)
- type CanTransferFunc
- type Context
- type Contract
- type EVM
- func (evm *EVM) Call(caller crypto.CommonAddress, addr crypto.CommonAddress, ...) (ret []byte, leftOverGas uint64, err error)
- func (evm *EVM) CallCode(caller crypto.CommonAddress, addr crypto.CommonAddress, input []byte, ...) (ret []byte, leftOverGas uint64, err error)
- func (evm *EVM) Cancel()
- func (evm *EVM) Create(caller crypto.CommonAddress, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr crypto.CommonAddress, leftOverGas uint64, err error)
- func (evm *EVM) Create2(caller crypto.CommonAddress, code []byte, gas uint64, endowment *big.Int, ...) (ret []byte, contractAddr crypto.CommonAddress, leftOverGas uint64, err error)
- func (evm *EVM) CreateContractCode(caller crypto.CommonAddress, codeAndHash *codeAndHash, gas uint64, ...) ([]byte, crypto.CommonAddress, uint64, error)
- func (evm *EVM) DelegateCall(con *Contract, contractAddr crypto.CommonAddress, input []byte, gas uint64) (ret []byte, leftGas uint64, err error)
- func (evm *EVM) Interpreter() *EVMInterpreter
- func (evm *EVM) StaticCall(caller crypto.CommonAddress, addr crypto.CommonAddress, input []byte, ...) (ret []byte, leftOverGas uint64, err error)
- type EVMInterpreter
- type GetHashFunc
- type JSONLogger
- func (l *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error
- func (l *JSONLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, ...) error
- func (l *JSONLogger) CaptureStart(from crypto.CommonAddress, to crypto.CommonAddress, create bool, input []byte, ...) error
- func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, ...) error
- type LogConfig
- type Memory
- func (m *Memory) Data() []byte
- func (m *Memory) Get(offset, size int64) (cpy []byte)
- func (m *Memory) GetPtr(offset, size int64) []byte
- func (m *Memory) Len() int
- func (m *Memory) Print()
- func (m *Memory) Resize(size uint64)
- func (m *Memory) Set(offset, size uint64, value []byte)
- func (m *Memory) Set32(offset uint64, val *big.Int)
- type Message
- type OpCode
- type PrecompiledContract
- type Stack
- type State
- func (s *State) AddBalance(addr *crypto.CommonAddress, amount *big.Int) error
- func (s *State) AddLog(contractAddr crypto.CommonAddress, txHash crypto.Hash, data []byte, ...) error
- func (s *State) AddRefund(gas uint64)
- func (s *State) CreateContractAccount(addr crypto.CommonAddress, byteCode []byte) (*types.Account, error)
- func (s *State) Empty(addr *crypto.CommonAddress) bool
- func (s *State) Exist(contractAddr crypto.CommonAddress) bool
- func (s *State) GetBalance(addr *crypto.CommonAddress) *big.Int
- func (s *State) GetByteCode(addr *crypto.CommonAddress) crypto.ByteCode
- func (s *State) GetCodeHash(addr crypto.CommonAddress) crypto.Hash
- func (s *State) GetCodeSize(addr crypto.CommonAddress) int
- func (s *State) GetLogs(txHash *crypto.Hash) []*types.Log
- func (s *State) GetNonce(addr *crypto.CommonAddress) uint64
- func (self *State) GetRefund() uint64
- func (s *State) HasSuicided(addr crypto.CommonAddress) bool
- func (s *State) Load(x *big.Int) ([]byte, error)
- func (s *State) SetByteCode(addr *crypto.CommonAddress, byteCode crypto.ByteCode) error
- func (s *State) SetNonce(addr *crypto.CommonAddress, nonce uint64) error
- func (s *State) Store(x, y *big.Int) error
- func (s *State) SubBalance(addr *crypto.CommonAddress, amount *big.Int) error
- func (s *State) SubRefund(gas uint64)
- func (s *State) Suicide(addr *crypto.CommonAddress) error
- type Storage
- type StructLog
- type StructLogger
- func (l *StructLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error
- func (l *StructLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, ...) error
- func (l *StructLogger) CaptureStart(from crypto.CommonAddress, to crypto.CommonAddress, create bool, input []byte, ...) error
- func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, ...) error
- func (l *StructLogger) Error() error
- func (l *StructLogger) Output() []byte
- func (l *StructLogger) StructLogs() []StructLog
- type Tracer
- type TransferFunc
- type VMConfig
- type VMState
Constants ¶
const ( GasQuickStep uint64 = 2000 //2 GasFastestStep uint64 = 3000 //3 GasFastStep uint64 = 5000 //5 GasMidStep uint64 = 8000 //8 GasSlowStep uint64 = 1000 //10 GasExtStep uint64 = 2000 //20 ExtcodeSize uint64 = 7000 //700 ExtcodeCopy uint64 = 7000 //700 ExtcodeHash uint64 = 4000 //400 Balance uint64 = 4000 //400 SLoad uint64 = 2000 //200 Calls uint64 = 7000 //700 Suicide uint64 = 5000 //5000 ExpByte uint64 = 5000 //50 CreateBySuicide uint64 = 2500 //25000 )
Gas costs
Variables ¶
var ( ErrOutOfGas = errors.New("out of gas") ErrCodeStoreOutOfGas = errors.New("contract creation code storage out of gas") ErrDepth = errors.New("max call depth exceeded") ErrTraceLimitReached = errors.New("the number of logs reached the specified limit") ErrInsufficientBalance = errors.New("insufficient balance for transfer") ErrContractAddressCollision = errors.New("contract address collision") ErrNoCompatibleInterpreter = errors.New("no compatible interpreter") ErrNotAccountAddress = errors.New("a non account address occupied") ErrAccountAlreadyExists = errors.New("account already exists") ErrAccountNotExists = errors.New("account not exists") ErrCodeAlreadyExists = errors.New("code already exists") ErrCodeNotExists = errors.New("code not exists") ErrNotLogAddress = errors.New("a non log address occupied") ErrLogAlreadyExists = errors.New("log already exists") ErrNoAccount = errors.New("the account not exist") )
List execution errors
var (
Big257 = big.NewInt(257)
)
var PrecompiledContracts = map[crypto.CommonAddress]PrecompiledContract{ crypto.BytesToAddress([]byte{1}): &ecrecover{}, crypto.BytesToAddress([]byte{2}): &sha256hash{}, crypto.BytesToAddress([]byte{3}): &ripemd160hash{}, crypto.BytesToAddress([]byte{4}): &dataCopy{}, crypto.BytesToAddress([]byte{5}): &bigModExp{}, crypto.BytesToAddress([]byte{6}): &bn256Add{}, crypto.BytesToAddress([]byte{7}): &bn256ScalarMul{}, crypto.BytesToAddress([]byte{8}): &bn256Pairing{}, }
Functions ¶
func RunPrecompiledContract ¶
func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error)
func WriteTrace ¶
WriteTrace writes a formatted trace to the given writer
Types ¶
type CanTransferFunc ¶
CanTransferFunc is the signature of a transfer guard function
type Context ¶
type Context struct { // CanTransfer returns whether the account contains // sufficient ether to transfer the value CanTransfer CanTransferFunc // Transfer transfers ether from one account to the other Transfer TransferFunc // GetHash returns the hash corresponding to n GetHash GetHashFunc // Message information Origin crypto.CommonAddress // Provides information for ORIGIN GasPrice *big.Int // Provides information for GASPRICE // Block information GasLimit uint64 // Provides information for GASLIMIT BlockNumber *big.Int // Provides information for NUMBER Time *big.Int // Provides information for TIME TxHash *crypto.Hash }
Context provides the EVM with auxiliary information. Once provided it shouldn't be modified.
type Contract ¶
type Contract struct { CallerAddr crypto.CommonAddress ContractAddr crypto.CommonAddress ChainId types.ChainIdType ByteCode crypto.ByteCode CodeHash crypto.Hash Input []byte Gas uint64 Value *big.Int Jumpdests destinations TxHash *crypto.Hash }
func NewContract ¶
func NewContract(callerAddr crypto.CommonAddress, txHash *crypto.Hash, chainId types.ChainIdType, gas uint64, value *big.Int, jumpdests destinations) *Contract
type EVM ¶
type EVM struct { // Context provides auxiliary blockchain related information Context // StateDB gives access to the underlying state State VMState // callGasTemp holds the gas available for the current call. This is needed because the // available gas is calculated in gasCall* according to the 63/64 rule and later // applied in opCall*. CallGasTemp uint64 ChainId types.ChainIdType // contains filtered or unexported fields }
EVM is the Ethereum Virtual Machine base object and provides the necessary tools to run a contract on the given state with the provided context. It should be noted that any error generated through any of the calls should be considered a revert-state-and-consume-all-gas operation, no checks on specific errors should ever be performed. The interpreter makes sure that any errors generated are to be considered faulty code.
The EVM should never be reused and is not thread safe.
func NewEVM ¶
NewEVM returns a new EVM. The returned EVM is not thread safe and should only ever be used *once*.
func (*EVM) Call ¶
func (evm *EVM) Call(caller crypto.CommonAddress, addr crypto.CommonAddress, chainId types.ChainIdType, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error)
Call executes the contract associated with the addr with the given input as parameters. It also handles any necessary value transfer required and takes the necessary steps to create accounts and reverses the state in case of an execution error or failed value transfer.
func (*EVM) CallCode ¶
func (evm *EVM) CallCode(caller crypto.CommonAddress, addr crypto.CommonAddress, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error)
CallCode executes the contract associated with the addr with the given input as parameters. It also handles any necessary value transfer required and takes the necessary steps to create accounts and reverses the state in case of an execution error or failed value transfer.
CallCode differs from Call in the sense that it executes the given address' code with the caller as context.
func (*EVM) Cancel ¶
func (evm *EVM) Cancel()
Cancel cancels any running EVM operation. This may be called concurrently and it's safe to be called multiple times.
func (*EVM) Create ¶
func (evm *EVM) Create(caller crypto.CommonAddress, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr crypto.CommonAddress, leftOverGas uint64, err error)
Create creates a new contract using code as deployment code.
func (*EVM) Create2 ¶
func (evm *EVM) Create2(caller crypto.CommonAddress, code []byte, gas uint64, endowment *big.Int, salt *big.Int) (ret []byte, contractAddr crypto.CommonAddress, leftOverGas uint64, err error)
Create2 creates a new contract using code as deployment code.
The different between Create2 with Create is Create2 uses sha3(0xff ++ msg.sender ++ salt ++ sha3(init_code))[12:] instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.
func (*EVM) CreateContractCode ¶
func (evm *EVM) CreateContractCode(caller crypto.CommonAddress, codeAndHash *codeAndHash, gas uint64, value *big.Int, address crypto.CommonAddress) ([]byte, crypto.CommonAddress, uint64, error)
create creates a new contract using code as deployment code.
func (*EVM) DelegateCall ¶
func (*EVM) Interpreter ¶
func (evm *EVM) Interpreter() *EVMInterpreter
Interpreter returns the current interpreter
func (*EVM) StaticCall ¶
func (evm *EVM) StaticCall(caller crypto.CommonAddress, addr crypto.CommonAddress, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error)
StaticCall executes the contract associated with the addr with the given input as parameters while disallowing any modifications to the state during the call. Opcodes that attempt to perform such modifications will result in exceptions instead of performing the modifications.
type EVMInterpreter ¶
type EVMInterpreter struct { IntPool *intPool EVM *EVM JumpTable [256]operation ReturnData []byte ReadOnly bool Tracer Tracer // Opcode logger }
func NewEVMInterpreter ¶
func NewEVMInterpreter(evm *EVM) *EVMInterpreter
type GetHashFunc ¶
GetHashFunc returns the nth block hash in the blockchain and is used by the BLOCKHASH EVM op code.
type JSONLogger ¶
type JSONLogger struct {
// contains filtered or unexported fields
}
func NewJSONLogger ¶
func NewJSONLogger(cfg *LogConfig, writer io.Writer) *JSONLogger
NewJSONLogger creates a new EVM tracer that prints execution steps as JSON objects into the provided stream.
func (*JSONLogger) CaptureEnd ¶
CaptureEnd is triggered at end of execution.
func (*JSONLogger) CaptureFault ¶
func (l *JSONLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error
CaptureFault outputs state information on the logger.
func (*JSONLogger) CaptureStart ¶
func (l *JSONLogger) CaptureStart(from crypto.CommonAddress, to crypto.CommonAddress, create bool, input []byte, gas uint64, value *big.Int) error
type LogConfig ¶
type LogConfig struct { DisableMemory bool // disable memory capture DisableStack bool // disable stack capture DisableStorage bool // disable storage capture Debug bool // print output during capture end Limit int // maximum length of output, but zero means unlimited }
LogConfig are the configuration options for structured logger the EVM
type Memory ¶
type Memory struct {
// contains filtered or unexported fields
}
Memory implements a simple memory model for the ethereum virtual machine.
type Message ¶
type Message struct { From crypto.CommonAddress To crypto.CommonAddress ChainId types.ChainIdType DestChain types.ChainIdType Gas uint64 Value *big.Int Nonce uint64 Input []byte ReadOnly bool }
type OpCode ¶
type OpCode byte
OpCode is an EVM opcode
0x0 range - arithmetic ops.
0x10 range - comparison ops.
const ( ADDRESS OpCode = 0x30 + iota BALANCE ORIGIN CALLER CALLVALUE CALLDATALOAD CALLDATASIZE CALLDATACOPY CODESIZE CODECOPY GASPRICE EXTCODESIZE EXTCODECOPY RETURNDATASIZE RETURNDATACOPY EXTCODEHASH )
0x30 range - closure state.
0x40 range - block operations.
const ( POP OpCode = 0x50 + iota MLOAD MSTORE MSTORE8 SLOAD SSTORE JUMP JUMPI PC MSIZE GAS JUMPDEST )
0x50 range - 'storage' and execution.
const ( PUSH1 OpCode = 0x60 + iota PUSH2 PUSH3 PUSH4 PUSH5 PUSH6 PUSH7 PUSH8 PUSH9 PUSH10 PUSH11 PUSH12 PUSH13 PUSH14 PUSH15 PUSH16 PUSH17 PUSH18 PUSH19 PUSH20 PUSH21 PUSH22 PUSH23 PUSH24 PUSH25 PUSH26 PUSH27 PUSH28 PUSH29 PUSH30 PUSH31 PUSH32 DUP1 DUP2 DUP3 DUP4 DUP5 DUP6 DUP7 DUP8 DUP9 DUP10 DUP11 DUP12 DUP13 DUP14 DUP15 DUP16 SWAP1 SWAP2 SWAP3 SWAP4 SWAP5 SWAP6 SWAP7 SWAP8 SWAP9 SWAP10 SWAP11 SWAP12 SWAP13 SWAP14 SWAP15 SWAP16 )
0x60 range.
const ( CREATE OpCode = 0xf0 + iota CALL CALLCODE RETURN DELEGATECALL CREATE2 STATICCALL = 0xfa REVERT = 0xfd SELFDESTRUCT = 0xff )
0xf0 range - closures.
func StringToOp ¶
StringToOp finds the opcode whose name is stored in `str`.
func (OpCode) IsStaticJump ¶
IsStaticJump specifies if an opcode is JUMP.
type PrecompiledContract ¶
type PrecompiledContract interface { RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use Run(input []byte) ([]byte, error) // Run runs the precompiled contract }
PrecompiledContract is the basic interface for native Go contracts. The implementation requires a deterministic gas count based on the input size of the Run method of the contract.
type Stack ¶
type Stack struct {
// contains filtered or unexported fields
}
Stack is an object for basic stack operations. Items popped to the stack are expected to be changed and modified. stack does not take care of adding newly initialised objects.
type State ¶
type State struct {
// contains filtered or unexported fields
}
func (*State) AddBalance ¶
func (*State) CreateContractAccount ¶
func (*State) GetBalance ¶
func (s *State) GetBalance(addr *crypto.CommonAddress) *big.Int
func (*State) GetByteCode ¶
func (s *State) GetByteCode(addr *crypto.CommonAddress) crypto.ByteCode
func (*State) GetCodeHash ¶
func (s *State) GetCodeHash(addr crypto.CommonAddress) crypto.Hash
func (*State) GetCodeSize ¶
func (s *State) GetCodeSize(addr crypto.CommonAddress) int
func (*State) HasSuicided ¶
func (s *State) HasSuicided(addr crypto.CommonAddress) bool
TODO test suicided
func (*State) SetByteCode ¶
func (*State) SubBalance ¶
type StructLog ¶
type StructLog struct { Pc uint64 `json:"pc"` Op OpCode `json:"op"` Gas uint64 `json:"gas"` GasCost uint64 `json:"gasCost"` Memory []byte `json:"memory"` MemorySize int `json:"memSize"` Stack []*big.Int `json:"stack"` Storage map[crypto.Hash]crypto.Hash `json:"-"` Depth int `json:"depth"` RefundCounter uint64 `json:"refund"` Err error `json:"-"` }
StructLog is emitted to the EVM each cycle and lists information about the current internal state prior to the execution of the statement.
func (*StructLog) ErrorString ¶
ErrorString formats the log's error as a string.
type StructLogger ¶
type StructLogger struct {
// contains filtered or unexported fields
}
StructLogger is an EVM state logger and implements Tracer.
StructLogger can capture state based on the given Log configuration and also keeps a track record of modified storage which is used in reporting snapshots of the contract their storage.
func NewStructLogger ¶
func NewStructLogger(cfg *LogConfig) *StructLogger
NewStructLogger returns a new logger
func (*StructLogger) CaptureEnd ¶
CaptureEnd is called after the call finishes to finalize the tracing.
func (*StructLogger) CaptureFault ¶
func (l *StructLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error
CaptureFault implements the Tracer interface to trace an execution fault while running an opcode.
func (*StructLogger) CaptureStart ¶
func (l *StructLogger) CaptureStart(from crypto.CommonAddress, to crypto.CommonAddress, create bool, input []byte, gas uint64, value *big.Int) error
CaptureStart implements the Tracer interface to initialize the tracing operation.
func (*StructLogger) CaptureState ¶
func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error
CaptureState logs a new structured log message and pushes it out to the environment
CaptureState also tracks SSTORE ops to track dirty values.
func (*StructLogger) Error ¶
func (l *StructLogger) Error() error
Error returns the VM error captured by the trace.
func (*StructLogger) Output ¶
func (l *StructLogger) Output() []byte
Output returns the VM return value captured by the trace.
func (*StructLogger) StructLogs ¶
func (l *StructLogger) StructLogs() []StructLog
StructLogs returns the captured log entries.
type Tracer ¶
type Tracer interface { CaptureStart(from crypto.CommonAddress, to crypto.CommonAddress, call bool, input []byte, gas uint64, value *big.Int) error CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error }
Tracer is used to collect execution traces from an EVM transaction execution. CaptureState is called for each step of the VM with the current VM state. Note that reference types are actual VM data structures; make copies if you need to retain them beyond the current call.
type TransferFunc ¶
type TransferFunc func(VMState, crypto.CommonAddress, crypto.CommonAddress, *big.Int)
TransferFunc is the signature of a transfer function
type VMConfig ¶
type VMConfig struct { // Debug enabled debugging Interpreter options LogConfig *LogConfig `json:"logconfig"` // Tracer is the op code logger // Tracer Tracer // NoRecursion disabled Interpreter call, callcode, // delegate call and create. NoRecursion bool `json:"noRecursion"` // StartMiner recording of SHA3/keccak preimages EnablePreimageRecording bool `json:"enablePreimageRecording"` // Type of the EWASM interpreter EWASMInterpreter string `json:"ewasmInterpreter"` // Type of the EVM interpreter EVMInterpreter string `json:"evmInterpreter"` }
type VMState ¶
type VMState interface { CreateContractAccount(addr crypto.CommonAddress, byteCode []byte) (*types.Account, error) SubBalance(addr *crypto.CommonAddress, amount *big.Int) error AddBalance(addr *crypto.CommonAddress, amount *big.Int) error GetBalance(addr *crypto.CommonAddress) *big.Int SetNonce(addr *crypto.CommonAddress, nonce uint64) error GetNonce(addr *crypto.CommonAddress) uint64 Suicide(addr *crypto.CommonAddress) error GetByteCode(addr *crypto.CommonAddress) crypto.ByteCode GetCodeSize(addr crypto.CommonAddress) int GetCodeHash(addr crypto.CommonAddress) crypto.Hash SetByteCode(addr *crypto.CommonAddress, byteCode crypto.ByteCode) error //GetLogs(txHash crypto.Hash) []*types.Log AddLog(contractAddr crypto.CommonAddress, txHash crypto.Hash, data []byte, topics []crypto.Hash, blockNumber uint64) error AddRefund(gas uint64) SubRefund(gas uint64) GetRefund() uint64 Load(x *big.Int) ([]byte, error) Store(x, y *big.Int) error Exist(contractAddr crypto.CommonAddress) bool Empty(addr *crypto.CommonAddress) bool HasSuicided(addr crypto.CommonAddress) bool }