aboutsummaryrefslogblamecommitdiffstats
path: root/ethchain/stack.go
blob: 429c31d082cb86d808fa4ffdd5098659a8833608 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12



                
                                              






                  































































                                               



                                                                     


























                                     
                                   

































                                               

                          


























                                        







































                                                        

                    

 










                                                                 
                 
         




                                                  
 
package ethchain

import (
    "fmt"
    _ "github.com/ethereum/eth-go/ethutil"
    "math/big"
)

type OpCode int

// Op codes
const (
    // 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{
    // 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",
    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",
}

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("#############")
}

type Memory struct {
    store []byte
}

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...)
        }
    }
    copy(m.store[offset:offset+size+1], value)
}

func (m *Memory) Get(offset, size int64) []byte {
    return m.store[offset : offset+size]
}