Merge branch 'unflip' of https://github.com/tendermint/tendermint into unflip

Conflicts:
	vm/vm.go
This commit is contained in:
Ethan Buchman 2015-04-17 17:46:02 -07:00
commit a28c1c83fc
14 changed files with 235 additions and 182 deletions

View File

@ -31,7 +31,10 @@ func (w Word256) Compare(other Word256) int {
func Uint64ToWord256(i uint64) Word256 {
word := Word256{}
PutUint64(word[:], i)
buf := [8]byte{}
PutUint64(buf[:], i)
word[24], word[25], word[26], word[27] = buf[7], buf[6], buf[5], buf[4]
word[28], word[29], word[30], word[31] = buf[3], buf[2], buf[1], buf[0]
return word
}
@ -46,7 +49,10 @@ func LeftPadWord256(bz []byte) (word Word256) {
}
func Uint64FromWord256(word Word256) uint64 {
return binary.LittleEndian.Uint64(word[:])
buf := [8]byte{}
buf[0], buf[1], buf[2], buf[3] = word[31], word[30], word[29], word[28]
buf[4], buf[5], buf[6], buf[7] = word[27], word[26], word[25], word[24]
return binary.LittleEndian.Uint64(buf[:])
}
//-------------------------------------

View File

@ -36,7 +36,7 @@ func GetStorage(address, key []byte) (*ctypes.ResponseGetStorage, error) {
storageRoot := account.StorageRoot
storageTree := state.LoadStorage(storageRoot)
_, value := storageTree.Get(RightPadWord256(key).Bytes())
_, value := storageTree.Get(LeftPadWord256(key).Bytes())
if value == nil {
return &ctypes.ResponseGetStorage{key, nil}, nil
}

View File

@ -16,7 +16,7 @@ func toVMAccount(acc *account.Account) *vm.Account {
Balance: acc.Balance,
Code: acc.Code, // This is crazy.
Nonce: uint64(acc.Sequence),
StorageRoot: RightPadWord256(acc.StorageRoot),
StorageRoot: LeftPadWord256(acc.StorageRoot),
Other: acc.PubKey,
}
}
@ -37,7 +37,7 @@ func Call(address, data []byte) (*ctypes.ResponseCall, error) {
txCache := state.NewTxCache(cache)
params := vm.Params{
BlockHeight: uint64(st.LastBlockHeight),
BlockHash: RightPadWord256(st.LastBlockHash),
BlockHash: LeftPadWord256(st.LastBlockHash),
BlockTime: st.LastBlockTime.Unix(),
GasLimit: 10000000,
}
@ -62,7 +62,7 @@ func CallCode(code, data []byte) (*ctypes.ResponseCall, error) {
txCache := state.NewTxCache(cache)
params := vm.Params{
BlockHeight: uint64(st.LastBlockHeight),
BlockHash: RightPadWord256(st.LastBlockHash),
BlockHash: LeftPadWord256(st.LastBlockHash),
BlockTime: st.LastBlockTime.Unix(),
GasLimit: 10000000,
}

View File

@ -288,7 +288,7 @@ func simpleContract() ([]byte, []byte, []byte) {
// the is the code we need to return the contractCode when the contract is initialized
lenCode := len(contractCode)
// push code to the stack
//code := append([]byte{byte(0x60 + lenCode - 1)}, LeftPadWord256(contractCode).Bytes()...)
//code := append([]byte{byte(0x60 + lenCode - 1)}, RightPadWord256(contractCode).Bytes()...)
code := append([]byte{0x7f}, RightPadWord256(contractCode).Bytes()...)
// store it in memory
code = append(code, []byte{0x60, 0x0, 0x52}...)

View File

@ -119,8 +119,8 @@ func testGetStorage(t *testing.T, typ string) {
mempoolCount = 0
v := getStorage(t, typ, contractAddr, []byte{0x1})
got := RightPadWord256(v)
expected := RightPadWord256([]byte{0x5})
got := LeftPadWord256(v)
expected := LeftPadWord256([]byte{0x5})
if got.Compare(expected) != 0 {
t.Fatalf("Wrong storage value. Got %x, expected %x", got.Bytes(), expected.Bytes())
}

View File

@ -106,7 +106,7 @@ func (cache *BlockCache) GetStorage(addr Word256, key Word256) (value Word256) {
_, val_ := storage.Get(key.Bytes())
value = Zero256
if val_ != nil {
value = RightPadWord256(val_.([]byte))
value = LeftPadWord256(val_.([]byte))
}
cache.storages[Tuple256{addr, key}] = storageInfo{value, false}
return value

View File

@ -395,7 +395,7 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
txCache = NewTxCache(blockCache)
params = vm.Params{
BlockHeight: uint64(_s.LastBlockHeight),
BlockHash: RightPadWord256(_s.LastBlockHash),
BlockHash: LeftPadWord256(_s.LastBlockHash),
BlockTime: _s.LastBlockTime.Unix(),
GasLimit: 10000000,
}

View File

@ -158,7 +158,7 @@ func toVMAccount(acc *ac.Account) *vm.Account {
Balance: acc.Balance,
Code: acc.Code, // This is crazy.
Nonce: uint64(acc.Sequence),
StorageRoot: RightPadWord256(acc.StorageRoot),
StorageRoot: LeftPadWord256(acc.StorageRoot),
Other: acc.PubKey,
}
}

26
vm/common.go Normal file
View File

@ -0,0 +1,26 @@
package vm
import (
"math/big"
)
// To256
//
// "cast" the big int to a 256 big int (i.e., limit to)
var tt256 = new(big.Int).Lsh(big.NewInt(1), 256)
var tt256m1 = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(1))
var tt255 = new(big.Int).Lsh(big.NewInt(1), 255)
func U256(x *big.Int) *big.Int {
x.And(x, tt256m1)
return x
}
func S256(x *big.Int) *big.Int {
if x.Cmp(tt255) < 0 {
return x
} else {
// We don't want to modify x, ever
return new(big.Int).Sub(x, tt256)
}
}

View File

@ -39,7 +39,7 @@ func ecrecoverFunc(input []byte, gas *uint64) (output []byte, err error) {
return nil, err
}
hashed := sha3.Sha3(recovered[1:])
return RightPadBytes(hashed, 32), nil
return LeftPadBytes(hashed, 32), nil
}
func sha256Func(input []byte, gas *uint64) (output []byte, err error) {
@ -73,7 +73,7 @@ func ripemd160Func(input []byte, gas *uint64) (output []byte, err error) {
if err != nil {
panic(err)
}
return RightPadBytes(hasher.Sum(nil), 32), nil
return LeftPadBytes(hasher.Sum(nil), 32), nil
}
func identityFunc(input []byte, gas *uint64) (output []byte, err error) {

View File

@ -51,7 +51,7 @@ func (st *Stack) PushBytes(bz []byte) {
if len(bz) != 32 {
panic("Invalid bytes size: expected 32")
}
st.Push(RightPadWord256(bz))
st.Push(LeftPadWord256(bz))
}
func (st *Stack) Push64(i uint64) {
@ -73,7 +73,8 @@ func (st *Stack) PopBytes() []byte {
}
func (st *Stack) Pop64() uint64 {
return GetUint64(st.Pop().Bytes())
d := st.Pop()
return Uint64FromWord256(d)
}
func (st *Stack) Len() int {

View File

@ -90,5 +90,5 @@ func createAddress(creator *Account) Word256 {
temp := make([]byte, 32+8)
copy(temp, creator.Address[:])
PutUint64(temp[32:], nonce)
return RightPadWord256(sha3.Sha3(temp)[:20])
return LeftPadWord256(sha3.Sha3(temp)[:20])
}

View File

@ -64,10 +64,10 @@ func TestSubcurrency(t *testing.T) {
st := newAppState()
// Create accounts
account1 := &Account{
Address: RightPadWord256(makeBytes(20)),
Address: LeftPadWord256(makeBytes(20)),
}
account2 := &Account{
Address: RightPadWord256(makeBytes(20)),
Address: LeftPadWord256(makeBytes(20)),
}
st.accounts[account1.Address.String()] = account1
st.accounts[account2.Address.String()] = account2

346
vm/vm.go
View File

@ -1,6 +1,7 @@
package vm
import (
"bytes"
"errors"
"fmt"
"math/big"
@ -131,207 +132,252 @@ 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)
x, y := stack.Pop(), stack.Pop()
xb := new(big.Int).SetBytes(flip(x[:]))
yb := new(big.Int).SetBytes(flip(y[:]))
xb := new(big.Int).SetBytes(x[:])
yb := new(big.Int).SetBytes(y[:])
sum := new(big.Int).Add(xb, yb)
stack.Push(RightPadWord256(flip(sum.Bytes())))
dbg.Printf(" %v + %v = %v\n", xb, yb, sum)
res := LeftPadWord256(U256(sum).Bytes())
stack.Push(res)
dbg.Printf(" %v + %v = %v (%X)\n", xb, yb, sum, res)
case MUL: // 0x02
//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[:]))
xb := new(big.Int).SetBytes(x[:])
yb := new(big.Int).SetBytes(y[:])
prod := new(big.Int).Mul(xb, yb)
stack.Push(RightPadWord256(flip(rightMostBytes(prod.Bytes(), 32))))
dbg.Printf(" %v * %v = %v\n", xb, yb, prod)
res := LeftPadWord256(U256(prod).Bytes())
stack.Push(res)
dbg.Printf(" %v * %v = %v (%X)\n", xb, yb, prod, res)
case SUB: // 0x03
//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[:]))
xb := new(big.Int).SetBytes(x[:])
yb := new(big.Int).SetBytes(y[:])
diff := new(big.Int).Sub(xb, yb)
stack.Push(RightPadWord256(flip(diff.Bytes())))
dbg.Printf(" %v - %v = %v\n", xb, yb, diff)
res := LeftPadWord256(U256(diff).Bytes())
stack.Push(res)
dbg.Printf(" %v - %v = %v (%X)\n", xb, yb, diff, res)
case DIV: // 0x04
//x, y := stack.Pop64(), stack.Pop64()
//stack.Push64(x / y)
x, y := stack.Pop(), stack.Pop()
if y.IsZero() { // TODO
if y.IsZero() {
stack.Push(Zero256)
dbg.Printf(" %x / %x = %v (TODO)\n", x, y, 0)
dbg.Printf(" %x / %x = %v\n", x, y, 0)
} else {
xb := new(big.Int).SetBytes(flip(x[:]))
yb := new(big.Int).SetBytes(flip(y[:]))
xb := new(big.Int).SetBytes(x[:])
yb := new(big.Int).SetBytes(y[:])
div := new(big.Int).Div(xb, yb)
stack.Push(RightPadWord256(flip(div.Bytes())))
dbg.Printf(" %v / %v = %v\n", xb, yb, div)
res := LeftPadWord256(U256(div).Bytes())
stack.Push(res)
dbg.Printf(" %v / %v = %v (%X)\n", xb, yb, div, res)
}
case SDIV: // 0x05
// TODO ... big?
x, y := int64(stack.Pop64()), int64(stack.Pop64())
if y == 0 { // TODO
x, y := stack.Pop(), stack.Pop()
if y.IsZero() {
stack.Push(Zero256)
dbg.Printf(" %v / %v = %v (TODO)\n", x, y, 0)
dbg.Printf(" %x / %x = %v\n", x, y, 0)
} else {
stack.Push64(uint64(x / y))
dbg.Printf(" %v / %v = %v\n", x, y, x/y)
xb := S256(new(big.Int).SetBytes(x[:]))
yb := S256(new(big.Int).SetBytes(y[:]))
div := new(big.Int).Div(xb, yb)
res := LeftPadWord256(U256(div).Bytes())
stack.Push(res)
dbg.Printf(" %v / %v = %v (%X)\n", xb, yb, div, res)
}
case MOD: // 0x06
//x, y := stack.Pop64(), stack.Pop64()
x, y := stack.Pop(), stack.Pop()
if y.IsZero() { // TODO
if y.IsZero() {
stack.Push(Zero256)
dbg.Printf(" %v %% %v = %v (TODO)\n", x, y, 0)
dbg.Printf(" %v %% %v = %v\n", x, y, 0)
} else {
xb := new(big.Int).SetBytes(flip(x[:]))
yb := new(big.Int).SetBytes(flip(y[:]))
xb := new(big.Int).SetBytes(x[:])
yb := new(big.Int).SetBytes(y[:])
mod := new(big.Int).Mod(xb, yb)
stack.Push(RightPadWord256(flip(mod.Bytes())))
dbg.Printf(" %v %% %v = %v\n", xb, yb, mod)
res := LeftPadWord256(U256(mod).Bytes())
stack.Push(res)
dbg.Printf(" %v %% %v = %v (%X)\n", xb, yb, mod, res)
}
case SMOD: // 0x07
// TODO ... big?
x, y := int64(stack.Pop64()), int64(stack.Pop64())
if y == 0 { // TODO
x, y := stack.Pop(), stack.Pop()
if y.IsZero() {
stack.Push(Zero256)
dbg.Printf(" %v %% %v = %v (TODO)\n", x, y, 0)
dbg.Printf(" %v %% %v = %v\n", x, y, 0)
} else {
stack.Push64(uint64(x % y))
dbg.Printf(" %v %% %v = %v\n", x, y, x%y)
xb := S256(new(big.Int).SetBytes(x[:]))
yb := S256(new(big.Int).SetBytes(y[:]))
mod := new(big.Int).Mod(xb, yb)
res := LeftPadWord256(U256(mod).Bytes())
stack.Push(res)
dbg.Printf(" %v %% %v = %v (%X)\n", xb, yb, mod, res)
}
case ADDMOD: // 0x08
// TODO ... big?
x, y, z := stack.Pop64(), stack.Pop64(), stack.Pop64()
if z == 0 { // TODO
x, y, z := stack.Pop(), stack.Pop(), stack.Pop()
if z.IsZero() {
stack.Push(Zero256)
dbg.Printf(" (%v + %v) %% %v = %v (TODO)\n", x, y, z, 0)
dbg.Printf(" %v %% %v = %v\n", x, y, 0)
} else {
stack.Push64((x + y) % z)
dbg.Printf(" (%v + %v) %% %v = %v\n", x, y, z, (x+y)%z)
xb := new(big.Int).SetBytes(x[:])
yb := new(big.Int).SetBytes(y[:])
zb := new(big.Int).SetBytes(z[:])
add := new(big.Int).Add(xb, yb)
mod := new(big.Int).Mod(add, zb)
res := LeftPadWord256(U256(mod).Bytes())
stack.Push(res)
dbg.Printf(" %v + %v %% %v = %v (%X)\n",
xb, yb, zb, mod, res)
}
case MULMOD: // 0x09
// TODO ... big?
x, y, z := stack.Pop64(), stack.Pop64(), stack.Pop64()
if z == 0 { // TODO
x, y, z := stack.Pop(), stack.Pop(), stack.Pop()
if z.IsZero() {
stack.Push(Zero256)
dbg.Printf(" (%v + %v) %% %v = %v (TODO)\n", x, y, z, 0)
dbg.Printf(" %v %% %v = %v\n", x, y, 0)
} else {
stack.Push64((x * y) % z)
dbg.Printf(" (%v + %v) %% %v = %v\n", x, y, z, (x*y)%z)
xb := new(big.Int).SetBytes(x[:])
yb := new(big.Int).SetBytes(y[:])
zb := new(big.Int).SetBytes(z[:])
mul := new(big.Int).Mul(xb, yb)
mod := new(big.Int).Mod(mul, zb)
res := LeftPadWord256(U256(mod).Bytes())
stack.Push(res)
dbg.Printf(" %v * %v %% %v = %v (%X)\n",
xb, yb, zb, mod, res)
}
case EXP: // 0x0A
//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[:]))
xb := new(big.Int).SetBytes(x[:])
yb := new(big.Int).SetBytes(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)
res := LeftPadWord256(U256(pow).Bytes())
dbg.Printf(" %v ** %v = %v (%X)\n", xb, yb, pow, res)
case SIGNEXTEND: // 0x0B
x, y := stack.Pop64(), stack.Pop64()
res := (y << uint(x)) >> x
stack.Push64(res)
dbg.Printf(" (%v << %v) >> %v = %v\n", y, x, x, res)
back := stack.Pop()
backb := new(big.Int).SetBytes(back[:])
if backb.Cmp(big.NewInt(31)) < 0 {
bit := uint(backb.Uint64()*8 + 7)
num := stack.Pop()
numb := new(big.Int).SetBytes(num[:])
mask := new(big.Int).Lsh(big.NewInt(1), bit)
mask.Sub(mask, big.NewInt(1))
if numb.Bit(int(bit)) == 1 {
numb.Or(numb, mask.Not(mask))
} else {
numb.Add(numb, mask)
}
res := LeftPadWord256(U256(numb).Bytes())
dbg.Printf(" = %v (%X)", numb, res)
stack.Push(res)
}
case LT: // 0x10
x, y := stack.Pop64(), stack.Pop64()
if x < y {
x, y := stack.Pop(), stack.Pop()
xb := new(big.Int).SetBytes(x[:])
yb := new(big.Int).SetBytes(y[:])
if xb.Cmp(yb) < 0 {
stack.Push64(1)
dbg.Printf(" %v < %v = %v\n", xb, yb, 1)
} else {
stack.Push(Zero256)
dbg.Printf(" %v < %v = %v\n", xb, yb, 0)
}
dbg.Printf(" %v < %v = %v\n", x, y, x < y)
case GT: // 0x11
x, y := stack.Pop64(), stack.Pop64()
if x > y {
x, y := stack.Pop(), stack.Pop()
xb := new(big.Int).SetBytes(x[:])
yb := new(big.Int).SetBytes(y[:])
if xb.Cmp(yb) > 0 {
stack.Push64(1)
dbg.Printf(" %v > %v = %v\n", xb, yb, 1)
} else {
stack.Push(Zero256)
dbg.Printf(" %v > %v = %v\n", xb, yb, 0)
}
dbg.Printf(" %v > %v = %v\n", x, y, x > y)
case SLT: // 0x12
x, y := int64(stack.Pop64()), int64(stack.Pop64())
if x < y {
x, y := stack.Pop(), stack.Pop()
xb := S256(new(big.Int).SetBytes(x[:]))
yb := S256(new(big.Int).SetBytes(y[:]))
if xb.Cmp(yb) < 0 {
stack.Push64(1)
dbg.Printf(" %v < %v = %v\n", xb, yb, 1)
} else {
stack.Push(Zero256)
dbg.Printf(" %v < %v = %v\n", xb, yb, 0)
}
dbg.Printf(" %v < %v = %v\n", x, y, x < y)
case SGT: // 0x13
x, y := int64(stack.Pop64()), int64(stack.Pop64())
if x > y {
x, y := stack.Pop(), stack.Pop()
xb := S256(new(big.Int).SetBytes(x[:]))
yb := S256(new(big.Int).SetBytes(y[:]))
if xb.Cmp(yb) > 0 {
stack.Push64(1)
dbg.Printf(" %v > %v = %v\n", xb, yb, 1)
} else {
stack.Push(Zero256)
dbg.Printf(" %v > %v = %v\n", xb, yb, 0)
}
dbg.Printf(" %v > %v = %v\n", x, y, x > y)
case EQ: // 0x14
x, y := stack.Pop64(), stack.Pop64()
if x == y {
x, y := stack.Pop(), stack.Pop()
if bytes.Equal(x[:], y[:]) {
stack.Push64(1)
dbg.Printf(" %X == %X = %v\n", x, y, 1)
} else {
stack.Push(Zero256)
dbg.Printf(" %X == %X = %v\n", x, y, 0)
}
dbg.Printf(" %v == %v = %v\n", x, y, x == y)
case ISZERO: // 0x15
x := stack.Pop64()
if x == 0 {
x := stack.Pop()
if x.IsZero() {
stack.Push64(1)
dbg.Printf(" %v == 0 = %v\n", x, 1)
} else {
stack.Push(Zero256)
dbg.Printf(" %v == 0 = %v\n", x, 0)
}
dbg.Printf(" %v == 0 = %v\n", x, x == 0)
case AND: // 0x16
//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[:]))
res := new(big.Int).And(xb, yb)
stack.Push(RightPadWord256(flip(res.Bytes())))
dbg.Printf(" %v & %v = %v\n", xb, yb, res)
z := [32]byte{}
for i := 0; i < 32; i++ {
z[i] = x[i] & y[i]
}
stack.Push(z)
dbg.Printf(" %X & %X = %X\n", x, y, z)
case OR: // 0x17
//x, y := stack.Pop64(), stack.Pop64()
//stack.Push64(x | y)
//dbg.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[:]))
res := new(big.Int).Or(xb, yb)
stack.Push(RightPadWord256(flip(res.Bytes())))
dbg.Printf(" %v & %v = %v\n", xb, yb, res)
z := [32]byte{}
for i := 0; i < 32; i++ {
z[i] = x[i] | y[i]
}
stack.Push(z)
dbg.Printf(" %X | %X = %X\n", x, y, z)
case XOR: // 0x18
x, y := stack.Pop64(), stack.Pop64()
stack.Push64(x ^ y)
dbg.Printf(" %v ^ %v = %v\n", x, y, x^y)
x, y := stack.Pop(), stack.Pop()
z := [32]byte{}
for i := 0; i < 32; i++ {
z[i] = x[i] ^ y[i]
}
stack.Push(z)
dbg.Printf(" %X ^ %X = %X\n", x, y, z)
case NOT: // 0x19
x := stack.Pop64()
stack.Push64(^x)
dbg.Printf(" !%v = %v\n", x, ^x)
x := stack.Pop()
z := [32]byte{}
for i := 0; i < 32; i++ {
z[i] = ^x[i]
}
stack.Push(z)
dbg.Printf(" !%X = %X\n", x, z)
case BYTE: // 0x1A
idx, val := stack.Pop64(), stack.Pop()
@ -347,12 +393,12 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
return nil, firstErr(err, ErrInsufficientGas)
}
offset, size := stack.Pop64(), stack.Pop64()
data, ok := subslice(memory, offset, size, false)
data, ok := subslice(memory, offset, size)
if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
data = sha3.Sha3(data)
stack.PushBytes(flip(data))
stack.PushBytes(data)
dbg.Printf(" => (%v) %X\n", size, data)
case ADDRESS: // 0x30
@ -364,7 +410,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)
}
acc := vm.appState.GetAccount(flipWord(addr)) // TODO ensure that 20byte lengths are supported.
acc := vm.appState.GetAccount(addr)
if acc == nil {
return nil, firstErr(err, ErrUnknownAddress)
}
@ -386,12 +432,13 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
case CALLDATALOAD: // 0x35
offset := stack.Pop64()
data, ok := subslice(input, offset, 32, true)
data, ok := subslice(input, offset, 32)
if !ok {
return nil, firstErr(err, ErrInputOutOfBounds)
}
stack.Push(RightPadWord256(data))
dbg.Printf(" => 0x%X\n", RightPadWord256(data))
res := LeftPadWord256(data)
stack.Push(res)
dbg.Printf(" => 0x%X\n", res)
case CALLDATASIZE: // 0x36
stack.Push64(uint64(len(input)))
@ -401,11 +448,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
memOff := stack.Pop64()
inputOff := stack.Pop64()
length := stack.Pop64()
data, ok := subslice(input, inputOff, length, false)
data, ok := subslice(input, inputOff, length)
if !ok {
return nil, firstErr(err, ErrInputOutOfBounds)
}
dest, ok := subslice(memory, memOff, length, false)
dest, ok := subslice(memory, memOff, length)
if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
@ -421,11 +468,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
memOff := stack.Pop64()
codeOff := stack.Pop64()
length := stack.Pop64()
data, ok := subslice(code, codeOff, length, false)
data, ok := subslice(code, codeOff, length)
if !ok {
return nil, firstErr(err, ErrCodeOutOfBounds)
}
dest, ok := subslice(memory, memOff, length, false)
dest, ok := subslice(memory, memOff, length)
if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
@ -441,7 +488,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)
}
acc := vm.appState.GetAccount(flipWord(addr))
acc := vm.appState.GetAccount(addr)
if acc == nil {
return nil, firstErr(err, ErrUnknownAddress)
}
@ -455,7 +502,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)
}
acc := vm.appState.GetAccount(flipWord(addr))
acc := vm.appState.GetAccount(addr)
if acc == nil {
return nil, firstErr(err, ErrUnknownAddress)
}
@ -463,11 +510,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
memOff := stack.Pop64()
codeOff := stack.Pop64()
length := stack.Pop64()
data, ok := subslice(code, codeOff, length, false)
data, ok := subslice(code, codeOff, length)
if !ok {
return nil, firstErr(err, ErrCodeOutOfBounds)
}
dest, ok := subslice(memory, memOff, length, false)
dest, ok := subslice(memory, memOff, length)
if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
@ -502,20 +549,20 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
case MLOAD: // 0x51
offset := stack.Pop64()
data, ok := subslice(memory, offset, 32, true)
data, ok := subslice(memory, offset, 32)
if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
stack.Push(RightPadWord256(data))
stack.Push(LeftPadWord256(data))
dbg.Printf(" => 0x%X\n", data)
case MSTORE: // 0x52
offset, data := stack.Pop64(), stack.Pop()
dest, ok := subslice(memory, offset, 32, false)
dest, ok := subslice(memory, offset, 32)
if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
copy(dest, flip(data[:]))
copy(dest, data[:])
dbg.Printf(" => 0x%X\n", data)
case MSTORE8: // 0x53
@ -543,8 +590,8 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
continue
case JUMPI: // 0x57
pos, cond := stack.Pop64(), stack.Pop64()
if cond >= 1 {
pos, cond := stack.Pop64(), stack.Pop()
if !cond.IsZero() {
err = jump(code, pos, &pc)
continue
}
@ -566,11 +613,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
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)
codeSegment, ok := subslice(code, pc+1, a, true)
codeSegment, ok := subslice(code, pc+1, a)
if !ok {
return nil, firstErr(err, ErrCodeOutOfBounds)
}
res := RightPadWord256(codeSegment)
res := LeftPadWord256(codeSegment)
stack.Push(res)
pc += a
dbg.Printf(" => 0x%X\n", res)
@ -592,7 +639,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
for i := 0; i < n; i++ {
topics[i] = stack.Pop()
}
data, ok := subslice(memory, offset, size, false)
data, ok := subslice(memory, offset, size)
if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
@ -608,7 +655,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
case CREATE: // 0xF0
contractValue := stack.Pop64()
offset, size := stack.Pop64(), stack.Pop64()
input, ok := subslice(memory, offset, size, false)
input, ok := subslice(memory, offset, size)
if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
@ -638,7 +685,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
dbg.Printf(" => %X\n", addr)
// Get the arguments from the memory
args, ok := subslice(memory, inOffset, inSize, false)
args, ok := subslice(memory, inOffset, inSize)
if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
@ -662,7 +709,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)
}
acc := vm.appState.GetAccount(flipWord(addr))
acc := vm.appState.GetAccount(addr)
if acc == nil {
return nil, firstErr(err, ErrUnknownAddress)
}
@ -678,7 +725,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
stack.Push(Zero256)
} else {
stack.Push(One256)
dest, ok := subslice(memory, retOffset, retSize, false)
dest, ok := subslice(memory, retOffset, retSize)
if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
@ -692,7 +739,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
case RETURN: // 0xF3
offset, size := stack.Pop64(), stack.Pop64()
ret, ok := subslice(memory, offset, size, false)
ret, ok := subslice(memory, offset, size)
if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
@ -705,7 +752,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
return nil, firstErr(err, ErrInsufficientGas)
}
// TODO if the receiver is , then make it the fee.
receiver := vm.appState.GetAccount(flipWord(addr))
receiver := vm.appState.GetAccount(addr)
if receiver == nil {
return nil, firstErr(err, ErrUnknownAddress)
}
@ -726,7 +773,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
}
}
func subslice(data []byte, offset, length uint64, flip_ bool) (ret []byte, ok bool) {
func subslice(data []byte, offset, length uint64) (ret []byte, ok bool) {
size := uint64(len(data))
if size < offset {
return nil, false
@ -737,9 +784,6 @@ func subslice(data []byte, offset, length uint64, flip_ bool) (ret []byte, ok bo
ret, ok = data[offset:offset+length], true
}
if flip_ {
ret = flip(ret)
}
return
}
@ -794,27 +838,3 @@ func transfer(from, to *Account, amount uint64) error {
return nil
}
}
func flip(in []byte) []byte {
l2 := len(in) / 2
flipped := make([]byte, len(in))
// 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
}