mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 02:12:23 +00:00
evmjit: Switch to aleth-interpreter
This commit is contained in:
parent
2cb5b8a3ef
commit
99caf5df5e
1 changed files with 107 additions and 81 deletions
|
|
@ -18,44 +18,46 @@ package vm
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
#include <evmjit.h>
|
#include <libaleth-interpreter/interpreter.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
static const struct evm_context_fn_table* get_context_fn_table()
|
static const struct evmc_context_fn_table* get_context_fn_table()
|
||||||
{
|
{
|
||||||
int account_exists(void*, void*);
|
int account_exists(void*, void*);
|
||||||
void get_storage(struct evm_uint256be*, void*, void*, struct evm_uint256be*);
|
void get_storage(struct evmc_uint256be*, void*, void*, struct evmc_uint256be*);
|
||||||
void set_storage(void*, void*, void*, void*);
|
void set_storage(void*, void*, void*, void*);
|
||||||
void get_balance(void*, void*, void*);
|
void get_balance(void*, void*, void*);
|
||||||
size_t get_code(unsigned char**, void*, void*);
|
size_t get_code_size(void*, void*);
|
||||||
|
size_t copy_code(void*, void*, size_t, uint8_t*, size_t);
|
||||||
void selfdestruct(void*, void*, void*);
|
void selfdestruct(void*, void*, void*);
|
||||||
void call(struct evm_result*, void*, struct evm_message*);
|
void call(struct evmc_result*, void*, struct evmc_message*);
|
||||||
void getTxCtx(void*, void*);
|
void getTxCtx(void*, void*);
|
||||||
void getBlockHash(void*, void*, long long);
|
void getBlockHash(void*, void*, long long);
|
||||||
void set_logs(void*, void*, void*, size_t, void*, size_t);
|
void emit_log(void*, void*, void*, size_t, void*, size_t);
|
||||||
|
|
||||||
static const struct evm_context_fn_table fn_table = {
|
static const struct evmc_context_fn_table fn_table = {
|
||||||
(evm_account_exists_fn) account_exists,
|
(evmc_account_exists_fn) account_exists,
|
||||||
(evm_get_storage_fn) get_storage,
|
(evmc_get_storage_fn) get_storage,
|
||||||
(evm_set_storage_fn) set_storage,
|
(evmc_set_storage_fn) set_storage,
|
||||||
(evm_get_balance_fn) get_balance,
|
(evmc_get_balance_fn) get_balance,
|
||||||
(evm_get_code_fn) get_code,
|
(evmc_get_code_size_fn) get_code_size,
|
||||||
(evm_selfdestruct_fn) selfdestruct,
|
(evmc_copy_code_fn) copy_code,
|
||||||
(evm_call_fn) call,
|
(evmc_selfdestruct_fn) selfdestruct,
|
||||||
(evm_get_tx_context_fn) getTxCtx,
|
(evmc_call_fn) call,
|
||||||
(evm_get_block_hash_fn) getBlockHash,
|
(evmc_get_tx_context_fn) getTxCtx,
|
||||||
(evm_log_fn) set_logs
|
(evmc_get_block_hash_fn) getBlockHash,
|
||||||
|
(evmc_emit_log_fn) emit_log
|
||||||
};
|
};
|
||||||
return &fn_table;
|
return &fn_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct evm_result evm_execute(
|
static struct evmc_result evmc_execute(
|
||||||
struct evm_instance* instance,
|
struct evmc_instance* instance,
|
||||||
struct evm_context* context,
|
struct evmc_context* context,
|
||||||
enum evm_revision rev,
|
enum evmc_revision rev,
|
||||||
const struct evm_message* msg,
|
const struct evmc_message* msg,
|
||||||
uint8_t const* code,
|
uint8_t const* code,
|
||||||
size_t code_size
|
size_t code_size
|
||||||
)
|
)
|
||||||
|
|
@ -63,23 +65,23 @@ static struct evm_result evm_execute(
|
||||||
return instance->execute(instance, context, rev, msg, code, code_size);
|
return instance->execute(instance, context, rev, msg, code, code_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void evm_release_result(struct evm_result* result)
|
static void evmc_release_result(struct evmc_result* result)
|
||||||
{
|
{
|
||||||
result->release(result);
|
result->release(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_result_output(const struct evm_result* result)
|
static void free_result_output(const struct evmc_result* result)
|
||||||
{
|
{
|
||||||
free((void*)result->output_data);
|
free((void*)result->output_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_result_releaser(struct evm_result* result)
|
static void add_result_releaser(struct evmc_result* result)
|
||||||
{
|
{
|
||||||
result->release = free_result_output;
|
result->release = free_result_output;
|
||||||
}
|
}
|
||||||
|
|
||||||
#cgo CFLAGS: -I/home/chfast/Projects/ethereum/evmjit/include
|
#cgo CFLAGS: -I/home/chfast/Projects/ethereum/cpp-ethereum -I/home/chfast/Projects/ethereum/cpp-ethereum/evmc/include
|
||||||
#cgo LDFLAGS: -levmjit-standalone -lstdc++ -lm -ldl -L/home/chfast/Projects/ethereum/evmjit/build/release-llvm/libevmjit
|
#cgo LDFLAGS: -laleth-interpreter -lstdc++ -lm -ldl -L/home/chfast/Projects/ethereum/cpp-ethereum/build/interpreter/libaleth-interpreter
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
|
|
@ -97,7 +99,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type EVMJIT struct {
|
type EVMJIT struct {
|
||||||
jit *C.struct_evm_instance
|
jit *C.struct_evmc_instance
|
||||||
env *EVM
|
env *EVM
|
||||||
intPool *intPool
|
intPool *intPool
|
||||||
readOnly bool
|
readOnly bool
|
||||||
|
|
@ -110,13 +112,13 @@ type EVMCContext struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ContextWrapper struct {
|
type ContextWrapper struct {
|
||||||
c C.struct_evm_context
|
c C.struct_evmc_context
|
||||||
index int
|
index int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewJit(env *EVM, cfg Config) *EVMJIT {
|
func NewJit(env *EVM, cfg Config) *EVMJIT {
|
||||||
// FIXME: Destroy the jit later.
|
// FIXME: Destroy the jit later.
|
||||||
return &EVMJIT{C.evmjit_create(), env, nil, false, nil}
|
return &EVMJIT{C.evmc_create_interpreter(), env, nil, false, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -158,15 +160,15 @@ func getContract(pCtx unsafe.Pointer) *Contract {
|
||||||
return getCtx(ctxWrapper.index).contract
|
return getCtx(ctxWrapper.index).contract
|
||||||
}
|
}
|
||||||
|
|
||||||
func HashToEvmc(hash common.Hash) C.struct_evm_uint256be {
|
func HashToEvmc(hash common.Hash) C.struct_evmc_uint256be {
|
||||||
return C.struct_evm_uint256be{*(*[32]C.uint8_t)(unsafe.Pointer(&hash[0]))}
|
return C.struct_evmc_uint256be{*(*[32]C.uint8_t)(unsafe.Pointer(&hash[0]))}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddressToEvmc(addr common.Address) C.struct_evm_address {
|
func AddressToEvmc(addr common.Address) C.struct_evmc_address {
|
||||||
return C.struct_evm_address{*(*[20]C.uint8_t)(unsafe.Pointer(&addr[0]))}
|
return C.struct_evmc_address{*(*[20]C.uint8_t)(unsafe.Pointer(&addr[0]))}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BigToEvmc(i *big.Int) C.struct_evm_uint256be {
|
func BigToEvmc(i *big.Int) C.struct_evmc_uint256be {
|
||||||
return HashToEvmc(common.BigToHash(i))
|
return HashToEvmc(common.BigToHash(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,7 +186,7 @@ func GoByteSlice(data unsafe.Pointer, size C.size_t) []byte {
|
||||||
return *(*[]byte)(unsafe.Pointer(&sliceHeader))
|
return *(*[]byte)(unsafe.Pointer(&sliceHeader))
|
||||||
}
|
}
|
||||||
|
|
||||||
func EvmcHashToSlice(uint256 *C.struct_evm_uint256be) []byte {
|
func EvmcHashToSlice(uint256 *C.struct_evmc_uint256be) []byte {
|
||||||
return GoByteSlice(unsafe.Pointer(uint256), 32)
|
return GoByteSlice(unsafe.Pointer(uint256), 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -210,7 +212,7 @@ func account_exists(pCtx unsafe.Pointer, pAddr unsafe.Pointer) C.int {
|
||||||
}
|
}
|
||||||
|
|
||||||
//export get_storage
|
//export get_storage
|
||||||
func get_storage(pResult *C.struct_evm_uint256be, pCtx unsafe.Pointer, pAddr unsafe.Pointer, pArg *C.struct_evm_uint256be) {
|
func get_storage(pResult *C.struct_evmc_uint256be, pCtx unsafe.Pointer, pAddr unsafe.Pointer, pArg *C.struct_evmc_uint256be) {
|
||||||
result := EvmcHashToSlice(pResult)
|
result := EvmcHashToSlice(pResult)
|
||||||
env := getEnv(pCtx)
|
env := getEnv(pCtx)
|
||||||
|
|
||||||
|
|
@ -234,8 +236,8 @@ func set_storage(pCtx unsafe.Pointer, pAddr unsafe.Pointer, pArg1 unsafe.Pointer
|
||||||
newVal := *(*[32]byte)(pArg2)
|
newVal := *(*[32]byte)(pArg2)
|
||||||
oldVal := env.StateDB.GetState(addr, key)
|
oldVal := env.StateDB.GetState(addr, key)
|
||||||
env.StateDB.SetState(addr, key, newVal)
|
env.StateDB.SetState(addr, key, newVal)
|
||||||
if !common.EmptyHash(oldVal) && common.EmptyHash(newVal) {
|
if oldVal != (common.Hash{}) && newVal == (common.Hash{}) {
|
||||||
env.StateDB.AddRefund(new(big.Int).SetUint64(params.SstoreRefundGas))
|
env.StateDB.AddRefund(params.SstoreRefundGas)
|
||||||
}
|
}
|
||||||
// fmt.Printf("EVMJIT STORE %x: %x := %x\n", addr, key, newVal)
|
// fmt.Printf("EVMJIT STORE %x: %x := %x\n", addr, key, newVal)
|
||||||
}
|
}
|
||||||
|
|
@ -253,21 +255,37 @@ func get_balance(pResult unsafe.Pointer, pCtx unsafe.Pointer, pAddr unsafe.Point
|
||||||
// fmt.Printf("BALANCE %x : %v\n", addr, balance)
|
// fmt.Printf("BALANCE %x : %v\n", addr, balance)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export get_code
|
//export get_code_size
|
||||||
func get_code(ppCode **C.uint8_t, pCtx unsafe.Pointer, pAddr unsafe.Pointer) C.size_t {
|
func get_code_size(pCtx unsafe.Pointer, pAddr unsafe.Pointer) C.size_t {
|
||||||
env := getEnv(pCtx)
|
env := getEnv(pCtx)
|
||||||
|
|
||||||
var addr common.Address
|
var addr common.Address
|
||||||
copy(addr[:], GoByteSlice(pAddr, 20))
|
copy(addr[:], GoByteSlice(pAddr, 20))
|
||||||
if ppCode != nil {
|
return C.size_t(env.StateDB.GetCodeSize(addr));
|
||||||
code := env.StateDB.GetCode(addr)
|
}
|
||||||
*ppCode = ptr(code)
|
|
||||||
|
|
||||||
// fmt.Printf("EXTCODE %x : %d\n", addr, pResAsMemRef.len)
|
//export copy_code
|
||||||
return C.size_t(len(code))
|
func copy_code(pCtx unsafe.Pointer, pAddr unsafe.Pointer, offset C.size_t, p *C.uint8_t, size C.size_t) C.size_t {
|
||||||
} else {
|
env := getEnv(pCtx)
|
||||||
return C.size_t(env.StateDB.GetCodeSize(addr))
|
|
||||||
|
var addr common.Address
|
||||||
|
copy(addr[:], GoByteSlice(pAddr, 20))
|
||||||
|
code := env.StateDB.GetCode(addr)
|
||||||
|
length := C.size_t(len(code))
|
||||||
|
|
||||||
|
if offset >= length {
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toCopy := length - offset;
|
||||||
|
if toCopy > size {
|
||||||
|
toCopy = size
|
||||||
|
}
|
||||||
|
|
||||||
|
out := GoByteSlice(unsafe.Pointer(p), size)
|
||||||
|
|
||||||
|
copy(out, code[offset:])
|
||||||
|
return toCopy
|
||||||
}
|
}
|
||||||
|
|
||||||
//export selfdestruct
|
//export selfdestruct
|
||||||
|
|
@ -282,7 +300,7 @@ func selfdestruct(pCtx unsafe.Pointer, pAddr unsafe.Pointer, pArg unsafe.Pointer
|
||||||
|
|
||||||
db := env.StateDB
|
db := env.StateDB
|
||||||
if !db.HasSuicided(addr) {
|
if !db.HasSuicided(addr) {
|
||||||
db.AddRefund(new(big.Int).SetUint64(params.SuicideRefundGas))
|
db.AddRefund(params.SuicideRefundGas)
|
||||||
}
|
}
|
||||||
balance := db.GetBalance(addr)
|
balance := db.GetBalance(addr)
|
||||||
db.AddBalance(beneficiary, balance)
|
db.AddBalance(beneficiary, balance)
|
||||||
|
|
@ -292,13 +310,13 @@ func selfdestruct(pCtx unsafe.Pointer, pAddr unsafe.Pointer, pArg unsafe.Pointer
|
||||||
//export getTxCtx
|
//export getTxCtx
|
||||||
func getTxCtx(pResult unsafe.Pointer, pCtx unsafe.Pointer) {
|
func getTxCtx(pResult unsafe.Pointer, pCtx unsafe.Pointer) {
|
||||||
env := getEnv(pCtx)
|
env := getEnv(pCtx)
|
||||||
txCtx := (*C.struct_evm_tx_context)(pResult)
|
txCtx := (*C.struct_evmc_tx_context)(pResult)
|
||||||
txCtx.tx_gas_price = BigToEvmc(env.GasPrice)
|
txCtx.tx_gas_price = BigToEvmc(env.GasPrice)
|
||||||
txCtx.tx_origin = AddressToEvmc(env.Origin)
|
txCtx.tx_origin = AddressToEvmc(env.Origin)
|
||||||
txCtx.block_coinbase = AddressToEvmc(env.Coinbase)
|
txCtx.block_coinbase = AddressToEvmc(env.Coinbase)
|
||||||
txCtx.block_number = C.int64_t(env.BlockNumber.Int64())
|
txCtx.block_number = C.int64_t(env.BlockNumber.Int64())
|
||||||
txCtx.block_timestamp = C.int64_t(env.Time.Int64())
|
txCtx.block_timestamp = C.int64_t(env.Time.Int64())
|
||||||
txCtx.block_gas_limit = C.int64_t(env.GasLimit.Int64())
|
txCtx.block_gas_limit = C.int64_t(env.GasLimit)
|
||||||
txCtx.block_difficulty = BigToEvmc(env.Difficulty)
|
txCtx.block_difficulty = BigToEvmc(env.Difficulty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -316,8 +334,8 @@ func getBlockHash(pResult unsafe.Pointer, pCtx unsafe.Pointer, number int64) {
|
||||||
copy(result, hash[:])
|
copy(result, hash[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
//export set_logs
|
//export emit_log
|
||||||
func set_logs(pCtx unsafe.Pointer, pAddr unsafe.Pointer, pData unsafe.Pointer, dataSize C.size_t, pTopics unsafe.Pointer, topicsCount C.size_t) {
|
func emit_log(pCtx unsafe.Pointer, pAddr unsafe.Pointer, pData unsafe.Pointer, dataSize C.size_t, pTopics unsafe.Pointer, topicsCount C.size_t) {
|
||||||
env := getEnv(pCtx)
|
env := getEnv(pCtx)
|
||||||
|
|
||||||
var addr common.Address
|
var addr common.Address
|
||||||
|
|
@ -340,13 +358,13 @@ func set_logs(pCtx unsafe.Pointer, pAddr unsafe.Pointer, pData unsafe.Pointer, d
|
||||||
}
|
}
|
||||||
|
|
||||||
//export call
|
//export call
|
||||||
func call(result *C.struct_evm_result, pCtx unsafe.Pointer, msg *C.struct_evm_message) {
|
func call(result *C.struct_evmc_result, pCtx unsafe.Pointer, msg *C.struct_evmc_message) {
|
||||||
env := getEnv(pCtx)
|
env := getEnv(pCtx)
|
||||||
contract := getContract(pCtx)
|
contract := getContract(pCtx)
|
||||||
|
|
||||||
addr := *(*common.Address)(unsafe.Pointer(&msg.address))
|
addr := *(*common.Address)(unsafe.Pointer(&msg.destination))
|
||||||
value := (*(*common.Hash)(unsafe.Pointer(&msg.value))).Big()
|
value := (*(*common.Hash)(unsafe.Pointer(&msg.value))).Big()
|
||||||
input := GoByteSlice(unsafe.Pointer(msg.input), msg.input_size)
|
input := GoByteSlice(unsafe.Pointer(msg.input_data), msg.input_size)
|
||||||
gas := uint64(msg.gas)
|
gas := uint64(msg.gas)
|
||||||
|
|
||||||
var output []byte
|
var output []byte
|
||||||
|
|
@ -354,8 +372,8 @@ func call(result *C.struct_evm_result, pCtx unsafe.Pointer, msg *C.struct_evm_me
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
switch msg.kind {
|
switch msg.kind {
|
||||||
case C.EVM_CALL:
|
case C.EVMC_CALL:
|
||||||
staticCall := (msg.flags & C.EVM_STATIC) != 0
|
staticCall := (msg.flags & C.EVMC_STATIC) != 0
|
||||||
if staticCall {
|
if staticCall {
|
||||||
// fmt.Printf("STATICCALL(gas %d, %x)\n", gas, addr)
|
// fmt.Printf("STATICCALL(gas %d, %x)\n", gas, addr)
|
||||||
output, gasLeft, err = env.StaticCall(contract, addr, input, gas)
|
output, gasLeft, err = env.StaticCall(contract, addr, input, gas)
|
||||||
|
|
@ -365,18 +383,19 @@ func call(result *C.struct_evm_result, pCtx unsafe.Pointer, msg *C.struct_evm_me
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
case C.EVM_CALLCODE:
|
case C.EVMC_CALLCODE:
|
||||||
// fmt.Printf("CALLCODE(gas %d, %x, value %d)\n", gas, addr, value)
|
// fmt.Printf("CALLCODE(gas %d, %x, value %d)\n", gas, addr, value)
|
||||||
output, gasLeft, err = env.CallCode(contract, addr, input, gas, value)
|
output, gasLeft, err = env.CallCode(contract, addr, input, gas, value)
|
||||||
|
|
||||||
case C.EVM_DELEGATECALL:
|
case C.EVMC_DELEGATECALL:
|
||||||
// fmt.Printf("DELEGATECALL(gas %d, %x)\n", gas, addr)
|
// fmt.Printf("DELEGATECALL(gas %d, %x)\n", gas, addr)
|
||||||
output, gasLeft, err = env.DelegateCall(contract, addr, input, gas)
|
output, gasLeft, err = env.DelegateCall(contract, addr, input, gas)
|
||||||
|
|
||||||
case C.EVM_CREATE:
|
case C.EVMC_CREATE:
|
||||||
// fmt.Printf("CREATE(gas %d, %x)\n", gas, addr)
|
// fmt.Printf("CREATE(gas %d, %x)\n", gas, addr)
|
||||||
var createAddr common.Address
|
var createAddr common.Address
|
||||||
_, createAddr, gasLeft, err = env.Create(contract, input, gas, value)
|
var createOutput []byte
|
||||||
|
createOutput, createAddr, gasLeft, err = env.Create(contract, input, gas, value)
|
||||||
isHomestead := env.ChainConfig().IsHomestead(env.BlockNumber)
|
isHomestead := env.ChainConfig().IsHomestead(env.BlockNumber)
|
||||||
if !isHomestead && err == ErrCodeStoreOutOfGas {
|
if !isHomestead && err == ErrCodeStoreOutOfGas {
|
||||||
err = nil
|
err = nil
|
||||||
|
|
@ -385,18 +404,25 @@ func call(result *C.struct_evm_result, pCtx unsafe.Pointer, msg *C.struct_evm_me
|
||||||
// Copy create address to result.
|
// Copy create address to result.
|
||||||
ca := GoByteSlice(unsafe.Pointer(&result.create_address.bytes), 20)
|
ca := GoByteSlice(unsafe.Pointer(&result.create_address.bytes), 20)
|
||||||
copy(ca, createAddr[:])
|
copy(ca, createAddr[:])
|
||||||
|
} else if err == errExecutionReverted {
|
||||||
|
// Assign return buffer from REVERT.
|
||||||
|
// TODO: Bad API design: return data buffer and the code is returned in the same place. In worst case
|
||||||
|
// the code is returned also when there is not enough funds to deploy the code.
|
||||||
|
output = createOutput
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(gasLeft <= gas, fmt.Sprintf("%d <= %d", gasLeft, gas))
|
assert(gasLeft <= gas, fmt.Sprintf("%d <= %d", gasLeft, gas))
|
||||||
// fmt.Printf("Gas left %d, err: %s\n", gasLeft, err)
|
//fmt.Printf("Gas left %d, err: %s, output: %x\n", gasLeft, err, output)
|
||||||
result.gas_left = C.int64_t(gasLeft)
|
result.gas_left = C.int64_t(gasLeft)
|
||||||
|
|
||||||
// Map error to status code.
|
// Map error to status code.
|
||||||
if err == nil {
|
if err == nil {
|
||||||
result.status_code = C.EVM_SUCCESS
|
result.status_code = C.EVMC_SUCCESS
|
||||||
|
} else if err == errExecutionReverted {
|
||||||
|
result.status_code = C.EVMC_REVERT
|
||||||
} else {
|
} else {
|
||||||
result.status_code = C.EVM_FAILURE
|
result.status_code = C.EVMC_FAILURE
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(output) > 0 {
|
if len(output) > 0 {
|
||||||
|
|
@ -419,21 +445,21 @@ func ptr(bytes []byte) *C.uint8_t {
|
||||||
return (*C.uint8_t)(unsafe.Pointer(header.Data))
|
return (*C.uint8_t)(unsafe.Pointer(header.Data))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRevision(env *EVM) C.enum_evm_revision {
|
func getRevision(env *EVM) C.enum_evmc_revision {
|
||||||
n := env.BlockNumber
|
n := env.BlockNumber
|
||||||
if env.ChainConfig().IsByzantium(n) {
|
if env.ChainConfig().IsByzantium(n) {
|
||||||
return C.EVM_BYZANTIUM
|
return C.EVMC_BYZANTIUM
|
||||||
}
|
}
|
||||||
if env.ChainConfig().IsEIP158(n) {
|
if env.ChainConfig().IsEIP158(n) {
|
||||||
return C.EVM_SPURIOUS_DRAGON
|
return C.EVMC_SPURIOUS_DRAGON
|
||||||
}
|
}
|
||||||
if env.ChainConfig().IsEIP150(n) {
|
if env.ChainConfig().IsEIP150(n) {
|
||||||
return C.EVM_TANGERINE_WHISTLE
|
return C.EVMC_TANGERINE_WHISTLE
|
||||||
}
|
}
|
||||||
if env.ChainConfig().IsHomestead(n) {
|
if env.ChainConfig().IsHomestead(n) {
|
||||||
return C.EVM_HOMESTEAD
|
return C.EVMC_HOMESTEAD
|
||||||
}
|
}
|
||||||
return C.EVM_FRONTIER
|
return C.EVMC_FRONTIER
|
||||||
}
|
}
|
||||||
|
|
||||||
func (evm *EVMJIT) Run(contract *Contract, input []byte) (ret []byte, err error) {
|
func (evm *EVMJIT) Run(contract *Contract, input []byte) (ret []byte, err error) {
|
||||||
|
|
@ -456,8 +482,8 @@ func (evm *EVMJIT) Run(contract *Contract, input []byte) (ret []byte, err error)
|
||||||
wrapper.c.fn_table = C.get_context_fn_table()
|
wrapper.c.fn_table = C.get_context_fn_table()
|
||||||
wrapper.index = pinCtx(&EVMCContext{contract, evm.env})
|
wrapper.index = pinCtx(&EVMCContext{contract, evm.env})
|
||||||
|
|
||||||
var msg C.struct_evm_message
|
var msg C.struct_evmc_message
|
||||||
msg.address = AddressToEvmc(contract.Address())
|
msg.destination = AddressToEvmc(contract.Address())
|
||||||
msg.sender = AddressToEvmc(contract.Caller())
|
msg.sender = AddressToEvmc(contract.Caller())
|
||||||
msg.value = BigToEvmc(contract.value)
|
msg.value = BigToEvmc(contract.value)
|
||||||
msg.gas = gas
|
msg.gas = gas
|
||||||
|
|
@ -465,45 +491,45 @@ func (evm *EVMJIT) Run(contract *Contract, input []byte) (ret []byte, err error)
|
||||||
codeHash := crypto.Keccak256Hash(code)
|
codeHash := crypto.Keccak256Hash(code)
|
||||||
msg.code_hash = HashToEvmc(codeHash)
|
msg.code_hash = HashToEvmc(codeHash)
|
||||||
if evm.readOnly {
|
if evm.readOnly {
|
||||||
msg.flags = C.EVM_STATIC
|
msg.flags = C.EVMC_STATIC
|
||||||
} else {
|
} else {
|
||||||
msg.flags = 0
|
msg.flags = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(input) > 0 {
|
if len(input) > 0 {
|
||||||
cInput := C.CBytes(input)
|
cInput := C.CBytes(input)
|
||||||
msg.input = (*C.uint8_t)(cInput)
|
msg.input_data = (*C.uint8_t)(cInput)
|
||||||
msg.input_size = C.size_t(len(input))
|
msg.input_size = C.size_t(len(input))
|
||||||
defer C.free(cInput)
|
defer C.free(cInput)
|
||||||
} else {
|
} else {
|
||||||
msg.input = nil
|
msg.input_data = nil
|
||||||
msg.input_size = 0
|
msg.input_size = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// fmt.Printf("EVMJIT pre Run (gas %d %d mode: %d, env: %d) %x %x\n", contract.Gas, gas, rev, wrapper.index, codeHash, contract.Address())
|
// fmt.Printf("EVMJIT pre Run (gas %d %d mode: %d, env: %d) %x %x\n", contract.Gas, gas, rev, wrapper.index, codeHash, contract.Address())
|
||||||
|
|
||||||
r := C.evm_execute(evm.jit, &wrapper.c, rev, &msg, codePtr, codeSize)
|
r := C.evmc_execute(evm.jit, &wrapper.c, rev, &msg, codePtr, codeSize)
|
||||||
|
|
||||||
unpinCtx(wrapper.index)
|
unpinCtx(wrapper.index)
|
||||||
|
|
||||||
// fmt.Printf("EVMJIT Run [%d]: %d %d %x\n", evm.env.depth - 1, r.status_code, r.gas_left, contract.Address())
|
// fmt.Printf("EVMJIT Run [%d]: %d %d %x\n", evm.env.depth - 1, r.status_code, r.gas_left, contract.Address())
|
||||||
if r.gas_left > gas {
|
if r.gas_left > gas {
|
||||||
panic("OOPS")
|
panic(fmt.Sprintf("gas left: %d, gas: %d, status: %d", r.gas_left, gas, r.status_code))
|
||||||
}
|
}
|
||||||
contract.Gas = uint64(r.gas_left)
|
contract.Gas = uint64(r.gas_left)
|
||||||
// fmt.Printf("Gas left: %d\n", contract.Gas)
|
// fmt.Printf("Gas left: %d\n", contract.Gas)
|
||||||
output := C.GoBytes(unsafe.Pointer(r.output_data), C.int(r.output_size))
|
output := C.GoBytes(unsafe.Pointer(r.output_data), C.int(r.output_size))
|
||||||
|
|
||||||
if r.status_code == C.EVM_REVERT {
|
if r.status_code == C.EVMC_REVERT {
|
||||||
err = errExecutionReverted
|
err = errExecutionReverted
|
||||||
} else if r.status_code != C.EVM_SUCCESS {
|
} else if r.status_code != C.EVMC_SUCCESS {
|
||||||
// EVMJIT does not informs about the kind of the EVM expection.
|
// EVMJIT does not informs about the kind of the EVM expection.
|
||||||
err = ErrOutOfGas
|
err = ErrOutOfGas
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.release != nil {
|
if r.release != nil {
|
||||||
// fmt.Printf("Releasing result with %p\n", r.release)
|
// fmt.Printf("Releasing result with %p\n", r.release)
|
||||||
C.evm_release_result(&r)
|
C.evmc_release_result(&r)
|
||||||
}
|
}
|
||||||
|
|
||||||
return output, err
|
return output, err
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue