Merge branch 'unflip' of https://github.com/tendermint/tendermint into unflip
Conflicts: vm/vm.go
This commit is contained in:
commit
a28c1c83fc
|
@ -31,7 +31,10 @@ func (w Word256) Compare(other Word256) int {
|
||||||
|
|
||||||
func Uint64ToWord256(i uint64) Word256 {
|
func Uint64ToWord256(i uint64) Word256 {
|
||||||
word := 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
|
return word
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +49,10 @@ func LeftPadWord256(bz []byte) (word Word256) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Uint64FromWord256(word Word256) uint64 {
|
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[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
|
|
|
@ -36,7 +36,7 @@ func GetStorage(address, key []byte) (*ctypes.ResponseGetStorage, error) {
|
||||||
storageRoot := account.StorageRoot
|
storageRoot := account.StorageRoot
|
||||||
storageTree := state.LoadStorage(storageRoot)
|
storageTree := state.LoadStorage(storageRoot)
|
||||||
|
|
||||||
_, value := storageTree.Get(RightPadWord256(key).Bytes())
|
_, value := storageTree.Get(LeftPadWord256(key).Bytes())
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return &ctypes.ResponseGetStorage{key, nil}, nil
|
return &ctypes.ResponseGetStorage{key, nil}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ func toVMAccount(acc *account.Account) *vm.Account {
|
||||||
Balance: acc.Balance,
|
Balance: acc.Balance,
|
||||||
Code: acc.Code, // This is crazy.
|
Code: acc.Code, // This is crazy.
|
||||||
Nonce: uint64(acc.Sequence),
|
Nonce: uint64(acc.Sequence),
|
||||||
StorageRoot: RightPadWord256(acc.StorageRoot),
|
StorageRoot: LeftPadWord256(acc.StorageRoot),
|
||||||
Other: acc.PubKey,
|
Other: acc.PubKey,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ func Call(address, data []byte) (*ctypes.ResponseCall, error) {
|
||||||
txCache := state.NewTxCache(cache)
|
txCache := state.NewTxCache(cache)
|
||||||
params := vm.Params{
|
params := vm.Params{
|
||||||
BlockHeight: uint64(st.LastBlockHeight),
|
BlockHeight: uint64(st.LastBlockHeight),
|
||||||
BlockHash: RightPadWord256(st.LastBlockHash),
|
BlockHash: LeftPadWord256(st.LastBlockHash),
|
||||||
BlockTime: st.LastBlockTime.Unix(),
|
BlockTime: st.LastBlockTime.Unix(),
|
||||||
GasLimit: 10000000,
|
GasLimit: 10000000,
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ func CallCode(code, data []byte) (*ctypes.ResponseCall, error) {
|
||||||
txCache := state.NewTxCache(cache)
|
txCache := state.NewTxCache(cache)
|
||||||
params := vm.Params{
|
params := vm.Params{
|
||||||
BlockHeight: uint64(st.LastBlockHeight),
|
BlockHeight: uint64(st.LastBlockHeight),
|
||||||
BlockHash: RightPadWord256(st.LastBlockHash),
|
BlockHash: LeftPadWord256(st.LastBlockHash),
|
||||||
BlockTime: st.LastBlockTime.Unix(),
|
BlockTime: st.LastBlockTime.Unix(),
|
||||||
GasLimit: 10000000,
|
GasLimit: 10000000,
|
||||||
}
|
}
|
||||||
|
|
|
@ -288,7 +288,7 @@ func simpleContract() ([]byte, []byte, []byte) {
|
||||||
// the is the code we need to return the contractCode when the contract is initialized
|
// the is the code we need to return the contractCode when the contract is initialized
|
||||||
lenCode := len(contractCode)
|
lenCode := len(contractCode)
|
||||||
// push code to the stack
|
// 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()...)
|
code := append([]byte{0x7f}, RightPadWord256(contractCode).Bytes()...)
|
||||||
// store it in memory
|
// store it in memory
|
||||||
code = append(code, []byte{0x60, 0x0, 0x52}...)
|
code = append(code, []byte{0x60, 0x0, 0x52}...)
|
||||||
|
|
|
@ -119,8 +119,8 @@ func testGetStorage(t *testing.T, typ string) {
|
||||||
mempoolCount = 0
|
mempoolCount = 0
|
||||||
|
|
||||||
v := getStorage(t, typ, contractAddr, []byte{0x1})
|
v := getStorage(t, typ, contractAddr, []byte{0x1})
|
||||||
got := RightPadWord256(v)
|
got := LeftPadWord256(v)
|
||||||
expected := RightPadWord256([]byte{0x5})
|
expected := LeftPadWord256([]byte{0x5})
|
||||||
if got.Compare(expected) != 0 {
|
if got.Compare(expected) != 0 {
|
||||||
t.Fatalf("Wrong storage value. Got %x, expected %x", got.Bytes(), expected.Bytes())
|
t.Fatalf("Wrong storage value. Got %x, expected %x", got.Bytes(), expected.Bytes())
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ func (cache *BlockCache) GetStorage(addr Word256, key Word256) (value Word256) {
|
||||||
_, val_ := storage.Get(key.Bytes())
|
_, val_ := storage.Get(key.Bytes())
|
||||||
value = Zero256
|
value = Zero256
|
||||||
if val_ != nil {
|
if val_ != nil {
|
||||||
value = RightPadWord256(val_.([]byte))
|
value = LeftPadWord256(val_.([]byte))
|
||||||
}
|
}
|
||||||
cache.storages[Tuple256{addr, key}] = storageInfo{value, false}
|
cache.storages[Tuple256{addr, key}] = storageInfo{value, false}
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -395,7 +395,7 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
|
||||||
txCache = NewTxCache(blockCache)
|
txCache = NewTxCache(blockCache)
|
||||||
params = vm.Params{
|
params = vm.Params{
|
||||||
BlockHeight: uint64(_s.LastBlockHeight),
|
BlockHeight: uint64(_s.LastBlockHeight),
|
||||||
BlockHash: RightPadWord256(_s.LastBlockHash),
|
BlockHash: LeftPadWord256(_s.LastBlockHash),
|
||||||
BlockTime: _s.LastBlockTime.Unix(),
|
BlockTime: _s.LastBlockTime.Unix(),
|
||||||
GasLimit: 10000000,
|
GasLimit: 10000000,
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,7 +158,7 @@ func toVMAccount(acc *ac.Account) *vm.Account {
|
||||||
Balance: acc.Balance,
|
Balance: acc.Balance,
|
||||||
Code: acc.Code, // This is crazy.
|
Code: acc.Code, // This is crazy.
|
||||||
Nonce: uint64(acc.Sequence),
|
Nonce: uint64(acc.Sequence),
|
||||||
StorageRoot: RightPadWord256(acc.StorageRoot),
|
StorageRoot: LeftPadWord256(acc.StorageRoot),
|
||||||
Other: acc.PubKey,
|
Other: acc.PubKey,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,7 +39,7 @@ func ecrecoverFunc(input []byte, gas *uint64) (output []byte, err error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
hashed := sha3.Sha3(recovered[1:])
|
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) {
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
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) {
|
func identityFunc(input []byte, gas *uint64) (output []byte, err error) {
|
||||||
|
|
|
@ -51,7 +51,7 @@ func (st *Stack) PushBytes(bz []byte) {
|
||||||
if len(bz) != 32 {
|
if len(bz) != 32 {
|
||||||
panic("Invalid bytes size: expected 32")
|
panic("Invalid bytes size: expected 32")
|
||||||
}
|
}
|
||||||
st.Push(RightPadWord256(bz))
|
st.Push(LeftPadWord256(bz))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *Stack) Push64(i uint64) {
|
func (st *Stack) Push64(i uint64) {
|
||||||
|
@ -73,7 +73,8 @@ func (st *Stack) PopBytes() []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *Stack) Pop64() uint64 {
|
func (st *Stack) Pop64() uint64 {
|
||||||
return GetUint64(st.Pop().Bytes())
|
d := st.Pop()
|
||||||
|
return Uint64FromWord256(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *Stack) Len() int {
|
func (st *Stack) Len() int {
|
||||||
|
|
|
@ -90,5 +90,5 @@ func createAddress(creator *Account) Word256 {
|
||||||
temp := make([]byte, 32+8)
|
temp := make([]byte, 32+8)
|
||||||
copy(temp, creator.Address[:])
|
copy(temp, creator.Address[:])
|
||||||
PutUint64(temp[32:], nonce)
|
PutUint64(temp[32:], nonce)
|
||||||
return RightPadWord256(sha3.Sha3(temp)[:20])
|
return LeftPadWord256(sha3.Sha3(temp)[:20])
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,10 +64,10 @@ func TestSubcurrency(t *testing.T) {
|
||||||
st := newAppState()
|
st := newAppState()
|
||||||
// Create accounts
|
// Create accounts
|
||||||
account1 := &Account{
|
account1 := &Account{
|
||||||
Address: RightPadWord256(makeBytes(20)),
|
Address: LeftPadWord256(makeBytes(20)),
|
||||||
}
|
}
|
||||||
account2 := &Account{
|
account2 := &Account{
|
||||||
Address: RightPadWord256(makeBytes(20)),
|
Address: LeftPadWord256(makeBytes(20)),
|
||||||
}
|
}
|
||||||
st.accounts[account1.Address.String()] = account1
|
st.accounts[account1.Address.String()] = account1
|
||||||
st.accounts[account2.Address.String()] = account2
|
st.accounts[account2.Address.String()] = account2
|
||||||
|
|
346
vm/vm.go
346
vm/vm.go
|
@ -1,6 +1,7 @@
|
||||||
package vm
|
package vm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
@ -131,207 +132,252 @@ 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()
|
|
||||||
//stack.Push64(x + y)
|
|
||||||
x, y := stack.Pop(), stack.Pop()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
xb := new(big.Int).SetBytes(flip(x[:]))
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
yb := new(big.Int).SetBytes(flip(y[:]))
|
yb := new(big.Int).SetBytes(y[:])
|
||||||
sum := new(big.Int).Add(xb, yb)
|
sum := new(big.Int).Add(xb, yb)
|
||||||
stack.Push(RightPadWord256(flip(sum.Bytes())))
|
res := LeftPadWord256(U256(sum).Bytes())
|
||||||
dbg.Printf(" %v + %v = %v\n", xb, yb, sum)
|
stack.Push(res)
|
||||||
|
dbg.Printf(" %v + %v = %v (%X)\n", xb, yb, sum, res)
|
||||||
|
|
||||||
case MUL: // 0x02
|
case MUL: // 0x02
|
||||||
//x, y := stack.Pop64(), stack.Pop64()
|
|
||||||
//stack.Push64(x * y)
|
|
||||||
x, y := stack.Pop(), stack.Pop()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
xb := new(big.Int).SetBytes(flip(x[:]))
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
yb := new(big.Int).SetBytes(flip(y[:]))
|
yb := new(big.Int).SetBytes(y[:])
|
||||||
prod := new(big.Int).Mul(xb, yb)
|
prod := new(big.Int).Mul(xb, yb)
|
||||||
stack.Push(RightPadWord256(flip(rightMostBytes(prod.Bytes(), 32))))
|
res := LeftPadWord256(U256(prod).Bytes())
|
||||||
dbg.Printf(" %v * %v = %v\n", xb, yb, prod)
|
stack.Push(res)
|
||||||
|
dbg.Printf(" %v * %v = %v (%X)\n", xb, yb, prod, res)
|
||||||
|
|
||||||
case SUB: // 0x03
|
case SUB: // 0x03
|
||||||
//x, y := stack.Pop64(), stack.Pop64()
|
|
||||||
//stack.Push64(x - y)
|
|
||||||
x, y := stack.Pop(), stack.Pop()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
xb := new(big.Int).SetBytes(flip(x[:]))
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
yb := new(big.Int).SetBytes(flip(y[:]))
|
yb := new(big.Int).SetBytes(y[:])
|
||||||
diff := new(big.Int).Sub(xb, yb)
|
diff := new(big.Int).Sub(xb, yb)
|
||||||
stack.Push(RightPadWord256(flip(diff.Bytes())))
|
res := LeftPadWord256(U256(diff).Bytes())
|
||||||
dbg.Printf(" %v - %v = %v\n", xb, yb, diff)
|
stack.Push(res)
|
||||||
|
dbg.Printf(" %v - %v = %v (%X)\n", xb, yb, diff, res)
|
||||||
|
|
||||||
case DIV: // 0x04
|
case DIV: // 0x04
|
||||||
//x, y := stack.Pop64(), stack.Pop64()
|
|
||||||
//stack.Push64(x / y)
|
|
||||||
x, y := stack.Pop(), stack.Pop()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
if y.IsZero() { // TODO
|
if y.IsZero() {
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
dbg.Printf(" %x / %x = %v (TODO)\n", x, y, 0)
|
dbg.Printf(" %x / %x = %v\n", x, y, 0)
|
||||||
} else {
|
} else {
|
||||||
xb := new(big.Int).SetBytes(flip(x[:]))
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
yb := new(big.Int).SetBytes(flip(y[:]))
|
yb := new(big.Int).SetBytes(y[:])
|
||||||
div := new(big.Int).Div(xb, yb)
|
div := new(big.Int).Div(xb, yb)
|
||||||
stack.Push(RightPadWord256(flip(div.Bytes())))
|
res := LeftPadWord256(U256(div).Bytes())
|
||||||
dbg.Printf(" %v / %v = %v\n", xb, yb, div)
|
stack.Push(res)
|
||||||
|
dbg.Printf(" %v / %v = %v (%X)\n", xb, yb, div, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
case SDIV: // 0x05
|
case SDIV: // 0x05
|
||||||
// TODO ... big?
|
x, y := stack.Pop(), stack.Pop()
|
||||||
x, y := int64(stack.Pop64()), int64(stack.Pop64())
|
if y.IsZero() {
|
||||||
if y == 0 { // TODO
|
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
dbg.Printf(" %v / %v = %v (TODO)\n", x, y, 0)
|
dbg.Printf(" %x / %x = %v\n", x, y, 0)
|
||||||
} else {
|
} else {
|
||||||
stack.Push64(uint64(x / y))
|
xb := S256(new(big.Int).SetBytes(x[:]))
|
||||||
dbg.Printf(" %v / %v = %v\n", x, y, x/y)
|
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
|
case MOD: // 0x06
|
||||||
//x, y := stack.Pop64(), stack.Pop64()
|
|
||||||
x, y := stack.Pop(), stack.Pop()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
if y.IsZero() { // TODO
|
if y.IsZero() {
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
dbg.Printf(" %v %% %v = %v (TODO)\n", x, y, 0)
|
dbg.Printf(" %v %% %v = %v\n", x, y, 0)
|
||||||
} else {
|
} else {
|
||||||
xb := new(big.Int).SetBytes(flip(x[:]))
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
yb := new(big.Int).SetBytes(flip(y[:]))
|
yb := new(big.Int).SetBytes(y[:])
|
||||||
mod := new(big.Int).Mod(xb, yb)
|
mod := new(big.Int).Mod(xb, yb)
|
||||||
stack.Push(RightPadWord256(flip(mod.Bytes())))
|
res := LeftPadWord256(U256(mod).Bytes())
|
||||||
dbg.Printf(" %v %% %v = %v\n", xb, yb, mod)
|
stack.Push(res)
|
||||||
|
dbg.Printf(" %v %% %v = %v (%X)\n", xb, yb, mod, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
case SMOD: // 0x07
|
case SMOD: // 0x07
|
||||||
// TODO ... big?
|
x, y := stack.Pop(), stack.Pop()
|
||||||
x, y := int64(stack.Pop64()), int64(stack.Pop64())
|
if y.IsZero() {
|
||||||
if y == 0 { // TODO
|
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
dbg.Printf(" %v %% %v = %v (TODO)\n", x, y, 0)
|
dbg.Printf(" %v %% %v = %v\n", x, y, 0)
|
||||||
} else {
|
} else {
|
||||||
stack.Push64(uint64(x % y))
|
xb := S256(new(big.Int).SetBytes(x[:]))
|
||||||
dbg.Printf(" %v %% %v = %v\n", x, y, x%y)
|
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
|
case ADDMOD: // 0x08
|
||||||
// TODO ... big?
|
x, y, z := stack.Pop(), stack.Pop(), stack.Pop()
|
||||||
x, y, z := stack.Pop64(), stack.Pop64(), stack.Pop64()
|
if z.IsZero() {
|
||||||
if z == 0 { // TODO
|
|
||||||
stack.Push(Zero256)
|
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 {
|
} else {
|
||||||
stack.Push64((x + y) % z)
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
dbg.Printf(" (%v + %v) %% %v = %v\n", x, y, z, (x+y)%z)
|
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
|
case MULMOD: // 0x09
|
||||||
// TODO ... big?
|
x, y, z := stack.Pop(), stack.Pop(), stack.Pop()
|
||||||
x, y, z := stack.Pop64(), stack.Pop64(), stack.Pop64()
|
if z.IsZero() {
|
||||||
if z == 0 { // TODO
|
|
||||||
stack.Push(Zero256)
|
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 {
|
} else {
|
||||||
stack.Push64((x * y) % z)
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
dbg.Printf(" (%v + %v) %% %v = %v\n", x, y, z, (x*y)%z)
|
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
|
case EXP: // 0x0A
|
||||||
//x, y := stack.Pop64(), stack.Pop64()
|
|
||||||
//stack.Push64(ExpUint64(x, y))
|
|
||||||
x, y := stack.Pop(), stack.Pop()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
xb := new(big.Int).SetBytes(flip(x[:]))
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
yb := new(big.Int).SetBytes(flip(y[:]))
|
yb := new(big.Int).SetBytes(y[:])
|
||||||
pow := new(big.Int).Exp(xb, yb, big.NewInt(0))
|
pow := new(big.Int).Exp(xb, yb, big.NewInt(0))
|
||||||
stack.Push(RightPadWord256(flip(pow.Bytes())))
|
res := LeftPadWord256(U256(pow).Bytes())
|
||||||
dbg.Printf(" %v ** %v = %v\n", xb, yb, pow)
|
dbg.Printf(" %v ** %v = %v (%X)\n", xb, yb, pow, res)
|
||||||
|
|
||||||
case SIGNEXTEND: // 0x0B
|
case SIGNEXTEND: // 0x0B
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
back := stack.Pop()
|
||||||
res := (y << uint(x)) >> x
|
backb := new(big.Int).SetBytes(back[:])
|
||||||
stack.Push64(res)
|
if backb.Cmp(big.NewInt(31)) < 0 {
|
||||||
dbg.Printf(" (%v << %v) >> %v = %v\n", y, x, x, res)
|
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
|
case LT: // 0x10
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
if x < y {
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
|
yb := new(big.Int).SetBytes(y[:])
|
||||||
|
if xb.Cmp(yb) < 0 {
|
||||||
stack.Push64(1)
|
stack.Push64(1)
|
||||||
|
dbg.Printf(" %v < %v = %v\n", xb, yb, 1)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(Zero256)
|
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
|
case GT: // 0x11
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
if x > y {
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
|
yb := new(big.Int).SetBytes(y[:])
|
||||||
|
if xb.Cmp(yb) > 0 {
|
||||||
stack.Push64(1)
|
stack.Push64(1)
|
||||||
|
dbg.Printf(" %v > %v = %v\n", xb, yb, 1)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(Zero256)
|
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
|
case SLT: // 0x12
|
||||||
x, y := int64(stack.Pop64()), int64(stack.Pop64())
|
x, y := stack.Pop(), stack.Pop()
|
||||||
if x < y {
|
xb := S256(new(big.Int).SetBytes(x[:]))
|
||||||
|
yb := S256(new(big.Int).SetBytes(y[:]))
|
||||||
|
if xb.Cmp(yb) < 0 {
|
||||||
stack.Push64(1)
|
stack.Push64(1)
|
||||||
|
dbg.Printf(" %v < %v = %v\n", xb, yb, 1)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(Zero256)
|
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
|
case SGT: // 0x13
|
||||||
x, y := int64(stack.Pop64()), int64(stack.Pop64())
|
x, y := stack.Pop(), stack.Pop()
|
||||||
if x > y {
|
xb := S256(new(big.Int).SetBytes(x[:]))
|
||||||
|
yb := S256(new(big.Int).SetBytes(y[:]))
|
||||||
|
if xb.Cmp(yb) > 0 {
|
||||||
stack.Push64(1)
|
stack.Push64(1)
|
||||||
|
dbg.Printf(" %v > %v = %v\n", xb, yb, 1)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(Zero256)
|
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
|
case EQ: // 0x14
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
if x == y {
|
if bytes.Equal(x[:], y[:]) {
|
||||||
stack.Push64(1)
|
stack.Push64(1)
|
||||||
|
dbg.Printf(" %X == %X = %v\n", x, y, 1)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(Zero256)
|
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
|
case ISZERO: // 0x15
|
||||||
x := stack.Pop64()
|
x := stack.Pop()
|
||||||
if x == 0 {
|
if x.IsZero() {
|
||||||
stack.Push64(1)
|
stack.Push64(1)
|
||||||
|
dbg.Printf(" %v == 0 = %v\n", x, 1)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
|
dbg.Printf(" %v == 0 = %v\n", x, 0)
|
||||||
}
|
}
|
||||||
dbg.Printf(" %v == 0 = %v\n", x, x == 0)
|
|
||||||
|
|
||||||
case AND: // 0x16
|
case AND: // 0x16
|
||||||
//x, y := stack.Pop64(), stack.Pop64()
|
|
||||||
//stack.Push64(x & y)
|
|
||||||
x, y := stack.Pop(), stack.Pop()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
xb := new(big.Int).SetBytes(flip(x[:]))
|
z := [32]byte{}
|
||||||
yb := new(big.Int).SetBytes(flip(y[:]))
|
for i := 0; i < 32; i++ {
|
||||||
res := new(big.Int).And(xb, yb)
|
z[i] = x[i] & y[i]
|
||||||
stack.Push(RightPadWord256(flip(res.Bytes())))
|
}
|
||||||
dbg.Printf(" %v & %v = %v\n", xb, yb, res)
|
stack.Push(z)
|
||||||
|
dbg.Printf(" %X & %X = %X\n", x, y, z)
|
||||||
|
|
||||||
case OR: // 0x17
|
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()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
xb := new(big.Int).SetBytes(flip(x[:]))
|
z := [32]byte{}
|
||||||
yb := new(big.Int).SetBytes(flip(y[:]))
|
for i := 0; i < 32; i++ {
|
||||||
res := new(big.Int).Or(xb, yb)
|
z[i] = x[i] | y[i]
|
||||||
stack.Push(RightPadWord256(flip(res.Bytes())))
|
}
|
||||||
dbg.Printf(" %v & %v = %v\n", xb, yb, res)
|
stack.Push(z)
|
||||||
|
dbg.Printf(" %X | %X = %X\n", x, y, z)
|
||||||
|
|
||||||
case XOR: // 0x18
|
case XOR: // 0x18
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
stack.Push64(x ^ y)
|
z := [32]byte{}
|
||||||
dbg.Printf(" %v ^ %v = %v\n", x, y, x^y)
|
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
|
case NOT: // 0x19
|
||||||
x := stack.Pop64()
|
x := stack.Pop()
|
||||||
stack.Push64(^x)
|
z := [32]byte{}
|
||||||
dbg.Printf(" !%v = %v\n", x, ^x)
|
for i := 0; i < 32; i++ {
|
||||||
|
z[i] = ^x[i]
|
||||||
|
}
|
||||||
|
stack.Push(z)
|
||||||
|
dbg.Printf(" !%X = %X\n", x, z)
|
||||||
|
|
||||||
case BYTE: // 0x1A
|
case BYTE: // 0x1A
|
||||||
idx, val := stack.Pop64(), stack.Pop()
|
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)
|
return nil, firstErr(err, ErrInsufficientGas)
|
||||||
}
|
}
|
||||||
offset, size := stack.Pop64(), stack.Pop64()
|
offset, size := stack.Pop64(), stack.Pop64()
|
||||||
data, ok := subslice(memory, offset, size, false)
|
data, ok := subslice(memory, offset, size)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
data = sha3.Sha3(data)
|
data = sha3.Sha3(data)
|
||||||
stack.PushBytes(flip(data))
|
stack.PushBytes(data)
|
||||||
dbg.Printf(" => (%v) %X\n", size, data)
|
dbg.Printf(" => (%v) %X\n", size, data)
|
||||||
|
|
||||||
case ADDRESS: // 0x30
|
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 {
|
if ok = useGas(gas, GasGetAccount); !ok {
|
||||||
return nil, firstErr(err, ErrInsufficientGas)
|
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 {
|
if acc == nil {
|
||||||
return nil, firstErr(err, ErrUnknownAddress)
|
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
|
case CALLDATALOAD: // 0x35
|
||||||
offset := stack.Pop64()
|
offset := stack.Pop64()
|
||||||
data, ok := subslice(input, offset, 32, true)
|
data, ok := subslice(input, offset, 32)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrInputOutOfBounds)
|
return nil, firstErr(err, ErrInputOutOfBounds)
|
||||||
}
|
}
|
||||||
stack.Push(RightPadWord256(data))
|
res := LeftPadWord256(data)
|
||||||
dbg.Printf(" => 0x%X\n", RightPadWord256(data))
|
stack.Push(res)
|
||||||
|
dbg.Printf(" => 0x%X\n", res)
|
||||||
|
|
||||||
case CALLDATASIZE: // 0x36
|
case CALLDATASIZE: // 0x36
|
||||||
stack.Push64(uint64(len(input)))
|
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()
|
memOff := stack.Pop64()
|
||||||
inputOff := stack.Pop64()
|
inputOff := stack.Pop64()
|
||||||
length := stack.Pop64()
|
length := stack.Pop64()
|
||||||
data, ok := subslice(input, inputOff, length, false)
|
data, ok := subslice(input, inputOff, length)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrInputOutOfBounds)
|
return nil, firstErr(err, ErrInputOutOfBounds)
|
||||||
}
|
}
|
||||||
dest, ok := subslice(memory, memOff, length, false)
|
dest, ok := subslice(memory, memOff, length)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
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()
|
memOff := stack.Pop64()
|
||||||
codeOff := stack.Pop64()
|
codeOff := stack.Pop64()
|
||||||
length := stack.Pop64()
|
length := stack.Pop64()
|
||||||
data, ok := subslice(code, codeOff, length, false)
|
data, ok := subslice(code, codeOff, length)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrCodeOutOfBounds)
|
return nil, firstErr(err, ErrCodeOutOfBounds)
|
||||||
}
|
}
|
||||||
dest, ok := subslice(memory, memOff, length, false)
|
dest, ok := subslice(memory, memOff, length)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
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 {
|
if ok = useGas(gas, GasGetAccount); !ok {
|
||||||
return nil, firstErr(err, ErrInsufficientGas)
|
return nil, firstErr(err, ErrInsufficientGas)
|
||||||
}
|
}
|
||||||
acc := vm.appState.GetAccount(flipWord(addr))
|
acc := vm.appState.GetAccount(addr)
|
||||||
if acc == nil {
|
if acc == nil {
|
||||||
return nil, firstErr(err, ErrUnknownAddress)
|
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 {
|
if ok = useGas(gas, GasGetAccount); !ok {
|
||||||
return nil, firstErr(err, ErrInsufficientGas)
|
return nil, firstErr(err, ErrInsufficientGas)
|
||||||
}
|
}
|
||||||
acc := vm.appState.GetAccount(flipWord(addr))
|
acc := vm.appState.GetAccount(addr)
|
||||||
if acc == nil {
|
if acc == nil {
|
||||||
return nil, firstErr(err, ErrUnknownAddress)
|
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()
|
memOff := stack.Pop64()
|
||||||
codeOff := stack.Pop64()
|
codeOff := stack.Pop64()
|
||||||
length := stack.Pop64()
|
length := stack.Pop64()
|
||||||
data, ok := subslice(code, codeOff, length, false)
|
data, ok := subslice(code, codeOff, length)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrCodeOutOfBounds)
|
return nil, firstErr(err, ErrCodeOutOfBounds)
|
||||||
}
|
}
|
||||||
dest, ok := subslice(memory, memOff, length, false)
|
dest, ok := subslice(memory, memOff, length)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
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
|
case MLOAD: // 0x51
|
||||||
offset := stack.Pop64()
|
offset := stack.Pop64()
|
||||||
data, ok := subslice(memory, offset, 32, true)
|
data, ok := subslice(memory, offset, 32)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
stack.Push(RightPadWord256(data))
|
stack.Push(LeftPadWord256(data))
|
||||||
dbg.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, false)
|
dest, ok := subslice(memory, offset, 32)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
copy(dest, flip(data[:]))
|
copy(dest, data[:])
|
||||||
dbg.Printf(" => 0x%X\n", data)
|
dbg.Printf(" => 0x%X\n", data)
|
||||||
|
|
||||||
case MSTORE8: // 0x53
|
case MSTORE8: // 0x53
|
||||||
|
@ -543,8 +590,8 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case JUMPI: // 0x57
|
case JUMPI: // 0x57
|
||||||
pos, cond := stack.Pop64(), stack.Pop64()
|
pos, cond := stack.Pop64(), stack.Pop()
|
||||||
if cond >= 1 {
|
if !cond.IsZero() {
|
||||||
err = jump(code, pos, &pc)
|
err = jump(code, pos, &pc)
|
||||||
continue
|
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:
|
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)
|
||||||
codeSegment, ok := subslice(code, pc+1, a, true)
|
codeSegment, ok := subslice(code, pc+1, a)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrCodeOutOfBounds)
|
return nil, firstErr(err, ErrCodeOutOfBounds)
|
||||||
}
|
}
|
||||||
res := RightPadWord256(codeSegment)
|
res := LeftPadWord256(codeSegment)
|
||||||
stack.Push(res)
|
stack.Push(res)
|
||||||
pc += a
|
pc += a
|
||||||
dbg.Printf(" => 0x%X\n", res)
|
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++ {
|
for i := 0; i < n; i++ {
|
||||||
topics[i] = stack.Pop()
|
topics[i] = stack.Pop()
|
||||||
}
|
}
|
||||||
data, ok := subslice(memory, offset, size, false)
|
data, ok := subslice(memory, offset, size)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
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
|
case CREATE: // 0xF0
|
||||||
contractValue := stack.Pop64()
|
contractValue := stack.Pop64()
|
||||||
offset, size := stack.Pop64(), stack.Pop64()
|
offset, size := stack.Pop64(), stack.Pop64()
|
||||||
input, ok := subslice(memory, offset, size, false)
|
input, ok := subslice(memory, offset, size)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
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)
|
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)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
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 {
|
if ok = useGas(gas, GasGetAccount); !ok {
|
||||||
return nil, firstErr(err, ErrInsufficientGas)
|
return nil, firstErr(err, ErrInsufficientGas)
|
||||||
}
|
}
|
||||||
acc := vm.appState.GetAccount(flipWord(addr))
|
acc := vm.appState.GetAccount(addr)
|
||||||
if acc == nil {
|
if acc == nil {
|
||||||
return nil, firstErr(err, ErrUnknownAddress)
|
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)
|
stack.Push(Zero256)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(One256)
|
stack.Push(One256)
|
||||||
dest, ok := subslice(memory, retOffset, retSize, false)
|
dest, ok := subslice(memory, retOffset, retSize)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
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
|
case RETURN: // 0xF3
|
||||||
offset, size := stack.Pop64(), stack.Pop64()
|
offset, size := stack.Pop64(), stack.Pop64()
|
||||||
ret, ok := subslice(memory, offset, size, false)
|
ret, ok := subslice(memory, offset, size)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
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)
|
return nil, firstErr(err, ErrInsufficientGas)
|
||||||
}
|
}
|
||||||
// TODO if the receiver is , then make it the fee.
|
// TODO if the receiver is , then make it the fee.
|
||||||
receiver := vm.appState.GetAccount(flipWord(addr))
|
receiver := vm.appState.GetAccount(addr)
|
||||||
if receiver == nil {
|
if receiver == nil {
|
||||||
return nil, firstErr(err, ErrUnknownAddress)
|
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))
|
size := uint64(len(data))
|
||||||
if size < offset {
|
if size < offset {
|
||||||
return nil, false
|
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
|
ret, ok = data[offset:offset+length], true
|
||||||
}
|
}
|
||||||
|
|
||||||
if flip_ {
|
|
||||||
ret = flip(ret)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -794,27 +838,3 @@ func transfer(from, to *Account, amount uint64) error {
|
||||||
return nil
|
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
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue