Merge branch 'unflip' into develop
This commit is contained in:
commit
e007d1a58d
|
@ -22,10 +22,18 @@ func (p Uint64Slice) Search(x uint64) int { return SearchUint64s(p, x) }
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
func PutUint64(dest []byte, i uint64) {
|
||||
func PutUint64LE(dest []byte, i uint64) {
|
||||
binary.LittleEndian.PutUint64(dest, i)
|
||||
}
|
||||
|
||||
func GetUint64(src []byte) uint64 {
|
||||
func GetUint64LE(src []byte) uint64 {
|
||||
return binary.LittleEndian.Uint64(src)
|
||||
}
|
||||
|
||||
func PutUint64BE(dest []byte, i uint64) {
|
||||
binary.BigEndian.PutUint64(dest, i)
|
||||
}
|
||||
|
||||
func GetUint64BE(src []byte) uint64 {
|
||||
return binary.BigEndian.Uint64(src)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package common
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"sort"
|
||||
)
|
||||
|
||||
|
@ -30,9 +29,9 @@ func (w Word256) Compare(other Word256) int {
|
|||
}
|
||||
|
||||
func Uint64ToWord256(i uint64) Word256 {
|
||||
word := Word256{}
|
||||
PutUint64(word[:], i)
|
||||
return word
|
||||
buf := [8]byte{}
|
||||
PutUint64BE(buf[:], i)
|
||||
return LeftPadWord256(buf[:])
|
||||
}
|
||||
|
||||
func RightPadWord256(bz []byte) (word Word256) {
|
||||
|
@ -46,7 +45,8 @@ func LeftPadWord256(bz []byte) (word Word256) {
|
|||
}
|
||||
|
||||
func Uint64FromWord256(word Word256) uint64 {
|
||||
return binary.LittleEndian.Uint64(word[:])
|
||||
buf := word.Postfix(8)
|
||||
return GetUint64BE(buf)
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
|
|
@ -235,9 +235,9 @@ func (ndb *nodeDB) SaveNode(t *IAVLTree, node *IAVLNode) {
|
|||
if node.persisted {
|
||||
panic("Shouldn't be calling save on an already persisted node.")
|
||||
}
|
||||
if _, ok := ndb.cache[string(node.hash)]; ok {
|
||||
/*if _, ok := ndb.cache[string(node.hash)]; ok {
|
||||
panic("Shouldn't be calling save on an already cached node.")
|
||||
}
|
||||
}*/
|
||||
// Save node bytes to db
|
||||
buf := bytes.NewBuffer(nil)
|
||||
_, _, err := node.writeToCountHashes(t, buf)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -12,11 +12,11 @@ import (
|
|||
|
||||
func toVMAccount(acc *account.Account) *vm.Account {
|
||||
return &vm.Account{
|
||||
Address: RightPadWord256(acc.Address),
|
||||
Address: LeftPadWord256(acc.Address),
|
||||
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,9 +26,8 @@ func toVMAccount(acc *account.Account) *vm.Account {
|
|||
// Run a contract's code on an isolated and unpersisted state
|
||||
// Cannot be used to create new contracts
|
||||
func Call(address, data []byte) (*ctypes.ResponseCall, error) {
|
||||
|
||||
st := consensusState.GetState() // performs a copy
|
||||
cache := mempoolReactor.Mempool.GetCache()
|
||||
cache := state.NewBlockCache(st)
|
||||
outAcc := cache.GetAccount(address)
|
||||
if outAcc == nil {
|
||||
return nil, fmt.Errorf("Account %x does not exist", address)
|
||||
|
@ -38,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,
|
||||
}
|
||||
|
@ -63,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,
|
||||
}
|
||||
|
|
|
@ -225,6 +225,7 @@ type WSConnection struct {
|
|||
id string
|
||||
wsConn *websocket.Conn
|
||||
writeChan chan WSResponse
|
||||
quitChan chan struct{}
|
||||
failedSends uint
|
||||
started uint32
|
||||
stopped uint32
|
||||
|
@ -238,6 +239,7 @@ func NewWSConnection(wsConn *websocket.Conn) *WSConnection {
|
|||
id: wsConn.RemoteAddr().String(),
|
||||
wsConn: wsConn,
|
||||
writeChan: make(chan WSResponse, WriteChanBufferSize), // buffered. we keep track when its full
|
||||
quitChan: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,8 +258,10 @@ func (con *WSConnection) Start(evsw *events.EventSwitch) {
|
|||
// close the connection
|
||||
func (con *WSConnection) Stop() {
|
||||
if atomic.CompareAndSwapUint32(&con.stopped, 0, 1) {
|
||||
con.wsConn.Close()
|
||||
close(con.writeChan)
|
||||
close(con.quitChan)
|
||||
// the write loop closes the websocket connection
|
||||
// when it exits its loop, and the read loop
|
||||
// closes the writeChan
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,6 +281,7 @@ func (con *WSConnection) safeWrite(resp WSResponse) {
|
|||
|
||||
// read from the socket and subscribe to or unsubscribe from events
|
||||
func (con *WSConnection) read() {
|
||||
defer close(con.writeChan)
|
||||
reaper := time.Tick(time.Second * WSConnectionReaperSeconds)
|
||||
for {
|
||||
select {
|
||||
|
@ -322,26 +327,21 @@ func (con *WSConnection) read() {
|
|||
default:
|
||||
con.safeWrite(WSResponse{Error: "Unknown request type: " + req.Type})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// receives on a write channel and writes out on the socket
|
||||
func (con *WSConnection) write() {
|
||||
defer con.wsConn.Close()
|
||||
n, err := new(int64), new(error)
|
||||
for {
|
||||
msg, more := <-con.writeChan
|
||||
if !more {
|
||||
// the channel was closed, so ensure
|
||||
// connection is stopped and return
|
||||
con.Stop()
|
||||
return
|
||||
}
|
||||
select {
|
||||
case msg := <-con.writeChan:
|
||||
buf := new(bytes.Buffer)
|
||||
binary.WriteJSON(msg, buf, n, err)
|
||||
if *err != nil {
|
||||
log.Error("Failed to write JSON WSResponse", "error", err)
|
||||
log.Error("Failed to marshal WSResponse to JSON", "error", err)
|
||||
} else {
|
||||
if err := con.wsConn.WriteMessage(websocket.TextMessage, buf.Bytes()); err != nil {
|
||||
log.Error("Failed to write response on websocket", "error", err)
|
||||
|
@ -349,6 +349,9 @@ func (con *WSConnection) write() {
|
|||
return
|
||||
}
|
||||
}
|
||||
case <-con.quitChan:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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}...)
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ func (cache *TxCache) AddLog(log *vm.Log) {
|
|||
func NewContractAddress(caller []byte, nonce uint64) []byte {
|
||||
temp := make([]byte, 32+8)
|
||||
copy(temp, caller)
|
||||
PutUint64(temp[32:], nonce)
|
||||
PutUint64LE(temp[32:], nonce)
|
||||
return sha3.Sha3(temp)[:20]
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
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) {
|
||||
|
|
13
vm/stack.go
13
vm/stack.go
|
@ -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 {
|
||||
|
@ -105,11 +106,13 @@ func (st *Stack) Peek() Word256 {
|
|||
return st.data[st.ptr-1]
|
||||
}
|
||||
|
||||
func (st *Stack) Print() {
|
||||
func (st *Stack) Print(n int) {
|
||||
fmt.Println("### stack ###")
|
||||
if st.ptr > 0 {
|
||||
for i, val := range st.data {
|
||||
fmt.Printf("%-3d %v\n", i, val)
|
||||
nn := MinInt(n, st.ptr)
|
||||
for j, i := 0, st.ptr-1; i > st.ptr-1-nn; i-- {
|
||||
fmt.Printf("%-3d %X\n", j, st.data[i])
|
||||
j += 1
|
||||
}
|
||||
} else {
|
||||
fmt.Println("-- empty --")
|
||||
|
|
|
@ -89,6 +89,6 @@ func createAddress(creator *Account) Word256 {
|
|||
creator.Nonce += 1
|
||||
temp := make([]byte, 32+8)
|
||||
copy(temp, creator.Address[:])
|
||||
PutUint64(temp[32:], nonce)
|
||||
return RightPadWord256(sha3.Sha3(temp)[:20])
|
||||
PutUint64LE(temp[32:], nonce)
|
||||
return LeftPadWord256(sha3.Sha3(temp)[:20])
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
350
vm/vm.go
350
vm/vm.go
|
@ -1,6 +1,7 @@
|
|||
package vm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
@ -131,196 +132,253 @@ 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(prod.Bytes())))
|
||||
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())
|
||||
stack.Push(res)
|
||||
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)
|
||||
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 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()
|
||||
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()
|
||||
|
@ -336,12 +394,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
|
||||
|
@ -353,7 +411,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)
|
||||
}
|
||||
|
@ -375,12 +433,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)))
|
||||
|
@ -390,11 +449,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)
|
||||
}
|
||||
|
@ -410,11 +469,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)
|
||||
}
|
||||
|
@ -430,7 +489,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)
|
||||
}
|
||||
|
@ -444,7 +503,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)
|
||||
}
|
||||
|
@ -452,11 +511,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)
|
||||
}
|
||||
|
@ -491,20 +550,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
|
||||
|
@ -532,8 +591,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
|
||||
}
|
||||
|
@ -555,14 +614,15 @@ 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)
|
||||
stack.Print(10)
|
||||
|
||||
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
|
||||
n := int(op - DUP1 + 1)
|
||||
|
@ -572,7 +632,8 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
|||
case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
|
||||
n := int(op - SWAP1 + 2)
|
||||
stack.Swap(n)
|
||||
dbg.Printf(" => [%d]\n", n)
|
||||
dbg.Printf(" => [%d] %X\n", n, stack.Peek())
|
||||
stack.Print(10)
|
||||
|
||||
case LOG0, LOG1, LOG2, LOG3, LOG4:
|
||||
n := int(op - LOG0)
|
||||
|
@ -581,7 +642,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)
|
||||
}
|
||||
|
@ -597,7 +658,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)
|
||||
}
|
||||
|
@ -627,7 +688,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)
|
||||
}
|
||||
|
@ -651,7 +712,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)
|
||||
}
|
||||
|
@ -667,7 +728,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)
|
||||
}
|
||||
|
@ -681,7 +742,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)
|
||||
}
|
||||
|
@ -694,7 +755,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)
|
||||
}
|
||||
|
@ -715,7 +776,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
|
||||
|
@ -726,12 +787,15 @@ 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
|
||||
}
|
||||
|
||||
func rightMostBytes(data []byte, n int) []byte {
|
||||
size := MinInt(len(data), n)
|
||||
offset := len(data) - size
|
||||
return data[offset:]
|
||||
}
|
||||
|
||||
func codeGetOp(code []byte, n uint64) OpCode {
|
||||
if uint64(len(code)) <= n {
|
||||
return OpCode(0) // stop
|
||||
|
@ -777,27 +841,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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue