core/vm: after merge

This commit is contained in:
Paweł Bylica 2017-01-20 22:14:10 +01:00
parent e27c5ef401
commit 284c0138fb
No known key found for this signature in database
GPG key ID: 7A0C037434FE77EF
2 changed files with 30 additions and 32 deletions

View file

@ -74,7 +74,7 @@ type EVM struct {
vmConfig Config vmConfig Config
// global (to this context) ethereum virtual machine // global (to this context) ethereum virtual machine
// used throughout the execution of the tx. // used throughout the execution of the tx.
interpreter *Interpreter interpreter *EVMJIT
// abort is used to abort the EVM calling operations // abort is used to abort the EVM calling operations
// NOTE: must be set atomically // NOTE: must be set atomically
abort int32 abort int32
@ -89,7 +89,7 @@ func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmCon
chainConfig: chainConfig, chainConfig: chainConfig,
} }
evm.interpreter = NewInterpreter(evm, vmConfig) evm.interpreter = NewJit(evm, vmConfig)
return evm return evm
} }
@ -325,4 +325,4 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas, value *big.Int) (re
func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig } func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }
// Interpreter returns the EVM interpreter // Interpreter returns the EVM interpreter
func (evm *EVM) Interpreter() *Interpreter { return evm.interpreter } func (evm *EVM) Interpreter() *EVMJIT { return evm.interpreter }

View file

@ -19,7 +19,6 @@ package vm
/* /*
#include <evmjit.h> #include <evmjit.h>
#include <stdlib.h>
static struct evm_instance* new_evmjit() static struct evm_instance* new_evmjit()
@ -63,6 +62,7 @@ import (
"sync" "sync"
"unsafe" "unsafe"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -70,15 +70,15 @@ import (
type EVMJIT struct { type EVMJIT struct {
jit *C.struct_evm_instance jit *C.struct_evm_instance
env *Environment env *EVM
} }
type EVMCContext struct { type EVMCContext struct {
contract *Contract contract *Contract
env *Environment env *EVM
} }
func NewJit(env *Environment, cfg Config) *EVMJIT { func NewJit(env *EVM, cfg Config) *EVMJIT {
// FIXME: Destroy the jit later. // FIXME: Destroy the jit later.
return &EVMJIT{C.new_evmjit(), env} return &EVMJIT{C.new_evmjit(), env}
} }
@ -226,7 +226,7 @@ func query(pResult unsafe.Pointer, ctxIdx uintptr, key int32, pArg unsafe.Pointe
*pInt64Result = exist *pInt64Result = exist
// fmt.Printf("EXISTS? %x : %v\n", addr, exist) // fmt.Printf("EXISTS? %x : %v\n", addr, exist)
case C.EVM_CALL_DEPTH: case C.EVM_CALL_DEPTH:
*pInt64Result = int64(ctx.env.Depth - 1) *pInt64Result = int64(ctx.env.depth - 1)
default: default:
panic(fmt.Sprintf("Unhandled EVM-C query %d\n", key)) panic(fmt.Sprintf("Unhandled EVM-C query %d\n", key))
@ -258,8 +258,12 @@ func update(ctxIdx uintptr, key int32, pArg1 unsafe.Pointer, pArg2 unsafe.Pointe
for i := 0; i < nTopics; i++ { for i := 0; i < nTopics; i++ {
copy(topics[i][:], tData[i*32:(i+1)*32]) copy(topics[i][:], tData[i*32:(i+1)*32])
} }
log := NewLog(ctx.contract.Address(), topics, data, ctx.env.BlockNumber.Uint64()) ctx.env.StateDB.AddLog(&types.Log{
ctx.env.StateDB.AddLog(log) Address: ctx.contract.Address(),
Topics: topics,
Data: data,
BlockNumber: ctx.env.BlockNumber.Uint64(),
})
case C.EVM_SELFDESTRUCT: case C.EVM_SELFDESTRUCT:
arg := GoByteSlice(pArg1, 32) arg := GoByteSlice(pArg1, 32)
db := ctx.env.StateDB db := ctx.env.StateDB
@ -293,6 +297,10 @@ func call(
output := GoByteSlice(pOutput, outputSize) output := GoByteSlice(pOutput, outputSize)
bigGas := new(big.Int).SetInt64(gas) bigGas := new(big.Int).SetInt64(gas)
// TODO: For some reason C.EVM_CALL_FAILURE "constant" is not visible
// by go linker. This probably should be reported as cgo bug.
const callFailureFlag int64 = -(1 << 63);
switch kind { switch kind {
case C.EVM_CALL: case C.EVM_CALL:
// fmt.Printf("CALL(gas %d, %x)\n", bigGas, address) // fmt.Printf("CALL(gas %d, %x)\n", bigGas, address)
@ -306,7 +314,7 @@ func call(
assert(gasLeft <= gas, fmt.Sprintf("%d <= %d", gasLeft, gas)) assert(gasLeft <= gas, fmt.Sprintf("%d <= %d", gasLeft, gas))
return gasLeft return gasLeft
} }
return gasLeft | C.EVM_CALL_FAILURE return gasLeft | callFailureFlag
case C.EVM_CALLCODE: case C.EVM_CALLCODE:
// fmt.Printf("CALLCODE(gas %d, %x, value %d)\n", bigGas, address, value) // fmt.Printf("CALLCODE(gas %d, %x, value %d)\n", bigGas, address, value)
ctx.contract.Gas.SetInt64(0) ctx.contract.Gas.SetInt64(0)
@ -320,7 +328,7 @@ func call(
} else { } else {
// fmt.Printf("Error: %v\n", err) // fmt.Printf("Error: %v\n", err)
} }
return gasLeft | C.EVM_CALL_FAILURE return gasLeft | callFailureFlag
case C.EVM_DELEGATECALL: case C.EVM_DELEGATECALL:
// fmt.Printf("DELEGATECALL(gas %d, %x)\n", bigGas, address) // fmt.Printf("DELEGATECALL(gas %d, %x)\n", bigGas, address)
ctx.contract.Gas.SetInt64(0) ctx.contract.Gas.SetInt64(0)
@ -332,16 +340,16 @@ func call(
copy(output, ret) copy(output, ret)
return gasLeft return gasLeft
} }
return gasLeft | C.EVM_CALL_FAILURE return gasLeft | callFailureFlag
case C.EVM_CREATE: case C.EVM_CREATE:
// fmt.Printf("DELEGATECALL(gas %d, %x)\n", bigGas, address) // fmt.Printf("DELEGATECALL(gas %d, %x)\n", bigGas, address)
ctx.contract.Gas.SetInt64(0) ctx.contract.Gas.SetInt64(0)
_, addr, err := ctx.env.Create(ctx.contract, input, bigGas, value) _, addr, err := ctx.env.Create(ctx.contract, input, bigGas, value)
gasLeft := ctx.contract.Gas.Int64() gasLeft := ctx.contract.Gas.Int64()
assert(gasLeft <= gas, fmt.Sprintf("%d <= %d", gasLeft, gas)) assert(gasLeft <= gas, fmt.Sprintf("%d <= %d", gasLeft, gas))
if (ctx.env.ChainConfig().IsHomestead(ctx.env.BlockNumber) && err == CodeStoreOutOfGasError) || if (ctx.env.ChainConfig().IsHomestead(ctx.env.BlockNumber) && err == ErrCodeStoreOutOfGas) ||
(err != nil && err != CodeStoreOutOfGasError) { (err != nil && err != ErrCodeStoreOutOfGas) {
return C.EVM_CALL_FAILURE return callFailureFlag
} else { } else {
copy(output, addr[:]) copy(output, addr[:])
return gasLeft return gasLeft
@ -355,7 +363,7 @@ func ptr(bytes []byte) *C.uint8_t {
return (*C.uint8_t)(unsafe.Pointer(header.Data)) return (*C.uint8_t)(unsafe.Pointer(header.Data))
} }
func getMode(env *Environment) C.enum_evm_mode { func getMode(env *EVM) C.enum_evm_mode {
n := env.BlockNumber n := env.BlockNumber
if env.ChainConfig().IsEIP158(n) { if env.ChainConfig().IsEIP158(n) {
return C.EVM_CLEARING return C.EVM_CLEARING
@ -370,12 +378,12 @@ func getMode(env *Environment) C.enum_evm_mode {
} }
func (evm *EVMJIT) Run(contract *Contract, input []byte) (ret []byte, err error) { func (evm *EVMJIT) Run(contract *Contract, input []byte) (ret []byte, err error) {
evm.env.Depth++ evm.env.depth++
defer func() { evm.env.Depth-- }() defer func() { evm.env.depth-- }()
if contract.CodeAddr != nil { if contract.CodeAddr != nil {
if p := Precompiled[contract.CodeAddr.Str()]; p != nil { if p := PrecompiledContracts[*contract.CodeAddr]; p != nil {
return evm.RunPrecompiled(p, input, contract) return RunPrecompiledContract(p, input, contract)
} }
} }
@ -412,19 +420,9 @@ func (evm *EVMJIT) Run(contract *Contract, input []byte) (ret []byte, err error)
if r.code != 0 { if r.code != 0 {
// EVMJIT does not informs about the kind of the EVM expection. // EVMJIT does not informs about the kind of the EVM expection.
err = OutOfGasError err = ErrOutOfGas
} }
C.evm_release_result(&r) C.evm_release_result(&r)
return output, err return output, err
} }
func (evm *EVMJIT) RunPrecompiled(p *PrecompiledAccount, input []byte, contract *Contract) (ret []byte, err error) {
gas := p.Gas(len(input))
if contract.UseGas(gas) {
ret = p.Call(input)
return ret, nil
} else {
return nil, OutOfGasError
}
}