good morning!!!!

Skip to content
Snippets Groups Projects
Commit 489576b6 authored by Jeffrey Wilcke's avatar Jeffrey Wilcke
Browse files

More opcodes

parent ee61cfcf
No related branches found
No related tags found
No related merge requests found
......@@ -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++
}
......
......@@ -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() {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment