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