github.com/karalabe/go-ethereum@v0.8.5/vm/stack.go (about) 1 package vm 2 3 import ( 4 "fmt" 5 "math/big" 6 ) 7 8 type OpType int 9 10 const ( 11 tNorm = iota 12 tData 13 tExtro 14 tCrypto 15 ) 16 17 type TxCallback func(opType OpType) bool 18 19 // Simple push/pop stack mechanism 20 type Stack struct { 21 data []*big.Int 22 } 23 24 func NewStack() *Stack { 25 return &Stack{} 26 } 27 28 func (st *Stack) Data() []*big.Int { 29 return st.data 30 } 31 32 func (st *Stack) Len() int { 33 return len(st.data) 34 } 35 36 func (st *Stack) Pop() *big.Int { 37 str := st.data[len(st.data)-1] 38 39 copy(st.data[:len(st.data)-1], st.data[:len(st.data)-1]) 40 st.data = st.data[:len(st.data)-1] 41 42 return str 43 } 44 45 func (st *Stack) Popn() (*big.Int, *big.Int) { 46 ints := st.data[len(st.data)-2:] 47 48 copy(st.data[:len(st.data)-2], st.data[:len(st.data)-2]) 49 st.data = st.data[:len(st.data)-2] 50 51 return ints[0], ints[1] 52 } 53 54 func (st *Stack) Peek() *big.Int { 55 str := st.data[len(st.data)-1] 56 57 return str 58 } 59 60 func (st *Stack) Peekn() (*big.Int, *big.Int) { 61 ints := st.data[len(st.data)-2:] 62 63 return ints[0], ints[1] 64 } 65 66 func (st *Stack) Swapn(n int) (*big.Int, *big.Int) { 67 st.data[len(st.data)-n], st.data[len(st.data)-1] = st.data[len(st.data)-1], st.data[len(st.data)-n] 68 69 return st.data[len(st.data)-n], st.data[len(st.data)-1] 70 } 71 72 func (st *Stack) Dupn(n int) *big.Int { 73 st.Push(st.data[len(st.data)-n]) 74 75 return st.Peek() 76 } 77 78 func (st *Stack) Push(d *big.Int) { 79 st.data = append(st.data, new(big.Int).Set(d)) 80 } 81 82 func (st *Stack) Get(amount *big.Int) []*big.Int { 83 // offset + size <= len(data) 84 length := big.NewInt(int64(len(st.data))) 85 if amount.Cmp(length) <= 0 { 86 start := new(big.Int).Sub(length, amount) 87 return st.data[start.Int64():length.Int64()] 88 } 89 90 return nil 91 } 92 93 func (st *Stack) require(n int) { 94 if st.Len() < n { 95 panic(fmt.Sprintf("stack underflow (%d <=> %d)", st.Len(), n)) 96 } 97 } 98 99 func (st *Stack) Print() { 100 fmt.Println("### stack ###") 101 if len(st.data) > 0 { 102 for i, val := range st.data { 103 fmt.Printf("%-3d %v\n", i, val) 104 } 105 } else { 106 fmt.Println("-- empty --") 107 } 108 fmt.Println("#############") 109 } 110 111 type Memory struct { 112 store []byte 113 } 114 115 func NewMemory() *Memory { 116 return &Memory{nil} 117 } 118 119 func (m *Memory) Set(offset, size uint64, value []byte) { 120 if len(value) > 0 { 121 totSize := offset + size 122 lenSize := uint64(len(m.store) - 1) 123 if totSize > lenSize { 124 // Calculate the diff between the sizes 125 diff := totSize - lenSize 126 if diff > 0 { 127 // Create a new empty slice and append it 128 newSlice := make([]byte, diff-1) 129 // Resize slice 130 m.store = append(m.store, newSlice...) 131 } 132 } 133 copy(m.store[offset:offset+size], value) 134 } 135 } 136 137 func (m *Memory) Resize(size uint64) { 138 if uint64(m.Len()) < size { 139 m.store = append(m.store, make([]byte, size-uint64(m.Len()))...) 140 } 141 } 142 143 func (self *Memory) Get(offset, size int64) (cpy []byte) { 144 if size == 0 { 145 return nil 146 } 147 148 if len(self.store) > int(offset) { 149 cpy = make([]byte, size) 150 copy(cpy, self.store[offset:offset+size]) 151 152 return 153 } 154 155 return 156 } 157 158 func (m *Memory) Len() int { 159 return len(m.store) 160 } 161 162 func (m *Memory) Data() []byte { 163 return m.store 164 } 165 166 func (m *Memory) Print() { 167 fmt.Printf("### mem %d bytes ###\n", len(m.store)) 168 if len(m.store) > 0 { 169 addr := 0 170 for i := 0; i+32 <= len(m.store); i += 32 { 171 fmt.Printf("%03d: % x\n", addr, m.store[i:i+32]) 172 addr++ 173 } 174 } else { 175 fmt.Println("-- empty --") 176 } 177 fmt.Println("####################") 178 }