Browse Source

Transcribe vm changes from vm_fixes by Ethan

pull/43/merge
Jae Kwon 10 years ago
parent
commit
4be97fa9d4
3 changed files with 253 additions and 125 deletions
  1. +0
    -29
      vm/test/fake_app_state.go
  2. +99
    -0
      vm/test/vm_test.go
  3. +154
    -96
      vm/vm.go

+ 0
- 29
vm/test/fake_app_state.go View File

@ -1,8 +1,6 @@
package vm
import (
"fmt"
. "github.com/tendermint/tendermint/common"
. "github.com/tendermint/tendermint/vm"
"github.com/tendermint/tendermint/vm/sha3"
@ -85,33 +83,6 @@ func (fas *FakeAppState) AddLog(log *Log) {
fas.logs = append(fas.logs, log)
}
func main() {
appState := &FakeAppState{
accounts: make(map[string]*Account),
storage: make(map[string]Word256),
logs: nil,
}
params := Params{
BlockHeight: 0,
BlockHash: Zero256,
BlockTime: 0,
GasLimit: 0,
}
ourVm := NewVM(appState, params, Zero256)
// Create accounts
account1 := &Account{
Address: Uint64ToWord256(100),
}
account2 := &Account{
Address: Uint64ToWord256(101),
}
var gas uint64 = 1000
output, err := ourVm.Call(account1, account2, []byte{0x5B, 0x60, 0x00, 0x56}, []byte{}, 0, &gas)
fmt.Printf("Output: %v Error: %v\n", output, err)
}
// Creates a 20 byte address and bumps the nonce.
func createAddress(creator *Account) Word256 {
nonce := creator.Nonce


+ 99
- 0
vm/test/vm_test.go View File

@ -0,0 +1,99 @@
package vm
import (
"crypto/rand"
"encoding/hex"
"fmt"
"strings"
"testing"
"time"
. "github.com/tendermint/tendermint/common"
. "github.com/tendermint/tendermint/vm"
)
func newAppState() *FakeAppState {
return &FakeAppState{
accounts: make(map[string]*Account),
storage: make(map[string]Word256),
logs: nil,
}
}
func newParams() Params {
return Params{
BlockHeight: 0,
BlockHash: Zero256,
BlockTime: 0,
GasLimit: 0,
}
}
func makeBytes(n int) []byte {
b := make([]byte, n)
rand.Read(b)
return b
}
func TestVM(t *testing.T) {
ourVm := NewVM(newAppState(), newParams(), Zero256)
// Create accounts
account1 := &Account{
Address: Uint64ToWord256(100),
}
account2 := &Account{
Address: Uint64ToWord256(101),
}
var gas uint64 = 1000
N := []byte{0xff, 0xff}
// Loop N times
code := []byte{0x60, 0x00, 0x60, 0x20, 0x52, 0x5B, byte(0x60 + len(N) - 1)}
for i := 0; i < len(N); i++ {
code = append(code, N[i])
}
code = append(code, []byte{0x60, 0x20, 0x51, 0x12, 0x15, 0x60, byte(0x1b + len(N)), 0x57, 0x60, 0x01, 0x60, 0x20, 0x51, 0x01, 0x60, 0x20, 0x52, 0x60, 0x05, 0x56, 0x5B}...)
start := time.Now()
output, err := ourVm.Call(account1, account2, code, []byte{}, 0, &gas)
fmt.Printf("Output: %v Error: %v\n", output, err)
fmt.Println("Call took:", time.Since(start))
}
func TestSubcurrency(t *testing.T) {
st := newAppState()
// Create accounts
account1 := &Account{
Address: RightPadWord256(makeBytes(20)),
}
account2 := &Account{
Address: RightPadWord256(makeBytes(20)),
}
st.accounts[account1.Address.String()] = account1
st.accounts[account2.Address.String()] = account2
ourVm := NewVM(st, newParams(), Zero256)
var gas uint64 = 1000
code_parts := []string{"620f42403355",
"7c0100000000000000000000000000000000000000000000000000000000",
"600035046315cf268481141561004657",
"6004356040526040515460605260206060f35b63693200ce81141561008757",
"60043560805260243560a052335460c0523360e05260a05160c05112151561008657",
"60a05160c0510360e0515560a0516080515401608051555b5b505b6000f3"}
code, _ := hex.DecodeString(strings.Join(code_parts, ""))
fmt.Printf("Code: %x\n", code)
data, _ := hex.DecodeString("693200CE0000000000000000000000004B4363CDE27C2EB05E66357DB05BC5C88F850C1A0000000000000000000000000000000000000000000000000000000000000005")
output, err := ourVm.Call(account1, account2, code, data, 0, &gas)
fmt.Printf("Output: %v Error: %v\n", output, err)
}
/*
// infinite loop
code := []byte{0x5B, 0x60, 0x00, 0x56}
// mstore
code := []byte{0x60, 0x00, 0x60, 0x20}
// mstore, mload
code := []byte{0x60, 0x01, 0x60, 0x20, 0x52, 0x60, 0x20, 0x51}
*/

+ 154
- 96
vm/vm.go View File

@ -3,7 +3,7 @@ package vm
import (
"errors"
"fmt"
"math"
"math/big"
. "github.com/tendermint/tendermint/common"
"github.com/tendermint/tendermint/vm/sha3"
@ -24,12 +24,21 @@ var (
ErrInvalidContract = errors.New("Invalid contract")
)
type Debug bool
const (
dataStackCapacity = 1024
callStackCapacity = 100 // TODO ensure usage.
memoryCapacity = 1024 * 1024 // 1 MB
dataStackCapacity = 1024
callStackCapacity = 100 // TODO ensure usage.
memoryCapacity = 1024 * 1024 // 1 MB
dbg Debug = true
)
func (d Debug) Printf(s string, a ...interface{}) {
if d {
fmt.Printf(s, a...)
}
}
type VM struct {
appState AppState
params Params
@ -74,7 +83,7 @@ func (vm *VM) Call(caller, callee *Account, code, input []byte, value uint64, ga
// Just like Call() but does not transfer 'value' or modify the callDepth.
func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, gas *uint64) (output []byte, err error) {
fmt.Printf("(%d) (%X) %X (code=%d) gas: %v (d) %X\n", vm.callDepth, caller.Address[:4], callee.Address, len(callee.Code), *gas, input)
dbg.Printf("(%d) (%X) %X (code=%d) gas: %v (d) %X\n", vm.callDepth, caller.Address[:4], callee.Address, len(callee.Code), *gas, input)
var (
pc uint64 = 0
@ -90,7 +99,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
}
var op = codeGetOp(code, pc)
fmt.Printf("(pc) %-3d (op) %-14s (st) %-4d ", pc, op.String(), stack.Len())
dbg.Printf("(pc) %-3d (op) %-14s (st) %-4d ", pc, op.String(), stack.Len())
switch op {
@ -98,90 +107,123 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
return nil, nil
case ADD: // 0x01
x, y := stack.Pop64(), stack.Pop64()
stack.Push64(x + y)
fmt.Printf(" %v + %v = %v\n", x, y, x+y)
//x, y := stack.Pop64(), stack.Pop64()
//stack.Push64(x + y)
x, y := stack.Pop(), stack.Pop()
xb := new(big.Int).SetBytes(flip(x[:]))
yb := new(big.Int).SetBytes(flip(y[:]))
sum := new(big.Int).Add(xb, yb)
stack.Push(RightPadWord256(flip(sum.Bytes())))
dbg.Printf(" %v + %v = %v\n", xb, yb, sum)
case MUL: // 0x02
x, y := stack.Pop64(), stack.Pop64()
stack.Push64(x * y)
fmt.Printf(" %v * %v = %v\n", x, y, x*y)
//x, y := stack.Pop64(), stack.Pop64()
//stack.Push64(x * y)
x, y := stack.Pop(), stack.Pop()
xb := new(big.Int).SetBytes(flip(x[:]))
yb := new(big.Int).SetBytes(flip(y[:]))
prod := new(big.Int).Mul(xb, yb)
stack.Push(RightPadWord256(flip(prod.Bytes())))
dbg.Printf(" %v * %v = %v\n", xb, yb, prod)
case SUB: // 0x03
x, y := stack.Pop64(), stack.Pop64()
stack.Push64(x - y)
fmt.Printf(" %v - %v = %v\n", x, y, x-y)
//x, y := stack.Pop64(), stack.Pop64()
//stack.Push64(x - y)
x, y := stack.Pop(), stack.Pop()
xb := new(big.Int).SetBytes(flip(x[:]))
yb := new(big.Int).SetBytes(flip(y[:]))
diff := new(big.Int).Sub(xb, yb)
stack.Push(RightPadWord256(flip(diff.Bytes())))
dbg.Printf(" %v - %v = %v\n", xb, yb, diff)
case DIV: // 0x04
x, y := stack.Pop64(), stack.Pop64()
if y == 0 { // TODO
//x, y := stack.Pop64(), stack.Pop64()
//stack.Push64(x / y)
x, y := stack.Pop(), stack.Pop()
if y.IsZero() { // TODO
stack.Push(Zero256)
fmt.Printf(" %v / %v = %v (TODO)\n", x, y, 0)
dbg.Printf(" %x / %x = %v (TODO)\n", x, y, 0)
} else {
stack.Push64(x / y)
fmt.Printf(" %v / %v = %v\n", x, y, x/y)
xb := new(big.Int).SetBytes(flip(x[:]))
yb := new(big.Int).SetBytes(flip(y[:]))
div := new(big.Int).Div(xb, yb)
stack.Push(RightPadWord256(flip(div.Bytes())))
dbg.Printf(" %v / %v = %v\n", xb, yb, div)
}
case SDIV: // 0x05
// TODO ... big?
x, y := int64(stack.Pop64()), int64(stack.Pop64())
if y == 0 { // TODO
stack.Push(Zero256)
fmt.Printf(" %v / %v = %v (TODO)\n", x, y, 0)
dbg.Printf(" %v / %v = %v (TODO)\n", x, y, 0)
} else {
stack.Push64(uint64(x / y))
fmt.Printf(" %v / %v = %v\n", x, y, x/y)
dbg.Printf(" %v / %v = %v\n", x, y, x/y)
}
case MOD: // 0x06
x, y := stack.Pop64(), stack.Pop64()
if y == 0 { // TODO
//x, y := stack.Pop64(), stack.Pop64()
x, y := stack.Pop(), stack.Pop()
if y.IsZero() { // TODO
stack.Push(Zero256)
fmt.Printf(" %v %% %v = %v (TODO)\n", x, y, 0)
dbg.Printf(" %v %% %v = %v (TODO)\n", x, y, 0)
} else {
stack.Push64(x % y)
fmt.Printf(" %v %% %v = %v\n", x, y, x%y)
xb := new(big.Int).SetBytes(flip(x[:]))
yb := new(big.Int).SetBytes(flip(y[:]))
mod := new(big.Int).Mod(xb, yb)
stack.Push(RightPadWord256(flip(mod.Bytes())))
dbg.Printf(" %v %% %v = %v\n", xb, yb, mod)
}
case SMOD: // 0x07
// TODO ... big?
x, y := int64(stack.Pop64()), int64(stack.Pop64())
if y == 0 { // TODO
stack.Push(Zero256)
fmt.Printf(" %v %% %v = %v (TODO)\n", x, y, 0)
dbg.Printf(" %v %% %v = %v (TODO)\n", x, y, 0)
} else {
stack.Push64(uint64(x % y))
fmt.Printf(" %v %% %v = %v\n", x, y, x%y)
dbg.Printf(" %v %% %v = %v\n", x, y, x%y)
}
case ADDMOD: // 0x08
// TODO ... big?
x, y, z := stack.Pop64(), stack.Pop64(), stack.Pop64()
if z == 0 { // TODO
stack.Push(Zero256)
fmt.Printf(" (%v + %v) %% %v = %v (TODO)\n", x, y, z, 0)
dbg.Printf(" (%v + %v) %% %v = %v (TODO)\n", x, y, z, 0)
} else {
stack.Push64(x % y)
fmt.Printf(" (%v + %v) %% %v = %v\n", x, y, z, (x+y)%z)
stack.Push64((x + y) % z)
dbg.Printf(" (%v + %v) %% %v = %v\n", x, y, z, (x+y)%z)
}
case MULMOD: // 0x09
// TODO ... big?
x, y, z := stack.Pop64(), stack.Pop64(), stack.Pop64()
if z == 0 { // TODO
stack.Push(Zero256)
fmt.Printf(" (%v + %v) %% %v = %v (TODO)\n", x, y, z, 0)
dbg.Printf(" (%v + %v) %% %v = %v (TODO)\n", x, y, z, 0)
} else {
stack.Push64(x % y)
fmt.Printf(" (%v + %v) %% %v = %v\n", x, y, z, (x*y)%z)
stack.Push64((x * y) % z)
dbg.Printf(" (%v + %v) %% %v = %v\n", x, y, z, (x*y)%z)
}
case EXP: // 0x0A
x, y := stack.Pop64(), stack.Pop64()
stack.Push64(ExpUint64(x, y))
fmt.Printf(" %v ** %v = %v\n", x, y, uint64(math.Pow(float64(x), float64(y))))
//x, y := stack.Pop64(), stack.Pop64()
//stack.Push64(ExpUint64(x, y))
x, y := stack.Pop(), stack.Pop()
xb := new(big.Int).SetBytes(flip(x[:]))
yb := new(big.Int).SetBytes(flip(y[:]))
pow := new(big.Int).Exp(xb, yb, big.NewInt(0))
stack.Push(RightPadWord256(flip(pow.Bytes())))
dbg.Printf(" %v ** %v = %v\n", xb, yb, pow)
case SIGNEXTEND: // 0x0B
x, y := stack.Pop64(), stack.Pop64()
res := (y << uint(x)) >> x
stack.Push64(res)
fmt.Printf(" (%v << %v) >> %v = %v\n", y, x, x, res)
dbg.Printf(" (%v << %v) >> %v = %v\n", y, x, x, res)
case LT: // 0x10
x, y := stack.Pop64(), stack.Pop64()
@ -190,7 +232,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
} else {
stack.Push(Zero256)
}
fmt.Printf(" %v < %v = %v\n", x, y, x < y)
dbg.Printf(" %v < %v = %v\n", x, y, x < y)
case GT: // 0x11
x, y := stack.Pop64(), stack.Pop64()
@ -199,7 +241,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
} else {
stack.Push(Zero256)
}
fmt.Printf(" %v > %v = %v\n", x, y, x > y)
dbg.Printf(" %v > %v = %v\n", x, y, x > y)
case SLT: // 0x12
x, y := int64(stack.Pop64()), int64(stack.Pop64())
@ -208,7 +250,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
} else {
stack.Push(Zero256)
}
fmt.Printf(" %v < %v = %v\n", x, y, x < y)
dbg.Printf(" %v < %v = %v\n", x, y, x < y)
case SGT: // 0x13
x, y := int64(stack.Pop64()), int64(stack.Pop64())
@ -217,16 +259,16 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
} else {
stack.Push(Zero256)
}
fmt.Printf(" %v > %v = %v\n", x, y, x > y)
dbg.Printf(" %v > %v = %v\n", x, y, x > y)
case EQ: // 0x14
x, y := stack.Pop64(), stack.Pop64()
if x > y {
if x == y {
stack.Push64(1)
} else {
stack.Push(Zero256)
}
fmt.Printf(" %v == %v = %v\n", x, y, x == y)
dbg.Printf(" %v == %v = %v\n", x, y, x == y)
case ISZERO: // 0x15
x := stack.Pop64()
@ -235,27 +277,27 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
} else {
stack.Push(Zero256)
}
fmt.Printf(" %v == 0 = %v\n", x, x == 0)
dbg.Printf(" %v == 0 = %v\n", x, x == 0)
case AND: // 0x16
x, y := stack.Pop64(), stack.Pop64()
stack.Push64(x & y)
fmt.Printf(" %v & %v = %v\n", x, y, x&y)
dbg.Printf(" %v & %v = %v\n", x, y, x&y)
case OR: // 0x17
x, y := stack.Pop64(), stack.Pop64()
stack.Push64(x | y)
fmt.Printf(" %v | %v = %v\n", x, y, x|y)
dbg.Printf(" %v | %v = %v\n", x, y, x|y)
case XOR: // 0x18
x, y := stack.Pop64(), stack.Pop64()
stack.Push64(x ^ y)
fmt.Printf(" %v ^ %v = %v\n", x, y, x^y)
dbg.Printf(" %v ^ %v = %v\n", x, y, x^y)
case NOT: // 0x19
x := stack.Pop64()
stack.Push64(^x)
fmt.Printf(" !%v = %v\n", x, ^x)
dbg.Printf(" !%v = %v\n", x, ^x)
case BYTE: // 0x1A
idx, val := stack.Pop64(), stack.Pop()
@ -264,7 +306,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
res = val[idx]
}
stack.Push64(uint64(res))
fmt.Printf(" => 0x%X\n", res)
dbg.Printf(" => 0x%X\n", res)
case SHA3: // 0x20
if ok = useGas(gas, GasSha3); !ok {
@ -277,11 +319,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
}
data = sha3.Sha3(data)
stack.PushBytes(data)
fmt.Printf(" => (%v) %X\n", size, data)
dbg.Printf(" => (%v) %X\n", size, data)
case ADDRESS: // 0x30
stack.Push(callee.Address)
fmt.Printf(" => %X\n", callee.Address)
dbg.Printf(" => %X\n", callee.Address)
case BALANCE: // 0x31
addr := stack.Pop()
@ -294,19 +336,19 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
}
balance := acc.Balance
stack.Push64(balance)
fmt.Printf(" => %v (%X)\n", balance, addr)
dbg.Printf(" => %v (%X)\n", balance, addr)
case ORIGIN: // 0x32
stack.Push(vm.origin)
fmt.Printf(" => %X\n", vm.origin)
dbg.Printf(" => %X\n", vm.origin)
case CALLER: // 0x33
stack.Push(caller.Address)
fmt.Printf(" => %X\n", caller.Address)
dbg.Printf(" => %X\n", caller.Address)
case CALLVALUE: // 0x34
stack.Push64(value)
fmt.Printf(" => %v\n", value)
dbg.Printf(" => %v\n", value)
case CALLDATALOAD: // 0x35
offset := stack.Pop64()
@ -315,11 +357,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
return nil, firstErr(err, ErrInputOutOfBounds)
}
stack.Push(RightPadWord256(data))
fmt.Printf(" => 0x%X\n", data)
dbg.Printf(" => 0x%X\n", data)
case CALLDATASIZE: // 0x36
stack.Push64(uint64(len(input)))
fmt.Printf(" => %d\n", len(input))
dbg.Printf(" => %d\n", len(input))
case CALLDATACOPY: // 0x37
memOff := stack.Pop64()
@ -334,18 +376,17 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
copy(dest, data)
fmt.Printf(" => [%v, %v, %v] %X\n", memOff, inputOff, length, data)
dbg.Printf(" => [%v, %v, %v] %X\n", memOff, inputOff, length, data)
case CODESIZE: // 0x38
l := uint64(len(code))
stack.Push64(l)
fmt.Printf(" => %d\n", l)
dbg.Printf(" => %d\n", l)
case CODECOPY: // 0x39
memOff := stack.Pop64()
codeOff := stack.Pop64()
length := stack.Pop64()
fmt.Println("CODECOPY: codeOff, length, codelength", codeOff, length, len(code))
data, ok := subslice(code, codeOff, length, false)
if !ok {
return nil, firstErr(err, ErrCodeOutOfBounds)
@ -355,11 +396,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
copy(dest, data)
fmt.Printf(" => [%v, %v, %v] %X\n", memOff, codeOff, length, data)
dbg.Printf(" => [%v, %v, %v] %X\n", memOff, codeOff, length, data)
case GASPRICE_DEPRECATED: // 0x3A
stack.Push(Zero256)
fmt.Printf(" => %X (GASPRICE IS DEPRECATED)\n")
dbg.Printf(" => %X (GASPRICE IS DEPRECATED)\n")
case EXTCODESIZE: // 0x3B
addr := stack.Pop()
@ -373,7 +414,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
code := acc.Code
l := uint64(len(code))
stack.Push64(l)
fmt.Printf(" => %d\n", l)
dbg.Printf(" => %d\n", l)
case EXTCODECOPY: // 0x3C
addr := stack.Pop()
@ -397,33 +438,33 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
copy(dest, data)
fmt.Printf(" => [%v, %v, %v] %X\n", memOff, codeOff, length, data)
dbg.Printf(" => [%v, %v, %v] %X\n", memOff, codeOff, length, data)
case BLOCKHASH: // 0x40
stack.Push(Zero256)
fmt.Printf(" => 0x%X (NOT SUPPORTED)\n", stack.Peek().Bytes())
dbg.Printf(" => 0x%X (NOT SUPPORTED)\n", stack.Peek().Bytes())
case COINBASE: // 0x41
stack.Push(Zero256)
fmt.Printf(" => 0x%X (NOT SUPPORTED)\n", stack.Peek().Bytes())
dbg.Printf(" => 0x%X (NOT SUPPORTED)\n", stack.Peek().Bytes())
case TIMESTAMP: // 0x42
time := vm.params.BlockTime
stack.Push64(uint64(time))
fmt.Printf(" => 0x%X\n", time)
dbg.Printf(" => 0x%X\n", time)
case BLOCKHEIGHT: // 0x43
number := uint64(vm.params.BlockHeight)
stack.Push64(number)
fmt.Printf(" => 0x%X\n", number)
dbg.Printf(" => 0x%X\n", number)
case GASLIMIT: // 0x45
stack.Push64(vm.params.GasLimit)
fmt.Printf(" => %v\n", vm.params.GasLimit)
dbg.Printf(" => %v\n", vm.params.GasLimit)
case POP: // 0x50
stack.Pop()
fmt.Printf(" => %v\n", vm.params.GasLimit)
dbg.Printf(" => %v\n", vm.params.GasLimit)
case MLOAD: // 0x51
offset := stack.Pop64()
@ -432,16 +473,16 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
stack.Push(RightPadWord256(data))
fmt.Printf(" => 0x%X\n", data)
dbg.Printf(" => 0x%X\n", data)
case MSTORE: // 0x52
offset, data := stack.Pop64(), stack.Pop()
dest, ok := subslice(memory, offset, 32, true)
dest, ok := subslice(memory, offset, 32, false)
if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
copy(dest, data[:])
fmt.Printf(" => 0x%X\n", data)
copy(dest, flip(data[:]))
dbg.Printf(" => 0x%X\n", data)
case MSTORE8: // 0x53
offset, val := stack.Pop64(), byte(stack.Pop64()&0xFF)
@ -449,19 +490,21 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
memory[offset] = val
fmt.Printf(" => [%v] 0x%X\n", offset, val)
dbg.Printf(" => [%v] 0x%X\n", offset, val)
case SLOAD: // 0x54
loc := stack.Pop()
data := vm.appState.GetStorage(callee.Address, loc)
stack.Push(data)
fmt.Printf(" {0x%X : 0x%X}\n", loc, data)
stack.Push(flipWord(data))
dbg.Printf(" {0x%X : 0x%X}\n", loc, data)
case SSTORE: // 0x55
loc, data := stack.Pop(), stack.Pop()
loc = flipWord(loc)
data = flipWord(data)
vm.appState.SetStorage(callee.Address, loc, data)
useGas(gas, GasStorageUpdate)
fmt.Printf(" {0x%X : 0x%X}\n", loc, data)
dbg.Printf(" {0x%X : 0x%X}\n", loc, data)
case JUMP: // 0x56
err = jump(code, stack.Pop64(), &pc)
@ -473,7 +516,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
err = jump(code, pos, &pc)
continue
}
fmt.Printf(" ~> false\n")
dbg.Printf(" ~> false\n")
case PC: // 0x58
stack.Push64(pc)
@ -483,10 +526,10 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
case GAS: // 0x5A
stack.Push64(*gas)
fmt.Printf(" => %X\n", *gas)
dbg.Printf(" => %X\n", *gas)
case JUMPDEST: // 0x5B
fmt.Printf("\n")
dbg.Printf("\n")
// Do nothing
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:
@ -498,17 +541,17 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
res := RightPadWord256(codeSegment)
stack.Push(res)
pc += a
fmt.Printf(" => 0x%X\n", res)
dbg.Printf(" => 0x%X\n", res)
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
n := int(op - DUP1 + 1)
stack.Dup(n)
fmt.Printf(" => [%d] 0x%X\n", n, stack.Peek().Bytes())
dbg.Printf(" => [%d] 0x%X\n", n, stack.Peek().Bytes())
case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
n := int(op - SWAP1 + 2)
stack.Swap(n)
fmt.Printf(" => [%d]\n", n)
dbg.Printf(" => [%d]\n", n)
case LOG0, LOG1, LOG2, LOG3, LOG4:
n := int(op - LOG0)
@ -528,7 +571,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
vm.params.BlockHeight,
}
vm.appState.AddLog(log)
fmt.Printf(" => %v\n", log)
dbg.Printf(" => %v\n", log)
case CREATE: // 0xF0
contractValue := stack.Pop64()
@ -560,7 +603,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
addr, value := stack.Pop(), stack.Pop64()
inOffset, inSize := stack.Pop64(), stack.Pop64() // inputs
retOffset, retSize := stack.Pop64(), stack.Pop64() // outputs
fmt.Printf(" => %X\n", addr)
dbg.Printf(" => %X\n", addr)
// Get the arguments from the memory
args, ok := subslice(memory, inOffset, inSize, false)
@ -613,7 +656,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
// Handle remaining gas.
*gas += gasLimit
fmt.Printf("resume %X (%v)\n", callee.Address, gas)
dbg.Printf("resume %X (%v)\n", callee.Address, gas)
case RETURN: // 0xF3
offset, size := stack.Pop64(), stack.Pop64()
@ -621,7 +664,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
fmt.Printf(" => [%v, %v] (%d) 0x%X\n", offset, size, len(ret), ret)
dbg.Printf(" => [%v, %v] (%d) 0x%X\n", offset, size, len(ret), ret)
return ret, nil
case SUICIDE: // 0xFF
@ -629,7 +672,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
if ok = useGas(gas, GasGetAccount); !ok {
return nil, firstErr(err, ErrInsufficientGas)
}
// TODO if the receiver is Zero256, then make it the fee.
// TODO if the receiver is , then make it the fee.
receiver := vm.appState.GetAccount(addr)
if receiver == nil {
return nil, firstErr(err, ErrUnknownAddress)
@ -638,11 +681,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
receiver.Balance += balance
vm.appState.UpdateAccount(receiver)
vm.appState.RemoveAccount(callee)
fmt.Printf(" => (%X) %v\n", addr[:4], balance)
dbg.Printf(" => (%X) %v\n", addr[:4], balance)
fallthrough
default:
fmt.Printf("(pc) %-3v Invalid opcode %X\n", pc, op)
dbg.Printf("(pc) %-3v Invalid opcode %X\n", pc, op)
panic(fmt.Errorf("Invalid opcode %X", op))
}
@ -677,10 +720,10 @@ func codeGetOp(code []byte, n uint64) OpCode {
func jump(code []byte, to uint64, pc *uint64) (err error) {
dest := codeGetOp(code, to)
if dest != JUMPDEST {
fmt.Printf(" ~> %v invalid jump dest %v\n", to, dest)
dbg.Printf(" ~> %v invalid jump dest %v\n", to, dest)
return ErrInvalidJumpDest
}
fmt.Printf(" ~> %v\n", to)
dbg.Printf(" ~> %v\n", to)
*pc = to
return nil
}
@ -713,10 +756,25 @@ func transfer(from, to *Account, amount uint64) error {
}
func flip(in []byte) []byte {
l2 := len(in) / 2
flipped := make([]byte, len(in))
for i := 0; i < len(flipped)/2; i++ {
// copy the middle bit (if its even it will get overwritten)
if len(in) != 0 {
flipped[l2] = in[l2]
}
for i := 0; i < l2; i++ {
flipped[i] = in[len(in)-1-i]
flipped[len(in)-1-i] = in[i]
}
return flipped
}
func flipWord(in Word256) Word256 {
word := Word256{}
// copy the middle bit (if its even it will get overwritten)
for i := 0; i < 16; i++ {
word[i] = in[len(in)-1-i]
word[len(in)-1-i] = in[i]
}
return word
}

Loading…
Cancel
Save