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