converted vm

This commit is contained in:
obscuren 2015-03-16 18:42:18 +01:00
parent bfcd2cf132
commit 91b0b14845
6 changed files with 75 additions and 58 deletions

View File

@ -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

View File

@ -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)
} }

View File

@ -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}

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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)
} }
} }