This commit is contained in:
Paweł Bylica 2015-01-15 12:03:52 +01:00
parent 9f93253f63
commit ed0f8d1d93

View file

@ -20,42 +20,42 @@ import "errors"
type JitVm struct { type JitVm struct {
env Environment env Environment
me ContextRef me ContextRef
} }
type i256 [32]byte type i256 [32]byte
const ( const (
Gas = iota Gas = iota
address address
Caller Caller
Origin Origin
CallValue CallValue
CallDataSize CallDataSize
GasPrice GasPrice
CoinBase CoinBase
TimeStamp TimeStamp
Number Number
Difficulty Difficulty
GasLimit GasLimit
CodeSize CodeSize
_size _size
ReturnDataOffset = CallValue // Reuse 2 fields for return data reference ReturnDataOffset = CallValue // Reuse 2 fields for return data reference
ReturnDataSize = CallDataSize ReturnDataSize = CallDataSize
SuicideDestAddress = address ///< Suicide balance destination address SuicideDestAddress = address ///< Suicide balance destination address
) )
type RuntimeData struct { type RuntimeData struct {
elems [_size]i256 elems [_size]i256
callData *byte callData *byte
code *byte code *byte
} }
func hash2llvm(h []byte) i256 { func hash2llvm(h []byte) i256 {
var m i256 var m i256
copy(m[len(m) - len(h):], h) // right aligned copy copy(m[len(m)-len(h):], h) // right aligned copy
return m return m
} }
@ -70,10 +70,10 @@ func llvm2hash(m *i256) []byte { //TODO: It should copy data
func big2llvm(n *big.Int) i256 { func big2llvm(n *big.Int) i256 {
m := hash2llvm(n.Bytes()) m := hash2llvm(n.Bytes())
for i, l := 0, len(m); i < l / 2; i++ { for i, l := 0, len(m); i < l/2; i++ {
m[i], m[l - i - 1] = m[l - i - 1], m[i] m[i], m[l-i-1] = m[l-i-1], m[i]
} }
return m return m
} }
@ -81,7 +81,7 @@ func llvm2big(m *i256) *big.Int {
n := big.NewInt(0) n := big.NewInt(0)
for i := 0; i < len(m); i++ { for i := 0; i < len(m); i++ {
b := big.NewInt(int64(m[i])) b := big.NewInt(int64(m[i]))
b.Lsh(b, uint(i) * 8) b.Lsh(b, uint(i)*8)
n.Add(n, b) n.Add(n, b)
} }
return n return n
@ -102,7 +102,7 @@ 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) {
self.me = me // FIXME: Make sure Run() is not used more than once self.me = me // FIXME: Make sure Run() is not used more than once
var data RuntimeData var data RuntimeData
data.elems[Gas] = big2llvm(gas) data.elems[Gas] = big2llvm(gas)
data.elems[address] = hash2llvm(self.me.Address()) data.elems[address] = hash2llvm(self.me.Address())
@ -122,14 +122,14 @@ func (self *JitVm) Run(me, caller ContextRef, code []byte, value, gas, price *bi
if len(code) > 0 { if len(code) > 0 {
data.code = &code[0] data.code = &code[0]
} }
r := C.evmjit_run(unsafe.Pointer(&data), unsafe.Pointer(self)); r := C.evmjit_run(unsafe.Pointer(&data), unsafe.Pointer(self))
fmt.Printf("JIT result: %d\n", r); fmt.Printf("JIT result: %d\n", r)
if r >= 100 { if r >= 100 {
err = errors.New("OOG from JIT") err = errors.New("OOG from JIT")
} }
return ret, err return ret, err
} }
@ -148,15 +148,15 @@ func (self *JitVm) Env() Environment {
//export env_sha3 //export env_sha3
func env_sha3(dataPtr *byte, length uint64, hashPtr unsafe.Pointer) { func env_sha3(dataPtr *byte, length uint64, hashPtr unsafe.Pointer) {
data := llvm2bytes(dataPtr, length) data := llvm2bytes(dataPtr, length)
hash := crypto.Sha3(data); hash := crypto.Sha3(data)
hashHdr := reflect.SliceHeader{ hashHdr := reflect.SliceHeader{
Data: uintptr(hashPtr), Data: uintptr(hashPtr),
Len: 32, Len: 32,
Cap: 32, Cap: 32,
} }
oHash := *(*[]byte)(unsafe.Pointer(&hashHdr)) oHash := *(*[]byte)(unsafe.Pointer(&hashHdr))
copy(oHash, hash) copy(oHash, hash)
} }
@ -198,10 +198,10 @@ func env_blockhash(_vm unsafe.Pointer, _number unsafe.Pointer, _result unsafe.Po
//export env_call //export env_call
func env_call(_vm unsafe.Pointer, _gas unsafe.Pointer, _receiveAddr unsafe.Pointer, _value unsafe.Pointer, inDataPtr *byte, inDataLen uint64, outDataPtr *byte, outDataLen uint64, _codeAddr unsafe.Pointer) bool { func env_call(_vm unsafe.Pointer, _gas unsafe.Pointer, _receiveAddr unsafe.Pointer, _value unsafe.Pointer, inDataPtr *byte, inDataLen uint64, outDataPtr *byte, outDataLen uint64, _codeAddr unsafe.Pointer) bool {
vm := (*JitVm)(_vm) vm := (*JitVm)(_vm)
balance := vm.Env().State().GetBalance(vm.me.Address()) balance := vm.Env().State().GetBalance(vm.me.Address())
value := llvm2big((*i256)(_value)) value := llvm2big((*i256)(_value))
if vm.env.Depth() < 1024 && balance.Cmp(value) >= 0 { if vm.env.Depth() < 1024 && balance.Cmp(value) >= 0 {
vm.env.State().AddBalance(vm.me.Address(), value.Neg(value)) vm.env.State().AddBalance(vm.me.Address(), value.Neg(value))
receiveAddr := llvm2hash((*i256)(_receiveAddr)) receiveAddr := llvm2hash((*i256)(_receiveAddr))
@ -210,7 +210,7 @@ func env_call(_vm unsafe.Pointer, _gas unsafe.Pointer, _receiveAddr unsafe.Point
//codeAddr := llvm2hash((*i256)(_codeAddr)) //TODO: Handle CallCode //codeAddr := llvm2hash((*i256)(_codeAddr)) //TODO: Handle CallCode
llvmGas := (*i256)(_gas) llvmGas := (*i256)(_gas)
gas := llvm2big(llvmGas) gas := llvm2big(llvmGas)
price := big.NewInt(0) // TODO price := big.NewInt(0) // TODO
out, err := vm.env.Call(vm.me, receiveAddr, inData, gas, price, value) out, err := vm.env.Call(vm.me, receiveAddr, inData, gas, price, value)
*llvmGas = big2llvm(gas) *llvmGas = big2llvm(gas)
if err == nil { if err == nil {
@ -219,17 +219,17 @@ func env_call(_vm unsafe.Pointer, _gas unsafe.Pointer, _receiveAddr unsafe.Point
} }
} }
return false; return false
} }
//export env_create //export env_create
func env_create(_vm unsafe.Pointer, _gas unsafe.Pointer, _value unsafe.Pointer, initDataPtr *byte, initDataLen uint64, _result unsafe.Pointer) { func env_create(_vm unsafe.Pointer, _gas unsafe.Pointer, _value unsafe.Pointer, initDataPtr *byte, initDataLen uint64, _result unsafe.Pointer) {
vm := (*JitVm)(_vm) vm := (*JitVm)(_vm)
balance := vm.Env().State().GetBalance(vm.me.Address()) balance := vm.Env().State().GetBalance(vm.me.Address())
value := llvm2big((*i256)(_value)) value := llvm2big((*i256)(_value))
result := (*i256)(_result) result := (*i256)(_result)
if vm.env.Depth() < 1024 && balance.Cmp(value) >= 0 { if vm.env.Depth() < 1024 && balance.Cmp(value) >= 0 {
vm.env.State().AddBalance(vm.me.Address(), value.Neg(value)) vm.env.State().AddBalance(vm.me.Address(), value.Neg(value))
initData := llvm2bytes(initDataPtr, initDataLen) initData := llvm2bytes(initDataPtr, initDataLen)
@ -245,13 +245,13 @@ func env_create(_vm unsafe.Pointer, _gas unsafe.Pointer, _value unsafe.Pointer,
} }
//export env_log //export env_log
func env_log(_vm unsafe.Pointer, dataPtr *byte, dataLen uint64, _topic1 unsafe.Pointer, _topic2 unsafe.Pointer, _topic3 unsafe.Pointer, _topic4 unsafe.Pointer) { func env_log(_vm unsafe.Pointer, dataPtr *byte, dataLen uint64, _topic1 unsafe.Pointer, _topic2 unsafe.Pointer, _topic3 unsafe.Pointer, _topic4 unsafe.Pointer) {
vm := (*JitVm)(_vm) vm := (*JitVm)(_vm)
dataRef := llvm2bytes(dataPtr, dataLen) dataRef := llvm2bytes(dataPtr, dataLen)
data := make([]byte, len(dataRef)) data := make([]byte, len(dataRef))
copy(data, dataRef) copy(data, dataRef)
topics := make([][]byte, 0, 4) topics := make([][]byte, 0, 4)
if _topic1 != nil { if _topic1 != nil {
topics = append(topics, llvm2hash((*i256)(_topic1))) topics = append(topics, llvm2hash((*i256)(_topic1)))
@ -265,6 +265,6 @@ func env_log(_vm unsafe.Pointer, dataPtr *byte, dataLen uint64, _topic1 unsafe.P
if _topic4 != nil { if _topic4 != nil {
topics = append(topics, llvm2hash((*i256)(_topic4))) topics = append(topics, llvm2hash((*i256)(_topic4)))
} }
vm.Env().AddLog(state.NewLog(vm.me.Address(), topics, data)) vm.Env().AddLog(state.NewLog(vm.me.Address(), topics, data))
} }