stack.go 4.83 KB
Newer Older
obscuren's avatar
obscuren committed
1 2 3 4
package ethchain

import (
	"fmt"
5
	"github.com/ethereum/eth-go/ethutil"
obscuren's avatar
obscuren committed
6 7 8 9 10 11 12
	"math/big"
)

type OpCode int

// Op codes
const (
obscuren's avatar
obscuren committed
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
	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
64 65 66 67

	// TODO FIX OPCODES
	oCALL   = 0x40
	oRETURN = 0x41
obscuren's avatar
obscuren committed
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
)

// 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",
122 123 124

	oCALL:   "CALL",
	oRETURN: "RETURN",
obscuren's avatar
obscuren committed
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
}

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 {
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
	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 {
obscuren's avatar
obscuren committed
202 203 204 205 206 207 208 209
	s := len(st.data)

	str := st.data[s-1]
	st.data = st.data[:s-1]

	return str
}

210
func (st *ValueStack) Popn() (*ethutil.Value, *ethutil.Value) {
obscuren's avatar
obscuren committed
211 212 213 214 215 216 217 218
	s := len(st.data)

	ints := st.data[s-2:]
	st.data = st.data[:s-2]

	return ints[0], ints[1]
}

219
func (st *ValueStack) Peek() *ethutil.Value {
obscuren's avatar
obscuren committed
220 221 222 223 224 225 226
	s := len(st.data)

	str := st.data[s-1]

	return str
}

227
func (st *ValueStack) Peekn() (*ethutil.Value, *ethutil.Value) {
obscuren's avatar
obscuren committed
228 229 230 231 232 233 234
	s := len(st.data)

	ints := st.data[s-2:]

	return ints[0], ints[1]
}

235
func (st *ValueStack) Push(d *ethutil.Value) {
obscuren's avatar
obscuren committed
236 237
	st.data = append(st.data, d)
}
238
func (st *ValueStack) Print() {
obscuren's avatar
obscuren committed
239
	fmt.Println("### STACK ###")
obscuren's avatar
obscuren committed
240 241 242 243 244 245 246
	if len(st.data) > 0 {
		for i, val := range st.data {
			fmt.Printf("%-3d  %v\n", i, val)
		}
	} else {
		fmt.Println("-- empty --")
	}
obscuren's avatar
obscuren committed
247
	fmt.Println("#############")
obscuren's avatar
obscuren committed
248
}