rework vm
This commit is contained in:
@@ -5,11 +5,10 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/state"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Environment interface {
|
type Environment interface {
|
||||||
State() *state.State
|
//State() *state.State
|
||||||
|
|
||||||
Origin() []byte
|
Origin() []byte
|
||||||
BlockNumber() *big.Int
|
BlockNumber() *big.Int
|
||||||
@@ -19,8 +18,16 @@ type Environment interface {
|
|||||||
Difficulty() *big.Int
|
Difficulty() *big.Int
|
||||||
BlockHash() []byte
|
BlockHash() []byte
|
||||||
GasLimit() *big.Int
|
GasLimit() *big.Int
|
||||||
|
|
||||||
Transfer(from, to Account, amount *big.Int) error
|
Transfer(from, to Account, amount *big.Int) error
|
||||||
AddLog(*state.Log)
|
AddLog(addr []byte, topics [][]byte, data []byte)
|
||||||
|
DeleteAccount(addr []byte)
|
||||||
|
SetState(addr, key, value []byte)
|
||||||
|
GetState(addr, key []byte) []byte
|
||||||
|
Balance(addr []byte) *big.Int
|
||||||
|
AddBalance(addr []byte, balance *big.Int)
|
||||||
|
GetCode(addr []byte) []byte
|
||||||
|
Refund(addr []byte, gas, price *big.Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Object interface {
|
type Object interface {
|
||||||
@@ -43,9 +50,5 @@ func Transfer(from, to Account, amount *big.Int) error {
|
|||||||
from.SubBalance(amount)
|
from.SubBalance(amount)
|
||||||
to.AddBalance(amount)
|
to.AddBalance(amount)
|
||||||
|
|
||||||
// Add default LOG. Default = big(sender.addr) + 1
|
|
||||||
//addr := ethutil.BigD(receiver.Address())
|
|
||||||
//tx.addLog(vm.Log{sender.Address(), [][]byte{ethutil.U256(addr.Add(addr, ethutil.Big1)).Bytes()}, nil})
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -90,6 +90,6 @@ func (self *Execution) exec(code, caddr []byte, caller ClosureRef) (ret []byte,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Execution) Create(caller ClosureRef) (ret []byte, err error) {
|
func (self *Execution) Create(caller []byte) (ret []byte, err error) {
|
||||||
return self.exec(self.input, nil, caller)
|
return self.exec(self.input, nil, caller)
|
||||||
}
|
}
|
||||||
|
269
vm/vm_debug.go
269
vm/vm_debug.go
@@ -6,7 +6,6 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/state"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type DebugVm struct {
|
type DebugVm struct {
|
||||||
@@ -29,6 +28,13 @@ type DebugVm struct {
|
|||||||
depth int
|
depth int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Options struct {
|
||||||
|
Address, Caller []byte
|
||||||
|
Data []byte
|
||||||
|
Code []byte
|
||||||
|
Value, Gas, Price *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
func NewDebugVm(env Environment) *DebugVm {
|
func NewDebugVm(env Environment) *DebugVm {
|
||||||
lt := LogTyPretty
|
lt := LogTyPretty
|
||||||
if ethutil.Config.Diff {
|
if ethutil.Config.Diff {
|
||||||
@@ -38,7 +44,13 @@ func NewDebugVm(env Environment) *DebugVm {
|
|||||||
return &DebugVm{env: env, logTy: lt, Recoverable: true}
|
return &DebugVm{env: env, logTy: lt, Recoverable: true}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
//func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
||||||
|
func (self *DebugVm) Run(call Options) (ret []byte, gas *big.Int, err error) {
|
||||||
|
// Don't bother with the execution if there's no code.
|
||||||
|
if len(call.Code) == 0 {
|
||||||
|
return nil, new(big.Int), nil
|
||||||
|
}
|
||||||
|
|
||||||
self.depth++
|
self.depth++
|
||||||
|
|
||||||
if self.Recoverable {
|
if self.Recoverable {
|
||||||
@@ -47,41 +59,49 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
self.Endl()
|
self.Endl()
|
||||||
|
|
||||||
closure.UseGas(closure.Gas)
|
gas = new(big.Int)
|
||||||
|
|
||||||
ret = closure.Return(nil)
|
|
||||||
|
|
||||||
err = fmt.Errorf("%v", r)
|
err = fmt.Errorf("%v", r)
|
||||||
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gas = new(big.Int).Set(opt.Gas)
|
||||||
var (
|
var (
|
||||||
op OpCode
|
op OpCode
|
||||||
|
|
||||||
destinations = analyseJumpDests(closure.Code)
|
destinations = analyseJumpDests(call.Code)
|
||||||
mem = NewMemory()
|
mem = NewMemory()
|
||||||
stack = NewStack()
|
stack = NewStack()
|
||||||
pc = big.NewInt(0)
|
pc = big.NewInt(0)
|
||||||
step = 0
|
step = 0
|
||||||
prevStep = 0
|
prevStep = 0
|
||||||
statedb = self.env.State()
|
//statedb = self.env.State()
|
||||||
require = func(m int) {
|
require = func(m int) {
|
||||||
if stack.Len() < m {
|
if stack.Len() < m {
|
||||||
panic(fmt.Sprintf("%04v (%v) stack err size = %d, required = %d", pc, op, stack.Len(), m))
|
panic(fmt.Sprintf("%04v (%v) stack err size = %d, required = %d", pc, op, stack.Len(), m))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useGas = func(amount *big.Int) bool {
|
||||||
|
if amount.Cmp(gas) > 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
gas.Sub(gas, amount)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
jump = func(from, to *big.Int) {
|
jump = func(from, to *big.Int) {
|
||||||
p := int(to.Int64())
|
p := to.Uint64()
|
||||||
|
|
||||||
self.Printf(" ~> %v", to)
|
self.Printf(" ~> %v", to)
|
||||||
// Return to start
|
// Return to start
|
||||||
if p == 0 {
|
if p == 0 {
|
||||||
pc = big.NewInt(0)
|
pc = big.NewInt(0)
|
||||||
} else {
|
} else {
|
||||||
nop := OpCode(closure.GetOp(p))
|
nop := OpCode(call.GetOp(p))
|
||||||
if !(nop == JUMPDEST || destinations[from.Int64()] != nil) {
|
if !(nop == JUMPDEST || destinations[from.Int64()] != nil) {
|
||||||
panic(fmt.Sprintf("JUMP missed JUMPDEST (%v) %v", nop, p))
|
panic(fmt.Sprintf("JUMP missed JUMPDEST (%v) %v", nop, p))
|
||||||
} else if nop == JUMP || nop == JUMPI {
|
} else if nop == JUMP || nop == JUMPI {
|
||||||
@@ -96,17 +116,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Debug hook
|
vmlogger.Debugf("(%d) %x gas: %v (d) %x\n", self.depth, call.Address, gas, call.Data)
|
||||||
if self.Dbg != nil {
|
|
||||||
self.Dbg.SetCode(closure.Code)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't bother with the execution if there's no code.
|
|
||||||
if len(closure.Code) == 0 {
|
|
||||||
return closure.Return(nil), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
vmlogger.Debugf("(%d) %x gas: %v (d) %x\n", self.depth, closure.Address(), closure.Gas, closure.Args)
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
prevStep = step
|
prevStep = step
|
||||||
@@ -115,31 +125,33 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
|
|
||||||
step++
|
step++
|
||||||
// Get the memory location of pc
|
// Get the memory location of pc
|
||||||
op = closure.GetOp(int(pc.Uint64()))
|
op = call.GetOp(pc.Uint64())
|
||||||
|
|
||||||
// XXX Leave this Println intact. Don't change this to the log system.
|
// XXX Leave this Println intact. Don't change this to the log system.
|
||||||
// Used for creating diffs between implementations
|
// Used for creating diffs between implementations
|
||||||
if self.logTy == LogTyDiff {
|
/*
|
||||||
switch op {
|
if self.logTy == LogTyDiff {
|
||||||
case STOP, RETURN, SUICIDE:
|
switch op {
|
||||||
statedb.GetStateObject(closure.Address()).EachStorage(func(key string, value *ethutil.Value) {
|
case STOP, RETURN, SUICIDE:
|
||||||
value.Decode()
|
statedb.GetStateObject(closure.Address()).EachStorage(func(key string, value *ethutil.Value) {
|
||||||
fmt.Printf("%x %x\n", new(big.Int).SetBytes([]byte(key)).Bytes(), value.Bytes())
|
value.Decode()
|
||||||
})
|
fmt.Printf("%x %x\n", new(big.Int).SetBytes([]byte(key)).Bytes(), value.Bytes())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
b := pc.Bytes()
|
||||||
|
if len(b) == 0 {
|
||||||
|
b = []byte{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%x %x %x %x\n", closure.Address(), b, []byte{byte(op)}, closure.Gas.Bytes())
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
b := pc.Bytes()
|
reqGas := new(big.Int)
|
||||||
if len(b) == 0 {
|
|
||||||
b = []byte{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("%x %x %x %x\n", closure.Address(), b, []byte{byte(op)}, closure.Gas.Bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
gas := new(big.Int)
|
|
||||||
addStepGasUsage := func(amount *big.Int) {
|
addStepGasUsage := func(amount *big.Int) {
|
||||||
if amount.Cmp(ethutil.Big0) >= 0 {
|
if amount.Cmp(ethutil.Big0) >= 0 {
|
||||||
gas.Add(gas, amount)
|
reqGas.Add(reqGas, amount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,42 +178,43 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
require(n + 2)
|
require(n + 2)
|
||||||
|
|
||||||
mSize, mStart := stack.Peekn()
|
mSize, mStart := stack.Peekn()
|
||||||
gas.Set(GasLog)
|
reqGs.Set(GasLog)
|
||||||
addStepGasUsage(new(big.Int).Mul(big.NewInt(int64(n)), GasLog))
|
addStepGasUsage(new(big.Int).Mul(big.NewInt(int64(n)), GasLog))
|
||||||
addStepGasUsage(new(big.Int).Add(mSize, mStart))
|
addStepGasUsage(new(big.Int).Add(mSize, mStart))
|
||||||
// Gas only
|
// Gas only
|
||||||
case STOP:
|
case STOP:
|
||||||
gas.Set(ethutil.Big0)
|
reqGas.Set(ethutil.Big0)
|
||||||
case SUICIDE:
|
case SUICIDE:
|
||||||
require(1)
|
require(1)
|
||||||
|
|
||||||
gas.Set(ethutil.Big0)
|
reqGas.Set(ethutil.Big0)
|
||||||
case SLOAD:
|
case SLOAD:
|
||||||
require(1)
|
require(1)
|
||||||
|
|
||||||
gas.Set(GasSLoad)
|
reqGas.Set(GasSLoad)
|
||||||
// Memory resize & Gas
|
// Memory resize & Gas
|
||||||
case SSTORE:
|
case SSTORE:
|
||||||
require(2)
|
require(2)
|
||||||
|
|
||||||
var mult *big.Int
|
var mult *big.Int
|
||||||
y, x := stack.Peekn()
|
y, x := stack.Peekn()
|
||||||
val := closure.GetStorage(x)
|
val := ethutil.BigD(self.env.GetState(x.Bytes())) //closure.GetStorage(x)
|
||||||
if val.BigInt().Cmp(ethutil.Big0) == 0 && len(y.Bytes()) > 0 {
|
if val.BigInt().Cmp(ethutil.Big0) == 0 && len(y.Bytes()) > 0 {
|
||||||
// 0 => non 0
|
// 0 => non 0
|
||||||
mult = ethutil.Big3
|
mult = ethutil.Big3
|
||||||
} else if val.BigInt().Cmp(ethutil.Big0) != 0 && len(y.Bytes()) == 0 {
|
} else if val.BigInt().Cmp(ethutil.Big0) != 0 && len(y.Bytes()) == 0 {
|
||||||
statedb.Refund(closure.caller.Address(), GasSStoreRefund, closure.Price)
|
//statedb.Refund(closure.caller.Address(), GasSStoreRefund, closure.Price)
|
||||||
|
self.env.Refund(call.Caller, GasSStoreRefund, call.Price)
|
||||||
|
|
||||||
mult = ethutil.Big0
|
mult = ethutil.Big0
|
||||||
} else {
|
} else {
|
||||||
// non 0 => non 0
|
// non 0 => non 0
|
||||||
mult = ethutil.Big1
|
mult = ethutil.Big1
|
||||||
}
|
}
|
||||||
gas.Set(new(big.Int).Mul(mult, GasSStore))
|
reqGas.Set(new(big.Int).Mul(mult, GasSStore))
|
||||||
case BALANCE:
|
case BALANCE:
|
||||||
require(1)
|
require(1)
|
||||||
gas.Set(GasBalance)
|
reqGas.Set(GasBalance)
|
||||||
case MSTORE:
|
case MSTORE:
|
||||||
require(2)
|
require(2)
|
||||||
newMemSize = calcMemSize(stack.Peek(), u256(32))
|
newMemSize = calcMemSize(stack.Peek(), u256(32))
|
||||||
@@ -219,7 +232,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
case SHA3:
|
case SHA3:
|
||||||
require(2)
|
require(2)
|
||||||
|
|
||||||
gas.Set(GasSha)
|
reqGas.Set(GasSha)
|
||||||
|
|
||||||
newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2])
|
newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2])
|
||||||
case CALLDATACOPY:
|
case CALLDATACOPY:
|
||||||
@@ -236,7 +249,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-4])
|
newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-4])
|
||||||
case CALL, CALLCODE:
|
case CALL, CALLCODE:
|
||||||
require(7)
|
require(7)
|
||||||
gas.Set(GasCall)
|
reqGas.Set(GasCall)
|
||||||
addStepGasUsage(stack.data[stack.Len()-1])
|
addStepGasUsage(stack.data[stack.Len()-1])
|
||||||
|
|
||||||
x := calcMemSize(stack.data[stack.Len()-6], stack.data[stack.Len()-7])
|
x := calcMemSize(stack.data[stack.Len()-6], stack.data[stack.Len()-7])
|
||||||
@@ -245,7 +258,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
newMemSize = ethutil.BigMax(x, y)
|
newMemSize = ethutil.BigMax(x, y)
|
||||||
case CREATE:
|
case CREATE:
|
||||||
require(3)
|
require(3)
|
||||||
gas.Set(GasCreate)
|
reqGas.Set(GasCreate)
|
||||||
|
|
||||||
newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-3])
|
newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-3])
|
||||||
}
|
}
|
||||||
@@ -255,6 +268,12 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
newMemSize.Div(newMemSize, u256(32))
|
newMemSize.Div(newMemSize, u256(32))
|
||||||
newMemSize.Mul(newMemSize, u256(32))
|
newMemSize.Mul(newMemSize, u256(32))
|
||||||
|
|
||||||
|
switch op {
|
||||||
|
// Additional gas usage on *CODPY
|
||||||
|
case CALLDATACOPY, CODECOPY, EXTCODECOPY:
|
||||||
|
addStepGasUsage(new(big.Int).Div(newMemSize, u256(32)))
|
||||||
|
}
|
||||||
|
|
||||||
if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 {
|
if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 {
|
||||||
memGasUsage := new(big.Int).Sub(newMemSize, u256(int64(mem.Len())))
|
memGasUsage := new(big.Int).Sub(newMemSize, u256(int64(mem.Len())))
|
||||||
memGasUsage.Mul(GasMemory, memGasUsage)
|
memGasUsage.Mul(GasMemory, memGasUsage)
|
||||||
@@ -268,16 +287,12 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.Printf("(pc) %-3d -o- %-14s", pc, op.String())
|
self.Printf("(pc) %-3d -o- %-14s", pc, op.String())
|
||||||
self.Printf(" (m) %-4d (s) %-4d (g) %-3v (%v)", mem.Len(), stack.Len(), gas, closure.Gas)
|
self.Printf(" (m) %-4d (s) %-4d (g) %-3v (%v)", mem.Len(), stack.Len(), reqGas, gas)
|
||||||
|
|
||||||
if !closure.UseGas(gas) {
|
if !useGas(regGas) {
|
||||||
self.Endl()
|
self.Endl()
|
||||||
|
|
||||||
tmp := new(big.Int).Set(closure.Gas)
|
return nil, new(big.Int), OOG(reqGas, gas)
|
||||||
|
|
||||||
closure.UseGas(closure.Gas)
|
|
||||||
|
|
||||||
return closure.Return(nil), OOG(gas, tmp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch op {
|
switch op {
|
||||||
@@ -553,13 +568,15 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
self.Printf(" => %x", data)
|
self.Printf(" => %x", data)
|
||||||
// 0x30 range
|
// 0x30 range
|
||||||
case ADDRESS:
|
case ADDRESS:
|
||||||
stack.Push(ethutil.BigD(closure.Address()))
|
//stack.Push(ethutil.BigD(closure.Address()))
|
||||||
|
stack.Push(ethutil.BigD(call.Address))
|
||||||
|
|
||||||
self.Printf(" => %x", closure.Address())
|
self.Printf(" => %x", call.Address)
|
||||||
case BALANCE:
|
case BALANCE:
|
||||||
|
|
||||||
addr := stack.Pop().Bytes()
|
addr := stack.Pop().Bytes()
|
||||||
balance := statedb.GetBalance(addr)
|
//balance := statedb.GetBalance(addr)
|
||||||
|
balance := self.env.GetBalance(addr)
|
||||||
|
|
||||||
stack.Push(balance)
|
stack.Push(balance)
|
||||||
|
|
||||||
@@ -571,41 +588,42 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
|
|
||||||
self.Printf(" => %x", origin)
|
self.Printf(" => %x", origin)
|
||||||
case CALLER:
|
case CALLER:
|
||||||
caller := closure.caller.Address()
|
//caller := closure.caller.Address()
|
||||||
stack.Push(ethutil.BigD(caller))
|
//stack.Push(ethutil.BigD(caller))
|
||||||
|
stack.Push(call.Caller)
|
||||||
|
|
||||||
self.Printf(" => %x", caller)
|
self.Printf(" => %x", call.Caller)
|
||||||
case CALLVALUE:
|
case CALLVALUE:
|
||||||
value := closure.exe.value
|
//value := closure.exe.value
|
||||||
|
|
||||||
stack.Push(value)
|
stack.Push(call.Value)
|
||||||
|
|
||||||
self.Printf(" => %v", value)
|
self.Printf(" => %v", call.Value)
|
||||||
case CALLDATALOAD:
|
case CALLDATALOAD:
|
||||||
var (
|
var (
|
||||||
offset = stack.Pop()
|
offset = stack.Pop()
|
||||||
data = make([]byte, 32)
|
data = make([]byte, 32)
|
||||||
lenData = big.NewInt(int64(len(closure.Args)))
|
lenData = big.NewInt(int64(len(call.Data)))
|
||||||
)
|
)
|
||||||
|
|
||||||
if lenData.Cmp(offset) >= 0 {
|
if lenData.Cmp(offset) >= 0 {
|
||||||
length := new(big.Int).Add(offset, ethutil.Big32)
|
length := new(big.Int).Add(offset, ethutil.Big32)
|
||||||
length = ethutil.BigMin(length, lenData)
|
length = ethutil.BigMin(length, lenData)
|
||||||
|
|
||||||
copy(data, closure.Args[offset.Int64():length.Int64()])
|
copy(data, call.Data[offset.Int64():length.Int64()])
|
||||||
}
|
}
|
||||||
|
|
||||||
self.Printf(" => 0x%x", data)
|
self.Printf(" => 0x%x", data)
|
||||||
|
|
||||||
stack.Push(ethutil.BigD(data))
|
stack.Push(ethutil.BigD(data))
|
||||||
case CALLDATASIZE:
|
case CALLDATASIZE:
|
||||||
l := int64(len(closure.Args))
|
l := int64(len(call.Data))
|
||||||
stack.Push(big.NewInt(l))
|
stack.Push(big.NewInt(l))
|
||||||
|
|
||||||
self.Printf(" => %d", l)
|
self.Printf(" => %d", l)
|
||||||
case CALLDATACOPY:
|
case CALLDATACOPY:
|
||||||
var (
|
var (
|
||||||
size = int64(len(closure.Args))
|
size = int64(len(call.Data))
|
||||||
mOff = stack.Pop().Int64()
|
mOff = stack.Pop().Int64()
|
||||||
cOff = stack.Pop().Int64()
|
cOff = stack.Pop().Int64()
|
||||||
l = stack.Pop().Int64()
|
l = stack.Pop().Int64()
|
||||||
@@ -618,7 +636,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
l = 0
|
l = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
code := closure.Args[cOff : cOff+l]
|
code := call.Data[cOff : cOff+l]
|
||||||
|
|
||||||
mem.Set(mOff, l, code)
|
mem.Set(mOff, l, code)
|
||||||
|
|
||||||
@@ -628,9 +646,9 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
if op == EXTCODESIZE {
|
if op == EXTCODESIZE {
|
||||||
addr := stack.Pop().Bytes()
|
addr := stack.Pop().Bytes()
|
||||||
|
|
||||||
code = statedb.GetCode(addr)
|
self.env.GetCode(addr)
|
||||||
} else {
|
} else {
|
||||||
code = closure.Code
|
code = call.Code
|
||||||
}
|
}
|
||||||
|
|
||||||
l := big.NewInt(int64(len(code)))
|
l := big.NewInt(int64(len(code)))
|
||||||
@@ -642,9 +660,9 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
if op == EXTCODECOPY {
|
if op == EXTCODECOPY {
|
||||||
addr := stack.Pop().Bytes()
|
addr := stack.Pop().Bytes()
|
||||||
|
|
||||||
code = statedb.GetCode(addr)
|
code = self.env.GetCode(addr)
|
||||||
} else {
|
} else {
|
||||||
code = closure.Code
|
code = call.Code
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -667,9 +685,9 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
|
|
||||||
self.Printf(" => [%v, %v, %v] %x", mOff, cOff, l, code[cOff:cOff+l])
|
self.Printf(" => [%v, %v, %v] %x", mOff, cOff, l, code[cOff:cOff+l])
|
||||||
case GASPRICE:
|
case GASPRICE:
|
||||||
stack.Push(closure.Price)
|
stack.Push(call.Price)
|
||||||
|
|
||||||
self.Printf(" => %v", closure.Price)
|
self.Printf(" => %v", call.Price)
|
||||||
|
|
||||||
// 0x40 range
|
// 0x40 range
|
||||||
case PREVHASH:
|
case PREVHASH:
|
||||||
@@ -707,17 +725,17 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
|
|
||||||
// 0x50 range
|
// 0x50 range
|
||||||
case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
|
case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
|
||||||
a := big.NewInt(int64(op) - int64(PUSH1) + 1)
|
a := uint64(op) - uint64(PUSH1) + 1
|
||||||
pc.Add(pc, ethutil.Big1)
|
pc.Add(pc, ethutil.Big1)
|
||||||
data := closure.Gets(pc, a)
|
data := call.Get(pc.Uint64(), a) //closure.Gets(pc, a)
|
||||||
val := ethutil.BigD(data.Bytes())
|
val := ethutil.BigD(data)
|
||||||
// Push value to stack
|
// Push value to stack
|
||||||
stack.Push(val)
|
stack.Push(val)
|
||||||
pc.Add(pc, a.Sub(a, big.NewInt(1)))
|
pc.Add(pc, big.NewInt(int64(a)-1))
|
||||||
|
|
||||||
step += int(op) - int(PUSH1) + 1
|
step += uint64(op) - uint64(PUSH1) + 1
|
||||||
|
|
||||||
self.Printf(" => 0x%x", data.Bytes())
|
self.Printf(" => 0x%x", data)
|
||||||
case POP:
|
case POP:
|
||||||
stack.Pop()
|
stack.Pop()
|
||||||
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
|
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
|
||||||
@@ -725,10 +743,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
v := stack.Dupn(n)
|
v := stack.Dupn(n)
|
||||||
|
|
||||||
self.Printf(" => [%d] 0x%x", n, stack.Peek().Bytes())
|
self.Printf(" => [%d] 0x%x", n, stack.Peek().Bytes())
|
||||||
|
|
||||||
if OpCode(closure.Get(new(big.Int).Add(pc, ethutil.Big1)).Uint()) == POP && OpCode(closure.Get(new(big.Int).Add(pc, big.NewInt(2))).Uint()) == POP {
|
|
||||||
fmt.Println(toValue(v))
|
|
||||||
}
|
|
||||||
case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
|
case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
|
||||||
n := int(op - SWAP1 + 2)
|
n := int(op - SWAP1 + 2)
|
||||||
x, y := stack.Swapn(n)
|
x, y := stack.Swapn(n)
|
||||||
@@ -743,8 +757,8 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
topics[i] = stack.Pop().Bytes()
|
topics[i] = stack.Pop().Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
log := &state.Log{closure.Address(), topics, data}
|
//log := &state.Log{closure.Address(), topics, data}
|
||||||
self.env.AddLog(log)
|
self.env.AddLog(call.Address, topics, data)
|
||||||
|
|
||||||
self.Printf(" => %v", log)
|
self.Printf(" => %v", log)
|
||||||
case MLOAD:
|
case MLOAD:
|
||||||
@@ -768,18 +782,16 @@ func (self *DebugVm) RunClosure(closure *Closure) (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 := stack.Pop()
|
||||||
val := ethutil.BigD(statedb.GetState(closure.Address(), loc.Bytes()))
|
val := ethutil.BigD(self.env.GetState(call.Address, loc.Bytes()))
|
||||||
stack.Push(val)
|
stack.Push(val)
|
||||||
|
|
||||||
self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
|
self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
|
||||||
case SSTORE:
|
case SSTORE:
|
||||||
val, loc := stack.Popn()
|
val, loc := stack.Popn()
|
||||||
statedb.SetState(closure.Address(), loc.Bytes(), val)
|
self.env.SetState(call.Address, loc.Bytes(), val.Bytes())
|
||||||
|
//statedb.SetState(closure.Address(), loc.Bytes(), val)
|
||||||
|
|
||||||
// Debug sessions are allowed to run without message
|
//closure.message.AddStorageChange(loc.Bytes())
|
||||||
if closure.message != nil {
|
|
||||||
closure.message.AddStorageChange(loc.Bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
|
self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
|
||||||
case JUMP:
|
case JUMP:
|
||||||
@@ -802,7 +814,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
case MSIZE:
|
case MSIZE:
|
||||||
stack.Push(big.NewInt(int64(mem.Len())))
|
stack.Push(big.NewInt(int64(mem.Len())))
|
||||||
case GAS:
|
case GAS:
|
||||||
stack.Push(closure.Gas)
|
stack.Push(call.Gas)
|
||||||
// 0x60 range
|
// 0x60 range
|
||||||
case CREATE:
|
case CREATE:
|
||||||
var (
|
var (
|
||||||
@@ -810,7 +822,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
value = stack.Pop()
|
value = stack.Pop()
|
||||||
size, offset = stack.Popn()
|
size, offset = stack.Popn()
|
||||||
input = mem.Get(offset.Int64(), size.Int64())
|
input = mem.Get(offset.Int64(), size.Int64())
|
||||||
gas = new(big.Int).Set(closure.Gas)
|
gas = new(big.Int).Set(call.Gas)
|
||||||
|
|
||||||
// Snapshot the current stack so we are able to
|
// Snapshot the current stack so we are able to
|
||||||
// revert back to it later.
|
// revert back to it later.
|
||||||
@@ -818,16 +830,19 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Generate a new address
|
// Generate a new address
|
||||||
n := statedb.GetNonce(closure.Address())
|
//n := statedb.GetNonce(closure.Address())
|
||||||
addr := crypto.CreateAddress(closure.Address(), n)
|
//addr := crypto.CreateAddress(closure.Address(), n)
|
||||||
statedb.SetNonce(closure.Address(), n+1)
|
//statedb.SetNonce(closure.Address(), n+1)
|
||||||
|
n := self.env.GetNonce(call.Address)
|
||||||
|
addr := crypto.CreateAddress(call.Address, n)
|
||||||
|
self.env.SetNonce(call.Address, n+1)
|
||||||
|
|
||||||
self.Printf(" (*) %x", addr).Endl()
|
self.Printf(" (*) %x", addr).Endl()
|
||||||
|
|
||||||
closure.UseGas(closure.Gas)
|
//closure.UseGas(closure.Gas)
|
||||||
|
|
||||||
msg := NewExecution(self, addr, input, gas, closure.Price, value)
|
msg := NewExecution(self, addr, input, gas, call.Price, value)
|
||||||
ret, err := msg.Create(closure)
|
ret, lgas, err := msg.Create(call.Address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
stack.Push(ethutil.BigFalse)
|
stack.Push(ethutil.BigFalse)
|
||||||
|
|
||||||
@@ -841,12 +856,9 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
stack.Push(ethutil.BigD(addr))
|
stack.Push(ethutil.BigD(addr))
|
||||||
}
|
}
|
||||||
|
|
||||||
self.Endl()
|
gas = lgas
|
||||||
|
|
||||||
// Debug hook
|
self.Endl()
|
||||||
if self.Dbg != nil {
|
|
||||||
self.Dbg.SetCode(closure.Code)
|
|
||||||
}
|
|
||||||
case CALL, CALLCODE:
|
case CALL, CALLCODE:
|
||||||
self.Endl()
|
self.Endl()
|
||||||
|
|
||||||
@@ -863,12 +875,12 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
|
|
||||||
var executeAddr []byte
|
var executeAddr []byte
|
||||||
if op == CALLCODE {
|
if op == CALLCODE {
|
||||||
executeAddr = closure.Address()
|
executeAddr = call.Address //closure.Address()
|
||||||
} else {
|
} else {
|
||||||
executeAddr = addr.Bytes()
|
executeAddr = addr.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := NewExecution(self, executeAddr, args, gas, closure.Price, value)
|
msg := NewExecution(self, executeAddr, args, gas, call.Price, value)
|
||||||
ret, err := msg.Exec(addr.Bytes(), closure)
|
ret, err := msg.Exec(addr.Bytes(), closure)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
stack.Push(ethutil.BigFalse)
|
stack.Push(ethutil.BigFalse)
|
||||||
@@ -881,24 +893,22 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
}
|
}
|
||||||
self.Printf("resume %x", closure.Address())
|
self.Printf("resume %x", closure.Address())
|
||||||
|
|
||||||
// Debug hook
|
|
||||||
if self.Dbg != nil {
|
|
||||||
self.Dbg.SetCode(closure.Code)
|
|
||||||
}
|
|
||||||
|
|
||||||
case RETURN:
|
case RETURN:
|
||||||
size, offset := stack.Popn()
|
size, offset := stack.Popn()
|
||||||
ret := mem.Get(offset.Int64(), size.Int64())
|
ret := mem.Get(offset.Int64(), size.Int64())
|
||||||
|
|
||||||
self.Printf(" => (%d) 0x%x", len(ret), ret).Endl()
|
self.Printf(" => (%d) 0x%x", len(ret), ret).Endl()
|
||||||
|
|
||||||
return closure.Return(ret), nil
|
return ret, gas, nil
|
||||||
|
|
||||||
|
//return closure.Return(ret), gas, nil
|
||||||
case SUICIDE:
|
case SUICIDE:
|
||||||
|
//receiver := statedb.GetOrNewStateObject(stack.Pop().Bytes())
|
||||||
|
//receiver.AddAmount(statedb.GetBalance(closure.Address()))
|
||||||
|
//statedb.Delete(closure.Address())
|
||||||
|
|
||||||
receiver := statedb.GetOrNewStateObject(stack.Pop().Bytes())
|
self.env.AddBalance(stack.Pop().Bytes(), self.env.Balance(call.Address))
|
||||||
|
self.env.DeleteAccount(call.Address)
|
||||||
receiver.AddAmount(statedb.GetBalance(closure.Address()))
|
|
||||||
statedb.Delete(closure.Address())
|
|
||||||
|
|
||||||
fallthrough
|
fallthrough
|
||||||
case STOP: // Stop the closure
|
case STOP: // Stop the closure
|
||||||
@@ -917,23 +927,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
pc.Add(pc, ethutil.Big1)
|
pc.Add(pc, ethutil.Big1)
|
||||||
|
|
||||||
self.Endl()
|
self.Endl()
|
||||||
|
|
||||||
if self.Dbg != nil {
|
|
||||||
for _, instrNo := range self.Dbg.BreakPoints() {
|
|
||||||
if pc.Cmp(big.NewInt(instrNo)) == 0 {
|
|
||||||
self.Stepping = true
|
|
||||||
|
|
||||||
if !self.Dbg.BreakHook(prevStep, op, mem, stack, statedb.GetStateObject(closure.Address())) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
} else if self.Stepping {
|
|
||||||
if !self.Dbg.StepHook(prevStep, op, mem, stack, statedb.GetStateObject(closure.Address())) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user