diff options
Diffstat (limited to 'vm.go')
-rw-r--r-- | vm.go | 451 |
1 files changed, 234 insertions, 217 deletions
@@ -1,267 +1,284 @@ package main import ( - "math/big" - "fmt" - "strconv" - "github.com/ethereum/ethutil-go" + "fmt" + "github.com/ethereum/ethutil-go" + "math/big" + "strconv" ) // Op codes const ( - oSTOP int = 0x00 - oADD int = 0x01 - oMUL int = 0x02 - oSUB int = 0x03 - oDIV int = 0x04 - oSDIV int = 0x05 - oMOD int = 0x06 - oSMOD int = 0x07 - oEXP int = 0x08 - oNEG int = 0x09 - oLT int = 0x0a - oLE int = 0x0b - oGT int = 0x0c - oGE int = 0x0d - oEQ int = 0x0e - oNOT int = 0x0f - oMYADDRESS int = 0x10 - oTXSENDER int = 0x11 - oTXVALUE int = 0x12 - oTXFEE int = 0x13 - oTXDATAN int = 0x14 - oTXDATA int = 0x15 - oBLK_PREVHASH int = 0x16 - oBLK_COINBASE int = 0x17 - oBLK_TIMESTAMP int = 0x18 - oBLK_NUMBER int = 0x19 - oBLK_DIFFICULTY int = 0x1a - oSHA256 int = 0x20 - oRIPEMD160 int = 0x21 - oECMUL int = 0x22 - oECADD int = 0x23 - oECSIGN int = 0x24 - oECRECOVER int = 0x25 - oECVALID int = 0x26 - oPUSH int = 0x30 - oPOP int = 0x31 - oDUP int = 0x32 - oDUPN int = 0x33 - oSWAP int = 0x34 - oSWAPN int = 0x35 - oLOAD int = 0x36 - oSTORE int = 0x37 - oJMP int = 0x40 - oJMPI int = 0x41 - oIND int = 0x42 - oEXTRO int = 0x50 - oBALANCE int = 0x51 - oMKTX int = 0x60 - oSUICIDE int = 0xff + oSTOP int = 0x00 + oADD int = 0x01 + oMUL int = 0x02 + oSUB int = 0x03 + oDIV int = 0x04 + oSDIV int = 0x05 + oMOD int = 0x06 + oSMOD int = 0x07 + oEXP int = 0x08 + oNEG int = 0x09 + oLT int = 0x0a + oLE int = 0x0b + oGT int = 0x0c + oGE int = 0x0d + oEQ int = 0x0e + oNOT int = 0x0f + oMYADDRESS int = 0x10 + oTXSENDER int = 0x11 + oTXVALUE int = 0x12 + oTXFEE int = 0x13 + oTXDATAN int = 0x14 + oTXDATA int = 0x15 + oBLK_PREVHASH int = 0x16 + oBLK_COINBASE int = 0x17 + oBLK_TIMESTAMP int = 0x18 + oBLK_NUMBER int = 0x19 + oBLK_DIFFICULTY int = 0x1a + oSHA256 int = 0x20 + oRIPEMD160 int = 0x21 + oECMUL int = 0x22 + oECADD int = 0x23 + oECSIGN int = 0x24 + oECRECOVER int = 0x25 + oECVALID int = 0x26 + oPUSH int = 0x30 + oPOP int = 0x31 + oDUP int = 0x32 + oDUPN int = 0x33 + oSWAP int = 0x34 + oSWAPN int = 0x35 + oLOAD int = 0x36 + oSTORE int = 0x37 + oJMP int = 0x40 + oJMPI int = 0x41 + oIND int = 0x42 + oEXTRO int = 0x50 + oBALANCE int = 0x51 + oMKTX int = 0x60 + oSUICIDE int = 0xff ) type OpType int + const ( - tNorm = iota - tData - tExtro - tCrypto + tNorm = iota + tData + tExtro + tCrypto ) + type TxCallback func(opType OpType) bool // Simple push/pop stack mechanism type Stack struct { - data []string + data []string } + func NewStack() *Stack { - return &Stack{} + return &Stack{} } func (st *Stack) Pop() string { - s := len(st.data) + s := len(st.data) - str := st.data[s-1] - st.data = st.data[:s-1] + str := st.data[s-1] + st.data = st.data[:s-1] - return str + return str } func (st *Stack) Popn() (*big.Int, *big.Int) { - s := len(st.data) + s := len(st.data) - strs := st.data[s-2:] - st.data = st.data[:s-2] + strs := st.data[s-2:] + st.data = st.data[:s-2] - return ethutil.Big(strs[0]), ethutil.Big(strs[1]) + return ethutil.Big(strs[0]), ethutil.Big(strs[1]) } func (st *Stack) Push(d string) { - st.data = append(st.data, d) + st.data = append(st.data, d) } func (st *Stack) Print() { - fmt.Println(st.data) + fmt.Println(st.data) } type Vm struct { - // Stack - stack *Stack + // Stack + stack *Stack } func NewVm() *Vm { - return &Vm{ - stack: NewStack(), - } + return &Vm{ + stack: NewStack(), + } } -func (vm *Vm) ProcContract( tx *ethutil.Transaction, - block *ethutil.Block, cb TxCallback) { - // Instruction pointer - pc := 0 +func (vm *Vm) 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 - } + contract := block.GetContract(tx.Hash()) + if contract == nil { + fmt.Println("Contract not found") + return + } - Pow256 := ethutil.BigPow(2, 256) + Pow256 := ethutil.BigPow(2, 256) - //fmt.Printf("# op arg\n") + //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) - op, _, _ := ethutil.Instr(contract.State().Get(string(nb))) + 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) + op, _, _ := ethutil.Instr(contract.State().Get(string(nb))) - if !cb(0) { break } + if !cb(0) { + break + } - if Debug { - //fmt.Printf("%-3d %-4d\n", pc, op) - } + if Debug { + //fmt.Printf("%-3d %-4d\n", pc, op) + } - switch op { - case oADD: - x, y := vm.stack.Popn() - // (x + y) % 2 ** 256 - base.Add(x, y) - base.Mod(base, Pow256) - // Pop result back on the stack - vm.stack.Push(base.String()) - case oSUB: - x, y := vm.stack.Popn() - // (x - y) % 2 ** 256 - base.Sub(x, y) - base.Mod(base, Pow256) - // Pop result back on the stack - vm.stack.Push(base.String()) - case oMUL: - x, y := vm.stack.Popn() - // (x * y) % 2 ** 256 - base.Mul(x, y) - base.Mod(base, Pow256) - // Pop result back on the stack - vm.stack.Push(base.String()) - case oDIV: - x, y := vm.stack.Popn() - // floor(x / y) - base.Div(x, y) - // Pop result back on the stack - vm.stack.Push(base.String()) - case oSDIV: - x, y := vm.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 - vm.stack.Push(z.String()) - case oMOD: - x, y := vm.stack.Popn() - base.Mod(x, y) - vm.stack.Push(base.String()) - case oSMOD: - x, y := vm.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 - vm.stack.Push(z.String()) - case oEXP: - x, y := vm.stack.Popn() - base.Exp(x, y, Pow256) + switch op { + case oADD: + x, y := vm.stack.Popn() + // (x + y) % 2 ** 256 + base.Add(x, y) + base.Mod(base, Pow256) + // Pop result back on the stack + vm.stack.Push(base.String()) + case oSUB: + x, y := vm.stack.Popn() + // (x - y) % 2 ** 256 + base.Sub(x, y) + base.Mod(base, Pow256) + // Pop result back on the stack + vm.stack.Push(base.String()) + case oMUL: + x, y := vm.stack.Popn() + // (x * y) % 2 ** 256 + base.Mul(x, y) + base.Mod(base, Pow256) + // Pop result back on the stack + vm.stack.Push(base.String()) + case oDIV: + x, y := vm.stack.Popn() + // floor(x / y) + base.Div(x, y) + // Pop result back on the stack + vm.stack.Push(base.String()) + case oSDIV: + x, y := vm.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 + vm.stack.Push(z.String()) + case oMOD: + x, y := vm.stack.Popn() + base.Mod(x, y) + vm.stack.Push(base.String()) + case oSMOD: + x, y := vm.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 + vm.stack.Push(z.String()) + case oEXP: + x, y := vm.stack.Popn() + base.Exp(x, y, Pow256) - vm.stack.Push(base.String()) - case oNEG: - base.Sub(Pow256, ethutil.Big(vm.stack.Pop())) - vm.stack.Push(base.String()) - case oLT: - x, y := vm.stack.Popn() - // x < y - if x.Cmp(y) < 0 { - vm.stack.Push("1") - } else { - vm.stack.Push("0") - } - case oLE: - x, y := vm.stack.Popn() - // x <= y - if x.Cmp(y) < 1 { - vm.stack.Push("1") - } else { - vm.stack.Push("0") - } - case oGT: - x, y := vm.stack.Popn() - // x > y - if x.Cmp(y) > 0 { - vm.stack.Push("1") - } else { - vm.stack.Push("0") - } - case oGE: - x, y := vm.stack.Popn() - // x >= y - if x.Cmp(y) > -1 { - vm.stack.Push("1") - } else { - vm.stack.Push("0") - } - case oNOT: - x, y := vm.stack.Popn() - // x != y - if x.Cmp(y) != 0 { - vm.stack.Push("1") - } else { - vm.stack.Push("0") - } - case oMYADDRESS: - vm.stack.Push(string(tx.Hash())) - case oTXSENDER: - vm.stack.Push(string(tx.Sender())) - case oPUSH: - // Get the next entry and pushes the value on the stack - pc++ - vm.stack.Push(contract.State().Get(string(ethutil.NumberToBytes(uint64(pc), 32)))) - case oPOP: - // Pop current value of the stack - vm.stack.Pop() - case oLOAD: - // Load instruction X on the stack - i, _ := strconv.Atoi(vm.stack.Pop()) - vm.stack.Push(contract.State().Get(string(ethutil.NumberToBytes(uint64(i), 32)))) - case oSTOP: - break out - } - pc++ - } + vm.stack.Push(base.String()) + case oNEG: + base.Sub(Pow256, ethutil.Big(vm.stack.Pop())) + vm.stack.Push(base.String()) + case oLT: + x, y := vm.stack.Popn() + // x < y + if x.Cmp(y) < 0 { + vm.stack.Push("1") + } else { + vm.stack.Push("0") + } + case oLE: + x, y := vm.stack.Popn() + // x <= y + if x.Cmp(y) < 1 { + vm.stack.Push("1") + } else { + vm.stack.Push("0") + } + case oGT: + x, y := vm.stack.Popn() + // x > y + if x.Cmp(y) > 0 { + vm.stack.Push("1") + } else { + vm.stack.Push("0") + } + case oGE: + x, y := vm.stack.Popn() + // x >= y + if x.Cmp(y) > -1 { + vm.stack.Push("1") + } else { + vm.stack.Push("0") + } + case oNOT: + x, y := vm.stack.Popn() + // x != y + if x.Cmp(y) != 0 { + vm.stack.Push("1") + } else { + vm.stack.Push("0") + } + case oMYADDRESS: + vm.stack.Push(string(tx.Hash())) + case oTXSENDER: + vm.stack.Push(string(tx.Sender())) + case oPUSH: + // Get the next entry and pushes the value on the stack + pc++ + vm.stack.Push(contract.State().Get(string(ethutil.NumberToBytes(uint64(pc), 32)))) + case oPOP: + // Pop current value of the stack + vm.stack.Pop() + case oLOAD: + // Load instruction X on the stack + i, _ := strconv.Atoi(vm.stack.Pop()) + vm.stack.Push(contract.State().Get(string(ethutil.NumberToBytes(uint64(i), 32)))) + case oSTOP: + break out + } + pc++ + } - vm.stack.Print() + vm.stack.Print() } |