mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-22 04:36:42 +00:00
EVM JIT called from Go, env_sha3 callback works
This commit is contained in:
parent
e1f84aef32
commit
d06988a65a
5 changed files with 124 additions and 3 deletions
|
|
@ -10,7 +10,8 @@ if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
set_source_files_properties(Cache.cpp PROPERTIES COMPILE_FLAGS -fno-rtti)
|
set_source_files_properties(Cache.cpp PROPERTIES COMPILE_FLAGS -fno-rtti)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
add_library(${TARGET_NAME} ${SOURCES} ${HEADERS})
|
link_directories(/usr/lib/llvm-3.5/lib)
|
||||||
|
add_library(${TARGET_NAME} SHARED ${SOURCES} ${HEADERS})
|
||||||
set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER "libs")
|
set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER "libs")
|
||||||
|
|
||||||
include_directories(${LLVM_INCLUDE_DIRS})
|
include_directories(${LLVM_INCLUDE_DIRS})
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ ReturnCode runEntryFunc(EntryFuncPtr _mainFunc, Runtime* _runtime)
|
||||||
|
|
||||||
std::string codeHash(bytes const& _code)
|
std::string codeHash(bytes const& _code)
|
||||||
{
|
{
|
||||||
std::array<dev::eth::jit::byte, 32> binHash;
|
std::array<byte, 32> binHash;
|
||||||
env_sha3(_code.data(), _code.size(), &binHash);
|
env_sha3(_code.data(), _code.size(), &binHash);
|
||||||
|
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
|
|
|
||||||
63
evmjit/libevmjit/interface.cpp
Normal file
63
evmjit/libevmjit/interface.cpp
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
#include "interface.h"
|
||||||
|
#include <cstdio>
|
||||||
|
#include "ExecutionEngine.h"
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
|
||||||
|
int evmjit_run()
|
||||||
|
{
|
||||||
|
using namespace dev::eth::jit;
|
||||||
|
|
||||||
|
ExecutionEngine engine;
|
||||||
|
u256 gas = 100000;
|
||||||
|
|
||||||
|
bytes bytecode = { 0x60, 0x01 };
|
||||||
|
|
||||||
|
// Create random runtime data
|
||||||
|
RuntimeData data;
|
||||||
|
data.set(RuntimeData::Gas, gas);
|
||||||
|
data.set(RuntimeData::Address, 0);
|
||||||
|
data.set(RuntimeData::Caller, 0);
|
||||||
|
data.set(RuntimeData::Origin, 0);
|
||||||
|
data.set(RuntimeData::CallValue, 0xabcd);
|
||||||
|
data.set(RuntimeData::CallDataSize, 3);
|
||||||
|
data.set(RuntimeData::GasPrice, 1003);
|
||||||
|
data.set(RuntimeData::CoinBase, 0);
|
||||||
|
data.set(RuntimeData::TimeStamp, 1005);
|
||||||
|
data.set(RuntimeData::Number, 1006);
|
||||||
|
data.set(RuntimeData::Difficulty, 16);
|
||||||
|
data.set(RuntimeData::GasLimit, 1008);
|
||||||
|
data.set(RuntimeData::CodeSize, bytecode.size());
|
||||||
|
data.callData = (uint8_t*)"abc";
|
||||||
|
data.code = bytecode.data();
|
||||||
|
|
||||||
|
// BROKEN: env_* functions must be implemented & RuntimeData struct created
|
||||||
|
// TODO: Do not compile module again
|
||||||
|
auto result = engine.run(bytecode, &data, nullptr);
|
||||||
|
return static_cast<int>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Runtime callback functions - implementations must be provided by external language (Go, C++, Python)
|
||||||
|
void evm_jit_rt_sload(evm_jit_rt* _rt, i256* _index, i256* _ret);
|
||||||
|
void evm_jit_rt_sstore(evm_jit_rt* _rt, i256* _index, i256* _value);
|
||||||
|
void evm_jit_rt_balance(evm_jit_rt* _rt, h256* _address, i256* _ret);
|
||||||
|
// And so on...
|
||||||
|
|
||||||
|
evm_jit* evm_jit_create(evm_jit_rt*)
|
||||||
|
{
|
||||||
|
printf("EVM JIT create");
|
||||||
|
|
||||||
|
int* a = nullptr;
|
||||||
|
*a = 1;
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
evm_jit_return_code evm_jit_execute(evm_jit* _jit);
|
||||||
|
|
||||||
|
void evm_jit_get_return_data(evm_jit* _jit, char* _return_data_offset, size_t* _return_data_size);
|
||||||
|
|
||||||
|
void evm_jit_destroy(evm_jit* _jit);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,10 @@
|
||||||
#include <stdint.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int evmjit_run();
|
||||||
|
|
||||||
// JIT object opaque type
|
// JIT object opaque type
|
||||||
typedef struct evm_jit evm_jit;
|
typedef struct evm_jit evm_jit;
|
||||||
|
|
@ -9,6 +15,11 @@ typedef int evm_jit_return_code;
|
||||||
// Host-endian 256-bit integer type
|
// Host-endian 256-bit integer type
|
||||||
typedef struct i256 i256;
|
typedef struct i256 i256;
|
||||||
|
|
||||||
|
struct h256
|
||||||
|
{
|
||||||
|
char b[33];
|
||||||
|
};
|
||||||
|
|
||||||
// Big-endian right aligned 256-bit hash
|
// Big-endian right aligned 256-bit hash
|
||||||
typedef struct h256 h256;
|
typedef struct h256 h256;
|
||||||
|
|
||||||
|
|
@ -28,3 +39,7 @@ evm_jit_return_code evm_jit_execute(evm_jit* _jit);
|
||||||
void evm_jit_get_return_data(evm_jit* _jit, char* _return_data_offset, size_t* _return_data_size);
|
void evm_jit_get_return_data(evm_jit* _jit, char* _return_data_offset, size_t* _return_data_size);
|
||||||
|
|
||||||
void evm_jit_destroy(evm_jit* _jit);
|
void evm_jit_destroy(evm_jit* _jit);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
42
vm/vm_jit.go
42
vm/vm_jit.go
|
|
@ -1,6 +1,18 @@
|
||||||
package vm
|
package vm
|
||||||
|
|
||||||
import "math/big"
|
import "math/big"
|
||||||
|
import "github.com/ethereum/go-ethereum/crypto"
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include "../evmjit/libevmjit/interface.h"
|
||||||
|
|
||||||
|
#cgo LDFLAGS: -L/home/chfast/go/src/github.com/ethereum/go-ethereum/evmjit/build/libevmjit -levmjit
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
import "fmt"
|
||||||
|
import "reflect"
|
||||||
|
|
||||||
type JitVm struct {
|
type JitVm struct {
|
||||||
env Environment
|
env Environment
|
||||||
|
|
@ -13,6 +25,9 @@ func NewJitVm(env Environment) *JitVm {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *JitVm) Run(me, caller ContextRef, code []byte, value, gas, price *big.Int, callData []byte) (ret []byte, err error) {
|
func (self *JitVm) Run(me, caller ContextRef, code []byte, value, gas, price *big.Int, callData []byte) (ret []byte, err error) {
|
||||||
|
r := C.evmjit_run();
|
||||||
|
fmt.Printf("JIT result: %d", r);
|
||||||
|
|
||||||
return self.backup.Run(me, caller, code, value, gas, price, callData)
|
return self.backup.Run(me, caller, code, value, gas, price, callData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -28,4 +43,31 @@ func (self *JitVm) Env() Environment {
|
||||||
return self.env
|
return self.env
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//export env_sha3
|
||||||
|
func env_sha3(dataPtr unsafe.Pointer, length uint64, hashPtr unsafe.Pointer) {
|
||||||
|
fmt.Printf("env_sha3(%p, %d, %p)\n", dataPtr, length, hashPtr);
|
||||||
|
|
||||||
|
dataHdr := reflect.SliceHeader{
|
||||||
|
Data: uintptr(dataPtr),
|
||||||
|
Len: int(length),
|
||||||
|
Cap: int(length),
|
||||||
|
}
|
||||||
|
data := *(*[]byte)(unsafe.Pointer(&dataHdr))
|
||||||
|
fmt.Printf("\tdata: %x\n", data)
|
||||||
|
|
||||||
|
hash := crypto.Sha3(data);
|
||||||
|
fmt.Printf("\thash: %x\n", hash)
|
||||||
|
|
||||||
|
hashHdr := reflect.SliceHeader{
|
||||||
|
Data: uintptr(hashPtr),
|
||||||
|
Len: 32,
|
||||||
|
Cap: 32,
|
||||||
|
}
|
||||||
|
oHash := *(*[]byte)(unsafe.Pointer(&hashHdr))
|
||||||
|
fmt.Printf("\tout0: %x\n", oHash)
|
||||||
|
|
||||||
|
copy(oHash, hash)
|
||||||
|
fmt.Printf("\tout1: %x\n", oHash)
|
||||||
|
}
|
||||||
|
|
||||||
//go is nice
|
//go is nice
|
||||||
Loading…
Reference in a new issue