mirror of https://github.com/status-im/op-geth.git
More opcodes
This commit is contained in:
parent
ee61cfcfa7
commit
489576b6f0
133
block_manager.go
133
block_manager.go
|
@ -9,6 +9,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BlockChain struct {
|
type BlockChain struct {
|
||||||
|
@ -52,14 +53,14 @@ type BlockManager struct {
|
||||||
// Stack for processing contracts
|
// Stack for processing contracts
|
||||||
stack *Stack
|
stack *Stack
|
||||||
// non-persistent key/value memory storage
|
// non-persistent key/value memory storage
|
||||||
mem map[string]string
|
mem map[string]*big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBlockManager() *BlockManager {
|
func NewBlockManager() *BlockManager {
|
||||||
bm := &BlockManager{
|
bm := &BlockManager{
|
||||||
bc: NewBlockChain(),
|
bc: NewBlockChain(),
|
||||||
stack: NewStack(),
|
stack: NewStack(),
|
||||||
mem: make(map[string]string),
|
mem: make(map[string]*big.Int),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the last known block number based on the blockchains last
|
// Set the last known block number based on the blockchains last
|
||||||
|
@ -276,27 +277,27 @@ out:
|
||||||
base.Add(x, y)
|
base.Add(x, y)
|
||||||
base.Mod(base, Pow256)
|
base.Mod(base, Pow256)
|
||||||
// Pop result back on the stack
|
// Pop result back on the stack
|
||||||
bm.stack.Push(base.String())
|
bm.stack.Push(base)
|
||||||
case oSUB:
|
case oSUB:
|
||||||
x, y := bm.stack.Popn()
|
x, y := bm.stack.Popn()
|
||||||
// (x - y) % 2 ** 256
|
// (x - y) % 2 ** 256
|
||||||
base.Sub(x, y)
|
base.Sub(x, y)
|
||||||
base.Mod(base, Pow256)
|
base.Mod(base, Pow256)
|
||||||
// Pop result back on the stack
|
// Pop result back on the stack
|
||||||
bm.stack.Push(base.String())
|
bm.stack.Push(base)
|
||||||
case oMUL:
|
case oMUL:
|
||||||
x, y := bm.stack.Popn()
|
x, y := bm.stack.Popn()
|
||||||
// (x * y) % 2 ** 256
|
// (x * y) % 2 ** 256
|
||||||
base.Mul(x, y)
|
base.Mul(x, y)
|
||||||
base.Mod(base, Pow256)
|
base.Mod(base, Pow256)
|
||||||
// Pop result back on the stack
|
// Pop result back on the stack
|
||||||
bm.stack.Push(base.String())
|
bm.stack.Push(base)
|
||||||
case oDIV:
|
case oDIV:
|
||||||
x, y := bm.stack.Popn()
|
x, y := bm.stack.Popn()
|
||||||
// floor(x / y)
|
// floor(x / y)
|
||||||
base.Div(x, y)
|
base.Div(x, y)
|
||||||
// Pop result back on the stack
|
// Pop result back on the stack
|
||||||
bm.stack.Push(base.String())
|
bm.stack.Push(base)
|
||||||
case oSDIV:
|
case oSDIV:
|
||||||
x, y := bm.stack.Popn()
|
x, y := bm.stack.Popn()
|
||||||
// n > 2**255
|
// n > 2**255
|
||||||
|
@ -312,11 +313,11 @@ out:
|
||||||
z.Sub(Pow256, z)
|
z.Sub(Pow256, z)
|
||||||
}
|
}
|
||||||
// Push result on to the stack
|
// Push result on to the stack
|
||||||
bm.stack.Push(z.String())
|
bm.stack.Push(z)
|
||||||
case oMOD:
|
case oMOD:
|
||||||
x, y := bm.stack.Popn()
|
x, y := bm.stack.Popn()
|
||||||
base.Mod(x, y)
|
base.Mod(x, y)
|
||||||
bm.stack.Push(base.String())
|
bm.stack.Push(base)
|
||||||
case oSMOD:
|
case oSMOD:
|
||||||
x, y := bm.stack.Popn()
|
x, y := bm.stack.Popn()
|
||||||
// n > 2**255
|
// n > 2**255
|
||||||
|
@ -332,87 +333,85 @@ out:
|
||||||
z.Sub(Pow256, z)
|
z.Sub(Pow256, z)
|
||||||
}
|
}
|
||||||
// Push result on to the stack
|
// Push result on to the stack
|
||||||
bm.stack.Push(z.String())
|
bm.stack.Push(z)
|
||||||
case oEXP:
|
case oEXP:
|
||||||
x, y := bm.stack.Popn()
|
x, y := bm.stack.Popn()
|
||||||
base.Exp(x, y, Pow256)
|
base.Exp(x, y, Pow256)
|
||||||
|
|
||||||
bm.stack.Push(base.String())
|
bm.stack.Push(base)
|
||||||
case oNEG:
|
case oNEG:
|
||||||
base.Sub(Pow256, ethutil.Big(bm.stack.Pop()))
|
base.Sub(Pow256, bm.stack.Pop())
|
||||||
bm.stack.Push(base.String())
|
bm.stack.Push(base)
|
||||||
case oLT:
|
case oLT:
|
||||||
x, y := bm.stack.Popn()
|
x, y := bm.stack.Popn()
|
||||||
// x < y
|
// x < y
|
||||||
if x.Cmp(y) < 0 {
|
if x.Cmp(y) < 0 {
|
||||||
bm.stack.Push("1")
|
bm.stack.Push(ethutil.BigTrue)
|
||||||
} else {
|
} else {
|
||||||
bm.stack.Push("0")
|
bm.stack.Push(ethutil.BigFalse)
|
||||||
}
|
}
|
||||||
case oLE:
|
case oLE:
|
||||||
x, y := bm.stack.Popn()
|
x, y := bm.stack.Popn()
|
||||||
// x <= y
|
// x <= y
|
||||||
if x.Cmp(y) < 1 {
|
if x.Cmp(y) < 1 {
|
||||||
bm.stack.Push("1")
|
bm.stack.Push(ethutil.BigTrue)
|
||||||
} else {
|
} else {
|
||||||
bm.stack.Push("0")
|
bm.stack.Push(ethutil.BigFalse)
|
||||||
}
|
}
|
||||||
case oGT:
|
case oGT:
|
||||||
x, y := bm.stack.Popn()
|
x, y := bm.stack.Popn()
|
||||||
// x > y
|
// x > y
|
||||||
if x.Cmp(y) > 0 {
|
if x.Cmp(y) > 0 {
|
||||||
bm.stack.Push("1")
|
bm.stack.Push(ethutil.BigTrue)
|
||||||
} else {
|
} else {
|
||||||
bm.stack.Push("0")
|
bm.stack.Push(ethutil.BigFalse)
|
||||||
}
|
}
|
||||||
case oGE:
|
case oGE:
|
||||||
x, y := bm.stack.Popn()
|
x, y := bm.stack.Popn()
|
||||||
// x >= y
|
// x >= y
|
||||||
if x.Cmp(y) > -1 {
|
if x.Cmp(y) > -1 {
|
||||||
bm.stack.Push("1")
|
bm.stack.Push(ethutil.BigTrue)
|
||||||
} else {
|
} else {
|
||||||
bm.stack.Push("0")
|
bm.stack.Push(ethutil.BigFalse)
|
||||||
}
|
}
|
||||||
case oNOT:
|
case oNOT:
|
||||||
x, y := bm.stack.Popn()
|
x, y := bm.stack.Popn()
|
||||||
// x != y
|
// x != y
|
||||||
if x.Cmp(y) != 0 {
|
if x.Cmp(y) != 0 {
|
||||||
bm.stack.Push("1")
|
bm.stack.Push(ethutil.BigTrue)
|
||||||
} else {
|
} else {
|
||||||
bm.stack.Push("0")
|
bm.stack.Push(ethutil.BigFalse)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Please note that the following code contains some
|
// Please note that the following code contains some
|
||||||
// ugly string casting. This will have to change to big
|
// ugly string casting. This will have to change to big
|
||||||
// ints. TODO :)
|
// ints. TODO :)
|
||||||
case oMYADDRESS:
|
case oMYADDRESS:
|
||||||
bm.stack.Push(string(tx.Hash()))
|
bm.stack.Push(ethutil.BigD(tx.Hash()))
|
||||||
case oTXSENDER:
|
case oTXSENDER:
|
||||||
bm.stack.Push(string(tx.Sender()))
|
bm.stack.Push(ethutil.BigD(tx.Sender()))
|
||||||
case oTXVALUE:
|
case oTXVALUE:
|
||||||
bm.stack.Push(tx.Value.String())
|
bm.stack.Push(tx.Value)
|
||||||
case oTXDATAN:
|
case oTXDATAN:
|
||||||
bm.stack.Push(big.NewInt(int64(len(tx.Data))).String())
|
bm.stack.Push(big.NewInt(int64(len(tx.Data))))
|
||||||
case oTXDATA:
|
case oTXDATA:
|
||||||
v := ethutil.Big(bm.stack.Pop())
|
v := bm.stack.Pop()
|
||||||
// v >= len(data)
|
// v >= len(data)
|
||||||
if v.Cmp(big.NewInt(int64(len(tx.Data)))) >= 0 {
|
if v.Cmp(big.NewInt(int64(len(tx.Data)))) >= 0 {
|
||||||
//I know this will change. It makes no
|
bm.stack.Push(ethutil.Big("0"))
|
||||||
//sense. Read comment above
|
|
||||||
bm.stack.Push(ethutil.Big("0").String())
|
|
||||||
} else {
|
} else {
|
||||||
bm.stack.Push(ethutil.Big(tx.Data[v.Uint64()]).String())
|
bm.stack.Push(ethutil.Big(tx.Data[v.Uint64()]))
|
||||||
}
|
}
|
||||||
case oBLK_PREVHASH:
|
case oBLK_PREVHASH:
|
||||||
bm.stack.Push(string(block.PrevHash))
|
bm.stack.Push(ethutil.Big(block.PrevHash))
|
||||||
case oBLK_COINBASE:
|
case oBLK_COINBASE:
|
||||||
bm.stack.Push(block.Coinbase)
|
bm.stack.Push(ethutil.Big(block.Coinbase))
|
||||||
case oBLK_TIMESTAMP:
|
case oBLK_TIMESTAMP:
|
||||||
bm.stack.Push(big.NewInt(block.Time).String())
|
bm.stack.Push(big.NewInt(block.Time))
|
||||||
case oBLK_NUMBER:
|
case oBLK_NUMBER:
|
||||||
bm.stack.Push(blockInfo.Number.String())
|
bm.stack.Push(blockInfo.Number)
|
||||||
case oBLK_DIFFICULTY:
|
case oBLK_DIFFICULTY:
|
||||||
bm.stack.Push(block.Difficulty.String())
|
bm.stack.Push(block.Difficulty)
|
||||||
case oBASEFEE:
|
case oBASEFEE:
|
||||||
// e = 10^21
|
// e = 10^21
|
||||||
e := big.NewInt(0).Exp(big.NewInt(10), big.NewInt(21), big.NewInt(0))
|
e := big.NewInt(0).Exp(big.NewInt(10), big.NewInt(21), big.NewInt(0))
|
||||||
|
@ -429,23 +428,23 @@ out:
|
||||||
x.Div(e, base)
|
x.Div(e, base)
|
||||||
|
|
||||||
// x = floor(10^21 / floor(diff^0.5))
|
// x = floor(10^21 / floor(diff^0.5))
|
||||||
bm.stack.Push(x.String())
|
bm.stack.Push(x)
|
||||||
case oSHA256, oRIPEMD160:
|
case oSHA256, oRIPEMD160:
|
||||||
// This is probably save
|
// This is probably save
|
||||||
// ceil(pop / 32)
|
// ceil(pop / 32)
|
||||||
length := int(math.Ceil(float64(ethutil.Big(bm.stack.Pop()).Uint64()) / 32.0))
|
length := int(math.Ceil(float64(bm.stack.Pop().Uint64()) / 32.0))
|
||||||
// New buffer which will contain the concatenated popped items
|
// New buffer which will contain the concatenated popped items
|
||||||
data := new(bytes.Buffer)
|
data := new(bytes.Buffer)
|
||||||
for i := 0; i < length; i++ {
|
for i := 0; i < length; i++ {
|
||||||
// Encode the number to bytes and have it 32bytes long
|
// Encode the number to bytes and have it 32bytes long
|
||||||
num := ethutil.NumberToBytes(ethutil.Big(bm.stack.Pop()).Bytes(), 256)
|
num := ethutil.NumberToBytes(bm.stack.Pop().Bytes(), 256)
|
||||||
data.WriteString(string(num))
|
data.WriteString(string(num))
|
||||||
}
|
}
|
||||||
|
|
||||||
if op == oSHA256 {
|
if op == oSHA256 {
|
||||||
bm.stack.Push(base.SetBytes(ethutil.Sha256Bin(data.Bytes())).String())
|
bm.stack.Push(base.SetBytes(ethutil.Sha256Bin(data.Bytes())))
|
||||||
} else {
|
} else {
|
||||||
bm.stack.Push(base.SetBytes(ethutil.Ripemd160(data.Bytes())).String())
|
bm.stack.Push(base.SetBytes(ethutil.Ripemd160(data.Bytes())))
|
||||||
}
|
}
|
||||||
case oECMUL:
|
case oECMUL:
|
||||||
y := bm.stack.Pop()
|
y := bm.stack.Pop()
|
||||||
|
@ -454,14 +453,14 @@ out:
|
||||||
|
|
||||||
//if ethutil.Big(x).Cmp(ethutil.Big(y)) {
|
//if ethutil.Big(x).Cmp(ethutil.Big(y)) {
|
||||||
data := new(bytes.Buffer)
|
data := new(bytes.Buffer)
|
||||||
data.WriteString(x)
|
data.WriteString(x.String())
|
||||||
data.WriteString(y)
|
data.WriteString(y.String())
|
||||||
if secp256k1.VerifyPubkeyValidity(data.Bytes()) == 1 {
|
if secp256k1.VerifyPubkeyValidity(data.Bytes()) == 1 {
|
||||||
// TODO
|
// TODO
|
||||||
} else {
|
} else {
|
||||||
// Invalid, push infinity
|
// Invalid, push infinity
|
||||||
bm.stack.Push("0")
|
bm.stack.Push(ethutil.Big("0"))
|
||||||
bm.stack.Push("0")
|
bm.stack.Push(ethutil.Big("0"))
|
||||||
}
|
}
|
||||||
//} else {
|
//} else {
|
||||||
// // Invalid, push infinity
|
// // Invalid, push infinity
|
||||||
|
@ -475,31 +474,59 @@ out:
|
||||||
case oECVALID:
|
case oECVALID:
|
||||||
case oSHA3:
|
case oSHA3:
|
||||||
case oPUSH:
|
case oPUSH:
|
||||||
// Get the next entry and pushes the value on the stack
|
|
||||||
pc++
|
pc++
|
||||||
bm.stack.Push(contract.State().Get(string(ethutil.NumberToBytes(uint64(pc), 32))))
|
bm.stack.Push(bm.mem[strconv.Itoa(pc)])
|
||||||
case oPOP:
|
case oPOP:
|
||||||
// Pop current value of the stack
|
// Pop current value of the stack
|
||||||
bm.stack.Pop()
|
bm.stack.Pop()
|
||||||
case oDUP:
|
case oDUP:
|
||||||
|
// Dup top stack
|
||||||
|
x := bm.stack.Pop()
|
||||||
|
bm.stack.Push(x)
|
||||||
|
bm.stack.Push(x)
|
||||||
case oSWAP:
|
case oSWAP:
|
||||||
|
// Swap two top most values
|
||||||
|
x, y := bm.stack.Popn()
|
||||||
|
bm.stack.Push(y)
|
||||||
|
bm.stack.Push(x)
|
||||||
case oMLOAD:
|
case oMLOAD:
|
||||||
|
x := bm.stack.Pop()
|
||||||
|
bm.stack.Push(bm.mem[x.String()])
|
||||||
case oMSTORE:
|
case oMSTORE:
|
||||||
|
x, y := bm.stack.Popn()
|
||||||
|
bm.mem[x.String()] = y
|
||||||
case oSLOAD:
|
case oSLOAD:
|
||||||
|
// Load the value in storage and push it on the stack
|
||||||
|
x := bm.stack.Pop()
|
||||||
|
// decode the object as a big integer
|
||||||
|
decoder := ethutil.NewRlpDecoder([]byte(contract.State().Get(x.String())))
|
||||||
|
if !decoder.IsNil() {
|
||||||
|
bm.stack.Push(decoder.AsBigInt())
|
||||||
|
} else {
|
||||||
|
bm.stack.Push(ethutil.BigFalse)
|
||||||
|
}
|
||||||
case oSSTORE:
|
case oSSTORE:
|
||||||
|
// Store Y at index X
|
||||||
|
x, y := bm.stack.Popn()
|
||||||
|
contract.State().Update(x.String(), string(ethutil.Encode(y)))
|
||||||
case oJMP:
|
case oJMP:
|
||||||
|
x := int(bm.stack.Pop().Uint64())
|
||||||
|
// Set pc to x - 1 (minus one so the incrementing at the end won't effect it)
|
||||||
|
pc = x
|
||||||
|
pc--
|
||||||
case oJMPI:
|
case oJMPI:
|
||||||
|
x := bm.stack.Pop()
|
||||||
|
// Set pc to x if it's non zero
|
||||||
|
if x.Cmp(ethutil.BigFalse) != 0 {
|
||||||
|
pc = int(x.Uint64())
|
||||||
|
pc--
|
||||||
|
}
|
||||||
case oIND:
|
case oIND:
|
||||||
|
bm.stack.Push(big.NewInt(int64(pc)))
|
||||||
case oEXTRO:
|
case oEXTRO:
|
||||||
case oBALANCE:
|
case oBALANCE:
|
||||||
case oMKTX:
|
case oMKTX:
|
||||||
case oSUICIDE:
|
case oSUICIDE:
|
||||||
/*
|
|
||||||
case oLOAD:
|
|
||||||
// Load instruction X on the stack
|
|
||||||
i, _ := strconv.Atoi(bm.stack.Pop())
|
|
||||||
bm.stack.Push(contract.State().Get(string(ethutil.NumberToBytes(uint64(i), 32))))
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
11
stack.go
11
stack.go
|
@ -2,7 +2,6 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/ethereum/ethutil-go"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -135,14 +134,14 @@ type TxCallback func(opType OpType) bool
|
||||||
|
|
||||||
// Simple push/pop stack mechanism
|
// Simple push/pop stack mechanism
|
||||||
type Stack struct {
|
type Stack struct {
|
||||||
data []string
|
data []*big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStack() *Stack {
|
func NewStack() *Stack {
|
||||||
return &Stack{}
|
return &Stack{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *Stack) Pop() string {
|
func (st *Stack) Pop() *big.Int {
|
||||||
s := len(st.data)
|
s := len(st.data)
|
||||||
|
|
||||||
str := st.data[s-1]
|
str := st.data[s-1]
|
||||||
|
@ -154,13 +153,13 @@ func (st *Stack) Pop() string {
|
||||||
func (st *Stack) Popn() (*big.Int, *big.Int) {
|
func (st *Stack) Popn() (*big.Int, *big.Int) {
|
||||||
s := len(st.data)
|
s := len(st.data)
|
||||||
|
|
||||||
strs := st.data[s-2:]
|
ints := st.data[s-2:]
|
||||||
st.data = st.data[:s-2]
|
st.data = st.data[:s-2]
|
||||||
|
|
||||||
return ethutil.Big(strs[0]), ethutil.Big(strs[1])
|
return ints[0], ints[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *Stack) Push(d string) {
|
func (st *Stack) Push(d *big.Int) {
|
||||||
st.data = append(st.data, d)
|
st.data = append(st.data, d)
|
||||||
}
|
}
|
||||||
func (st *Stack) Print() {
|
func (st *Stack) Print() {
|
||||||
|
|
Loading…
Reference in New Issue