mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 06:36:43 +00:00
core/vm: EVMJIT: improve callbacks
This commit is contained in:
parent
deff301c33
commit
9391a910b6
1 changed files with 28 additions and 66 deletions
|
|
@ -21,56 +21,20 @@ package vm
|
||||||
#include <evmjit.h>
|
#include <evmjit.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
static union evm_variant query_gateway(struct evm_env* env,
|
|
||||||
enum evm_query_key key,
|
|
||||||
union evm_variant arg)
|
|
||||||
{
|
|
||||||
void query(void*, size_t, int, void*);
|
|
||||||
|
|
||||||
union evm_variant result;
|
|
||||||
query(&result, (size_t)env, key, &arg);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void update(void* env, int key, void* arg1, void* arg2);
|
|
||||||
static void update_gateway(struct evm_env* env,
|
|
||||||
enum evm_update_key key,
|
|
||||||
union evm_variant arg1,
|
|
||||||
union evm_variant arg2)
|
|
||||||
{
|
|
||||||
update(env, key, &arg1, &arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef long long int64;
|
|
||||||
|
|
||||||
extern int64 call(
|
|
||||||
void* env,
|
|
||||||
int kind,
|
|
||||||
int64 gas,
|
|
||||||
void* address,
|
|
||||||
void* value,
|
|
||||||
void* input,
|
|
||||||
size_t input_size,
|
|
||||||
void* output,
|
|
||||||
size_t output_size);
|
|
||||||
static int64_t call_gateway(
|
|
||||||
struct evm_env* env,
|
|
||||||
enum evm_call_kind kind,
|
|
||||||
int64_t gas,
|
|
||||||
struct evm_uint160be address,
|
|
||||||
struct evm_uint256be value,
|
|
||||||
uint8_t const* input,
|
|
||||||
size_t input_size,
|
|
||||||
uint8_t* output,
|
|
||||||
size_t output_size)
|
|
||||||
{
|
|
||||||
return call(env, kind, gas, &address, &value, (void*)input, input_size, output, output_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct evm_instance* new_evmjit()
|
static struct evm_instance* new_evmjit()
|
||||||
{
|
{
|
||||||
|
// Declare exported Go functions. The are ABI compatible with C callbacks
|
||||||
|
// but differ by type names and const pointers.
|
||||||
|
void query(void*, size_t, int, void*);
|
||||||
|
void update(size_t env, int key, void* arg1, void* arg2);
|
||||||
|
long long call(void* env, int kind, long long gas, void* address,
|
||||||
|
void* value, void* input, size_t input_size, void* output,
|
||||||
|
size_t output_size);
|
||||||
|
|
||||||
struct evm_factory factory = evmjit_get_factory();
|
struct evm_factory factory = evmjit_get_factory();
|
||||||
return factory.create(query_gateway, update_gateway, call_gateway);
|
return factory.create((evm_query_fn)query, (evm_update_fn)update,
|
||||||
|
(evm_call_fn)call);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct evm_result evm_execute(struct evm_instance* instance,
|
static struct evm_result evm_execute(struct evm_instance* instance,
|
||||||
|
|
@ -183,44 +147,39 @@ func query(pResult unsafe.Pointer, ctxIdx uintptr, key int32, pArg unsafe.Pointe
|
||||||
// Or as pointer to int64.
|
// Or as pointer to int64.
|
||||||
pInt64Result := (*int64)(pResult)
|
pInt64Result := (*int64)(pResult)
|
||||||
|
|
||||||
// Copy the argument to [32]byte array.
|
|
||||||
arg := *(*[32]byte)(pArg)
|
|
||||||
|
|
||||||
// Get the execution context.
|
// Get the execution context.
|
||||||
ctx := getCtx(ctxIdx)
|
ctx := getCtx(ctxIdx)
|
||||||
|
|
||||||
switch key {
|
switch key {
|
||||||
case C.EVM_SLOAD:
|
case C.EVM_SLOAD:
|
||||||
|
arg := *(*[32]byte)(pArg)
|
||||||
val := ctx.env.StateDB.GetState(ctx.contract.Address(), arg)
|
val := ctx.env.StateDB.GetState(ctx.contract.Address(), arg)
|
||||||
copy(result, val[:])
|
copy(result, val[:])
|
||||||
// fmt.Printf("EVMJIT SLOAD %x : %x\n", arg, result)
|
// fmt.Printf("EVMJIT SLOAD %x : %x\n", arg, result)
|
||||||
case C.EVM_ADDRESS:
|
case C.EVM_ADDRESS:
|
||||||
addr := ctx.contract.Address()
|
addr := ctx.contract.Address()
|
||||||
copy(result[12:], addr[:])
|
copy(result[12:], addr[:])
|
||||||
// fmt.Printf("ADDRESS %x : %x\n", addr, result[12:])
|
|
||||||
case C.EVM_CALLER:
|
case C.EVM_CALLER:
|
||||||
addr := ctx.contract.Caller()
|
addr := ctx.contract.Caller()
|
||||||
copy(result[12:], addr[:])
|
copy(result[12:], addr[:])
|
||||||
case C.EVM_ORIGIN:
|
case C.EVM_ORIGIN:
|
||||||
addr := ctx.env.Origin
|
copy(result[12:], ctx.env.Origin[:])
|
||||||
copy(result[12:], addr[:])
|
|
||||||
case C.EVM_GAS_PRICE:
|
case C.EVM_GAS_PRICE:
|
||||||
val := common.BigToHash(ctx.env.GasPrice)
|
val := common.BigToHash(ctx.env.GasPrice)
|
||||||
copy(result, val[:])
|
copy(result, val[:])
|
||||||
case C.EVM_COINBASE:
|
case C.EVM_COINBASE:
|
||||||
addr := ctx.env.Coinbase
|
copy(result[12:], ctx.env.Coinbase[:])
|
||||||
copy(result[12:], addr[:])
|
|
||||||
case C.EVM_DIFFICULTY:
|
case C.EVM_DIFFICULTY:
|
||||||
val := common.BigToHash(ctx.env.Difficulty)
|
val := common.BigToHash(ctx.env.Difficulty)
|
||||||
copy(result, val[:])
|
copy(result, val[:])
|
||||||
case C.EVM_GAS_LIMIT:
|
case C.EVM_GAS_LIMIT:
|
||||||
*pInt64Result = ctx.env.GasLimit.Int64()
|
*pInt64Result = ctx.env.GasLimit.Int64()
|
||||||
// fmt.Printf("GASLIMIT %d %d\n", *pInt64Result, ctx.env.GasLimit())
|
|
||||||
case C.EVM_NUMBER:
|
case C.EVM_NUMBER:
|
||||||
*pInt64Result = ctx.env.BlockNumber.Int64()
|
*pInt64Result = ctx.env.BlockNumber.Int64()
|
||||||
case C.EVM_TIMESTAMP:
|
case C.EVM_TIMESTAMP:
|
||||||
*pInt64Result = ctx.env.Time.Int64()
|
*pInt64Result = ctx.env.Time.Int64()
|
||||||
case C.EVM_CODE_BY_ADDRESS:
|
case C.EVM_CODE_BY_ADDRESS:
|
||||||
|
arg := GoByteSlice(pArg, 32)
|
||||||
var addr common.Address
|
var addr common.Address
|
||||||
copy(addr[:], arg[12:])
|
copy(addr[:], arg[12:])
|
||||||
code := ctx.env.StateDB.GetCode(addr)
|
code := ctx.env.StateDB.GetCode(addr)
|
||||||
|
|
@ -229,12 +188,14 @@ func query(pResult unsafe.Pointer, ctxIdx uintptr, key int32, pArg unsafe.Pointe
|
||||||
pResAsMemRef.len = len(code)
|
pResAsMemRef.len = len(code)
|
||||||
// fmt.Printf("EXTCODE %x : %d\n", addr, pResAsMemRef.len)
|
// fmt.Printf("EXTCODE %x : %d\n", addr, pResAsMemRef.len)
|
||||||
case C.EVM_CODE_SIZE:
|
case C.EVM_CODE_SIZE:
|
||||||
|
arg := GoByteSlice(pArg, 32)
|
||||||
var addr common.Address
|
var addr common.Address
|
||||||
copy(addr[:], arg[12:])
|
copy(addr[:], arg[12:])
|
||||||
pInt64Result := (*int64)(pResult)
|
pInt64Result := (*int64)(pResult)
|
||||||
*pInt64Result = int64(ctx.env.StateDB.GetCodeSize(addr))
|
*pInt64Result = int64(ctx.env.StateDB.GetCodeSize(addr))
|
||||||
// fmt.Printf("EXTCODESIZE %x : %d\n", addr, *pInt64Result)
|
// fmt.Printf("EXTCODESIZE %x : %d\n", addr, *pInt64Result)
|
||||||
case C.EVM_BALANCE:
|
case C.EVM_BALANCE:
|
||||||
|
arg := GoByteSlice(pArg, 32)
|
||||||
var addr common.Address
|
var addr common.Address
|
||||||
copy(addr[:], arg[12:])
|
copy(addr[:], arg[12:])
|
||||||
balance := ctx.env.StateDB.GetBalance(addr)
|
balance := ctx.env.StateDB.GetBalance(addr)
|
||||||
|
|
@ -251,6 +212,7 @@ func query(pResult unsafe.Pointer, ctxIdx uintptr, key int32, pArg unsafe.Pointe
|
||||||
copy(result, hash[:])
|
copy(result, hash[:])
|
||||||
// fmt.Printf("BLOCKHASH %x : %x (%d, %d, %d)\n", result, hash, n, a, b)
|
// fmt.Printf("BLOCKHASH %x : %x (%d, %d, %d)\n", result, hash, n, a, b)
|
||||||
case C.EVM_ACCOUNT_EXISTS:
|
case C.EVM_ACCOUNT_EXISTS:
|
||||||
|
arg := GoByteSlice(pArg, 32)
|
||||||
var addr common.Address
|
var addr common.Address
|
||||||
copy(addr[:], arg[12:])
|
copy(addr[:], arg[12:])
|
||||||
eip158 := ctx.env.ChainConfig().IsEIP158(ctx.env.BlockNumber)
|
eip158 := ctx.env.ChainConfig().IsEIP158(ctx.env.BlockNumber)
|
||||||
|
|
@ -268,22 +230,21 @@ func query(pResult unsafe.Pointer, ctxIdx uintptr, key int32, pArg unsafe.Pointe
|
||||||
*pInt64Result = int64(ctx.env.Depth - 1)
|
*pInt64Result = int64(ctx.env.Depth - 1)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// fmt.Printf("Unhandled %d\n", key)
|
panic(fmt.Sprintf("Unhandled EVM-C query %d\n", key))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//export update
|
//export update
|
||||||
func update(pCtx unsafe.Pointer, key int32, pArg1 unsafe.Pointer, pArg2 unsafe.Pointer) {
|
func update(ctxIdx uintptr, key int32, pArg1 unsafe.Pointer, pArg2 unsafe.Pointer) {
|
||||||
arg1 := *(*[32]byte)(pArg1)
|
ctx := getCtx(ctxIdx)
|
||||||
arg2 := *(*[32]byte)(pArg2)
|
|
||||||
ctx := getCtx(uintptr(pCtx))
|
|
||||||
|
|
||||||
switch key {
|
switch key {
|
||||||
case C.EVM_SSTORE:
|
case C.EVM_SSTORE:
|
||||||
val := ctx.env.StateDB.GetState(ctx.contract.Address(), arg1)
|
key := *(*[32]byte)(pArg1)
|
||||||
ctx.env.StateDB.SetState(ctx.contract.Address(), arg1, arg2)
|
newVal := *(*[32]byte)(pArg2)
|
||||||
if !common.EmptyHash(val) && common.EmptyHash(arg2) {
|
oldVal := ctx.env.StateDB.GetState(ctx.contract.Address(), key)
|
||||||
// panic("SSTORE REFUND")
|
ctx.env.StateDB.SetState(ctx.contract.Address(), key, newVal)
|
||||||
|
if !common.EmptyHash(oldVal) && common.EmptyHash(newVal) {
|
||||||
ctx.env.StateDB.AddRefund(params.SstoreRefundGas)
|
ctx.env.StateDB.AddRefund(params.SstoreRefundGas)
|
||||||
}
|
}
|
||||||
// fmt.Printf("EVMJIT STORE %x : %x [%x, %d]\n", arg1, arg2, ctx.contract.Address(), int(uintptr(pEnv)))
|
// fmt.Printf("EVMJIT STORE %x : %x [%x, %d]\n", arg1, arg2, ctx.contract.Address(), int(uintptr(pEnv)))
|
||||||
|
|
@ -301,13 +262,14 @@ func update(pCtx unsafe.Pointer, key int32, pArg1 unsafe.Pointer, pArg2 unsafe.P
|
||||||
log := NewLog(ctx.contract.Address(), topics, data, ctx.env.BlockNumber.Uint64())
|
log := NewLog(ctx.contract.Address(), topics, data, ctx.env.BlockNumber.Uint64())
|
||||||
ctx.env.StateDB.AddLog(log)
|
ctx.env.StateDB.AddLog(log)
|
||||||
case C.EVM_SELFDESTRUCT:
|
case C.EVM_SELFDESTRUCT:
|
||||||
|
arg := GoByteSlice(pArg1, 32)
|
||||||
db := ctx.env.StateDB
|
db := ctx.env.StateDB
|
||||||
addr := ctx.contract.Address()
|
addr := ctx.contract.Address()
|
||||||
if !db.HasSuicided(addr) {
|
if !db.HasSuicided(addr) {
|
||||||
db.AddRefund(params.SuicideRefundGas)
|
db.AddRefund(params.SuicideRefundGas)
|
||||||
}
|
}
|
||||||
balance := db.GetBalance(addr)
|
balance := db.GetBalance(addr)
|
||||||
beneficiary := common.BytesToAddress(arg1[12:])
|
beneficiary := common.BytesToAddress(arg[12:])
|
||||||
db.AddBalance(beneficiary, balance)
|
db.AddBalance(beneficiary, balance)
|
||||||
db.Suicide(addr)
|
db.Suicide(addr)
|
||||||
}
|
}
|
||||||
|
|
@ -457,7 +419,7 @@ func (evm *EVMJIT) Run(contract *Contract, input []byte) (ret []byte, err error)
|
||||||
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.code != 0 {
|
if r.code != 0 {
|
||||||
// FIXME: Produce better error messages.
|
// EVMJIT does not informs about the kind of the EVM expection.
|
||||||
err = OutOfGasError
|
err = OutOfGasError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue