aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ethchain/stack.go303
-rw-r--r--ethchain/state_manager.go3
-rw-r--r--ethchain/vm.go41
-rw-r--r--ethutil/parsing.go119
4 files changed, 219 insertions, 247 deletions
diff --git a/ethchain/stack.go b/ethchain/stack.go
index bfb19614e..429c31d08 100644
--- a/ethchain/stack.go
+++ b/ethchain/stack.go
@@ -2,7 +2,7 @@ package ethchain
import (
"fmt"
- "github.com/ethereum/eth-go/ethutil"
+ _ "github.com/ethereum/eth-go/ethutil"
"math/big"
)
@@ -10,116 +10,136 @@ type OpCode int
// Op codes
const (
- oSTOP = 0x00
- oADD = 0x01
- oMUL = 0x02
- oSUB = 0x03
- oDIV = 0x04
- oSDIV = 0x05
- oMOD = 0x06
- oSMOD = 0x07
- oEXP = 0x08
- oNEG = 0x09
- oLT = 0x0a
- oLE = 0x0b
- oGT = 0x0c
- oGE = 0x0d
- oEQ = 0x0e
- oNOT = 0x0f
- oMYADDRESS = 0x10
- oTXSENDER = 0x11
- oTXVALUE = 0x12
- oTXDATAN = 0x13
- oTXDATA = 0x14
- oBLK_PREVHASH = 0x15
- oBLK_COINBASE = 0x16
- oBLK_TIMESTAMP = 0x17
- oBLK_NUMBER = 0x18
- oBLK_DIFFICULTY = 0x19
- oBLK_NONCE = 0x1a
- oBASEFEE = 0x1b
- oSHA256 = 0x20
- oRIPEMD160 = 0x21
- oECMUL = 0x22
- oECADD = 0x23
- oECSIGN = 0x24
- oECRECOVER = 0x25
- oECVALID = 0x26
- oSHA3 = 0x27
- oPUSH = 0x30
- oPOP = 0x31
- oDUP = 0x32
- oSWAP = 0x33
- oMLOAD = 0x34
- oMSTORE = 0x35
- oSLOAD = 0x36
- oSSTORE = 0x37
- oJMP = 0x38
- oJMPI = 0x39
- oIND = 0x3a
- oEXTRO = 0x3b
- oBALANCE = 0x3c
- oMKTX = 0x3d
- oSUICIDE = 0x3f
-
- // TODO FIX OPCODES
- oCALL = 0x40
- oRETURN = 0x41
+ // 0x0 range - arithmetic ops
+ oSTOP = 0x00
+ oADD = 0x01
+ oMUL = 0x02
+ oSUB = 0x03
+ oDIV = 0x04
+ oSDIV = 0x05
+ oMOD = 0x06
+ oSMOD = 0x07
+ oEXP = 0x08
+ oNEG = 0x09
+ oLT = 0x0a
+ oGT = 0x0b
+ oEQ = 0x0c
+ oNOT = 0x0d
+
+ // 0x10 range - bit ops
+ oAND = 0x10
+ oOR = 0x11
+ oXOR = 0x12
+ oBYTE = 0x13
+
+ // 0x20 range - crypto
+ oSHA3 = 0x20
+
+ // 0x30 range - closure state
+ oADDRESS = 0x30
+ oBALANCE = 0x31
+ oORIGIN = 0x32
+ oCALLER = 0x33
+ oCALLVALUE = 0x34
+ oCALLDATA = 0x35
+ oCALLDATASIZE = 0x36
+ oRETURNDATASIZE = 0x37
+ oTXGASPRICE = 0x38
+
+ // 0x40 range - block operations
+ oPREVHASH = 0x40
+ oPREVNONCE = 0x41
+ oCOINBASE = 0x42
+ oTIMESTAMP = 0x43
+ oNUMBER = 0x44
+ oDIFFICULTY = 0x45
+ oGASLIMIT = 0x46
+
+ // 0x50 range - 'storage' and execution
+ oPUSH = 0x50
+ oPOP = 0x51
+ oDUP = 0x52
+ oSWAP = 0x53
+ oMLOAD = 0x54
+ oMSTORE = 0x55
+ oMSTORE8 = 0x56
+ oSLOAD = 0x57
+ oSSTORE = 0x58
+ oJUMP = 0x59
+ oJUMPI = 0x5a
+ oPC = 0x5b
+ oMEMSIZE = 0x5c
+
+ // 0x60 range - closures
+ oCREATE = 0x60
+ oCALL = 0x61
+ oRETURN = 0x62
)
// 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",
- oTXDATAN: "TXDATAN",
- oTXDATA: "TXDATA",
- oBLK_PREVHASH: "BLK_PREVHASH",
- oBLK_COINBASE: "BLK_COINBASE",
- oBLK_TIMESTAMP: "BLK_TIMESTAMP",
- oBLK_NUMBER: "BLK_NUMBER",
- oBLK_DIFFICULTY: "BLK_DIFFICULTY",
- oBASEFEE: "BASEFEE",
- oSHA256: "SHA256",
- oRIPEMD160: "RIPEMD160",
- oECMUL: "ECMUL",
- oECADD: "ECADD",
- oECSIGN: "ECSIGN",
- oECRECOVER: "ECRECOVER",
- oECVALID: "ECVALID",
- oSHA3: "SHA3",
- oPUSH: "PUSH",
- oPOP: "POP",
- oDUP: "DUP",
- oSWAP: "SWAP",
- oMLOAD: "MLOAD",
- oMSTORE: "MSTORE",
- oSLOAD: "SLOAD",
- oSSTORE: "SSTORE",
- oJMP: "JMP",
- oJMPI: "JMPI",
- oIND: "IND",
- oEXTRO: "EXTRO",
+ // 0x0 range - arithmetic ops
+ oSTOP: "STOP",
+ oADD: "ADD",
+ oMUL: "MUL",
+ oSUB: "SUB",
+ oDIV: "DIV",
+ oSDIV: "SDIV",
+ oMOD: "MOD",
+ oSMOD: "SMOD",
+ oEXP: "EXP",
+ oNEG: "NEG",
+ oLT: "LT",
+ oGT: "GT",
+ oEQ: "EQ",
+ oNOT: "NOT",
+
+ // 0x10 range - bit ops
+ oAND: "AND",
+ oOR: "OR",
+ oXOR: "XOR",
+ oBYTE: "BYTE",
+
+ // 0x20 range - crypto
+ oSHA3: "SHA3",
+
+ // 0x30 range - closure state
+ oADDRESS: "ADDRESS",
oBALANCE: "BALANCE",
- oMKTX: "MKTX",
- oSUICIDE: "SUICIDE",
-
+ oORIGIN: "ORIGIN",
+ oCALLER: "CALLER",
+ oCALLVALUE: "CALLVALUE",
+ oCALLDATA: "CALLDATA",
+ oCALLDATASIZE: "CALLDATASIZE",
+ oRETURNDATASIZE: "RETURNDATASIZE",
+ oTXGASPRICE: "TXGASPRICE",
+
+ // 0x40 range - block operations
+ oPREVHASH: "PREVHASH",
+ oPREVNONCE: "PREVNONCE",
+ oCOINBASE: "COINBASE",
+ oTIMESTAMP: "TIMESTAMP",
+ oNUMBER: "NUMBER",
+ oDIFFICULTY: "DIFFICULTY",
+ oGASLIMIT: "GASLIMIT",
+
+ // 0x50 range - 'storage' and execution
+ oPUSH: "PUSH",
+ oPOP: "POP",
+ oDUP: "DUP",
+ oSWAP: "SWAP",
+ oMLOAD: "MLOAD",
+ oMSTORE: "MSTORE",
+ oMSTORE8: "MSTORE8",
+ oSLOAD: "SLOAD",
+ oSSTORE: "SSTORE",
+ oJUMP: "JUMP",
+ oJUMPI: "JUMPI",
+ oPC: "PC",
+ oMEMSIZE: "MEMSIZE",
+
+ // 0x60 range - closures
+ oCREATE: "CREATE",
oCALL: "CALL",
oRETURN: "RETURN",
}
@@ -189,61 +209,26 @@ func (st *Stack) Print() {
fmt.Println("#############")
}
-////////////// TODO this will eventually become the main stack once the big ints are removed from the VM
-type ValueStack struct {
- data []*ethutil.Value
-}
-
-func NewValueStack() *ValueStack {
- return &ValueStack{}
-}
-
-func (st *ValueStack) Pop() *ethutil.Value {
- s := len(st.data)
-
- str := st.data[s-1]
- st.data = st.data[:s-1]
-
- return str
-}
-
-func (st *ValueStack) Popn() (*ethutil.Value, *ethutil.Value) {
- s := len(st.data)
-
- ints := st.data[s-2:]
- st.data = st.data[:s-2]
-
- return ints[0], ints[1]
-}
-
-func (st *ValueStack) Peek() *ethutil.Value {
- s := len(st.data)
-
- str := st.data[s-1]
-
- return str
+type Memory struct {
+ store []byte
}
-func (st *ValueStack) Peekn() (*ethutil.Value, *ethutil.Value) {
- s := len(st.data)
-
- ints := st.data[s-2:]
-
- return ints[0], ints[1]
-}
-
-func (st *ValueStack) Push(d *ethutil.Value) {
- st.data = append(st.data, d)
-}
-
-func (st *ValueStack) Print() {
- fmt.Println("### STACK ###")
- if len(st.data) > 0 {
- for i, val := range st.data {
- fmt.Printf("%-3d %v\n", i, val)
+func (m *Memory) Set(offset, size int64, value []byte) {
+ totSize := offset + size
+ lenSize := int64(len(m.store))
+ if totSize > lenSize {
+ // Calculate the diff between the sizes
+ diff := totSize - lenSize
+ if diff > 0 {
+ // Create a new empty slice and append it
+ newSlice := make([]byte, diff+1)
+ // Resize slice
+ m.store = append(m.store, newSlice...)
}
- } else {
- fmt.Println("-- empty --")
}
- fmt.Println("#############")
+ copy(m.store[offset:offset+size+1], value)
+}
+
+func (m *Memory) Get(offset, size int64) []byte {
+ return m.store[offset : offset+size]
}
diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go
index e67f0f680..14686b217 100644
--- a/ethchain/state_manager.go
+++ b/ethchain/state_manager.go
@@ -306,8 +306,8 @@ func (sm *StateManager) ProcessContract(contract *Contract, tx *Transaction, blo
}()
*/
+ /*TODO to be fixed and replaced by the new vm
vm := &Vm{}
- //vm.Process(contract, block.state, RuntimeVars{
vm.Process(contract, sm.procState, RuntimeVars{
address: tx.Hash()[12:],
blockNumber: block.BlockInfo().Number,
@@ -319,4 +319,5 @@ func (sm *StateManager) ProcessContract(contract *Contract, tx *Transaction, blo
txValue: tx.Value,
txData: tx.Data,
})
+ */
}
diff --git a/ethchain/vm.go b/ethchain/vm.go
index 2fa78a748..6479409f8 100644
--- a/ethchain/vm.go
+++ b/ethchain/vm.go
@@ -1,12 +1,12 @@
package ethchain
import (
- "bytes"
+ _ "bytes"
"fmt"
"github.com/ethereum/eth-go/ethutil"
- "github.com/obscuren/secp256k1-go"
+ _ "github.com/obscuren/secp256k1-go"
"log"
- "math"
+ _ "math"
"math/big"
)
@@ -45,7 +45,7 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
}
// Memory for the current closure
- var mem []byte
+ mem := &Memory{}
// New stack (should this be shared?)
stack := NewStack()
// Instruction pointer
@@ -86,19 +86,7 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
case oMSTORE: // Store the value at stack top-1 in to memory at location stack top
// Pop value of the stack
val, mStart := stack.Popn()
- // Ensure that memory is large enough to hold the data
- // If it isn't resize the memory slice so that it may hold the value
- bytesLen := big.NewInt(32)
- totSize := new(big.Int).Add(mStart, bytesLen)
- lenSize := big.NewInt(int64(len(mem)))
- if totSize.Cmp(lenSize) > 0 {
- // Calculate the diff between the sizes
- diff := new(big.Int).Sub(totSize, lenSize)
- // Create a new empty slice and append it
- newSlice := make([]byte, diff.Int64()+1)
- mem = append(mem, newSlice...)
- }
- copy(mem[mStart.Int64():mStart.Int64()+bytesLen.Int64()+1], ethutil.BigToBytes(val, 256))
+ mem.Set(mStart.Int64(), 32, ethutil.BigToBytes(val, 256))
case oCALL:
// Pop return size and offset
retSize, retOffset := stack.Popn()
@@ -116,23 +104,10 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
closure := NewClosure(closure, contract, vm.state, gas, value)
// Executer the closure and get the return value (if any)
ret := closure.Call(vm, nil)
-
- // Ensure that memory is large enough to hold the returned data
- // If it isn't resize the memory slice so that it may hold the value
- totSize := new(big.Int).Add(retOffset, retSize)
- lenSize := big.NewInt(int64(len(mem)))
- if totSize.Cmp(lenSize) > 0 {
- // Calculate the diff between the sizes
- diff := new(big.Int).Sub(totSize, lenSize)
- // Create a new empty slice and append it
- newSlice := make([]byte, diff.Int64()+1)
- mem = append(mem, newSlice...)
- }
- // Copy over the returned values to the memory given the offset and size
- copy(mem[retOffset.Int64():retOffset.Int64()+retSize.Int64()+1], ret)
+ mem.Set(retOffset.Int64(), retSize.Int64(), ret)
case oRETURN:
size, offset := stack.Popn()
- ret := mem[offset.Int64() : offset.Int64()+size.Int64()+1]
+ ret := mem.Get(offset.Int64(), size.Int64())
return closure.Return(ret)
}
@@ -141,6 +116,7 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
}
}
+/*
// Old VM code
func (vm *Vm) Process(contract *Contract, state *State, vars RuntimeVars) {
vm.mem = make(map[string]*big.Int)
@@ -507,6 +483,7 @@ out:
state.UpdateContract(addr, contract)
}
+*/
func makeInlineTx(addr []byte, value, from, length *big.Int, contract *Contract, state *State) {
ethutil.Config.Log.Debugf(" => creating inline tx %x %v %v %v", addr, value, from, length)
diff --git a/ethutil/parsing.go b/ethutil/parsing.go
index 459cdc284..9ff2827a0 100644
--- a/ethutil/parsing.go
+++ b/ethutil/parsing.go
@@ -7,61 +7,70 @@ import (
// Op codes
var OpCodes = map[string]byte{
- "STOP": 0x00,
- "ADD": 0x01,
- "MUL": 0x02,
- "SUB": 0x03,
- "DIV": 0x04,
- "SDIV": 0x05,
- "MOD": 0x06,
- "SMOD": 0x07,
- "EXP": 0x08,
- "NEG": 0x09,
- "LT": 0x0a,
- "LE": 0x0b,
- "GT": 0x0c,
- "GE": 0x0d,
- "EQ": 0x0e,
- "NOT": 0x0f,
- "MYADDRESS": 0x10,
- "TXSENDER": 0x11,
- "TXVALUE": 0x12,
- "TXDATAN": 0x13,
- "TXDATA": 0x14,
- "BLK_PREVHASH": 0x15,
- "BLK_COINBASE": 0x16,
- "BLK_TIMESTAMP": 0x17,
- "BLK_NUMBER": 0x18,
- "BLK_DIFFICULTY": 0x19,
- "BLK_NONCE": 0x1a,
- "BASEFEE": 0x1b,
- "SHA256": 0x20,
- "RIPEMD160": 0x21,
- "ECMUL": 0x22,
- "ECADD": 0x23,
- "ECSIGN": 0x24,
- "ECRECOVER": 0x25,
- "ECVALID": 0x26,
- "SHA3": 0x27,
- "PUSH": 0x30,
- "POP": 0x31,
- "DUP": 0x32,
- "SWAP": 0x33,
- "MLOAD": 0x34,
- "MSTORE": 0x35,
- "SLOAD": 0x36,
- "SSTORE": 0x37,
- "JMP": 0x38,
- "JMPI": 0x39,
- "IND": 0x3a,
- "EXTRO": 0x3b,
- "BALANCE": 0x3c,
- "MKTX": 0x3d,
- "SUICIDE": 0x3f,
-
- // TODO FIX OPCODES
- "CALL": 0x40,
- "RETURN": 0x41,
+ // 0x0 range - arithmetic ops
+ "STOP": 0x00,
+ "ADD": 0x01,
+ "MUL": 0x02,
+ "SUB": 0x03,
+ "DIV": 0x04,
+ "SDIV": 0x05,
+ "MOD": 0x06,
+ "SMOD": 0x07,
+ "EXP": 0x08,
+ "NEG": 0x09,
+ "LT": 0x0a,
+ "GT": 0x0b,
+ "EQ": 0x0c,
+ "NOT": 0x0d,
+
+ // 0x10 range - bit ops
+ "AND": 0x10,
+ "OR": 0x11,
+ "XOR": 0x12,
+ "BYTE": 0x13,
+
+ // 0x20 range - crypto
+ "SHA3": 0x20,
+
+ // 0x30 range - closure state
+ "ADDRESS": 0x30,
+ "BALANCE": 0x31,
+ "ORIGIN": 0x32,
+ "CALLER": 0x33,
+ "CALLVALUE": 0x34,
+ "CALLDATA": 0x35,
+ "CALLDATASIZE": 0x36,
+ "RETURNDATASIZE": 0x37,
+ "TXGASPRICE": 0x38,
+
+ // 0x40 range - block operations
+ "PREVHASH": 0x40,
+ "PREVNONCE": 0x41,
+ "COINBASE": 0x42,
+ "TIMESTAMP": 0x43,
+ "NUMBER": 0x44,
+ "DIFFICULTY": 0x45,
+ "GASLIMIT": 0x46,
+
+ // 0x50 range - 'storage' and execution
+ "PUSH": 0x50,
+ "POP": 0x51,
+ "DUP": 0x52,
+ "SWAP": 0x53,
+ "MLOAD": 0x54,
+ "MSTORE": 0x55,
+ "MSTORE8": 0x56,
+ "SLOAD": 0x57,
+ "SSTORE": 0x58,
+ "JUMP": 0x59,
+ "JUMPI": 0x5a,
+ "PC": 0x5b,
+ "MEMSIZE": 0x5c,
+
+ // 0x60 range - closures
+ "CREATE": 0x60,
+ "CALL": 0x61,
+ "RETURN": 0x62,
}
func IsOpCode(s string) bool {