github.com/datachainlab/burrow@v0.25.0/execution/evm/stack.go (about) 1 // Copyright 2017 Monax Industries Limited 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package evm 16 17 import ( 18 "fmt" 19 20 "github.com/hyperledger/burrow/crypto" 21 22 "math/big" 23 24 "math" 25 26 . "github.com/hyperledger/burrow/binary" 27 "github.com/hyperledger/burrow/execution/errors" 28 ) 29 30 // Not goroutine safe 31 type Stack struct { 32 slice []Word256 33 maxCapacity uint64 34 ptr int 35 36 gas *uint64 37 errSink errors.Sink 38 } 39 40 func NewStack(initialCapacity uint64, maxCapacity uint64, gas *uint64, errSink errors.Sink) *Stack { 41 return &Stack{ 42 slice: make([]Word256, initialCapacity), 43 ptr: 0, 44 maxCapacity: maxCapacity, 45 gas: gas, 46 errSink: errSink, 47 } 48 } 49 50 func (st *Stack) useGas(gasToUse uint64) { 51 if *st.gas > gasToUse { 52 *st.gas -= gasToUse 53 } else { 54 st.pushErr(errors.ErrorCodeInsufficientGas) 55 } 56 } 57 58 func (st *Stack) pushErr(err errors.CodedError) { 59 st.errSink.PushError(err) 60 } 61 62 func (st *Stack) Push(d Word256) { 63 st.useGas(GasStackOp) 64 err := st.ensureCapacity(uint64(st.ptr) + 1) 65 if err != nil { 66 st.pushErr(errors.ErrorCodeDataStackOverflow) 67 return 68 } 69 st.slice[st.ptr] = d 70 st.ptr++ 71 } 72 73 // currently only called after sha3.Sha3 74 func (st *Stack) PushBytes(bz []byte) { 75 if len(bz) != 32 { 76 panic("Invalid bytes size: expected 32") 77 } 78 st.Push(LeftPadWord256(bz)) 79 } 80 81 func (st *Stack) PushAddress(address crypto.Address) { 82 st.Push(address.Word256()) 83 } 84 85 func (st *Stack) Push64(i int64) { 86 st.Push(Int64ToWord256(i)) 87 } 88 89 func (st *Stack) PushU64(i uint64) { 90 st.Push(Uint64ToWord256(i)) 91 } 92 93 // Pushes the bigInt as a Word256 encoding negative values in 32-byte twos complement and returns the encoded result 94 func (st *Stack) PushBigInt(bigInt *big.Int) Word256 { 95 word := LeftPadWord256(U256(bigInt).Bytes()) 96 st.Push(word) 97 return word 98 } 99 100 // Pops 101 102 func (st *Stack) Pop() Word256 { 103 st.useGas(GasStackOp) 104 if st.ptr == 0 { 105 st.pushErr(errors.ErrorCodeDataStackUnderflow) 106 return Zero256 107 } 108 st.ptr-- 109 return st.slice[st.ptr] 110 } 111 112 func (st *Stack) PopBytes() []byte { 113 return st.Pop().Bytes() 114 } 115 116 func (st *Stack) PopAddress() crypto.Address { 117 return crypto.AddressFromWord256(st.Pop()) 118 } 119 120 func (st *Stack) Pop64() int64 { 121 d := st.Pop() 122 if Is64BitOverflow(d) { 123 st.pushErr(errors.ErrorCodef(errors.ErrorCodeCallStackOverflow, "int64 overflow from word: %v", d)) 124 return 0 125 } 126 return Int64FromWord256(d) 127 } 128 129 func (st *Stack) PopU64() uint64 { 130 d := st.Pop() 131 if Is64BitOverflow(d) { 132 st.pushErr(errors.ErrorCodef(errors.ErrorCodeCallStackOverflow, "int64 overflow from word: %v", d)) 133 return 0 134 } 135 return Uint64FromWord256(d) 136 } 137 138 func (st *Stack) PopBigIntSigned() *big.Int { 139 return S256(st.PopBigInt()) 140 } 141 142 func (st *Stack) PopBigInt() *big.Int { 143 d := st.Pop() 144 return new(big.Int).SetBytes(d[:]) 145 } 146 147 func (st *Stack) Len() int { 148 return st.ptr 149 } 150 151 func (st *Stack) Swap(n int) { 152 st.useGas(GasStackOp) 153 if st.ptr < n { 154 st.pushErr(errors.ErrorCodeDataStackUnderflow) 155 return 156 } 157 st.slice[st.ptr-n], st.slice[st.ptr-1] = st.slice[st.ptr-1], st.slice[st.ptr-n] 158 } 159 160 func (st *Stack) Dup(n int) { 161 st.useGas(GasStackOp) 162 if st.ptr < n { 163 st.pushErr(errors.ErrorCodeDataStackUnderflow) 164 return 165 } 166 st.Push(st.slice[st.ptr-n]) 167 } 168 169 // Not an opcode, costs no gas. 170 func (st *Stack) Peek() Word256 { 171 if st.ptr == 0 { 172 st.pushErr(errors.ErrorCodeDataStackUnderflow) 173 return Zero256 174 } 175 return st.slice[st.ptr-1] 176 } 177 178 func (st *Stack) Print(n int) { 179 fmt.Println("### stack ###") 180 if st.ptr > 0 { 181 nn := n 182 if st.ptr < n { 183 nn = st.ptr 184 } 185 for j, i := 0, st.ptr-1; i > st.ptr-1-nn; i-- { 186 fmt.Printf("%-3d %X\n", j, st.slice[i]) 187 j += 1 188 } 189 } else { 190 fmt.Println("-- empty --") 191 } 192 fmt.Println("#############") 193 } 194 195 func Is64BitOverflow(word Word256) bool { 196 for i := 0; i < len(word)-8; i++ { 197 if word[i] != 0 { 198 return true 199 } 200 } 201 return false 202 } 203 204 // Ensures the current stack can hold a new element. Will only grow the 205 // backing array (will not shrink). 206 func (st *Stack) ensureCapacity(newCapacity uint64) error { 207 // Maximum length of a slice that allocates memory is the same as the native int max size 208 // We could rethink this limit, but we don't want different validators to disagree on 209 // transaction validity so we pick the lowest common denominator 210 if newCapacity > math.MaxInt32 { 211 // If we ever did want more than an int32 of space then we would need to 212 // maintain multiple pages of memory 213 return fmt.Errorf("cannot address memory beyond a maximum index "+ 214 "with int32 width (%v bytes)", math.MaxInt32) 215 } 216 newCapacityInt := int(newCapacity) 217 // We're already big enough so return 218 if newCapacityInt <= len(st.slice) { 219 return nil 220 } 221 if st.maxCapacity > 0 && newCapacity > st.maxCapacity { 222 return fmt.Errorf("cannot grow memory because it would exceed the "+ 223 "current maximum limit of %v bytes", st.maxCapacity) 224 } 225 // Ensure the backing array of slice is big enough 226 // Grow the memory one word at time using the pre-allocated zeroWords to avoid 227 // unnecessary allocations. Use append to make use of any spare capacity in 228 // the slice's backing array. 229 for newCapacityInt > cap(st.slice) { 230 // We'll trust Go exponentially grow our arrays (at first). 231 st.slice = append(st.slice, Zero256) 232 } 233 // Now we've ensured the backing array of the slice is big enough we can 234 // just re-slice (even if len(mem.slice) < newCapacity) 235 st.slice = st.slice[:newCapacity] 236 return nil 237 }