forked from cerc-io/plugeth
converted vm
This commit is contained in:
parent
bfcd2cf132
commit
91b0b14845
@ -1,8 +1,16 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import "fmt"
|
import "math/big"
|
||||||
|
|
||||||
type Hash [32]byte
|
const (
|
||||||
|
hashLength = 32
|
||||||
|
addressLength = 20
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Hash [hashLength]byte
|
||||||
|
Address [addressLength]byte
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
zeroHash Hash
|
zeroHash Hash
|
||||||
@ -15,25 +23,19 @@ func BytesToHash(b []byte) Hash {
|
|||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
func StringToHash(s string) Hash { return BytesToHash([]byte(s)) }
|
func StringToHash(s string) Hash { return BytesToHash([]byte(s)) }
|
||||||
|
func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) }
|
||||||
func BytesToAddress(b []byte) Address {
|
|
||||||
var a Address
|
|
||||||
a.SetBytes(b)
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
func StringToAddress(s string) Address { return BytesToAddress([]byte(s)) }
|
|
||||||
|
|
||||||
// Don't use the default 'String' method in case we want to overwrite
|
// Don't use the default 'String' method in case we want to overwrite
|
||||||
|
|
||||||
// Get the string representation of the underlying hash
|
// Get the string representation of the underlying hash
|
||||||
func (h Hash) Str() string {
|
func (h Hash) Str() string { return string(h[:]) }
|
||||||
return string(h[:])
|
func (h Hash) Bytes() []byte { return h[:] }
|
||||||
}
|
func (h Hash) Big() *big.Int { return Bytes2Big(h[:]) }
|
||||||
|
|
||||||
// Sets the hash to the value of b. If b is larger than len(h) it will panic
|
// Sets the hash to the value of b. If b is larger than len(h) it will panic
|
||||||
func (h *Hash) SetBytes(b []byte) {
|
func (h *Hash) SetBytes(b []byte) {
|
||||||
if len(b) > len(h) {
|
if len(b) > len(h) {
|
||||||
panic(fmt.Sprintf("unable to set bytes. too big = %d", len(b)))
|
b = b[len(b)-hashLength:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// reverse loop
|
// reverse loop
|
||||||
@ -52,17 +54,24 @@ func (h *Hash) Set(other Hash) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Address [20]byte
|
/////////// Address
|
||||||
|
func BytesToAddress(b []byte) Address {
|
||||||
|
var a Address
|
||||||
|
a.SetBytes(b)
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
func StringToAddress(s string) Address { return BytesToAddress([]byte(s)) }
|
||||||
|
func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) }
|
||||||
|
|
||||||
// Get the string representation of the underlying address
|
// Get the string representation of the underlying address
|
||||||
func (a Address) Str() string {
|
func (a Address) Str() string { return string(a[:]) }
|
||||||
return string(a[:])
|
func (a Address) Bytes() []byte { return a[:] }
|
||||||
}
|
func (a Address) Big() *big.Int { return Bytes2Big(a[:]) }
|
||||||
|
|
||||||
// Sets the address to the value of b. If b is larger than len(a) it will panic
|
// Sets the address to the value of b. If b is larger than len(a) it will panic
|
||||||
func (a *Address) SetBytes(b []byte) {
|
func (a *Address) SetBytes(b []byte) {
|
||||||
if len(b) > len(a) {
|
if len(b) > len(a) {
|
||||||
panic(fmt.Sprintf("unable to set bytes. too big = %d", len(b)))
|
b = b[len(b)-addressLength:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// reverse loop
|
// reverse loop
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// XXX Tests doesn't really do anything. This tests exists while working on the fixed size conversions
|
||||||
func TestConversion(t *testing.T) {
|
func TestConversion(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
parent common.Hash
|
parent common.Hash
|
||||||
@ -15,6 +15,5 @@ func TestConversion(t *testing.T) {
|
|||||||
hash common.Hash
|
hash common.Hash
|
||||||
)
|
)
|
||||||
|
|
||||||
block := NewBlock(parent, coinbase, hash, big.NewInt(0), 0, "")
|
NewBlock(parent, coinbase, hash, big.NewInt(0), 0, "")
|
||||||
fmt.Println(block)
|
|
||||||
}
|
}
|
||||||
|
14
state/log.go
14
state/log.go
@ -9,7 +9,7 @@ import (
|
|||||||
type Log interface {
|
type Log interface {
|
||||||
common.RlpEncodable
|
common.RlpEncodable
|
||||||
|
|
||||||
Address() []byte
|
Address() common.Address
|
||||||
Topics() [][]byte
|
Topics() [][]byte
|
||||||
Data() []byte
|
Data() []byte
|
||||||
|
|
||||||
@ -17,17 +17,17 @@ type Log interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type StateLog struct {
|
type StateLog struct {
|
||||||
address []byte
|
address common.Address
|
||||||
topics [][]byte
|
topics [][]byte
|
||||||
data []byte
|
data []byte
|
||||||
number uint64
|
number uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLog(address []byte, topics [][]byte, data []byte, number uint64) *StateLog {
|
func NewLog(address common.Address, topics [][]byte, data []byte, number uint64) *StateLog {
|
||||||
return &StateLog{address, topics, data, number}
|
return &StateLog{address, topics, data, number}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateLog) Address() []byte {
|
func (self *StateLog) Address() common.Address {
|
||||||
return self.address
|
return self.address
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +43,12 @@ func (self *StateLog) Number() uint64 {
|
|||||||
return self.number
|
return self.number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
func NewLogFromValue(decoder *common.Value) *StateLog {
|
func NewLogFromValue(decoder *common.Value) *StateLog {
|
||||||
|
var extlog struct {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
log := &StateLog{
|
log := &StateLog{
|
||||||
address: decoder.Get(0).Bytes(),
|
address: decoder.Get(0).Bytes(),
|
||||||
data: decoder.Get(2).Bytes(),
|
data: decoder.Get(2).Bytes(),
|
||||||
@ -56,6 +61,7 @@ func NewLogFromValue(decoder *common.Value) *StateLog {
|
|||||||
|
|
||||||
return log
|
return log
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func (self *StateLog) RlpData() interface{} {
|
func (self *StateLog) RlpData() interface{} {
|
||||||
return []interface{}{self.address, common.ByteSliceToInterface(self.topics), self.data}
|
return []interface{}{self.address, common.ByteSliceToInterface(self.topics), self.data}
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
type ContextRef interface {
|
type ContextRef interface {
|
||||||
ReturnGas(*big.Int, *big.Int)
|
ReturnGas(*big.Int, *big.Int)
|
||||||
Address() []byte
|
Address() common.Address
|
||||||
SetCode([]byte)
|
SetCode([]byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ type Context struct {
|
|||||||
self ContextRef
|
self ContextRef
|
||||||
|
|
||||||
Code []byte
|
Code []byte
|
||||||
CodeAddr []byte
|
CodeAddr common.Address
|
||||||
|
|
||||||
value, Gas, UsedGas, Price *big.Int
|
value, Gas, UsedGas, Price *big.Int
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ func (c *Context) ReturnGas(gas, price *big.Int) {
|
|||||||
/*
|
/*
|
||||||
* Set / Get
|
* Set / Get
|
||||||
*/
|
*/
|
||||||
func (c *Context) Address() []byte {
|
func (c *Context) Address() common.Address {
|
||||||
return c.self.Address()
|
return c.self.Address()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ func (self *Context) SetCode(code []byte) {
|
|||||||
self.Code = code
|
self.Code = code
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Context) SetCallCode(addr, code []byte) {
|
func (self *Context) SetCallCode(addr common.Address, code []byte) {
|
||||||
self.Code = code
|
self.Code = code
|
||||||
self.CodeAddr = addr
|
self.CodeAddr = addr
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
type Environment interface {
|
type Environment interface {
|
||||||
State() *state.StateDB
|
State() *state.StateDB
|
||||||
|
|
||||||
Origin() []byte
|
Origin() common.Address
|
||||||
BlockNumber() *big.Int
|
BlockNumber() *big.Int
|
||||||
GetHash(n uint64) []byte
|
GetHash(n uint64) []byte
|
||||||
Coinbase() []byte
|
Coinbase() []byte
|
||||||
@ -27,9 +27,9 @@ type Environment interface {
|
|||||||
Depth() int
|
Depth() int
|
||||||
SetDepth(i int)
|
SetDepth(i int)
|
||||||
|
|
||||||
Call(me ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error)
|
Call(me ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error)
|
||||||
CallCode(me ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error)
|
CallCode(me ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error)
|
||||||
Create(me ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, ContextRef)
|
Create(me ContextRef, data []byte, gas, price, value *big.Int) ([]byte, error, ContextRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Account interface {
|
type Account interface {
|
||||||
@ -53,13 +53,13 @@ func Transfer(from, to Account, amount *big.Int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Log struct {
|
type Log struct {
|
||||||
address []byte
|
address common.Address
|
||||||
topics [][]byte
|
topics [][]byte
|
||||||
data []byte
|
data []byte
|
||||||
log uint64
|
log uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Log) Address() []byte {
|
func (self *Log) Address() common.Address {
|
||||||
return self.address
|
return self.address
|
||||||
}
|
}
|
||||||
|
|
||||||
|
49
vm/vm.go
49
vm/vm.go
@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/state"
|
"github.com/ethereum/go-ethereum/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
|
|||||||
price = context.Price
|
price = context.Price
|
||||||
)
|
)
|
||||||
|
|
||||||
self.Printf("(%d) (%x) %x (code=%d) gas: %v (d) %x", self.env.Depth(), caller.Address()[:4], context.Address(), len(code), context.Gas, callData).Endl()
|
self.Printf("(%d) (%x) %x (code=%d) gas: %v (d) %x", self.env.Depth(), caller.Address().Bytes()[:4], context.Address(), len(code), context.Gas, callData).Endl()
|
||||||
|
|
||||||
if self.Recoverable {
|
if self.Recoverable {
|
||||||
// Recover from any require exception
|
// Recover from any require exception
|
||||||
@ -62,7 +62,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
if p := Precompiled[string(context.CodeAddr)]; p != nil {
|
if p := Precompiled[context.CodeAddr.Str()]; p != nil {
|
||||||
return self.RunPrecompiled(p, callData, context)
|
return self.RunPrecompiled(p, callData, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,11 +394,11 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
|
|||||||
self.Printf(" => (%v) %x", size, data)
|
self.Printf(" => (%v) %x", size, data)
|
||||||
// 0x30 range
|
// 0x30 range
|
||||||
case ADDRESS:
|
case ADDRESS:
|
||||||
stack.push(common.BigD(context.Address()))
|
stack.push(common.Bytes2Big(context.Address().Bytes()))
|
||||||
|
|
||||||
self.Printf(" => %x", context.Address())
|
self.Printf(" => %x", context.Address())
|
||||||
case BALANCE:
|
case BALANCE:
|
||||||
addr := stack.pop().Bytes()
|
addr := common.BigToAddress(stack.pop())
|
||||||
balance := statedb.GetBalance(addr)
|
balance := statedb.GetBalance(addr)
|
||||||
|
|
||||||
stack.push(balance)
|
stack.push(balance)
|
||||||
@ -407,12 +407,12 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
|
|||||||
case ORIGIN:
|
case ORIGIN:
|
||||||
origin := self.env.Origin()
|
origin := self.env.Origin()
|
||||||
|
|
||||||
stack.push(common.BigD(origin))
|
stack.push(origin.Big())
|
||||||
|
|
||||||
self.Printf(" => %x", origin)
|
self.Printf(" => %x", origin)
|
||||||
case CALLER:
|
case CALLER:
|
||||||
caller := context.caller.Address()
|
caller := context.caller.Address()
|
||||||
stack.push(common.BigD(caller))
|
stack.push(common.Bytes2Big(caller.Bytes()))
|
||||||
|
|
||||||
self.Printf(" => %x", caller)
|
self.Printf(" => %x", caller)
|
||||||
case CALLVALUE:
|
case CALLVALUE:
|
||||||
@ -464,7 +464,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
|
|||||||
case CODESIZE, EXTCODESIZE:
|
case CODESIZE, EXTCODESIZE:
|
||||||
var code []byte
|
var code []byte
|
||||||
if op == EXTCODESIZE {
|
if op == EXTCODESIZE {
|
||||||
addr := stack.pop().Bytes()
|
addr := common.BigToAddress(stack.pop())
|
||||||
|
|
||||||
code = statedb.GetCode(addr)
|
code = statedb.GetCode(addr)
|
||||||
} else {
|
} else {
|
||||||
@ -478,7 +478,8 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
|
|||||||
case CODECOPY, EXTCODECOPY:
|
case CODECOPY, EXTCODECOPY:
|
||||||
var code []byte
|
var code []byte
|
||||||
if op == EXTCODECOPY {
|
if op == EXTCODECOPY {
|
||||||
code = statedb.GetCode(stack.pop().Bytes())
|
addr := common.BigToAddress(stack.pop())
|
||||||
|
code = statedb.GetCode(addr)
|
||||||
} else {
|
} else {
|
||||||
code = context.Code
|
code = context.Code
|
||||||
}
|
}
|
||||||
@ -593,16 +594,18 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
|
|||||||
|
|
||||||
self.Printf(" => [%v] 0x%x", off, val)
|
self.Printf(" => [%v] 0x%x", off, val)
|
||||||
case SLOAD:
|
case SLOAD:
|
||||||
loc := stack.pop()
|
loc := common.BigToHash(stack.pop())
|
||||||
val := common.BigD(statedb.GetState(context.Address(), loc.Bytes()))
|
val := common.Bytes2Big(statedb.GetState(context.Address(), loc))
|
||||||
stack.push(val)
|
stack.push(val)
|
||||||
|
|
||||||
self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
|
self.Printf(" {0x%x : 0x%x}", loc, val.Bytes())
|
||||||
case SSTORE:
|
case SSTORE:
|
||||||
loc, val := stack.pop(), stack.pop()
|
loc := common.BigToHash(stack.pop())
|
||||||
statedb.SetState(context.Address(), loc.Bytes(), val)
|
val := stack.pop()
|
||||||
|
|
||||||
self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
|
statedb.SetState(context.Address(), loc, val)
|
||||||
|
|
||||||
|
self.Printf(" {0x%x : 0x%x}", loc, val.Bytes())
|
||||||
case JUMP:
|
case JUMP:
|
||||||
jump(pc, stack.pop())
|
jump(pc, stack.pop())
|
||||||
|
|
||||||
@ -635,12 +638,12 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
|
|||||||
offset, size = stack.pop(), stack.pop()
|
offset, size = stack.pop(), stack.pop()
|
||||||
input = mem.Get(offset.Int64(), size.Int64())
|
input = mem.Get(offset.Int64(), size.Int64())
|
||||||
gas = new(big.Int).Set(context.Gas)
|
gas = new(big.Int).Set(context.Gas)
|
||||||
addr []byte
|
addr common.Address
|
||||||
)
|
)
|
||||||
self.Endl()
|
self.Endl()
|
||||||
|
|
||||||
context.UseGas(context.Gas)
|
context.UseGas(context.Gas)
|
||||||
ret, suberr, ref := self.env.Create(context, nil, input, gas, price, value)
|
ret, suberr, ref := self.env.Create(context, input, gas, price, value)
|
||||||
if suberr != nil {
|
if suberr != nil {
|
||||||
stack.push(common.BigFalse)
|
stack.push(common.BigFalse)
|
||||||
|
|
||||||
@ -655,7 +658,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
|
|||||||
}
|
}
|
||||||
addr = ref.Address()
|
addr = ref.Address()
|
||||||
|
|
||||||
stack.push(common.BigD(addr))
|
stack.push(addr.Big())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -669,7 +672,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
|
|||||||
// pop return size and offset
|
// pop return size and offset
|
||||||
retOffset, retSize := stack.pop(), stack.pop()
|
retOffset, retSize := stack.pop(), stack.pop()
|
||||||
|
|
||||||
address := common.Address(addr.Bytes())
|
address := common.BigToAddress(addr)
|
||||||
self.Printf(" => %x", address).Endl()
|
self.Printf(" => %x", address).Endl()
|
||||||
|
|
||||||
// Get the arguments from the memory
|
// Get the arguments from the memory
|
||||||
@ -707,10 +710,10 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
|
|||||||
|
|
||||||
return context.Return(ret), nil
|
return context.Return(ret), nil
|
||||||
case SUICIDE:
|
case SUICIDE:
|
||||||
receiver := statedb.GetOrNewStateObject(stack.pop().Bytes())
|
receiver := statedb.GetOrNewStateObject(common.BigToAddress(stack.pop()))
|
||||||
balance := statedb.GetBalance(context.Address())
|
balance := statedb.GetBalance(context.Address())
|
||||||
|
|
||||||
self.Printf(" => (%x) %v", receiver.Address()[:4], balance)
|
self.Printf(" => (%x) %v", receiver.Address().Bytes()[:4], balance)
|
||||||
|
|
||||||
receiver.AddBalance(balance)
|
receiver.AddBalance(balance)
|
||||||
|
|
||||||
@ -770,7 +773,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
|
|||||||
|
|
||||||
var g *big.Int
|
var g *big.Int
|
||||||
y, x := stack.data[stack.len()-2], stack.data[stack.len()-1]
|
y, x := stack.data[stack.len()-2], stack.data[stack.len()-1]
|
||||||
val := statedb.GetState(context.Address(), x.Bytes())
|
val := statedb.GetState(context.Address(), common.BigToHash(x))
|
||||||
if len(val) == 0 && len(y.Bytes()) > 0 {
|
if len(val) == 0 && len(y.Bytes()) > 0 {
|
||||||
// 0 => non 0
|
// 0 => non 0
|
||||||
g = GasStorageAdd
|
g = GasStorageAdd
|
||||||
@ -822,7 +825,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
|
|||||||
gas.Add(gas, stack.data[stack.len()-1])
|
gas.Add(gas, stack.data[stack.len()-1])
|
||||||
|
|
||||||
if op == CALL {
|
if op == CALL {
|
||||||
if self.env.State().GetStateObject(stack.data[stack.len()-2].Bytes()) == nil {
|
if self.env.State().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil {
|
||||||
gas.Add(gas, GasCallNewAccount)
|
gas.Add(gas, GasCallNewAccount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user