aboutsummaryrefslogtreecommitdiffstats
path: root/ethchain
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-03-21 05:51:20 +0800
committerobscuren <geffobscura@gmail.com>2014-03-21 05:51:20 +0800
commitf3d27bf5d878120346f8cdd0744e7f1f8e1ee631 (patch)
tree8b265236e4707a5260a7bf365cf103499c0c5767 /ethchain
parentc68ff9886bdd59294bc2bf0a6b8bf9b83645cc9a (diff)
downloadgo-tangerine-f3d27bf5d878120346f8cdd0744e7f1f8e1ee631.tar.gz
go-tangerine-f3d27bf5d878120346f8cdd0744e7f1f8e1ee631.tar.zst
go-tangerine-f3d27bf5d878120346f8cdd0744e7f1f8e1ee631.zip
Rewrote opcodes again
Diffstat (limited to 'ethchain')
-rw-r--r--ethchain/stack.go303
-rw-r--r--ethchain/state_manager.go3
-rw-r--r--ethchain/vm.go41
3 files changed, 155 insertions, 192 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)