Moved stack to its own file. Moved contract processing to block manager
This commit is contained in:
parent
a80a3eeb23
commit
83396cd836
207
block_manager.go
207
block_manager.go
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/ethereum/ethutil-go"
|
"github.com/ethereum/ethutil-go"
|
||||||
"log"
|
"log"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BlockChain struct {
|
type BlockChain struct {
|
||||||
@ -40,16 +41,17 @@ func (bc *BlockChain) GenesisBlock() *ethutil.Block {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type BlockManager struct {
|
type BlockManager struct {
|
||||||
// Ethereum virtual machine for processing contracts
|
|
||||||
vm *Vm
|
|
||||||
// The block chain :)
|
// The block chain :)
|
||||||
bc *BlockChain
|
bc *BlockChain
|
||||||
|
|
||||||
|
// Stack for processing contracts
|
||||||
|
stack *Stack
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBlockManager() *BlockManager {
|
func NewBlockManager() *BlockManager {
|
||||||
bm := &BlockManager{
|
bm := &BlockManager{
|
||||||
vm: NewVm(),
|
bc: NewBlockChain(),
|
||||||
bc: NewBlockChain(),
|
stack: NewStack(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return bm
|
return bm
|
||||||
@ -189,7 +191,7 @@ func (bm *BlockManager) ProcessContract(tx *ethutil.Transaction, block *ethutil.
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// Process contract
|
// Process contract
|
||||||
bm.vm.ProcContract(tx, block, func(opType OpType) bool {
|
bm.ProcContract(tx, block, func(opType OpType) bool {
|
||||||
// TODO turn on once big ints are in place
|
// TODO turn on once big ints are in place
|
||||||
//if !block.PayFee(tx.Hash(), StepFee.Uint64()) {
|
//if !block.PayFee(tx.Hash(), StepFee.Uint64()) {
|
||||||
// return false
|
// return false
|
||||||
@ -201,3 +203,198 @@ func (bm *BlockManager) ProcessContract(tx *ethutil.Transaction, block *ethutil.
|
|||||||
// Broadcast we're done
|
// Broadcast we're done
|
||||||
lockChan <- true
|
lockChan <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bm *BlockManager) ProcContract(tx *ethutil.Transaction,
|
||||||
|
block *ethutil.Block, cb TxCallback) {
|
||||||
|
// Instruction pointer
|
||||||
|
pc := 0
|
||||||
|
|
||||||
|
contract := block.GetContract(tx.Hash())
|
||||||
|
if contract == nil {
|
||||||
|
fmt.Println("Contract not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Pow256 := ethutil.BigPow(2, 256)
|
||||||
|
|
||||||
|
//fmt.Printf("# op arg\n")
|
||||||
|
out:
|
||||||
|
for {
|
||||||
|
// The base big int for all calculations. Use this for any results.
|
||||||
|
base := new(big.Int)
|
||||||
|
// XXX Should Instr return big int slice instead of string slice?
|
||||||
|
// Get the next instruction from the contract
|
||||||
|
//op, _, _ := Instr(contract.state.Get(string(Encode(uint32(pc)))))
|
||||||
|
nb := ethutil.NumberToBytes(uint64(pc), 32)
|
||||||
|
o, _, _ := ethutil.Instr(contract.State().Get(string(nb)))
|
||||||
|
op := OpCode(o)
|
||||||
|
|
||||||
|
if !cb(0) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if Debug {
|
||||||
|
//fmt.Printf("%-3d %-4s\n", pc, op.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
switch op {
|
||||||
|
case oADD:
|
||||||
|
x, y := bm.stack.Popn()
|
||||||
|
// (x + y) % 2 ** 256
|
||||||
|
base.Add(x, y)
|
||||||
|
base.Mod(base, Pow256)
|
||||||
|
// Pop result back on the stack
|
||||||
|
bm.stack.Push(base.String())
|
||||||
|
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())
|
||||||
|
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())
|
||||||
|
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())
|
||||||
|
case oSDIV:
|
||||||
|
x, y := bm.stack.Popn()
|
||||||
|
// n > 2**255
|
||||||
|
if x.Cmp(Pow256) > 0 {
|
||||||
|
x.Sub(Pow256, x)
|
||||||
|
}
|
||||||
|
if y.Cmp(Pow256) > 0 {
|
||||||
|
y.Sub(Pow256, y)
|
||||||
|
}
|
||||||
|
z := new(big.Int)
|
||||||
|
z.Div(x, y)
|
||||||
|
if z.Cmp(Pow256) > 0 {
|
||||||
|
z.Sub(Pow256, z)
|
||||||
|
}
|
||||||
|
// Push result on to the stack
|
||||||
|
bm.stack.Push(z.String())
|
||||||
|
case oMOD:
|
||||||
|
x, y := bm.stack.Popn()
|
||||||
|
base.Mod(x, y)
|
||||||
|
bm.stack.Push(base.String())
|
||||||
|
case oSMOD:
|
||||||
|
x, y := bm.stack.Popn()
|
||||||
|
// n > 2**255
|
||||||
|
if x.Cmp(Pow256) > 0 {
|
||||||
|
x.Sub(Pow256, x)
|
||||||
|
}
|
||||||
|
if y.Cmp(Pow256) > 0 {
|
||||||
|
y.Sub(Pow256, y)
|
||||||
|
}
|
||||||
|
z := new(big.Int)
|
||||||
|
z.Mod(x, y)
|
||||||
|
if z.Cmp(Pow256) > 0 {
|
||||||
|
z.Sub(Pow256, z)
|
||||||
|
}
|
||||||
|
// Push result on to the stack
|
||||||
|
bm.stack.Push(z.String())
|
||||||
|
case oEXP:
|
||||||
|
x, y := bm.stack.Popn()
|
||||||
|
base.Exp(x, y, Pow256)
|
||||||
|
|
||||||
|
bm.stack.Push(base.String())
|
||||||
|
case oNEG:
|
||||||
|
base.Sub(Pow256, ethutil.Big(bm.stack.Pop()))
|
||||||
|
bm.stack.Push(base.String())
|
||||||
|
case oLT:
|
||||||
|
x, y := bm.stack.Popn()
|
||||||
|
// x < y
|
||||||
|
if x.Cmp(y) < 0 {
|
||||||
|
bm.stack.Push("1")
|
||||||
|
} else {
|
||||||
|
bm.stack.Push("0")
|
||||||
|
}
|
||||||
|
case oLE:
|
||||||
|
x, y := bm.stack.Popn()
|
||||||
|
// x <= y
|
||||||
|
if x.Cmp(y) < 1 {
|
||||||
|
bm.stack.Push("1")
|
||||||
|
} else {
|
||||||
|
bm.stack.Push("0")
|
||||||
|
}
|
||||||
|
case oGT:
|
||||||
|
x, y := bm.stack.Popn()
|
||||||
|
// x > y
|
||||||
|
if x.Cmp(y) > 0 {
|
||||||
|
bm.stack.Push("1")
|
||||||
|
} else {
|
||||||
|
bm.stack.Push("0")
|
||||||
|
}
|
||||||
|
case oGE:
|
||||||
|
x, y := bm.stack.Popn()
|
||||||
|
// x >= y
|
||||||
|
if x.Cmp(y) > -1 {
|
||||||
|
bm.stack.Push("1")
|
||||||
|
} else {
|
||||||
|
bm.stack.Push("0")
|
||||||
|
}
|
||||||
|
case oNOT:
|
||||||
|
x, y := bm.stack.Popn()
|
||||||
|
// x != y
|
||||||
|
if x.Cmp(y) != 0 {
|
||||||
|
bm.stack.Push("1")
|
||||||
|
} else {
|
||||||
|
bm.stack.Push("0")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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()))
|
||||||
|
case oTXSENDER:
|
||||||
|
bm.stack.Push(string(tx.Sender()))
|
||||||
|
case oTXVALUE:
|
||||||
|
bm.stack.Push(tx.Value.String())
|
||||||
|
case oTXDATAN:
|
||||||
|
bm.stack.Push(big.NewInt(int64(len(tx.Data))).String())
|
||||||
|
case oTXDATA:
|
||||||
|
v := ethutil.Big(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())
|
||||||
|
} else {
|
||||||
|
bm.stack.Push(ethutil.Big(tx.Data[v.Uint64()]).String())
|
||||||
|
}
|
||||||
|
case oBLK_PREVHASH:
|
||||||
|
bm.stack.Push(string(block.PrevHash))
|
||||||
|
case oBLK_COINBASE:
|
||||||
|
bm.stack.Push(block.Coinbase)
|
||||||
|
case oBLK_TIMESTAMP:
|
||||||
|
bm.stack.Push(big.NewInt(block.Time).String())
|
||||||
|
case oBLK_NUMBER:
|
||||||
|
|
||||||
|
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))))
|
||||||
|
case oPOP:
|
||||||
|
// Pop current value of the stack
|
||||||
|
bm.stack.Pop()
|
||||||
|
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))))
|
||||||
|
case oSTOP:
|
||||||
|
break out
|
||||||
|
}
|
||||||
|
pc++
|
||||||
|
}
|
||||||
|
|
||||||
|
bm.stack.Print()
|
||||||
|
}
|
||||||
|
164
stack.go
Normal file
164
stack.go
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/ethereum/ethutil-go"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OpCode byte
|
||||||
|
|
||||||
|
// Op codes
|
||||||
|
const (
|
||||||
|
oSTOP OpCode = 0x00
|
||||||
|
oADD OpCode = 0x01
|
||||||
|
oMUL OpCode = 0x02
|
||||||
|
oSUB OpCode = 0x03
|
||||||
|
oDIV OpCode = 0x04
|
||||||
|
oSDIV OpCode = 0x05
|
||||||
|
oMOD OpCode = 0x06
|
||||||
|
oSMOD OpCode = 0x07
|
||||||
|
oEXP OpCode = 0x08
|
||||||
|
oNEG OpCode = 0x09
|
||||||
|
oLT OpCode = 0x0a
|
||||||
|
oLE OpCode = 0x0b
|
||||||
|
oGT OpCode = 0x0c
|
||||||
|
oGE OpCode = 0x0d
|
||||||
|
oEQ OpCode = 0x0e
|
||||||
|
oNOT OpCode = 0x0f
|
||||||
|
oMYADDRESS OpCode = 0x10
|
||||||
|
oTXSENDER OpCode = 0x11
|
||||||
|
oTXVALUE OpCode = 0x12
|
||||||
|
oTXFEE OpCode = 0x13
|
||||||
|
oTXDATAN OpCode = 0x14
|
||||||
|
oTXDATA OpCode = 0x15
|
||||||
|
oBLK_PREVHASH OpCode = 0x16
|
||||||
|
oBLK_COINBASE OpCode = 0x17
|
||||||
|
oBLK_TIMESTAMP OpCode = 0x18
|
||||||
|
oBLK_NUMBER OpCode = 0x19
|
||||||
|
oBLK_DIFFICULTY OpCode = 0x1a
|
||||||
|
oSHA256 OpCode = 0x20
|
||||||
|
oRIPEMD160 OpCode = 0x21
|
||||||
|
oECMUL OpCode = 0x22
|
||||||
|
oECADD OpCode = 0x23
|
||||||
|
oECSIGN OpCode = 0x24
|
||||||
|
oECRECOVER OpCode = 0x25
|
||||||
|
oECVALID OpCode = 0x26
|
||||||
|
oPUSH OpCode = 0x30
|
||||||
|
oPOP OpCode = 0x31
|
||||||
|
oDUP OpCode = 0x32
|
||||||
|
oDUPN OpCode = 0x33
|
||||||
|
oSWAP OpCode = 0x34
|
||||||
|
oSWAPN OpCode = 0x35
|
||||||
|
oLOAD OpCode = 0x36
|
||||||
|
oSTORE OpCode = 0x37
|
||||||
|
oJMP OpCode = 0x40
|
||||||
|
oJMPI OpCode = 0x41
|
||||||
|
oIND OpCode = 0x42
|
||||||
|
oEXTRO OpCode = 0x50
|
||||||
|
oBALANCE OpCode = 0x51
|
||||||
|
oMKTX OpCode = 0x60
|
||||||
|
oSUICIDE OpCode = 0xff
|
||||||
|
)
|
||||||
|
|
||||||
|
// Since the opcodes aren't all in order we can't use a regular slice
|
||||||
|
var opCodeToString = map[OpCode]string{
|
||||||
|
oSTOP: "STOP",
|
||||||
|
oADD: "ADD",
|
||||||
|
oMUL: "MUL",
|
||||||
|
oSUB: "SUB",
|
||||||
|
oDIV: "DIV",
|
||||||
|
oSDIV: "SDIV",
|
||||||
|
oMOD: "MOD",
|
||||||
|
oSMOD: "SMOD",
|
||||||
|
oEXP: "EXP",
|
||||||
|
oNEG: "NEG",
|
||||||
|
oLT: "LT",
|
||||||
|
oLE: "LE",
|
||||||
|
oGT: "GT",
|
||||||
|
oGE: "GE",
|
||||||
|
oEQ: "EQ",
|
||||||
|
oNOT: "NOT",
|
||||||
|
oMYADDRESS: "MYADDRESS",
|
||||||
|
oTXSENDER: "TXSENDER",
|
||||||
|
oTXVALUE: "TXVALUE",
|
||||||
|
oTXFEE: "TXFEE",
|
||||||
|
oTXDATAN: "TXDATAN",
|
||||||
|
oTXDATA: "TXDATA",
|
||||||
|
oBLK_PREVHASH: "BLK_PREVHASH",
|
||||||
|
oBLK_COINBASE: "BLK_COINBASE",
|
||||||
|
oBLK_TIMESTAMP: "BLK_TIMESTAMP",
|
||||||
|
oBLK_NUMBER: "BLK_NUMBER",
|
||||||
|
oBLK_DIFFICULTY: "BLK_DIFFIFULTY",
|
||||||
|
oSHA256: "SHA256",
|
||||||
|
oRIPEMD160: "RIPEMD160",
|
||||||
|
oECMUL: "ECMUL",
|
||||||
|
oECADD: "ECADD",
|
||||||
|
oECSIGN: "ECSIGN",
|
||||||
|
oECRECOVER: "ECRECOVER",
|
||||||
|
oECVALID: "ECVALID",
|
||||||
|
oPUSH: "PUSH",
|
||||||
|
oPOP: "POP",
|
||||||
|
oDUP: "DUP",
|
||||||
|
oDUPN: "DUPN",
|
||||||
|
oSWAP: "SWAP",
|
||||||
|
oSWAPN: "SWAPN",
|
||||||
|
oLOAD: "LOAD",
|
||||||
|
oSTORE: "STORE",
|
||||||
|
oJMP: "JMP",
|
||||||
|
oJMPI: "JMPI",
|
||||||
|
oIND: "IND",
|
||||||
|
oEXTRO: "EXTRO",
|
||||||
|
oBALANCE: "BALANCE",
|
||||||
|
oMKTX: "MKTX",
|
||||||
|
oSUICIDE: "SUICIDE",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o OpCode) String() string {
|
||||||
|
return opCodeToString[o]
|
||||||
|
}
|
||||||
|
|
||||||
|
type OpType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
tNorm = iota
|
||||||
|
tData
|
||||||
|
tExtro
|
||||||
|
tCrypto
|
||||||
|
)
|
||||||
|
|
||||||
|
type TxCallback func(opType OpType) bool
|
||||||
|
|
||||||
|
// Simple push/pop stack mechanism
|
||||||
|
type Stack struct {
|
||||||
|
data []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStack() *Stack {
|
||||||
|
return &Stack{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (st *Stack) Pop() string {
|
||||||
|
s := len(st.data)
|
||||||
|
|
||||||
|
str := st.data[s-1]
|
||||||
|
st.data = st.data[:s-1]
|
||||||
|
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
func (st *Stack) Popn() (*big.Int, *big.Int) {
|
||||||
|
s := len(st.data)
|
||||||
|
|
||||||
|
strs := st.data[s-2:]
|
||||||
|
st.data = st.data[:s-2]
|
||||||
|
|
||||||
|
return ethutil.Big(strs[0]), ethutil.Big(strs[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (st *Stack) Push(d string) {
|
||||||
|
st.data = append(st.data, d)
|
||||||
|
}
|
||||||
|
func (st *Stack) Print() {
|
||||||
|
fmt.Println(st.data)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user