250 lines
4.8 KiB
Go
250 lines
4.8 KiB
Go
package ethchain
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/ethereum/eth-go/ethutil"
|
|
"math/big"
|
|
)
|
|
|
|
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
|
|
)
|
|
|
|
// 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",
|
|
oBALANCE: "BALANCE",
|
|
oMKTX: "MKTX",
|
|
oSUICIDE: "SUICIDE",
|
|
|
|
oCALL: "CALL",
|
|
oRETURN: "RETURN",
|
|
}
|
|
|
|
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 []*big.Int
|
|
}
|
|
|
|
func NewStack() *Stack {
|
|
return &Stack{}
|
|
}
|
|
|
|
func (st *Stack) Pop() *big.Int {
|
|
str := st.data[0]
|
|
st.data = st.data[1:]
|
|
|
|
return str
|
|
}
|
|
|
|
func (st *Stack) Popn() (*big.Int, *big.Int) {
|
|
ints := st.data[:2]
|
|
st.data = st.data[2:]
|
|
|
|
return ints[0], ints[1]
|
|
}
|
|
|
|
func (st *Stack) Peek() *big.Int {
|
|
str := st.data[0]
|
|
|
|
return str
|
|
}
|
|
|
|
func (st *Stack) Peekn() (*big.Int, *big.Int) {
|
|
ints := st.data[:2]
|
|
|
|
return ints[0], ints[1]
|
|
}
|
|
|
|
func (st *Stack) Push(d *big.Int) {
|
|
st.data = append(st.data, d)
|
|
}
|
|
func (st *Stack) Print() {
|
|
fmt.Println("### STACK ###")
|
|
if len(st.data) > 0 {
|
|
for i, val := range st.data {
|
|
fmt.Printf("%-3d %v\n", i, val)
|
|
}
|
|
} else {
|
|
fmt.Println("-- empty --")
|
|
}
|
|
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
|
|
}
|
|
|
|
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)
|
|
}
|
|
} else {
|
|
fmt.Println("-- empty --")
|
|
}
|
|
fmt.Println("#############")
|
|
}
|