github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/protocol/vm/stack.go (about) 1 package vm 2 3 import "github.com/bytom/bytom/math/checked" 4 5 func opToAltStack(vm *virtualMachine) error { 6 err := vm.applyCost(2) 7 if err != nil { 8 return err 9 } 10 if len(vm.dataStack) == 0 { 11 return ErrDataStackUnderflow 12 } 13 // no standard memory cost accounting here 14 vm.altStack = append(vm.altStack, vm.dataStack[len(vm.dataStack)-1]) 15 vm.dataStack = vm.dataStack[:len(vm.dataStack)-1] 16 return nil 17 } 18 19 func opFromAltStack(vm *virtualMachine) error { 20 err := vm.applyCost(2) 21 if err != nil { 22 return err 23 } 24 if len(vm.altStack) == 0 { 25 return ErrAltStackUnderflow 26 } 27 // no standard memory cost accounting here 28 vm.dataStack = append(vm.dataStack, vm.altStack[len(vm.altStack)-1]) 29 vm.altStack = vm.altStack[:len(vm.altStack)-1] 30 return nil 31 } 32 33 func op2Drop(vm *virtualMachine) error { 34 err := vm.applyCost(2) 35 if err != nil { 36 return err 37 } 38 for i := 0; i < 2; i++ { 39 _, err = vm.pop(false) 40 if err != nil { 41 return err 42 } 43 } 44 return nil 45 } 46 47 func op2Dup(vm *virtualMachine) error { 48 return nDup(vm, 2) 49 } 50 51 func op3Dup(vm *virtualMachine) error { 52 return nDup(vm, 3) 53 } 54 55 func nDup(vm *virtualMachine, n int) error { 56 err := vm.applyCost(int64(n)) 57 if err != nil { 58 return err 59 } 60 if len(vm.dataStack) < n { 61 return ErrDataStackUnderflow 62 } 63 for i := 0; i < n; i++ { 64 err = vm.push(vm.dataStack[len(vm.dataStack)-n], false) 65 if err != nil { 66 return err 67 } 68 } 69 return nil 70 } 71 72 func op2Over(vm *virtualMachine) error { 73 err := vm.applyCost(2) 74 if err != nil { 75 return err 76 } 77 if len(vm.dataStack) < 4 { 78 return ErrDataStackUnderflow 79 } 80 for i := 0; i < 2; i++ { 81 err = vm.push(vm.dataStack[len(vm.dataStack)-4], false) 82 if err != nil { 83 return err 84 } 85 } 86 return nil 87 } 88 89 func op2Rot(vm *virtualMachine) error { 90 err := vm.applyCost(2) 91 if err != nil { 92 return err 93 } 94 if len(vm.dataStack) < 6 { 95 return ErrDataStackUnderflow 96 } 97 newStack := make([][]byte, 0, len(vm.dataStack)) 98 newStack = append(newStack, vm.dataStack[:len(vm.dataStack)-6]...) 99 newStack = append(newStack, vm.dataStack[len(vm.dataStack)-4:]...) 100 newStack = append(newStack, vm.dataStack[len(vm.dataStack)-6]) 101 newStack = append(newStack, vm.dataStack[len(vm.dataStack)-5]) 102 vm.dataStack = newStack 103 return nil 104 } 105 106 func op2Swap(vm *virtualMachine) error { 107 err := vm.applyCost(2) 108 if err != nil { 109 return err 110 } 111 if len(vm.dataStack) < 4 { 112 return ErrDataStackUnderflow 113 } 114 newStack := make([][]byte, 0, len(vm.dataStack)) 115 newStack = append(newStack, vm.dataStack[:len(vm.dataStack)-4]...) 116 newStack = append(newStack, vm.dataStack[len(vm.dataStack)-2:]...) 117 newStack = append(newStack, vm.dataStack[len(vm.dataStack)-4]) 118 newStack = append(newStack, vm.dataStack[len(vm.dataStack)-3]) 119 vm.dataStack = newStack 120 return nil 121 } 122 123 func opIfDup(vm *virtualMachine) error { 124 err := vm.applyCost(1) 125 if err != nil { 126 return err 127 } 128 item, err := vm.top() 129 if err != nil { 130 return err 131 } 132 if AsBool(item) { 133 err = vm.push(item, false) 134 if err != nil { 135 return err 136 } 137 } 138 return nil 139 } 140 141 func opDepth(vm *virtualMachine) error { 142 err := vm.applyCost(1) 143 if err != nil { 144 return err 145 } 146 err = vm.pushInt64(int64(len(vm.dataStack)), false) 147 if err != nil { 148 return err 149 } 150 return nil 151 } 152 153 func opDrop(vm *virtualMachine) error { 154 err := vm.applyCost(1) 155 if err != nil { 156 return err 157 } 158 _, err = vm.pop(false) 159 if err != nil { 160 return err 161 } 162 return nil 163 } 164 165 func opDup(vm *virtualMachine) error { 166 return nDup(vm, 1) 167 } 168 169 func opNip(vm *virtualMachine) error { 170 err := vm.applyCost(1) 171 if err != nil { 172 return err 173 } 174 top, err := vm.top() 175 if err != nil { 176 return err 177 } 178 // temporarily pop off the top value with no standard memory accounting 179 vm.dataStack = vm.dataStack[:len(vm.dataStack)-1] 180 _, err = vm.pop(false) 181 if err != nil { 182 return err 183 } 184 // now put the top item back 185 vm.dataStack = append(vm.dataStack, top) 186 return nil 187 } 188 189 func opOver(vm *virtualMachine) error { 190 err := vm.applyCost(1) 191 if err != nil { 192 return err 193 } 194 if len(vm.dataStack) < 2 { 195 return ErrDataStackUnderflow 196 } 197 err = vm.push(vm.dataStack[len(vm.dataStack)-2], false) 198 if err != nil { 199 return err 200 } 201 return nil 202 } 203 204 func opPick(vm *virtualMachine) error { 205 err := vm.applyCost(2) 206 if err != nil { 207 return err 208 } 209 n, err := vm.popInt64(false) 210 if err != nil { 211 return err 212 } 213 if n < 0 { 214 return ErrBadValue 215 } 216 off, ok := checked.AddInt64(n, 1) 217 if !ok { 218 return ErrBadValue 219 } 220 if int64(len(vm.dataStack)) < off { 221 return ErrDataStackUnderflow 222 } 223 err = vm.push(vm.dataStack[int64(len(vm.dataStack))-(off)], false) 224 if err != nil { 225 return err 226 } 227 return nil 228 } 229 230 func opRoll(vm *virtualMachine) error { 231 err := vm.applyCost(2) 232 if err != nil { 233 return err 234 } 235 n, err := vm.popInt64(false) 236 if err != nil { 237 return err 238 } 239 if n < 0 { 240 return ErrBadValue 241 } 242 off, ok := checked.AddInt64(n, 1) 243 if !ok { 244 return ErrBadValue 245 } 246 err = rot(vm, off) 247 if err != nil { 248 return err 249 } 250 return nil 251 } 252 253 func opRot(vm *virtualMachine) error { 254 err := vm.applyCost(2) 255 if err != nil { 256 return err 257 } 258 err = rot(vm, 3) 259 if err != nil { 260 return err 261 } 262 return nil 263 } 264 265 func rot(vm *virtualMachine, n int64) error { 266 if n < 1 { 267 return ErrBadValue 268 } 269 if int64(len(vm.dataStack)) < n { 270 return ErrDataStackUnderflow 271 } 272 index := int64(len(vm.dataStack)) - n 273 newStack := make([][]byte, 0, len(vm.dataStack)) 274 newStack = append(newStack, vm.dataStack[:index]...) 275 newStack = append(newStack, vm.dataStack[index+1:]...) 276 newStack = append(newStack, vm.dataStack[index]) 277 vm.dataStack = newStack 278 return nil 279 } 280 281 func opSwap(vm *virtualMachine) error { 282 err := vm.applyCost(1) 283 if err != nil { 284 return err 285 } 286 l := len(vm.dataStack) 287 if l < 2 { 288 return ErrDataStackUnderflow 289 } 290 vm.dataStack[l-1], vm.dataStack[l-2] = vm.dataStack[l-2], vm.dataStack[l-1] 291 return nil 292 } 293 294 func opTuck(vm *virtualMachine) error { 295 err := vm.applyCost(1) 296 if err != nil { 297 return err 298 } 299 if len(vm.dataStack) < 2 { 300 return ErrDataStackUnderflow 301 } 302 top2 := make([][]byte, 2) 303 copy(top2, vm.dataStack[len(vm.dataStack)-2:]) 304 // temporarily remove the top two items without standard memory accounting 305 vm.dataStack = vm.dataStack[:len(vm.dataStack)-2] 306 err = vm.push(top2[1], false) 307 if err != nil { 308 return err 309 } 310 vm.dataStack = append(vm.dataStack, top2...) 311 return nil 312 }