forked from cerc-io/plugeth
reworked stack
This commit is contained in:
parent
0795fd2701
commit
9007f2bbdc
@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/state"
|
"github.com/ethereum/go-ethereum/state"
|
||||||
"github.com/ethereum/go-ethereum/tests/helper"
|
"github.com/ethereum/go-ethereum/tests/helper"
|
||||||
"github.com/ethereum/go-ethereum/vm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Account struct {
|
type Account struct {
|
||||||
@ -81,11 +80,6 @@ func RunVmTest(p string, t *testing.T) {
|
|||||||
helper.CreateFileTests(t, p, &tests)
|
helper.CreateFileTests(t, p, &tests)
|
||||||
|
|
||||||
for name, test := range tests {
|
for name, test := range tests {
|
||||||
vm.Debug = true
|
|
||||||
helper.Logger.SetLogLevel(4)
|
|
||||||
if name != "addmod0" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db, _ := ethdb.NewMemDatabase()
|
||||||
statedb := state.New(nil, db)
|
statedb := state.New(nil, db)
|
||||||
for addr, account := range test.Pre {
|
for addr, account := range test.Pre {
|
||||||
|
@ -1,10 +1 @@
|
|||||||
package vm
|
package vm
|
||||||
|
|
||||||
import "github.com/ethereum/go-ethereum/state"
|
|
||||||
|
|
||||||
type Debugger interface {
|
|
||||||
BreakHook(step int, op OpCode, mem *Memory, stack *Stack, object *state.StateObject) bool
|
|
||||||
StepHook(step int, op OpCode, mem *Memory, stack *Stack, object *state.StateObject) bool
|
|
||||||
BreakPoints() []int64
|
|
||||||
SetCode(byteCode []byte)
|
|
||||||
}
|
|
||||||
|
86
vm/gas.go
Normal file
86
vm/gas.go
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package vm
|
||||||
|
|
||||||
|
import "math/big"
|
||||||
|
|
||||||
|
type req struct {
|
||||||
|
stack int
|
||||||
|
gas *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
var _baseCheck = map[OpCode]req{
|
||||||
|
// Req stack Gas price
|
||||||
|
ADD: {2, GasFastestStep},
|
||||||
|
LT: {2, GasFastestStep},
|
||||||
|
GT: {2, GasFastestStep},
|
||||||
|
SLT: {2, GasFastestStep},
|
||||||
|
SGT: {2, GasFastestStep},
|
||||||
|
EQ: {2, GasFastestStep},
|
||||||
|
ISZERO: {1, GasFastestStep},
|
||||||
|
SUB: {2, GasFastestStep},
|
||||||
|
AND: {2, GasFastestStep},
|
||||||
|
OR: {2, GasFastestStep},
|
||||||
|
XOR: {2, GasFastestStep},
|
||||||
|
NOT: {1, GasFastestStep},
|
||||||
|
BYTE: {2, GasFastestStep},
|
||||||
|
CALLDATALOAD: {1, GasFastestStep},
|
||||||
|
CALLDATACOPY: {3, GasFastestStep},
|
||||||
|
MLOAD: {1, GasFastestStep},
|
||||||
|
MSTORE: {2, GasFastestStep},
|
||||||
|
MSTORE8: {2, GasFastestStep},
|
||||||
|
CODECOPY: {3, GasFastestStep},
|
||||||
|
MUL: {2, GasFastStep},
|
||||||
|
DIV: {2, GasFastStep},
|
||||||
|
SDIV: {2, GasFastStep},
|
||||||
|
MOD: {2, GasFastStep},
|
||||||
|
SMOD: {2, GasFastStep},
|
||||||
|
SIGNEXTEND: {2, GasFastStep},
|
||||||
|
ADDMOD: {3, GasMidStep},
|
||||||
|
MULMOD: {3, GasMidStep},
|
||||||
|
JUMP: {1, GasMidStep},
|
||||||
|
JUMPI: {2, GasSlowStep},
|
||||||
|
EXP: {2, GasSlowStep},
|
||||||
|
ADDRESS: {0, GasQuickStep},
|
||||||
|
ORIGIN: {0, GasQuickStep},
|
||||||
|
CALLER: {0, GasQuickStep},
|
||||||
|
CALLVALUE: {0, GasQuickStep},
|
||||||
|
CODESIZE: {0, GasQuickStep},
|
||||||
|
GASPRICE: {0, GasQuickStep},
|
||||||
|
COINBASE: {0, GasQuickStep},
|
||||||
|
TIMESTAMP: {0, GasQuickStep},
|
||||||
|
NUMBER: {0, GasQuickStep},
|
||||||
|
CALLDATASIZE: {0, GasQuickStep},
|
||||||
|
DIFFICULTY: {0, GasQuickStep},
|
||||||
|
GASLIMIT: {0, GasQuickStep},
|
||||||
|
POP: {0, GasQuickStep},
|
||||||
|
PC: {0, GasQuickStep},
|
||||||
|
MSIZE: {0, GasQuickStep},
|
||||||
|
GAS: {0, GasQuickStep},
|
||||||
|
BLOCKHASH: {1, GasExtStep},
|
||||||
|
BALANCE: {0, GasExtStep},
|
||||||
|
EXTCODESIZE: {1, GasExtStep},
|
||||||
|
EXTCODECOPY: {4, GasExtStep},
|
||||||
|
SLOAD: {1, GasStorageGet},
|
||||||
|
SSTORE: {2, Zero},
|
||||||
|
SHA3: {1, GasSha3Base},
|
||||||
|
CREATE: {3, GasCreate},
|
||||||
|
CALL: {7, GasCall},
|
||||||
|
CALLCODE: {7, GasCall},
|
||||||
|
JUMPDEST: {0, GasJumpDest},
|
||||||
|
SUICIDE: {1, Zero},
|
||||||
|
RETURN: {2, Zero},
|
||||||
|
}
|
||||||
|
|
||||||
|
func baseCheck(op OpCode, stack *stack, gas *big.Int) {
|
||||||
|
if r, ok := _baseCheck[op]; ok {
|
||||||
|
stack.require(r.stack)
|
||||||
|
|
||||||
|
gas.Add(gas, r.gas)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toWordSize(size *big.Int) *big.Int {
|
||||||
|
tmp := new(big.Int)
|
||||||
|
tmp.Add(size, u256(31))
|
||||||
|
tmp.Div(tmp, u256(32))
|
||||||
|
return tmp
|
||||||
|
}
|
72
vm/memory.go
Normal file
72
vm/memory.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package vm
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type Memory struct {
|
||||||
|
store []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMemory() *Memory {
|
||||||
|
return &Memory{nil}
|
||||||
|
}
|
||||||
|
|
||||||
|
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...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
copy(m.store[offset:offset+size], value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Memory) Resize(size uint64) {
|
||||||
|
if uint64(m.Len()) < size {
|
||||||
|
m.store = append(m.store, make([]byte, size-uint64(m.Len()))...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Memory) Get(offset, size int64) (cpy []byte) {
|
||||||
|
if size == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(self.store) > int(offset) {
|
||||||
|
cpy = make([]byte, size)
|
||||||
|
copy(cpy, self.store[offset:offset+size])
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Memory) Len() int {
|
||||||
|
return len(m.store)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Memory) Data() []byte {
|
||||||
|
return m.store
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Memory) Print() {
|
||||||
|
fmt.Printf("### mem %d bytes ###\n", len(m.store))
|
||||||
|
if len(m.store) > 0 {
|
||||||
|
addr := 0
|
||||||
|
for i := 0; i+32 <= len(m.store); i += 32 {
|
||||||
|
fmt.Printf("%03d: % x\n", addr, m.store[i:i+32])
|
||||||
|
addr++
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println("-- empty --")
|
||||||
|
}
|
||||||
|
fmt.Println("####################")
|
||||||
|
}
|
188
vm/stack.go
188
vm/stack.go
@ -5,98 +5,53 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OpType int
|
func newStack() *stack {
|
||||||
|
return &stack{}
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
type stack struct {
|
||||||
tNorm = iota
|
|
||||||
tData
|
|
||||||
tExtro
|
|
||||||
tCrypto
|
|
||||||
)
|
|
||||||
|
|
||||||
type TxCallback func(opType OpType) bool
|
|
||||||
|
|
||||||
// Simple push/pop stack mechanism
|
|
||||||
type Stack struct {
|
|
||||||
data []*big.Int
|
data []*big.Int
|
||||||
|
ptr int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStack() *Stack {
|
func (st *stack) push(d *big.Int) {
|
||||||
return &Stack{}
|
if len(st.data) > st.ptr {
|
||||||
}
|
st.data[st.ptr] = d
|
||||||
|
} else {
|
||||||
func (st *Stack) Data() []*big.Int {
|
st.data = append(st.data, d)
|
||||||
return st.data
|
|
||||||
}
|
|
||||||
|
|
||||||
func (st *Stack) Len() int {
|
|
||||||
return len(st.data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (st *Stack) Pop() *big.Int {
|
|
||||||
str := st.data[len(st.data)-1]
|
|
||||||
|
|
||||||
copy(st.data[:len(st.data)-1], st.data[:len(st.data)-1])
|
|
||||||
st.data = st.data[:len(st.data)-1]
|
|
||||||
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
|
|
||||||
func (st *Stack) Popn() (*big.Int, *big.Int) {
|
|
||||||
ints := st.data[len(st.data)-2:]
|
|
||||||
|
|
||||||
copy(st.data[:len(st.data)-2], st.data[:len(st.data)-2])
|
|
||||||
st.data = st.data[:len(st.data)-2]
|
|
||||||
|
|
||||||
return ints[0], ints[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (st *Stack) Peek() *big.Int {
|
|
||||||
str := st.data[len(st.data)-1]
|
|
||||||
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
|
|
||||||
func (st *Stack) Peekn() (*big.Int, *big.Int) {
|
|
||||||
ints := st.data[len(st.data)-2:]
|
|
||||||
|
|
||||||
return ints[0], ints[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (st *Stack) Swapn(n int) (*big.Int, *big.Int) {
|
|
||||||
st.data[len(st.data)-n], st.data[len(st.data)-1] = st.data[len(st.data)-1], st.data[len(st.data)-n]
|
|
||||||
|
|
||||||
return st.data[len(st.data)-n], st.data[len(st.data)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (st *Stack) Dupn(n int) *big.Int {
|
|
||||||
st.Push(st.data[len(st.data)-n])
|
|
||||||
|
|
||||||
return st.Peek()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (st *Stack) Push(d *big.Int) {
|
|
||||||
st.data = append(st.data, new(big.Int).Set(d))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (st *Stack) Get(amount *big.Int) []*big.Int {
|
|
||||||
// offset + size <= len(data)
|
|
||||||
length := big.NewInt(int64(len(st.data)))
|
|
||||||
if amount.Cmp(length) <= 0 {
|
|
||||||
start := new(big.Int).Sub(length, amount)
|
|
||||||
return st.data[start.Int64():length.Int64()]
|
|
||||||
}
|
}
|
||||||
|
st.ptr++
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *Stack) require(n int) {
|
func (st *stack) pop() (ret *big.Int) {
|
||||||
if st.Len() < n {
|
st.ptr--
|
||||||
panic(fmt.Sprintf("stack underflow (%d <=> %d)", st.Len(), n))
|
ret = st.data[st.ptr]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (st *stack) len() int {
|
||||||
|
return st.ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (st *stack) swap(n int) {
|
||||||
|
st.data[st.len()-n], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-n]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (st *stack) dup(n int) {
|
||||||
|
st.push(st.data[st.len()-n])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (st *stack) peek() *big.Int {
|
||||||
|
return st.data[st.len()-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (st *stack) require(n int) {
|
||||||
|
if st.len() < n {
|
||||||
|
panic(fmt.Sprintf("stack underflow (%d <=> %d)", len(st.data), n))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *Stack) Print() {
|
func (st *stack) Print() {
|
||||||
fmt.Println("### stack ###")
|
fmt.Println("### stack ###")
|
||||||
if len(st.data) > 0 {
|
if len(st.data) > 0 {
|
||||||
for i, val := range st.data {
|
for i, val := range st.data {
|
||||||
@ -107,72 +62,3 @@ func (st *Stack) Print() {
|
|||||||
}
|
}
|
||||||
fmt.Println("#############")
|
fmt.Println("#############")
|
||||||
}
|
}
|
||||||
|
|
||||||
type Memory struct {
|
|
||||||
store []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewMemory() *Memory {
|
|
||||||
return &Memory{nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
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...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
copy(m.store[offset:offset+size], value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Memory) Resize(size uint64) {
|
|
||||||
if uint64(m.Len()) < size {
|
|
||||||
m.store = append(m.store, make([]byte, size-uint64(m.Len()))...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Memory) Get(offset, size int64) (cpy []byte) {
|
|
||||||
if size == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(self.store) > int(offset) {
|
|
||||||
cpy = make([]byte, size)
|
|
||||||
copy(cpy, self.store[offset:offset+size])
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Memory) Len() int {
|
|
||||||
return len(m.store)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Memory) Data() []byte {
|
|
||||||
return m.store
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Memory) Print() {
|
|
||||||
fmt.Printf("### mem %d bytes ###\n", len(m.store))
|
|
||||||
if len(m.store) > 0 {
|
|
||||||
addr := 0
|
|
||||||
for i := 0; i+32 <= len(m.store); i += 32 {
|
|
||||||
fmt.Printf("%03d: % x\n", addr, m.store[i:i+32])
|
|
||||||
addr++
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Println("-- empty --")
|
|
||||||
}
|
|
||||||
fmt.Println("####################")
|
|
||||||
}
|
|
||||||
|
451
vm/vm.go
451
vm/vm.go
@ -19,8 +19,6 @@ type Vm struct {
|
|||||||
// For logging
|
// For logging
|
||||||
debug bool
|
debug bool
|
||||||
|
|
||||||
Dbg Debugger
|
|
||||||
|
|
||||||
BreakPoints []int64
|
BreakPoints []int64
|
||||||
Stepping bool
|
Stepping bool
|
||||||
Fn string
|
Fn string
|
||||||
@ -66,10 +64,9 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
|
|
||||||
destinations = analyseJumpDests(context.Code)
|
destinations = analyseJumpDests(context.Code)
|
||||||
mem = NewMemory()
|
mem = NewMemory()
|
||||||
stack = NewStack()
|
stack = newStack()
|
||||||
pc uint64 = 0
|
pc uint64 = 0
|
||||||
step = 0
|
step = 0
|
||||||
prevStep = 0
|
|
||||||
statedb = self.env.State()
|
statedb = self.env.State()
|
||||||
|
|
||||||
jump = func(from uint64, to *big.Int) {
|
jump = func(from uint64, to *big.Int) {
|
||||||
@ -93,7 +90,6 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
prevStep = step
|
|
||||||
// The base for all big integer arithmetic
|
// The base for all big integer arithmetic
|
||||||
base := new(big.Int)
|
base := new(big.Int)
|
||||||
|
|
||||||
@ -101,11 +97,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
// Get the memory location of pc
|
// Get the memory location of pc
|
||||||
op = context.GetOp(pc)
|
op = context.GetOp(pc)
|
||||||
|
|
||||||
self.Printf("(pc) %-3d -o- %-14s (m) %-4d (s) %-4d ", pc, op.String(), mem.Len(), stack.Len())
|
self.Printf("(pc) %-3d -o- %-14s (m) %-4d (s) %-4d ", pc, op.String(), mem.Len(), stack.len())
|
||||||
if self.Dbg != nil {
|
|
||||||
//self.Dbg.Step(self, op, mem, stack, context)
|
|
||||||
}
|
|
||||||
|
|
||||||
newMemSize, gas := self.calculateGasAndSize(context, caller, op, statedb, mem, stack)
|
newMemSize, gas := self.calculateGasAndSize(context, caller, op, statedb, mem, stack)
|
||||||
|
|
||||||
self.Printf("(g) %-3v (%v)", gas, context.Gas)
|
self.Printf("(g) %-3v (%v)", gas, context.Gas)
|
||||||
@ -125,40 +117,40 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
switch op {
|
switch op {
|
||||||
// 0x20 range
|
// 0x20 range
|
||||||
case ADD:
|
case ADD:
|
||||||
x, y := stack.Popn()
|
x, y := stack.pop(), stack.pop()
|
||||||
self.Printf(" %v + %v", y, x)
|
self.Printf(" %v + %v", y, x)
|
||||||
|
|
||||||
base.Add(y, x)
|
base.Add(x, y)
|
||||||
|
|
||||||
U256(base)
|
U256(base)
|
||||||
|
|
||||||
self.Printf(" = %v", base)
|
self.Printf(" = %v", base)
|
||||||
// Pop result back on the stack
|
// pop result back on the stack
|
||||||
stack.Push(base)
|
stack.push(base)
|
||||||
case SUB:
|
case SUB:
|
||||||
x, y := stack.Popn()
|
x, y := stack.pop(), stack.pop()
|
||||||
self.Printf(" %v - %v", y, x)
|
self.Printf(" %v - %v", y, x)
|
||||||
|
|
||||||
base.Sub(y, x)
|
base.Sub(x, y)
|
||||||
|
|
||||||
U256(base)
|
U256(base)
|
||||||
|
|
||||||
self.Printf(" = %v", base)
|
self.Printf(" = %v", base)
|
||||||
// Pop result back on the stack
|
// pop result back on the stack
|
||||||
stack.Push(base)
|
stack.push(base)
|
||||||
case MUL:
|
case MUL:
|
||||||
x, y := stack.Popn()
|
x, y := stack.pop(), stack.pop()
|
||||||
self.Printf(" %v * %v", y, x)
|
self.Printf(" %v * %v", y, x)
|
||||||
|
|
||||||
base.Mul(y, x)
|
base.Mul(x, y)
|
||||||
|
|
||||||
U256(base)
|
U256(base)
|
||||||
|
|
||||||
self.Printf(" = %v", base)
|
self.Printf(" = %v", base)
|
||||||
// Pop result back on the stack
|
// pop result back on the stack
|
||||||
stack.Push(base)
|
stack.push(base)
|
||||||
case DIV:
|
case DIV:
|
||||||
x, y := stack.Pop(), stack.Pop()
|
x, y := stack.pop(), stack.pop()
|
||||||
self.Printf(" %v / %v", x, y)
|
self.Printf(" %v / %v", x, y)
|
||||||
|
|
||||||
if y.Cmp(ethutil.Big0) != 0 {
|
if y.Cmp(ethutil.Big0) != 0 {
|
||||||
@ -168,10 +160,10 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
U256(base)
|
U256(base)
|
||||||
|
|
||||||
self.Printf(" = %v", base)
|
self.Printf(" = %v", base)
|
||||||
// Pop result back on the stack
|
// pop result back on the stack
|
||||||
stack.Push(base)
|
stack.push(base)
|
||||||
case SDIV:
|
case SDIV:
|
||||||
x, y := S256(stack.Pop()), S256(stack.Pop())
|
x, y := S256(stack.pop()), S256(stack.pop())
|
||||||
|
|
||||||
self.Printf(" %v / %v", x, y)
|
self.Printf(" %v / %v", x, y)
|
||||||
|
|
||||||
@ -191,9 +183,9 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.Printf(" = %v", base)
|
self.Printf(" = %v", base)
|
||||||
stack.Push(base)
|
stack.push(base)
|
||||||
case MOD:
|
case MOD:
|
||||||
x, y := stack.Pop(), stack.Pop()
|
x, y := stack.pop(), stack.pop()
|
||||||
|
|
||||||
self.Printf(" %v %% %v", x, y)
|
self.Printf(" %v %% %v", x, y)
|
||||||
|
|
||||||
@ -206,9 +198,9 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
U256(base)
|
U256(base)
|
||||||
|
|
||||||
self.Printf(" = %v", base)
|
self.Printf(" = %v", base)
|
||||||
stack.Push(base)
|
stack.push(base)
|
||||||
case SMOD:
|
case SMOD:
|
||||||
x, y := S256(stack.Pop()), S256(stack.Pop())
|
x, y := S256(stack.pop()), S256(stack.pop())
|
||||||
|
|
||||||
self.Printf(" %v %% %v", x, y)
|
self.Printf(" %v %% %v", x, y)
|
||||||
|
|
||||||
@ -228,25 +220,25 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.Printf(" = %v", base)
|
self.Printf(" = %v", base)
|
||||||
stack.Push(base)
|
stack.push(base)
|
||||||
|
|
||||||
case EXP:
|
case EXP:
|
||||||
x, y := stack.Popn()
|
x, y := stack.pop(), stack.pop()
|
||||||
|
|
||||||
self.Printf(" %v ** %v", y, x)
|
self.Printf(" %v ** %v", x, y)
|
||||||
|
|
||||||
base.Exp(y, x, Pow256)
|
base.Exp(x, y, Pow256)
|
||||||
|
|
||||||
U256(base)
|
U256(base)
|
||||||
|
|
||||||
self.Printf(" = %v", base)
|
self.Printf(" = %v", base)
|
||||||
|
|
||||||
stack.Push(base)
|
stack.push(base)
|
||||||
case SIGNEXTEND:
|
case SIGNEXTEND:
|
||||||
back := stack.Pop().Uint64()
|
back := stack.pop().Uint64()
|
||||||
if back < 31 {
|
if back < 31 {
|
||||||
bit := uint(back*8 + 7)
|
bit := uint(back*8 + 7)
|
||||||
num := stack.Pop()
|
num := stack.pop()
|
||||||
mask := new(big.Int).Lsh(ethutil.Big1, bit)
|
mask := new(big.Int).Lsh(ethutil.Big1, bit)
|
||||||
mask.Sub(mask, ethutil.Big1)
|
mask.Sub(mask, ethutil.Big1)
|
||||||
if ethutil.BitTest(num, int(bit)) {
|
if ethutil.BitTest(num, int(bit)) {
|
||||||
@ -259,91 +251,91 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
|
|
||||||
self.Printf(" = %v", num)
|
self.Printf(" = %v", num)
|
||||||
|
|
||||||
stack.Push(num)
|
stack.push(num)
|
||||||
}
|
}
|
||||||
case NOT:
|
case NOT:
|
||||||
base.Sub(Pow256, stack.Pop()).Sub(base, ethutil.Big1)
|
base.Sub(Pow256, stack.pop()).Sub(base, ethutil.Big1)
|
||||||
|
|
||||||
// Not needed
|
// Not needed
|
||||||
base = U256(base)
|
base = U256(base)
|
||||||
|
|
||||||
stack.Push(base)
|
stack.push(base)
|
||||||
case LT:
|
case LT:
|
||||||
x, y := stack.Popn()
|
x, y := stack.pop(), stack.pop()
|
||||||
self.Printf(" %v < %v", y, x)
|
self.Printf(" %v < %v", x, y)
|
||||||
// x < y
|
// x < y
|
||||||
if y.Cmp(x) < 0 {
|
if x.Cmp(y) < 0 {
|
||||||
stack.Push(ethutil.BigTrue)
|
stack.push(ethutil.BigTrue)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(ethutil.BigFalse)
|
stack.push(ethutil.BigFalse)
|
||||||
}
|
}
|
||||||
case GT:
|
case GT:
|
||||||
x, y := stack.Popn()
|
x, y := stack.pop(), stack.pop()
|
||||||
self.Printf(" %v > %v", y, x)
|
self.Printf(" %v > %v", x, y)
|
||||||
|
|
||||||
// x > y
|
// x > y
|
||||||
if y.Cmp(x) > 0 {
|
if x.Cmp(y) > 0 {
|
||||||
stack.Push(ethutil.BigTrue)
|
stack.push(ethutil.BigTrue)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(ethutil.BigFalse)
|
stack.push(ethutil.BigFalse)
|
||||||
}
|
}
|
||||||
|
|
||||||
case SLT:
|
case SLT:
|
||||||
y, x := S256(stack.Pop()), S256(stack.Pop())
|
x, y := S256(stack.pop()), S256(stack.pop())
|
||||||
self.Printf(" %v < %v", y, x)
|
self.Printf(" %v < %v", x, y)
|
||||||
// x < y
|
// x < y
|
||||||
if y.Cmp(S256(x)) < 0 {
|
if x.Cmp(S256(y)) < 0 {
|
||||||
stack.Push(ethutil.BigTrue)
|
stack.push(ethutil.BigTrue)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(ethutil.BigFalse)
|
stack.push(ethutil.BigFalse)
|
||||||
}
|
}
|
||||||
case SGT:
|
case SGT:
|
||||||
y, x := S256(stack.Pop()), S256(stack.Pop())
|
x, y := S256(stack.pop()), S256(stack.pop())
|
||||||
self.Printf(" %v > %v", y, x)
|
self.Printf(" %v > %v", x, y)
|
||||||
|
|
||||||
// x > y
|
// x > y
|
||||||
if y.Cmp(x) > 0 {
|
if x.Cmp(y) > 0 {
|
||||||
stack.Push(ethutil.BigTrue)
|
stack.push(ethutil.BigTrue)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(ethutil.BigFalse)
|
stack.push(ethutil.BigFalse)
|
||||||
}
|
}
|
||||||
|
|
||||||
case EQ:
|
case EQ:
|
||||||
x, y := stack.Popn()
|
x, y := stack.pop(), stack.pop()
|
||||||
self.Printf(" %v == %v", y, x)
|
self.Printf(" %v == %v", y, x)
|
||||||
|
|
||||||
// x == y
|
// x == y
|
||||||
if x.Cmp(y) == 0 {
|
if x.Cmp(y) == 0 {
|
||||||
stack.Push(ethutil.BigTrue)
|
stack.push(ethutil.BigTrue)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(ethutil.BigFalse)
|
stack.push(ethutil.BigFalse)
|
||||||
}
|
}
|
||||||
case ISZERO:
|
case ISZERO:
|
||||||
x := stack.Pop()
|
x := stack.pop()
|
||||||
if x.Cmp(ethutil.BigFalse) > 0 {
|
if x.Cmp(ethutil.BigFalse) > 0 {
|
||||||
stack.Push(ethutil.BigFalse)
|
stack.push(ethutil.BigFalse)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(ethutil.BigTrue)
|
stack.push(ethutil.BigTrue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x10 range
|
// 0x10 range
|
||||||
case AND:
|
case AND:
|
||||||
x, y := stack.Popn()
|
x, y := stack.pop(), stack.pop()
|
||||||
self.Printf(" %v & %v", y, x)
|
self.Printf(" %v & %v", y, x)
|
||||||
|
|
||||||
stack.Push(base.And(y, x))
|
stack.push(base.And(x, y))
|
||||||
case OR:
|
case OR:
|
||||||
x, y := stack.Popn()
|
x, y := stack.pop(), stack.pop()
|
||||||
self.Printf(" %v | %v", y, x)
|
self.Printf(" %v | %v", x, y)
|
||||||
|
|
||||||
stack.Push(base.Or(y, x))
|
stack.push(base.Or(x, y))
|
||||||
case XOR:
|
case XOR:
|
||||||
x, y := stack.Popn()
|
x, y := stack.pop(), stack.pop()
|
||||||
self.Printf(" %v ^ %v", y, x)
|
self.Printf(" %v ^ %v", x, y)
|
||||||
|
|
||||||
stack.Push(base.Xor(y, x))
|
stack.push(base.Xor(x, y))
|
||||||
case BYTE:
|
case BYTE:
|
||||||
val, th := stack.Popn()
|
th, val := stack.pop(), stack.pop()
|
||||||
|
|
||||||
if th.Cmp(big.NewInt(32)) < 0 {
|
if th.Cmp(big.NewInt(32)) < 0 {
|
||||||
byt := big.NewInt(int64(ethutil.LeftPadBytes(val.Bytes(), 32)[th.Int64()]))
|
byt := big.NewInt(int64(ethutil.LeftPadBytes(val.Bytes(), 32)[th.Int64()]))
|
||||||
@ -355,12 +347,12 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
|
|
||||||
self.Printf(" => 0x%x", base.Bytes())
|
self.Printf(" => 0x%x", base.Bytes())
|
||||||
|
|
||||||
stack.Push(base)
|
stack.push(base)
|
||||||
case ADDMOD:
|
case ADDMOD:
|
||||||
|
|
||||||
x := stack.Pop()
|
x := stack.pop()
|
||||||
y := stack.Pop()
|
y := stack.pop()
|
||||||
z := stack.Pop()
|
z := stack.pop()
|
||||||
|
|
||||||
add := new(big.Int).Add(x, y)
|
add := new(big.Int).Add(x, y)
|
||||||
if len(z.Bytes()) > 0 { // NOT 0x0
|
if len(z.Bytes()) > 0 { // NOT 0x0
|
||||||
@ -371,12 +363,12 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
|
|
||||||
self.Printf(" %v + %v %% %v = %v", x, y, z, base)
|
self.Printf(" %v + %v %% %v = %v", x, y, z, base)
|
||||||
|
|
||||||
stack.Push(base)
|
stack.push(base)
|
||||||
case MULMOD:
|
case MULMOD:
|
||||||
|
|
||||||
x := stack.Pop()
|
x := stack.pop()
|
||||||
y := stack.Pop()
|
y := stack.pop()
|
||||||
z := stack.Pop()
|
z := stack.pop()
|
||||||
|
|
||||||
mul := new(big.Int).Mul(x, y)
|
mul := new(big.Int).Mul(x, y)
|
||||||
if len(z.Bytes()) > 0 { // NOT 0x0
|
if len(z.Bytes()) > 0 { // NOT 0x0
|
||||||
@ -387,24 +379,24 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
|
|
||||||
self.Printf(" %v + %v %% %v = %v", x, y, z, base)
|
self.Printf(" %v + %v %% %v = %v", x, y, z, base)
|
||||||
|
|
||||||
stack.Push(base)
|
stack.push(base)
|
||||||
|
|
||||||
// 0x20 range
|
// 0x20 range
|
||||||
case SHA3:
|
case SHA3:
|
||||||
size, offset := stack.Popn()
|
size, offset := stack.pop(), stack.pop()
|
||||||
data := crypto.Sha3(mem.Get(offset.Int64(), size.Int64()))
|
data := crypto.Sha3(mem.Get(offset.Int64(), size.Int64()))
|
||||||
|
|
||||||
stack.Push(ethutil.BigD(data))
|
stack.push(ethutil.BigD(data))
|
||||||
|
|
||||||
self.Printf(" => (%v) %x", size, data)
|
self.Printf(" => (%v) %x", size, data)
|
||||||
// 0x30 range
|
// 0x30 range
|
||||||
case ADDRESS:
|
case ADDRESS:
|
||||||
stack.Push(ethutil.BigD(context.Address()))
|
stack.push(ethutil.BigD(context.Address()))
|
||||||
|
|
||||||
self.Printf(" => %x", context.Address())
|
self.Printf(" => %x", context.Address())
|
||||||
case BALANCE:
|
case BALANCE:
|
||||||
|
|
||||||
addr := stack.Pop().Bytes()
|
addr := stack.pop().Bytes()
|
||||||
var balance *big.Int
|
var balance *big.Int
|
||||||
if statedb.GetStateObject(addr) != nil {
|
if statedb.GetStateObject(addr) != nil {
|
||||||
balance = statedb.GetBalance(addr)
|
balance = statedb.GetBalance(addr)
|
||||||
@ -412,27 +404,27 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
balance = base
|
balance = base
|
||||||
}
|
}
|
||||||
|
|
||||||
stack.Push(balance)
|
stack.push(balance)
|
||||||
|
|
||||||
self.Printf(" => %v (%x)", balance, addr)
|
self.Printf(" => %v (%x)", balance, addr)
|
||||||
case ORIGIN:
|
case ORIGIN:
|
||||||
origin := self.env.Origin()
|
origin := self.env.Origin()
|
||||||
|
|
||||||
stack.Push(ethutil.BigD(origin))
|
stack.push(ethutil.BigD(origin))
|
||||||
|
|
||||||
self.Printf(" => %x", origin)
|
self.Printf(" => %x", origin)
|
||||||
case CALLER:
|
case CALLER:
|
||||||
caller := context.caller.Address()
|
caller := context.caller.Address()
|
||||||
stack.Push(ethutil.BigD(caller))
|
stack.push(ethutil.BigD(caller))
|
||||||
|
|
||||||
self.Printf(" => %x", caller)
|
self.Printf(" => %x", caller)
|
||||||
case CALLVALUE:
|
case CALLVALUE:
|
||||||
stack.Push(value)
|
stack.push(value)
|
||||||
|
|
||||||
self.Printf(" => %v", value)
|
self.Printf(" => %v", 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(callData)))
|
lenData = big.NewInt(int64(len(callData)))
|
||||||
)
|
)
|
||||||
@ -446,18 +438,18 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
|
|
||||||
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(callData))
|
l := int64(len(callData))
|
||||||
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 = uint64(len(callData))
|
size = uint64(len(callData))
|
||||||
mOff = stack.Pop().Uint64()
|
mOff = stack.pop().Uint64()
|
||||||
cOff = stack.Pop().Uint64()
|
cOff = stack.pop().Uint64()
|
||||||
l = stack.Pop().Uint64()
|
l = stack.pop().Uint64()
|
||||||
)
|
)
|
||||||
|
|
||||||
if cOff > size {
|
if cOff > size {
|
||||||
@ -475,7 +467,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
case CODESIZE, EXTCODESIZE:
|
case CODESIZE, EXTCODESIZE:
|
||||||
var code []byte
|
var code []byte
|
||||||
if op == EXTCODESIZE {
|
if op == EXTCODESIZE {
|
||||||
addr := stack.Pop().Bytes()
|
addr := stack.pop().Bytes()
|
||||||
|
|
||||||
code = statedb.GetCode(addr)
|
code = statedb.GetCode(addr)
|
||||||
} else {
|
} else {
|
||||||
@ -483,21 +475,21 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
}
|
}
|
||||||
|
|
||||||
l := big.NewInt(int64(len(code)))
|
l := big.NewInt(int64(len(code)))
|
||||||
stack.Push(l)
|
stack.push(l)
|
||||||
|
|
||||||
self.Printf(" => %d", l)
|
self.Printf(" => %d", l)
|
||||||
case CODECOPY, EXTCODECOPY:
|
case CODECOPY, EXTCODECOPY:
|
||||||
var code []byte
|
var code []byte
|
||||||
if op == EXTCODECOPY {
|
if op == EXTCODECOPY {
|
||||||
code = statedb.GetCode(stack.Pop().Bytes())
|
code = statedb.GetCode(stack.pop().Bytes())
|
||||||
} else {
|
} else {
|
||||||
code = context.Code
|
code = context.Code
|
||||||
}
|
}
|
||||||
context := NewContext(nil, nil, code, ethutil.Big0, ethutil.Big0)
|
context := NewContext(nil, nil, code, ethutil.Big0, ethutil.Big0)
|
||||||
var (
|
var (
|
||||||
mOff = stack.Pop().Uint64()
|
mOff = stack.pop().Uint64()
|
||||||
cOff = stack.Pop().Uint64()
|
cOff = stack.pop().Uint64()
|
||||||
l = stack.Pop().Uint64()
|
l = stack.pop().Uint64()
|
||||||
)
|
)
|
||||||
codeCopy := context.GetCode(cOff, l)
|
codeCopy := context.GetCode(cOff, l)
|
||||||
|
|
||||||
@ -505,80 +497,80 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
|
|
||||||
self.Printf(" => [%v, %v, %v] %x", mOff, cOff, l, codeCopy)
|
self.Printf(" => [%v, %v, %v] %x", mOff, cOff, l, codeCopy)
|
||||||
case GASPRICE:
|
case GASPRICE:
|
||||||
stack.Push(context.Price)
|
stack.push(context.Price)
|
||||||
|
|
||||||
self.Printf(" => %x", context.Price)
|
self.Printf(" => %x", context.Price)
|
||||||
|
|
||||||
// 0x40 range
|
// 0x40 range
|
||||||
case BLOCKHASH:
|
case BLOCKHASH:
|
||||||
num := stack.Pop()
|
num := stack.pop()
|
||||||
|
|
||||||
n := new(big.Int).Sub(self.env.BlockNumber(), ethutil.Big257)
|
n := new(big.Int).Sub(self.env.BlockNumber(), ethutil.Big257)
|
||||||
if num.Cmp(n) > 0 && num.Cmp(self.env.BlockNumber()) < 0 {
|
if num.Cmp(n) > 0 && num.Cmp(self.env.BlockNumber()) < 0 {
|
||||||
stack.Push(ethutil.BigD(self.env.GetHash(num.Uint64())))
|
stack.push(ethutil.BigD(self.env.GetHash(num.Uint64())))
|
||||||
} else {
|
} else {
|
||||||
stack.Push(ethutil.Big0)
|
stack.push(ethutil.Big0)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.Printf(" => 0x%x", stack.Peek().Bytes())
|
self.Printf(" => 0x%x", stack.peek().Bytes())
|
||||||
case COINBASE:
|
case COINBASE:
|
||||||
coinbase := self.env.Coinbase()
|
coinbase := self.env.Coinbase()
|
||||||
|
|
||||||
stack.Push(ethutil.BigD(coinbase))
|
stack.push(ethutil.BigD(coinbase))
|
||||||
|
|
||||||
self.Printf(" => 0x%x", coinbase)
|
self.Printf(" => 0x%x", coinbase)
|
||||||
case TIMESTAMP:
|
case TIMESTAMP:
|
||||||
time := self.env.Time()
|
time := self.env.Time()
|
||||||
|
|
||||||
stack.Push(big.NewInt(time))
|
stack.push(big.NewInt(time))
|
||||||
|
|
||||||
self.Printf(" => 0x%x", time)
|
self.Printf(" => 0x%x", time)
|
||||||
case NUMBER:
|
case NUMBER:
|
||||||
number := self.env.BlockNumber()
|
number := self.env.BlockNumber()
|
||||||
|
|
||||||
stack.Push(U256(number))
|
stack.push(U256(number))
|
||||||
|
|
||||||
self.Printf(" => 0x%x", number.Bytes())
|
self.Printf(" => 0x%x", number.Bytes())
|
||||||
case DIFFICULTY:
|
case DIFFICULTY:
|
||||||
difficulty := self.env.Difficulty()
|
difficulty := self.env.Difficulty()
|
||||||
|
|
||||||
stack.Push(difficulty)
|
stack.push(difficulty)
|
||||||
|
|
||||||
self.Printf(" => 0x%x", difficulty.Bytes())
|
self.Printf(" => 0x%x", difficulty.Bytes())
|
||||||
case GASLIMIT:
|
case GASLIMIT:
|
||||||
self.Printf(" => %v", self.env.GasLimit())
|
self.Printf(" => %v", self.env.GasLimit())
|
||||||
|
|
||||||
stack.Push(self.env.GasLimit())
|
stack.push(self.env.GasLimit())
|
||||||
|
|
||||||
// 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 := uint64(op - PUSH1 + 1)
|
a := uint64(op - PUSH1 + 1)
|
||||||
byts := context.GetRangeValue(pc+1, a)
|
byts := context.GetRangeValue(pc+1, a)
|
||||||
// Push value to stack
|
// push value to stack
|
||||||
stack.Push(ethutil.BigD(byts))
|
stack.push(ethutil.BigD(byts))
|
||||||
pc += a
|
pc += a
|
||||||
|
|
||||||
step += int(op) - int(PUSH1) + 1
|
step += int(op) - int(PUSH1) + 1
|
||||||
|
|
||||||
self.Printf(" => 0x%x", byts)
|
self.Printf(" => 0x%x", byts)
|
||||||
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:
|
||||||
n := int(op - DUP1 + 1)
|
n := int(op - DUP1 + 1)
|
||||||
stack.Dupn(n)
|
stack.dup(n)
|
||||||
|
|
||||||
self.Printf(" => [%d] 0x%x", n, stack.Peek().Bytes())
|
self.Printf(" => [%d] 0x%x", n, stack.peek().Bytes())
|
||||||
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)
|
stack.swap(n)
|
||||||
|
|
||||||
self.Printf(" => [%d] %x [0] %x", n, x.Bytes(), y.Bytes())
|
self.Printf(" => [%d]", n)
|
||||||
case LOG0, LOG1, LOG2, LOG3, LOG4:
|
case LOG0, LOG1, LOG2, LOG3, LOG4:
|
||||||
n := int(op - LOG0)
|
n := int(op - LOG0)
|
||||||
topics := make([][]byte, n)
|
topics := make([][]byte, n)
|
||||||
mSize, mStart := stack.Popn()
|
mStart, mSize := stack.pop(), stack.pop()
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
topics[i] = ethutil.LeftPadBytes(stack.Pop().Bytes(), 32)
|
topics[i] = ethutil.LeftPadBytes(stack.pop().Bytes(), 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
data := mem.Get(mStart.Int64(), mSize.Int64())
|
data := mem.Get(mStart.Int64(), mSize.Int64())
|
||||||
@ -587,41 +579,40 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
|
|
||||||
self.Printf(" => %v", log)
|
self.Printf(" => %v", log)
|
||||||
case MLOAD:
|
case MLOAD:
|
||||||
offset := stack.Pop()
|
offset := stack.pop()
|
||||||
val := ethutil.BigD(mem.Get(offset.Int64(), 32))
|
val := ethutil.BigD(mem.Get(offset.Int64(), 32))
|
||||||
stack.Push(val)
|
stack.push(val)
|
||||||
|
|
||||||
self.Printf(" => 0x%x", val.Bytes())
|
self.Printf(" => 0x%x", val.Bytes())
|
||||||
case MSTORE: // Store the value at stack top-1 in to memory at location stack top
|
case MSTORE: // Store the value at stack top-1 in to memory at location stack top
|
||||||
// Pop value of the stack
|
// pop value of the stack
|
||||||
val, mStart := stack.Popn()
|
mStart, val := stack.pop(), stack.pop()
|
||||||
mem.Set(mStart.Uint64(), 32, ethutil.BigToBytes(val, 256))
|
mem.Set(mStart.Uint64(), 32, ethutil.BigToBytes(val, 256))
|
||||||
|
|
||||||
self.Printf(" => 0x%x", val)
|
self.Printf(" => 0x%x", val)
|
||||||
case MSTORE8:
|
case MSTORE8:
|
||||||
off := stack.Pop()
|
off, val := stack.pop(), stack.pop()
|
||||||
val := stack.Pop()
|
|
||||||
|
|
||||||
mem.store[off.Int64()] = byte(val.Int64() & 0xff)
|
mem.store[off.Int64()] = byte(val.Int64() & 0xff)
|
||||||
|
|
||||||
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(context.Address(), loc.Bytes()))
|
val := ethutil.BigD(statedb.GetState(context.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()
|
loc, val := stack.pop(), stack.pop()
|
||||||
statedb.SetState(context.Address(), loc.Bytes(), val)
|
statedb.SetState(context.Address(), loc.Bytes(), val)
|
||||||
|
|
||||||
self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
|
self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
|
||||||
case JUMP:
|
case JUMP:
|
||||||
jump(pc, stack.Pop())
|
jump(pc, stack.pop())
|
||||||
|
|
||||||
continue
|
continue
|
||||||
case JUMPI:
|
case JUMPI:
|
||||||
cond, pos := stack.Popn()
|
pos, cond := stack.pop(), stack.pop()
|
||||||
|
|
||||||
if cond.Cmp(ethutil.BigTrue) >= 0 {
|
if cond.Cmp(ethutil.BigTrue) >= 0 {
|
||||||
jump(pc, pos)
|
jump(pc, pos)
|
||||||
@ -633,19 +624,19 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
|
|
||||||
case JUMPDEST:
|
case JUMPDEST:
|
||||||
case PC:
|
case PC:
|
||||||
stack.Push(big.NewInt(int64(pc)))
|
stack.push(big.NewInt(int64(pc)))
|
||||||
case MSIZE:
|
case MSIZE:
|
||||||
stack.Push(big.NewInt(int64(mem.Len())))
|
stack.push(big.NewInt(int64(mem.Len())))
|
||||||
case GAS:
|
case GAS:
|
||||||
stack.Push(context.Gas)
|
stack.push(context.Gas)
|
||||||
|
|
||||||
self.Printf(" => %x", context.Gas)
|
self.Printf(" => %x", context.Gas)
|
||||||
// 0x60 range
|
// 0x60 range
|
||||||
case CREATE:
|
case CREATE:
|
||||||
|
|
||||||
var (
|
var (
|
||||||
value = stack.Pop()
|
value = stack.pop()
|
||||||
size, offset = stack.Popn()
|
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 []byte
|
||||||
@ -655,7 +646,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
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, nil, input, gas, price, value)
|
||||||
if suberr != nil {
|
if suberr != nil {
|
||||||
stack.Push(ethutil.BigFalse)
|
stack.push(ethutil.BigFalse)
|
||||||
|
|
||||||
self.Printf(" (*) 0x0 %v", suberr)
|
self.Printf(" (*) 0x0 %v", suberr)
|
||||||
} else {
|
} else {
|
||||||
@ -668,23 +659,19 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
}
|
}
|
||||||
addr = ref.Address()
|
addr = ref.Address()
|
||||||
|
|
||||||
stack.Push(ethutil.BigD(addr))
|
stack.push(ethutil.BigD(addr))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug hook
|
|
||||||
if self.Dbg != nil {
|
|
||||||
self.Dbg.SetCode(context.Code)
|
|
||||||
}
|
|
||||||
case CALL, CALLCODE:
|
case CALL, CALLCODE:
|
||||||
gas := stack.Pop()
|
gas := stack.pop()
|
||||||
// Pop gas and value of the stack.
|
// pop gas and value of the stack.
|
||||||
value, addr := stack.Popn()
|
addr, value := stack.pop(), stack.pop()
|
||||||
value = U256(value)
|
value = U256(value)
|
||||||
// Pop input size and offset
|
// pop input size and offset
|
||||||
inSize, inOffset := stack.Popn()
|
inOffset, inSize := stack.pop(), stack.pop()
|
||||||
// Pop return size and offset
|
// pop return size and offset
|
||||||
retSize, retOffset := stack.Popn()
|
retOffset, retSize := stack.pop(), stack.pop()
|
||||||
|
|
||||||
address := ethutil.Address(addr.Bytes())
|
address := ethutil.Address(addr.Bytes())
|
||||||
self.Printf(" => %x", address).Endl()
|
self.Printf(" => %x", address).Endl()
|
||||||
@ -707,30 +694,24 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
stack.Push(ethutil.BigFalse)
|
stack.push(ethutil.BigFalse)
|
||||||
|
|
||||||
vmlogger.Debugln(err)
|
vmlogger.Debugln(err)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(ethutil.BigTrue)
|
stack.push(ethutil.BigTrue)
|
||||||
|
|
||||||
mem.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
mem.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||||
}
|
}
|
||||||
self.Printf("resume %x (%v)", context.Address(), context.Gas)
|
self.Printf("resume %x (%v)", context.Address(), context.Gas)
|
||||||
|
|
||||||
// Debug hook
|
|
||||||
if self.Dbg != nil {
|
|
||||||
self.Dbg.SetCode(context.Code)
|
|
||||||
}
|
|
||||||
|
|
||||||
case RETURN:
|
case RETURN:
|
||||||
size, offset := stack.Popn()
|
offset, size := stack.pop(), stack.pop()
|
||||||
ret := mem.Get(offset.Int64(), size.Int64())
|
ret := mem.Get(offset.Int64(), size.Int64())
|
||||||
|
|
||||||
self.Printf(" => [%v, %v] (%d) 0x%x", offset, size, len(ret), ret).Endl()
|
self.Printf(" => [%v, %v] (%d) 0x%x", offset, size, len(ret), ret).Endl()
|
||||||
|
|
||||||
return context.Return(ret), nil
|
return context.Return(ret), nil
|
||||||
case SUICIDE:
|
case SUICIDE:
|
||||||
receiver := statedb.GetOrNewStateObject(stack.Pop().Bytes())
|
receiver := statedb.GetOrNewStateObject(stack.pop().Bytes())
|
||||||
balance := statedb.GetBalance(context.Address())
|
balance := statedb.GetBalance(context.Address())
|
||||||
|
|
||||||
self.Printf(" => (%x) %v", receiver.Address()[:4], balance)
|
self.Printf(" => (%x) %v", receiver.Address()[:4], balance)
|
||||||
@ -753,117 +734,17 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
|
|||||||
pc++
|
pc++
|
||||||
|
|
||||||
self.Endl()
|
self.Endl()
|
||||||
|
|
||||||
if self.Dbg != nil {
|
|
||||||
for _, instrNo := range self.Dbg.BreakPoints() {
|
|
||||||
if pc == uint64(instrNo) {
|
|
||||||
self.Stepping = true
|
|
||||||
|
|
||||||
if !self.Dbg.BreakHook(prevStep, op, mem, stack, statedb.GetStateObject(context.Address())) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
} else if self.Stepping {
|
|
||||||
if !self.Dbg.StepHook(prevStep, op, mem, stack, statedb.GetStateObject(context.Address())) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type req struct {
|
func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCode, statedb *state.StateDB, mem *Memory, stack *stack) (*big.Int, *big.Int) {
|
||||||
stack int
|
|
||||||
gas *big.Int
|
|
||||||
}
|
|
||||||
|
|
||||||
var _baseCheck = map[OpCode]req{
|
|
||||||
// Req Stack Gas price
|
|
||||||
ADD: {2, GasFastestStep},
|
|
||||||
LT: {2, GasFastestStep},
|
|
||||||
GT: {2, GasFastestStep},
|
|
||||||
SLT: {2, GasFastestStep},
|
|
||||||
SGT: {2, GasFastestStep},
|
|
||||||
EQ: {2, GasFastestStep},
|
|
||||||
ISZERO: {1, GasFastestStep},
|
|
||||||
SUB: {2, GasFastestStep},
|
|
||||||
AND: {2, GasFastestStep},
|
|
||||||
OR: {2, GasFastestStep},
|
|
||||||
XOR: {2, GasFastestStep},
|
|
||||||
NOT: {1, GasFastestStep},
|
|
||||||
BYTE: {2, GasFastestStep},
|
|
||||||
CALLDATALOAD: {1, GasFastestStep},
|
|
||||||
CALLDATACOPY: {3, GasFastestStep},
|
|
||||||
MLOAD: {1, GasFastestStep},
|
|
||||||
MSTORE: {2, GasFastestStep},
|
|
||||||
MSTORE8: {2, GasFastestStep},
|
|
||||||
CODECOPY: {3, GasFastestStep},
|
|
||||||
MUL: {2, GasFastStep},
|
|
||||||
DIV: {2, GasFastStep},
|
|
||||||
SDIV: {2, GasFastStep},
|
|
||||||
MOD: {2, GasFastStep},
|
|
||||||
SMOD: {2, GasFastStep},
|
|
||||||
SIGNEXTEND: {2, GasFastStep},
|
|
||||||
ADDMOD: {3, GasMidStep},
|
|
||||||
MULMOD: {3, GasMidStep},
|
|
||||||
JUMP: {1, GasMidStep},
|
|
||||||
JUMPI: {2, GasSlowStep},
|
|
||||||
EXP: {2, GasSlowStep},
|
|
||||||
ADDRESS: {0, GasQuickStep},
|
|
||||||
ORIGIN: {0, GasQuickStep},
|
|
||||||
CALLER: {0, GasQuickStep},
|
|
||||||
CALLVALUE: {0, GasQuickStep},
|
|
||||||
CODESIZE: {0, GasQuickStep},
|
|
||||||
GASPRICE: {0, GasQuickStep},
|
|
||||||
COINBASE: {0, GasQuickStep},
|
|
||||||
TIMESTAMP: {0, GasQuickStep},
|
|
||||||
NUMBER: {0, GasQuickStep},
|
|
||||||
CALLDATASIZE: {0, GasQuickStep},
|
|
||||||
DIFFICULTY: {0, GasQuickStep},
|
|
||||||
GASLIMIT: {0, GasQuickStep},
|
|
||||||
POP: {0, GasQuickStep},
|
|
||||||
PC: {0, GasQuickStep},
|
|
||||||
MSIZE: {0, GasQuickStep},
|
|
||||||
GAS: {0, GasQuickStep},
|
|
||||||
BLOCKHASH: {1, GasExtStep},
|
|
||||||
BALANCE: {0, GasExtStep},
|
|
||||||
EXTCODESIZE: {1, GasExtStep},
|
|
||||||
EXTCODECOPY: {4, GasExtStep},
|
|
||||||
SLOAD: {1, GasStorageGet},
|
|
||||||
SSTORE: {2, Zero},
|
|
||||||
SHA3: {1, GasSha3Base},
|
|
||||||
CREATE: {3, GasCreate},
|
|
||||||
CALL: {7, GasCall},
|
|
||||||
CALLCODE: {7, GasCall},
|
|
||||||
JUMPDEST: {0, GasJumpDest},
|
|
||||||
SUICIDE: {1, Zero},
|
|
||||||
RETURN: {2, Zero},
|
|
||||||
}
|
|
||||||
|
|
||||||
func baseCheck(op OpCode, stack *Stack, gas *big.Int) {
|
|
||||||
if r, ok := _baseCheck[op]; ok {
|
|
||||||
stack.require(r.stack)
|
|
||||||
|
|
||||||
gas.Add(gas, r.gas)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func toWordSize(size *big.Int) *big.Int {
|
|
||||||
tmp := new(big.Int)
|
|
||||||
tmp.Add(size, u256(31))
|
|
||||||
tmp.Div(tmp, u256(32))
|
|
||||||
return tmp
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCode, statedb *state.StateDB, mem *Memory, stack *Stack) (*big.Int, *big.Int) {
|
|
||||||
var (
|
var (
|
||||||
gas = new(big.Int)
|
gas = new(big.Int)
|
||||||
newMemSize *big.Int = new(big.Int)
|
newMemSize *big.Int = new(big.Int)
|
||||||
)
|
)
|
||||||
baseCheck(op, stack, gas)
|
baseCheck(op, stack, gas)
|
||||||
|
|
||||||
// Stack Check, memory resize & gas phase
|
// stack Check, memory resize & gas phase
|
||||||
switch op {
|
switch op {
|
||||||
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:
|
||||||
gas.Set(GasFastestStep)
|
gas.Set(GasFastestStep)
|
||||||
@ -879,7 +760,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
|
|||||||
n := int(op - LOG0)
|
n := int(op - LOG0)
|
||||||
stack.require(n + 2)
|
stack.require(n + 2)
|
||||||
|
|
||||||
mSize, mStart := stack.Peekn()
|
mSize, mStart := stack.data[stack.len()-2], stack.data[stack.len()-1]
|
||||||
|
|
||||||
gas.Add(gas, GasLogBase)
|
gas.Add(gas, GasLogBase)
|
||||||
gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), GasLogTopic))
|
gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), GasLogTopic))
|
||||||
@ -887,12 +768,12 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
|
|||||||
|
|
||||||
newMemSize = calcMemSize(mStart, mSize)
|
newMemSize = calcMemSize(mStart, mSize)
|
||||||
case EXP:
|
case EXP:
|
||||||
gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.Len()-2].Bytes()))), GasExpByte))
|
gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), GasExpByte))
|
||||||
case SSTORE:
|
case SSTORE:
|
||||||
stack.require(2)
|
stack.require(2)
|
||||||
|
|
||||||
var g *big.Int
|
var g *big.Int
|
||||||
y, x := stack.Peekn()
|
y, x := stack.data[stack.len()-2], stack.data[stack.len()-1]
|
||||||
val := statedb.GetState(context.Address(), x.Bytes())
|
val := statedb.GetState(context.Address(), x.Bytes())
|
||||||
if len(val) == 0 && len(y.Bytes()) > 0 {
|
if len(val) == 0 && len(y.Bytes()) > 0 {
|
||||||
// 0 => non 0
|
// 0 => non 0
|
||||||
@ -911,51 +792,51 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
|
|||||||
statedb.Refund(self.env.Origin(), RefundSuicide)
|
statedb.Refund(self.env.Origin(), RefundSuicide)
|
||||||
}
|
}
|
||||||
case MLOAD:
|
case MLOAD:
|
||||||
newMemSize = calcMemSize(stack.Peek(), u256(32))
|
newMemSize = calcMemSize(stack.peek(), u256(32))
|
||||||
case MSTORE8:
|
case MSTORE8:
|
||||||
newMemSize = calcMemSize(stack.Peek(), u256(1))
|
newMemSize = calcMemSize(stack.peek(), u256(1))
|
||||||
case MSTORE:
|
case MSTORE:
|
||||||
newMemSize = calcMemSize(stack.Peek(), u256(32))
|
newMemSize = calcMemSize(stack.peek(), u256(32))
|
||||||
case RETURN:
|
case RETURN:
|
||||||
newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2])
|
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
|
||||||
case SHA3:
|
case SHA3:
|
||||||
newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2])
|
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
|
||||||
|
|
||||||
words := toWordSize(stack.data[stack.Len()-2])
|
words := toWordSize(stack.data[stack.len()-2])
|
||||||
gas.Add(gas, words.Mul(words, GasSha3Word))
|
gas.Add(gas, words.Mul(words, GasSha3Word))
|
||||||
case CALLDATACOPY:
|
case CALLDATACOPY:
|
||||||
newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3])
|
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
|
||||||
|
|
||||||
words := toWordSize(stack.data[stack.Len()-3])
|
words := toWordSize(stack.data[stack.len()-3])
|
||||||
gas.Add(gas, words.Mul(words, GasCopyWord))
|
gas.Add(gas, words.Mul(words, GasCopyWord))
|
||||||
case CODECOPY:
|
case CODECOPY:
|
||||||
newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3])
|
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
|
||||||
|
|
||||||
words := toWordSize(stack.data[stack.Len()-3])
|
words := toWordSize(stack.data[stack.len()-3])
|
||||||
gas.Add(gas, words.Mul(words, GasCopyWord))
|
gas.Add(gas, words.Mul(words, GasCopyWord))
|
||||||
case EXTCODECOPY:
|
case EXTCODECOPY:
|
||||||
newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-4])
|
newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-4])
|
||||||
|
|
||||||
words := toWordSize(stack.data[stack.Len()-4])
|
words := toWordSize(stack.data[stack.len()-4])
|
||||||
gas.Add(gas, words.Mul(words, GasCopyWord))
|
gas.Add(gas, words.Mul(words, GasCopyWord))
|
||||||
|
|
||||||
case CREATE:
|
case CREATE:
|
||||||
newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-3])
|
newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-3])
|
||||||
case CALL, CALLCODE:
|
case CALL, CALLCODE:
|
||||||
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(stack.data[stack.len()-2].Bytes()) == nil {
|
||||||
gas.Add(gas, GasCallNewAccount)
|
gas.Add(gas, GasCallNewAccount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(stack.data[stack.Len()-3].Bytes()) > 0 {
|
if len(stack.data[stack.len()-3].Bytes()) > 0 {
|
||||||
gas.Add(gas, GasCallValueTransfer)
|
gas.Add(gas, GasCallValueTransfer)
|
||||||
}
|
}
|
||||||
|
|
||||||
x := calcMemSize(stack.data[stack.Len()-6], stack.data[stack.Len()-7])
|
x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
|
||||||
y := calcMemSize(stack.data[stack.Len()-4], stack.data[stack.Len()-5])
|
y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5])
|
||||||
|
|
||||||
newMemSize = ethutil.BigMax(x, y)
|
newMemSize = ethutil.BigMax(x, y)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user