aboutsummaryrefslogtreecommitdiffstats
path: root/vm
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2015-03-22 01:18:19 +0800
committerobscuren <geffobscura@gmail.com>2015-03-22 01:18:19 +0800
commit7f85608f30a2e34005c8d15566849229c758c2f1 (patch)
tree7aeb9d8bdfda7ec10ea38688a96ed245028764ad /vm
parent09766d1729f7530093aec7e9acd3e5339b2c2028 (diff)
parentfcacfabe1959c4aff6a63cb4e275f65328660601 (diff)
downloaddexon-7f85608f30a2e34005c8d15566849229c758c2f1.tar.gz
dexon-7f85608f30a2e34005c8d15566849229c758c2f1.tar.zst
dexon-7f85608f30a2e34005c8d15566849229c758c2f1.zip
Merge branch 'conversion' into develop
Diffstat (limited to 'vm')
-rw-r--r--vm/common.go87
-rw-r--r--vm/context.go12
-rw-r--r--vm/environment.go32
-rw-r--r--vm/gas.go49
-rw-r--r--vm/memory.go32
-rw-r--r--vm/vm.go79
6 files changed, 149 insertions, 142 deletions
diff --git a/vm/common.go b/vm/common.go
index 90c3361de..8d8f4253f 100644
--- a/vm/common.go
+++ b/vm/common.go
@@ -18,8 +18,23 @@ type Type byte
const (
StdVmTy Type = iota
JitVmTy
-
MaxVmTy
+
+ MaxCallDepth = 1025
+
+ LogTyPretty byte = 0x1
+ LogTyDiff byte = 0x2
+)
+
+var (
+ Pow256 = common.BigPow(2, 256)
+
+ U256 = common.U256
+ S256 = common.S256
+
+ Zero = common.Big0
+
+ max = big.NewInt(math.MaxInt64)
)
func NewVm(env Environment) VirtualMachine {
@@ -34,67 +49,6 @@ func NewVm(env Environment) VirtualMachine {
}
}
-var (
- GasQuickStep = big.NewInt(2)
- GasFastestStep = big.NewInt(3)
- GasFastStep = big.NewInt(5)
- GasMidStep = big.NewInt(8)
- GasSlowStep = big.NewInt(10)
- GasExtStep = big.NewInt(20)
-
- GasStorageGet = big.NewInt(50)
- GasStorageAdd = big.NewInt(20000)
- GasStorageMod = big.NewInt(5000)
- GasLogBase = big.NewInt(375)
- GasLogTopic = big.NewInt(375)
- GasLogByte = big.NewInt(8)
- GasCreate = big.NewInt(32000)
- GasCreateByte = big.NewInt(200)
- GasCall = big.NewInt(40)
- GasCallValueTransfer = big.NewInt(9000)
- GasStipend = big.NewInt(2300)
- GasCallNewAccount = big.NewInt(25000)
- GasReturn = big.NewInt(0)
- GasStop = big.NewInt(0)
- GasJumpDest = big.NewInt(1)
-
- RefundStorage = big.NewInt(15000)
- RefundSuicide = big.NewInt(24000)
-
- GasMemWord = big.NewInt(3)
- GasQuadCoeffDenom = big.NewInt(512)
- GasContractByte = big.NewInt(200)
- GasTransaction = big.NewInt(21000)
- GasTxDataNonzeroByte = big.NewInt(68)
- GasTxDataZeroByte = big.NewInt(4)
- GasTx = big.NewInt(21000)
- GasExp = big.NewInt(10)
- GasExpByte = big.NewInt(10)
-
- GasSha3Base = big.NewInt(30)
- GasSha3Word = big.NewInt(6)
- GasSha256Base = big.NewInt(60)
- GasSha256Word = big.NewInt(12)
- GasRipemdBase = big.NewInt(600)
- GasRipemdWord = big.NewInt(12)
- GasEcrecover = big.NewInt(3000)
- GasIdentityBase = big.NewInt(15)
- GasIdentityWord = big.NewInt(3)
- GasCopyWord = big.NewInt(3)
-
- Pow256 = common.BigPow(2, 256)
-
- LogTyPretty byte = 0x1
- LogTyDiff byte = 0x2
-
- U256 = common.U256
- S256 = common.S256
-
- Zero = common.Big0
-)
-
-const MaxCallDepth = 1025
-
func calcMemSize(off, l *big.Int) *big.Int {
if l.Cmp(common.Big0) == 0 {
return common.Big0
@@ -119,9 +73,10 @@ func toValue(val *big.Int) interface{} {
return val
}
-func getData(data []byte, start, size uint64) []byte {
- x := uint64(math.Min(float64(start), float64(len(data))))
- y := uint64(math.Min(float64(x+size), float64(len(data))))
+func getData(data []byte, start, size *big.Int) []byte {
+ dlen := big.NewInt(int64(len(data)))
- return common.RightPadBytes(data[x:y], int(size))
+ s := common.BigMin(start, dlen)
+ e := common.BigMin(new(big.Int).Add(s, size), dlen)
+ return common.RightPadBytes(data[s.Uint64():e.Uint64()], int(size.Uint64()))
}
diff --git a/vm/context.go b/vm/context.go
index 1c2f665a4..e73199b77 100644
--- a/vm/context.go
+++ b/vm/context.go
@@ -9,7 +9,7 @@ import (
type ContextRef interface {
ReturnGas(*big.Int, *big.Int)
- Address() []byte
+ Address() common.Address
SetCode([]byte)
}
@@ -18,7 +18,7 @@ type Context struct {
self ContextRef
Code []byte
- CodeAddr []byte
+ CodeAddr *common.Address
value, Gas, UsedGas, Price *big.Int
@@ -64,10 +64,6 @@ func (c *Context) GetRangeValue(x, size uint64) []byte {
return common.RightPadBytes(c.Code[x:y], int(size))
}
-func (c *Context) GetCode(x, size uint64) []byte {
- return getData(c.Code, x, size)
-}
-
func (c *Context) Return(ret []byte) []byte {
// Return the remaining gas to the caller
c.caller.ReturnGas(c.Gas, c.Price)
@@ -100,7 +96,7 @@ func (c *Context) ReturnGas(gas, price *big.Int) {
/*
* Set / Get
*/
-func (c *Context) Address() []byte {
+func (c *Context) Address() common.Address {
return c.self.Address()
}
@@ -108,7 +104,7 @@ func (self *Context) SetCode(code []byte) {
self.Code = code
}
-func (self *Context) SetCallCode(addr, code []byte) {
+func (self *Context) SetCallCode(addr *common.Address, code []byte) {
self.Code = code
self.CodeAddr = addr
}
diff --git a/vm/environment.go b/vm/environment.go
index 83faaa23e..5d493166c 100644
--- a/vm/environment.go
+++ b/vm/environment.go
@@ -3,19 +3,21 @@ package vm
import (
"errors"
"fmt"
+ "io"
"math/big"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/state"
)
type Environment interface {
State() *state.StateDB
- Origin() []byte
+ Origin() common.Address
BlockNumber() *big.Int
- GetHash(n uint64) []byte
- Coinbase() []byte
+ GetHash(n uint64) common.Hash
+ Coinbase() common.Address
Time() int64
Difficulty() *big.Int
GasLimit() *big.Int
@@ -27,16 +29,16 @@ type Environment interface {
Depth() int
SetDepth(i int)
- Call(me ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error)
- CallCode(me ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error)
- Create(me ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, ContextRef)
+ Call(me ContextRef, addr common.Address, 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 *common.Address, data []byte, gas, price, value *big.Int) ([]byte, error, ContextRef)
}
type Account interface {
SubBalance(amount *big.Int)
AddBalance(amount *big.Int)
Balance() *big.Int
- Address() []byte
+ Address() common.Address
}
// generic transfer method
@@ -53,17 +55,17 @@ func Transfer(from, to Account, amount *big.Int) error {
}
type Log struct {
- address []byte
- topics [][]byte
+ address common.Address
+ topics []common.Hash
data []byte
log uint64
}
-func (self *Log) Address() []byte {
+func (self *Log) Address() common.Address {
return self.address
}
-func (self *Log) Topics() [][]byte {
+func (self *Log) Topics() []common.Hash {
return self.topics
}
@@ -75,10 +77,16 @@ func (self *Log) Number() uint64 {
return self.log
}
+func (self *Log) EncodeRLP(w io.Writer) error {
+ return rlp.Encode(w, []interface{}{self.address, self.topics, self.data})
+}
+
+/*
func (self *Log) RlpData() interface{} {
return []interface{}{self.address, common.ByteSliceToInterface(self.topics), self.data}
}
+*/
func (self *Log) String() string {
- return fmt.Sprintf("[A=%x T=%x D=%x]", self.address, self.topics, self.data)
+ return fmt.Sprintf("{%x %x %x}", self.address, self.data, self.topics)
}
diff --git a/vm/gas.go b/vm/gas.go
index a19afeb67..c4d5e4c4e 100644
--- a/vm/gas.go
+++ b/vm/gas.go
@@ -7,6 +7,55 @@ type req struct {
gas *big.Int
}
+var (
+ GasQuickStep = big.NewInt(2)
+ GasFastestStep = big.NewInt(3)
+ GasFastStep = big.NewInt(5)
+ GasMidStep = big.NewInt(8)
+ GasSlowStep = big.NewInt(10)
+ GasExtStep = big.NewInt(20)
+
+ GasStorageGet = big.NewInt(50)
+ GasStorageAdd = big.NewInt(20000)
+ GasStorageMod = big.NewInt(5000)
+ GasLogBase = big.NewInt(375)
+ GasLogTopic = big.NewInt(375)
+ GasLogByte = big.NewInt(8)
+ GasCreate = big.NewInt(32000)
+ GasCreateByte = big.NewInt(200)
+ GasCall = big.NewInt(40)
+ GasCallValueTransfer = big.NewInt(9000)
+ GasStipend = big.NewInt(2300)
+ GasCallNewAccount = big.NewInt(25000)
+ GasReturn = big.NewInt(0)
+ GasStop = big.NewInt(0)
+ GasJumpDest = big.NewInt(1)
+
+ RefundStorage = big.NewInt(15000)
+ RefundSuicide = big.NewInt(24000)
+
+ GasMemWord = big.NewInt(3)
+ GasQuadCoeffDenom = big.NewInt(512)
+ GasContractByte = big.NewInt(200)
+ GasTransaction = big.NewInt(21000)
+ GasTxDataNonzeroByte = big.NewInt(68)
+ GasTxDataZeroByte = big.NewInt(4)
+ GasTx = big.NewInt(21000)
+ GasExp = big.NewInt(10)
+ GasExpByte = big.NewInt(10)
+
+ GasSha3Base = big.NewInt(30)
+ GasSha3Word = big.NewInt(6)
+ GasSha256Base = big.NewInt(60)
+ GasSha256Word = big.NewInt(12)
+ GasRipemdBase = big.NewInt(600)
+ GasRipemdWord = big.NewInt(12)
+ GasEcrecover = big.NewInt(3000)
+ GasIdentityBase = big.NewInt(15)
+ GasIdentityWord = big.NewInt(3)
+ GasCopyWord = big.NewInt(3)
+)
+
var _baseCheck = map[OpCode]req{
// Req stack Gas price
ADD: {2, GasFastestStep},
diff --git a/vm/memory.go b/vm/memory.go
index 2a1e6e1b9..dd47fa1b5 100644
--- a/vm/memory.go
+++ b/vm/memory.go
@@ -1,6 +1,10 @@
package vm
-import "fmt"
+import (
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/common"
+)
type Memory struct {
store []byte
@@ -11,21 +15,21 @@ func NewMemory() *Memory {
}
func (m *Memory) Set(offset, size uint64, value []byte) {
- if len(value) > 0 {
- totSize := offset + size
- lenSize := uint64(len(m.store) - 1)
- if totSize > lenSize {
- // Calculate the diff between the sizes
- diff := totSize - lenSize
- if diff > 0 {
- // Create a new empty slice and append it
- newSlice := make([]byte, diff-1)
- // Resize slice
- m.store = append(m.store, newSlice...)
- }
+ value = common.RightPadBytes(value, int(size))
+
+ totSize := offset + size
+ lenSize := uint64(len(m.store) - 1)
+ if totSize > lenSize {
+ // Calculate the diff between the sizes
+ diff := totSize - lenSize
+ if diff > 0 {
+ // Create a new empty slice and append it
+ newSlice := make([]byte, diff-1)
+ // Resize slice
+ m.store = append(m.store, newSlice...)
}
- copy(m.store[offset:offset+size], value)
}
+ copy(m.store[offset:offset+size], value)
}
func (m *Memory) Resize(size uint64) {
diff --git a/vm/vm.go b/vm/vm.go
index 089047a95..7400a48c4 100644
--- a/vm/vm.go
+++ b/vm/vm.go
@@ -33,10 +33,7 @@ func New(env Environment) *Vm {
}
func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
- //func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.Int, callData []byte) (ret []byte, err error) {
self.env.SetDepth(self.env.Depth() + 1)
-
- //context := NewContext(caller, me, code, gas, price)
var (
caller = context.caller
code = context.Code
@@ -44,7 +41,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
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 {
// Recover from any require exception
@@ -57,13 +54,14 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
ret = context.Return(nil)
err = fmt.Errorf("%v", r)
-
}
}()
}
- if p := Precompiled[string(context.CodeAddr)]; p != nil {
- return self.RunPrecompiled(p, callData, context)
+ if context.CodeAddr != nil {
+ if p := Precompiled[context.CodeAddr.Str()]; p != nil {
+ return self.RunPrecompiled(p, callData, context)
+ }
}
var (
@@ -394,11 +392,11 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
self.Printf(" => (%v) %x", size, data)
// 0x30 range
case ADDRESS:
- stack.push(common.BigD(context.Address()))
+ stack.push(common.Bytes2Big(context.Address().Bytes()))
self.Printf(" => %x", context.Address())
case BALANCE:
- addr := stack.pop().Bytes()
+ addr := common.BigToAddress(stack.pop())
balance := statedb.GetBalance(addr)
stack.push(balance)
@@ -407,12 +405,12 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
case ORIGIN:
origin := self.env.Origin()
- stack.push(common.BigD(origin))
+ stack.push(origin.Big())
self.Printf(" => %x", origin)
case CALLER:
caller := context.caller.Address()
- stack.push(common.BigD(caller))
+ stack.push(common.Bytes2Big(caller.Bytes()))
self.Printf(" => %x", caller)
case CALLVALUE:
@@ -447,18 +445,15 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
cOff = stack.pop()
l = stack.pop()
)
- var data []byte
- if cOff.Cmp(big.NewInt(int64(len(callData)))) <= 0 {
- data = getData(callData, cOff.Uint64(), l.Uint64())
- }
+ data := getData(callData, cOff, l)
mem.Set(mOff.Uint64(), l.Uint64(), data)
- self.Printf(" => [%v, %v, %v] %x", mOff, cOff, l, data)
+ self.Printf(" => [%v, %v, %v]", mOff, cOff, l)
case CODESIZE, EXTCODESIZE:
var code []byte
if op == EXTCODESIZE {
- addr := stack.pop().Bytes()
+ addr := common.BigToAddress(stack.pop())
code = statedb.GetCode(addr)
} else {
@@ -472,7 +467,8 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
case CODECOPY, EXTCODECOPY:
var code []byte
if op == EXTCODECOPY {
- code = statedb.GetCode(stack.pop().Bytes())
+ addr := common.BigToAddress(stack.pop())
+ code = statedb.GetCode(addr)
} else {
code = context.Code
}
@@ -483,10 +479,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
l = stack.pop()
)
- var codeCopy []byte
- if cOff.Cmp(big.NewInt(int64(len(code)))) <= 0 {
- codeCopy = getData(code, cOff.Uint64(), l.Uint64())
- }
+ codeCopy := getData(code, cOff, l)
mem.Set(mOff.Uint64(), l.Uint64(), codeCopy)
@@ -502,7 +495,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
n := new(big.Int).Sub(self.env.BlockNumber(), common.Big257)
if num.Cmp(n) > 0 && num.Cmp(self.env.BlockNumber()) < 0 {
- stack.push(common.BigD(self.env.GetHash(num.Uint64())))
+ stack.push(self.env.GetHash(num.Uint64()).Big())
} else {
stack.push(common.Big0)
}
@@ -511,7 +504,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
case COINBASE:
coinbase := self.env.Coinbase()
- stack.push(common.BigD(coinbase))
+ stack.push(coinbase.Big())
self.Printf(" => 0x%x", coinbase)
case TIMESTAMP:
@@ -562,10 +555,10 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
self.Printf(" => [%d]", n)
case LOG0, LOG1, LOG2, LOG3, LOG4:
n := int(op - LOG0)
- topics := make([][]byte, n)
+ topics := make([]common.Hash, n)
mStart, mSize := stack.pop(), stack.pop()
for i := 0; i < n; i++ {
- topics[i] = common.LeftPadBytes(stack.pop().Bytes(), 32)
+ topics[i] = common.BigToHash(stack.pop()) //common.LeftPadBytes(stack.pop().Bytes(), 32)
}
data := mem.Get(mStart.Int64(), mSize.Int64())
@@ -586,22 +579,24 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
self.Printf(" => 0x%x", val)
case MSTORE8:
- off, val := stack.pop(), stack.pop()
+ off, val := stack.pop().Int64(), stack.pop().Int64()
- mem.store[off.Int64()] = byte(val.Int64() & 0xff)
+ mem.store[off] = byte(val & 0xff)
- self.Printf(" => [%v] 0x%x", off, val)
+ self.Printf(" => [%v] 0x%x", off, mem.store[off])
case SLOAD:
- loc := stack.pop()
- val := common.BigD(statedb.GetState(context.Address(), loc.Bytes()))
+ loc := common.BigToHash(stack.pop())
+ val := common.Bytes2Big(statedb.GetState(context.Address(), loc))
stack.push(val)
- self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
+ self.Printf(" {0x%x : 0x%x}", loc, val.Bytes())
case SSTORE:
- loc, val := stack.pop(), stack.pop()
- statedb.SetState(context.Address(), loc.Bytes(), val)
+ loc := common.BigToHash(stack.pop())
+ val := stack.pop()
+
+ statedb.SetState(context.Address(), loc, val)
- self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
+ self.Printf(" {0x%x : 0x%x}", loc, val.Bytes())
case JUMP:
jump(pc, stack.pop())
@@ -634,7 +629,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
offset, size = stack.pop(), stack.pop()
input = mem.Get(offset.Int64(), size.Int64())
gas = new(big.Int).Set(context.Gas)
- addr []byte
+ addr common.Address
)
self.Endl()
@@ -654,7 +649,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
}
addr = ref.Address()
- stack.push(common.BigD(addr))
+ stack.push(addr.Big())
}
@@ -668,7 +663,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
// pop return size and offset
retOffset, retSize := stack.pop(), stack.pop()
- address := common.Address(addr.Bytes())
+ address := common.BigToAddress(addr)
self.Printf(" => %x", address).Endl()
// Get the arguments from the memory
@@ -706,10 +701,10 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
return context.Return(ret), nil
case SUICIDE:
- receiver := statedb.GetOrNewStateObject(stack.pop().Bytes())
+ receiver := statedb.GetOrNewStateObject(common.BigToAddress(stack.pop()))
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)
@@ -769,7 +764,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
var g *big.Int
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 {
// 0 => non 0
g = GasStorageAdd
@@ -821,7 +816,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
gas.Add(gas, stack.data[stack.len()-1])
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)
}
}