mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-26 11:11:41 +00:00
Transcribe vm changes from vm_fixes by Ethan
This commit is contained in:
@ -1,8 +1,6 @@
|
|||||||
package vm
|
package vm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
. "github.com/tendermint/tendermint/vm"
|
. "github.com/tendermint/tendermint/vm"
|
||||||
"github.com/tendermint/tendermint/vm/sha3"
|
"github.com/tendermint/tendermint/vm/sha3"
|
||||||
@ -85,33 +83,6 @@ func (fas *FakeAppState) AddLog(log *Log) {
|
|||||||
fas.logs = append(fas.logs, 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.
|
// Creates a 20 byte address and bumps the nonce.
|
||||||
func createAddress(creator *Account) Word256 {
|
func createAddress(creator *Account) Word256 {
|
||||||
nonce := creator.Nonce
|
nonce := creator.Nonce
|
||||||
|
99
vm/test/vm_test.go
Normal file
99
vm/test/vm_test.go
Normal 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}
|
||||||
|
*/
|
244
vm/vm.go
244
vm/vm.go
@ -3,7 +3,7 @@ package vm
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math/big"
|
||||||
|
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
"github.com/tendermint/tendermint/vm/sha3"
|
"github.com/tendermint/tendermint/vm/sha3"
|
||||||
@ -24,12 +24,21 @@ var (
|
|||||||
ErrInvalidContract = errors.New("Invalid contract")
|
ErrInvalidContract = errors.New("Invalid contract")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Debug bool
|
||||||
|
|
||||||
const (
|
const (
|
||||||
dataStackCapacity = 1024
|
dataStackCapacity = 1024
|
||||||
callStackCapacity = 100 // TODO ensure usage.
|
callStackCapacity = 100 // TODO ensure usage.
|
||||||
memoryCapacity = 1024 * 1024 // 1 MB
|
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 {
|
type VM struct {
|
||||||
appState AppState
|
appState AppState
|
||||||
params Params
|
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.
|
// 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) {
|
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 (
|
var (
|
||||||
pc uint64 = 0
|
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)
|
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 {
|
switch op {
|
||||||
|
|
||||||
@ -98,90 +107,123 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
||||||
case ADD: // 0x01
|
case ADD: // 0x01
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
//x, y := stack.Pop64(), stack.Pop64()
|
||||||
stack.Push64(x + y)
|
//stack.Push64(x + y)
|
||||||
fmt.Printf(" %v + %v = %v\n", x, y, 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
|
case MUL: // 0x02
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
//x, y := stack.Pop64(), stack.Pop64()
|
||||||
stack.Push64(x * y)
|
//stack.Push64(x * y)
|
||||||
fmt.Printf(" %v * %v = %v\n", x, y, 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
|
case SUB: // 0x03
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
//x, y := stack.Pop64(), stack.Pop64()
|
||||||
stack.Push64(x - y)
|
//stack.Push64(x - y)
|
||||||
fmt.Printf(" %v - %v = %v\n", x, y, 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
|
case DIV: // 0x04
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
//x, y := stack.Pop64(), stack.Pop64()
|
||||||
if y == 0 { // TODO
|
//stack.Push64(x / y)
|
||||||
|
x, y := stack.Pop(), stack.Pop()
|
||||||
|
if y.IsZero() { // TODO
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
fmt.Printf(" %v / %v = %v (TODO)\n", x, y, 0)
|
dbg.Printf(" %x / %x = %v (TODO)\n", x, y, 0)
|
||||||
} else {
|
} else {
|
||||||
stack.Push64(x / y)
|
xb := new(big.Int).SetBytes(flip(x[:]))
|
||||||
fmt.Printf(" %v / %v = %v\n", x, y, x/y)
|
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
|
case SDIV: // 0x05
|
||||||
|
// TODO ... big?
|
||||||
x, y := int64(stack.Pop64()), int64(stack.Pop64())
|
x, y := int64(stack.Pop64()), int64(stack.Pop64())
|
||||||
if y == 0 { // TODO
|
if y == 0 { // TODO
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
fmt.Printf(" %v / %v = %v (TODO)\n", x, y, 0)
|
dbg.Printf(" %v / %v = %v (TODO)\n", x, y, 0)
|
||||||
} else {
|
} else {
|
||||||
stack.Push64(uint64(x / y))
|
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
|
case MOD: // 0x06
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
//x, y := stack.Pop64(), stack.Pop64()
|
||||||
if y == 0 { // TODO
|
x, y := stack.Pop(), stack.Pop()
|
||||||
|
if y.IsZero() { // TODO
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
fmt.Printf(" %v %% %v = %v (TODO)\n", x, y, 0)
|
dbg.Printf(" %v %% %v = %v (TODO)\n", x, y, 0)
|
||||||
} else {
|
} else {
|
||||||
stack.Push64(x % y)
|
xb := new(big.Int).SetBytes(flip(x[:]))
|
||||||
fmt.Printf(" %v %% %v = %v\n", x, y, x%y)
|
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
|
case SMOD: // 0x07
|
||||||
|
// TODO ... big?
|
||||||
x, y := int64(stack.Pop64()), int64(stack.Pop64())
|
x, y := int64(stack.Pop64()), int64(stack.Pop64())
|
||||||
if y == 0 { // TODO
|
if y == 0 { // TODO
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
fmt.Printf(" %v %% %v = %v (TODO)\n", x, y, 0)
|
dbg.Printf(" %v %% %v = %v (TODO)\n", x, y, 0)
|
||||||
} else {
|
} else {
|
||||||
stack.Push64(uint64(x % y))
|
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
|
case ADDMOD: // 0x08
|
||||||
|
// TODO ... big?
|
||||||
x, y, z := stack.Pop64(), stack.Pop64(), stack.Pop64()
|
x, y, z := stack.Pop64(), stack.Pop64(), stack.Pop64()
|
||||||
if z == 0 { // TODO
|
if z == 0 { // TODO
|
||||||
stack.Push(Zero256)
|
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 {
|
} else {
|
||||||
stack.Push64(x % y)
|
stack.Push64((x + y) % z)
|
||||||
fmt.Printf(" (%v + %v) %% %v = %v\n", x, y, z, (x+y)%z)
|
dbg.Printf(" (%v + %v) %% %v = %v\n", x, y, z, (x+y)%z)
|
||||||
}
|
}
|
||||||
|
|
||||||
case MULMOD: // 0x09
|
case MULMOD: // 0x09
|
||||||
|
// TODO ... big?
|
||||||
x, y, z := stack.Pop64(), stack.Pop64(), stack.Pop64()
|
x, y, z := stack.Pop64(), stack.Pop64(), stack.Pop64()
|
||||||
if z == 0 { // TODO
|
if z == 0 { // TODO
|
||||||
stack.Push(Zero256)
|
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 {
|
} else {
|
||||||
stack.Push64(x % y)
|
stack.Push64((x * y) % z)
|
||||||
fmt.Printf(" (%v + %v) %% %v = %v\n", x, y, z, (x*y)%z)
|
dbg.Printf(" (%v + %v) %% %v = %v\n", x, y, z, (x*y)%z)
|
||||||
}
|
}
|
||||||
|
|
||||||
case EXP: // 0x0A
|
case EXP: // 0x0A
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
//x, y := stack.Pop64(), stack.Pop64()
|
||||||
stack.Push64(ExpUint64(x, y))
|
//stack.Push64(ExpUint64(x, y))
|
||||||
fmt.Printf(" %v ** %v = %v\n", x, y, uint64(math.Pow(float64(x), float64(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
|
case SIGNEXTEND: // 0x0B
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
x, y := stack.Pop64(), stack.Pop64()
|
||||||
res := (y << uint(x)) >> x
|
res := (y << uint(x)) >> x
|
||||||
stack.Push64(res)
|
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
|
case LT: // 0x10
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
x, y := stack.Pop64(), stack.Pop64()
|
||||||
@ -190,7 +232,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
|||||||
} else {
|
} else {
|
||||||
stack.Push(Zero256)
|
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
|
case GT: // 0x11
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
x, y := stack.Pop64(), stack.Pop64()
|
||||||
@ -199,7 +241,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
|||||||
} else {
|
} else {
|
||||||
stack.Push(Zero256)
|
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
|
case SLT: // 0x12
|
||||||
x, y := int64(stack.Pop64()), int64(stack.Pop64())
|
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 {
|
} else {
|
||||||
stack.Push(Zero256)
|
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
|
case SGT: // 0x13
|
||||||
x, y := int64(stack.Pop64()), int64(stack.Pop64())
|
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 {
|
} else {
|
||||||
stack.Push(Zero256)
|
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
|
case EQ: // 0x14
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
x, y := stack.Pop64(), stack.Pop64()
|
||||||
if x > y {
|
if x == y {
|
||||||
stack.Push64(1)
|
stack.Push64(1)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(Zero256)
|
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
|
case ISZERO: // 0x15
|
||||||
x := stack.Pop64()
|
x := stack.Pop64()
|
||||||
@ -235,27 +277,27 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
|||||||
} else {
|
} else {
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
}
|
}
|
||||||
fmt.Printf(" %v == 0 = %v\n", x, x == 0)
|
dbg.Printf(" %v == 0 = %v\n", x, x == 0)
|
||||||
|
|
||||||
case AND: // 0x16
|
case AND: // 0x16
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
x, y := stack.Pop64(), stack.Pop64()
|
||||||
stack.Push64(x & y)
|
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
|
case OR: // 0x17
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
x, y := stack.Pop64(), stack.Pop64()
|
||||||
stack.Push64(x | y)
|
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
|
case XOR: // 0x18
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
x, y := stack.Pop64(), stack.Pop64()
|
||||||
stack.Push64(x ^ y)
|
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
|
case NOT: // 0x19
|
||||||
x := stack.Pop64()
|
x := stack.Pop64()
|
||||||
stack.Push64(^x)
|
stack.Push64(^x)
|
||||||
fmt.Printf(" !%v = %v\n", x, ^x)
|
dbg.Printf(" !%v = %v\n", x, ^x)
|
||||||
|
|
||||||
case BYTE: // 0x1A
|
case BYTE: // 0x1A
|
||||||
idx, val := stack.Pop64(), stack.Pop()
|
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]
|
res = val[idx]
|
||||||
}
|
}
|
||||||
stack.Push64(uint64(res))
|
stack.Push64(uint64(res))
|
||||||
fmt.Printf(" => 0x%X\n", res)
|
dbg.Printf(" => 0x%X\n", res)
|
||||||
|
|
||||||
case SHA3: // 0x20
|
case SHA3: // 0x20
|
||||||
if ok = useGas(gas, GasSha3); !ok {
|
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)
|
data = sha3.Sha3(data)
|
||||||
stack.PushBytes(data)
|
stack.PushBytes(data)
|
||||||
fmt.Printf(" => (%v) %X\n", size, data)
|
dbg.Printf(" => (%v) %X\n", size, data)
|
||||||
|
|
||||||
case ADDRESS: // 0x30
|
case ADDRESS: // 0x30
|
||||||
stack.Push(callee.Address)
|
stack.Push(callee.Address)
|
||||||
fmt.Printf(" => %X\n", callee.Address)
|
dbg.Printf(" => %X\n", callee.Address)
|
||||||
|
|
||||||
case BALANCE: // 0x31
|
case BALANCE: // 0x31
|
||||||
addr := stack.Pop()
|
addr := stack.Pop()
|
||||||
@ -294,19 +336,19 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
|||||||
}
|
}
|
||||||
balance := acc.Balance
|
balance := acc.Balance
|
||||||
stack.Push64(balance)
|
stack.Push64(balance)
|
||||||
fmt.Printf(" => %v (%X)\n", balance, addr)
|
dbg.Printf(" => %v (%X)\n", balance, addr)
|
||||||
|
|
||||||
case ORIGIN: // 0x32
|
case ORIGIN: // 0x32
|
||||||
stack.Push(vm.origin)
|
stack.Push(vm.origin)
|
||||||
fmt.Printf(" => %X\n", vm.origin)
|
dbg.Printf(" => %X\n", vm.origin)
|
||||||
|
|
||||||
case CALLER: // 0x33
|
case CALLER: // 0x33
|
||||||
stack.Push(caller.Address)
|
stack.Push(caller.Address)
|
||||||
fmt.Printf(" => %X\n", caller.Address)
|
dbg.Printf(" => %X\n", caller.Address)
|
||||||
|
|
||||||
case CALLVALUE: // 0x34
|
case CALLVALUE: // 0x34
|
||||||
stack.Push64(value)
|
stack.Push64(value)
|
||||||
fmt.Printf(" => %v\n", value)
|
dbg.Printf(" => %v\n", value)
|
||||||
|
|
||||||
case CALLDATALOAD: // 0x35
|
case CALLDATALOAD: // 0x35
|
||||||
offset := stack.Pop64()
|
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)
|
return nil, firstErr(err, ErrInputOutOfBounds)
|
||||||
}
|
}
|
||||||
stack.Push(RightPadWord256(data))
|
stack.Push(RightPadWord256(data))
|
||||||
fmt.Printf(" => 0x%X\n", data)
|
dbg.Printf(" => 0x%X\n", data)
|
||||||
|
|
||||||
case CALLDATASIZE: // 0x36
|
case CALLDATASIZE: // 0x36
|
||||||
stack.Push64(uint64(len(input)))
|
stack.Push64(uint64(len(input)))
|
||||||
fmt.Printf(" => %d\n", len(input))
|
dbg.Printf(" => %d\n", len(input))
|
||||||
|
|
||||||
case CALLDATACOPY: // 0x37
|
case CALLDATACOPY: // 0x37
|
||||||
memOff := stack.Pop64()
|
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)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
copy(dest, data)
|
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
|
case CODESIZE: // 0x38
|
||||||
l := uint64(len(code))
|
l := uint64(len(code))
|
||||||
stack.Push64(l)
|
stack.Push64(l)
|
||||||
fmt.Printf(" => %d\n", l)
|
dbg.Printf(" => %d\n", l)
|
||||||
|
|
||||||
case CODECOPY: // 0x39
|
case CODECOPY: // 0x39
|
||||||
memOff := stack.Pop64()
|
memOff := stack.Pop64()
|
||||||
codeOff := stack.Pop64()
|
codeOff := stack.Pop64()
|
||||||
length := stack.Pop64()
|
length := stack.Pop64()
|
||||||
fmt.Println("CODECOPY: codeOff, length, codelength", codeOff, length, len(code))
|
|
||||||
data, ok := subslice(code, codeOff, length, false)
|
data, ok := subslice(code, codeOff, length, false)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrCodeOutOfBounds)
|
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)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
copy(dest, data)
|
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
|
case GASPRICE_DEPRECATED: // 0x3A
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
fmt.Printf(" => %X (GASPRICE IS DEPRECATED)\n")
|
dbg.Printf(" => %X (GASPRICE IS DEPRECATED)\n")
|
||||||
|
|
||||||
case EXTCODESIZE: // 0x3B
|
case EXTCODESIZE: // 0x3B
|
||||||
addr := stack.Pop()
|
addr := stack.Pop()
|
||||||
@ -373,7 +414,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
|||||||
code := acc.Code
|
code := acc.Code
|
||||||
l := uint64(len(code))
|
l := uint64(len(code))
|
||||||
stack.Push64(l)
|
stack.Push64(l)
|
||||||
fmt.Printf(" => %d\n", l)
|
dbg.Printf(" => %d\n", l)
|
||||||
|
|
||||||
case EXTCODECOPY: // 0x3C
|
case EXTCODECOPY: // 0x3C
|
||||||
addr := stack.Pop()
|
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)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
copy(dest, data)
|
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
|
case BLOCKHASH: // 0x40
|
||||||
stack.Push(Zero256)
|
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
|
case COINBASE: // 0x41
|
||||||
stack.Push(Zero256)
|
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
|
case TIMESTAMP: // 0x42
|
||||||
time := vm.params.BlockTime
|
time := vm.params.BlockTime
|
||||||
stack.Push64(uint64(time))
|
stack.Push64(uint64(time))
|
||||||
fmt.Printf(" => 0x%X\n", time)
|
dbg.Printf(" => 0x%X\n", time)
|
||||||
|
|
||||||
case BLOCKHEIGHT: // 0x43
|
case BLOCKHEIGHT: // 0x43
|
||||||
number := uint64(vm.params.BlockHeight)
|
number := uint64(vm.params.BlockHeight)
|
||||||
stack.Push64(number)
|
stack.Push64(number)
|
||||||
fmt.Printf(" => 0x%X\n", number)
|
dbg.Printf(" => 0x%X\n", number)
|
||||||
|
|
||||||
case GASLIMIT: // 0x45
|
case GASLIMIT: // 0x45
|
||||||
stack.Push64(vm.params.GasLimit)
|
stack.Push64(vm.params.GasLimit)
|
||||||
fmt.Printf(" => %v\n", vm.params.GasLimit)
|
dbg.Printf(" => %v\n", vm.params.GasLimit)
|
||||||
|
|
||||||
case POP: // 0x50
|
case POP: // 0x50
|
||||||
stack.Pop()
|
stack.Pop()
|
||||||
fmt.Printf(" => %v\n", vm.params.GasLimit)
|
dbg.Printf(" => %v\n", vm.params.GasLimit)
|
||||||
|
|
||||||
case MLOAD: // 0x51
|
case MLOAD: // 0x51
|
||||||
offset := stack.Pop64()
|
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)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
stack.Push(RightPadWord256(data))
|
stack.Push(RightPadWord256(data))
|
||||||
fmt.Printf(" => 0x%X\n", data)
|
dbg.Printf(" => 0x%X\n", data)
|
||||||
|
|
||||||
case MSTORE: // 0x52
|
case MSTORE: // 0x52
|
||||||
offset, data := stack.Pop64(), stack.Pop()
|
offset, data := stack.Pop64(), stack.Pop()
|
||||||
dest, ok := subslice(memory, offset, 32, true)
|
dest, ok := subslice(memory, offset, 32, false)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
copy(dest, data[:])
|
copy(dest, flip(data[:]))
|
||||||
fmt.Printf(" => 0x%X\n", data)
|
dbg.Printf(" => 0x%X\n", data)
|
||||||
|
|
||||||
case MSTORE8: // 0x53
|
case MSTORE8: // 0x53
|
||||||
offset, val := stack.Pop64(), byte(stack.Pop64()&0xFF)
|
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)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
memory[offset] = val
|
memory[offset] = val
|
||||||
fmt.Printf(" => [%v] 0x%X\n", offset, val)
|
dbg.Printf(" => [%v] 0x%X\n", offset, val)
|
||||||
|
|
||||||
case SLOAD: // 0x54
|
case SLOAD: // 0x54
|
||||||
loc := stack.Pop()
|
loc := stack.Pop()
|
||||||
data := vm.appState.GetStorage(callee.Address, loc)
|
data := vm.appState.GetStorage(callee.Address, loc)
|
||||||
stack.Push(data)
|
stack.Push(flipWord(data))
|
||||||
fmt.Printf(" {0x%X : 0x%X}\n", loc, data)
|
dbg.Printf(" {0x%X : 0x%X}\n", loc, data)
|
||||||
|
|
||||||
case SSTORE: // 0x55
|
case SSTORE: // 0x55
|
||||||
loc, data := stack.Pop(), stack.Pop()
|
loc, data := stack.Pop(), stack.Pop()
|
||||||
|
loc = flipWord(loc)
|
||||||
|
data = flipWord(data)
|
||||||
vm.appState.SetStorage(callee.Address, loc, data)
|
vm.appState.SetStorage(callee.Address, loc, data)
|
||||||
useGas(gas, GasStorageUpdate)
|
useGas(gas, GasStorageUpdate)
|
||||||
fmt.Printf(" {0x%X : 0x%X}\n", loc, data)
|
dbg.Printf(" {0x%X : 0x%X}\n", loc, data)
|
||||||
|
|
||||||
case JUMP: // 0x56
|
case JUMP: // 0x56
|
||||||
err = jump(code, stack.Pop64(), &pc)
|
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)
|
err = jump(code, pos, &pc)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fmt.Printf(" ~> false\n")
|
dbg.Printf(" ~> false\n")
|
||||||
|
|
||||||
case PC: // 0x58
|
case PC: // 0x58
|
||||||
stack.Push64(pc)
|
stack.Push64(pc)
|
||||||
@ -483,10 +526,10 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
|||||||
|
|
||||||
case GAS: // 0x5A
|
case GAS: // 0x5A
|
||||||
stack.Push64(*gas)
|
stack.Push64(*gas)
|
||||||
fmt.Printf(" => %X\n", *gas)
|
dbg.Printf(" => %X\n", *gas)
|
||||||
|
|
||||||
case JUMPDEST: // 0x5B
|
case JUMPDEST: // 0x5B
|
||||||
fmt.Printf("\n")
|
dbg.Printf("\n")
|
||||||
// Do nothing
|
// 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:
|
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)
|
res := RightPadWord256(codeSegment)
|
||||||
stack.Push(res)
|
stack.Push(res)
|
||||||
pc += a
|
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:
|
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.Dup(n)
|
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:
|
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)
|
||||||
stack.Swap(n)
|
stack.Swap(n)
|
||||||
fmt.Printf(" => [%d]\n", n)
|
dbg.Printf(" => [%d]\n", n)
|
||||||
|
|
||||||
case LOG0, LOG1, LOG2, LOG3, LOG4:
|
case LOG0, LOG1, LOG2, LOG3, LOG4:
|
||||||
n := int(op - LOG0)
|
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.params.BlockHeight,
|
||||||
}
|
}
|
||||||
vm.appState.AddLog(log)
|
vm.appState.AddLog(log)
|
||||||
fmt.Printf(" => %v\n", log)
|
dbg.Printf(" => %v\n", log)
|
||||||
|
|
||||||
case CREATE: // 0xF0
|
case CREATE: // 0xF0
|
||||||
contractValue := stack.Pop64()
|
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()
|
addr, value := stack.Pop(), stack.Pop64()
|
||||||
inOffset, inSize := stack.Pop64(), stack.Pop64() // inputs
|
inOffset, inSize := stack.Pop64(), stack.Pop64() // inputs
|
||||||
retOffset, retSize := stack.Pop64(), stack.Pop64() // outputs
|
retOffset, retSize := stack.Pop64(), stack.Pop64() // outputs
|
||||||
fmt.Printf(" => %X\n", addr)
|
dbg.Printf(" => %X\n", addr)
|
||||||
|
|
||||||
// Get the arguments from the memory
|
// Get the arguments from the memory
|
||||||
args, ok := subslice(memory, inOffset, inSize, false)
|
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.
|
// Handle remaining gas.
|
||||||
*gas += gasLimit
|
*gas += gasLimit
|
||||||
|
|
||||||
fmt.Printf("resume %X (%v)\n", callee.Address, gas)
|
dbg.Printf("resume %X (%v)\n", callee.Address, gas)
|
||||||
|
|
||||||
case RETURN: // 0xF3
|
case RETURN: // 0xF3
|
||||||
offset, size := stack.Pop64(), stack.Pop64()
|
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 {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
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
|
return ret, nil
|
||||||
|
|
||||||
case SUICIDE: // 0xFF
|
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 {
|
if ok = useGas(gas, GasGetAccount); !ok {
|
||||||
return nil, firstErr(err, ErrInsufficientGas)
|
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)
|
receiver := vm.appState.GetAccount(addr)
|
||||||
if receiver == nil {
|
if receiver == nil {
|
||||||
return nil, firstErr(err, ErrUnknownAddress)
|
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
|
receiver.Balance += balance
|
||||||
vm.appState.UpdateAccount(receiver)
|
vm.appState.UpdateAccount(receiver)
|
||||||
vm.appState.RemoveAccount(callee)
|
vm.appState.RemoveAccount(callee)
|
||||||
fmt.Printf(" => (%X) %v\n", addr[:4], balance)
|
dbg.Printf(" => (%X) %v\n", addr[:4], balance)
|
||||||
fallthrough
|
fallthrough
|
||||||
|
|
||||||
default:
|
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))
|
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) {
|
func jump(code []byte, to uint64, pc *uint64) (err error) {
|
||||||
dest := codeGetOp(code, to)
|
dest := codeGetOp(code, to)
|
||||||
if dest != JUMPDEST {
|
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
|
return ErrInvalidJumpDest
|
||||||
}
|
}
|
||||||
fmt.Printf(" ~> %v\n", to)
|
dbg.Printf(" ~> %v\n", to)
|
||||||
*pc = to
|
*pc = to
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -713,10 +756,25 @@ func transfer(from, to *Account, amount uint64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func flip(in []byte) []byte {
|
func flip(in []byte) []byte {
|
||||||
|
l2 := len(in) / 2
|
||||||
flipped := make([]byte, len(in))
|
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[i] = in[len(in)-1-i]
|
||||||
flipped[len(in)-1-i] = in[i]
|
flipped[len(in)-1-i] = in[i]
|
||||||
}
|
}
|
||||||
return flipped
|
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
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user