github.com/core-coin/go-core/v2@v2.1.9/core/vm/instructions.go (about) 1 // Copyright 2015 by the Authors 2 // This file is part of the go-core library. 3 // 4 // The go-core library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-core library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-core library. If not, see <http://www.gnu.org/licenses/>. 16 17 package vm 18 19 import ( 20 "github.com/core-coin/uint256" 21 "golang.org/x/crypto/sha3" 22 23 "github.com/core-coin/go-core/v2/common" 24 "github.com/core-coin/go-core/v2/core/types" 25 "github.com/core-coin/go-core/v2/params" 26 ) 27 28 func opAdd(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 29 x, y := callContext.stack.pop(), callContext.stack.peek() 30 y.Add(&x, y) 31 return nil, nil 32 } 33 34 func opSub(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 35 x, y := callContext.stack.pop(), callContext.stack.peek() 36 y.Sub(&x, y) 37 return nil, nil 38 } 39 40 func opMul(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 41 x, y := callContext.stack.pop(), callContext.stack.peek() 42 y.Mul(&x, y) 43 return nil, nil 44 } 45 46 func opDiv(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 47 x, y := callContext.stack.pop(), callContext.stack.peek() 48 y.Div(&x, y) 49 return nil, nil 50 } 51 52 func opSdiv(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 53 x, y := callContext.stack.pop(), callContext.stack.peek() 54 y.SDiv(&x, y) 55 return nil, nil 56 } 57 58 func opMod(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 59 x, y := callContext.stack.pop(), callContext.stack.peek() 60 y.Mod(&x, y) 61 return nil, nil 62 } 63 64 func opSmod(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 65 x, y := callContext.stack.pop(), callContext.stack.peek() 66 y.SMod(&x, y) 67 return nil, nil 68 } 69 70 func opExp(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 71 base, exponent := callContext.stack.pop(), callContext.stack.peek() 72 exponent.Exp(&base, exponent) 73 return nil, nil 74 } 75 76 func opSignExtend(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 77 back, num := callContext.stack.pop(), callContext.stack.peek() 78 num.ExtendSign(num, &back) 79 return nil, nil 80 } 81 82 func opNot(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 83 x := callContext.stack.peek() 84 x.Not(x) 85 return nil, nil 86 } 87 88 func opLt(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 89 x, y := callContext.stack.pop(), callContext.stack.peek() 90 if x.Lt(y) { 91 y.SetOne() 92 } else { 93 y.Clear() 94 } 95 return nil, nil 96 } 97 98 func opGt(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 99 x, y := callContext.stack.pop(), callContext.stack.peek() 100 if x.Gt(y) { 101 y.SetOne() 102 } else { 103 y.Clear() 104 } 105 return nil, nil 106 } 107 108 func opSlt(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 109 x, y := callContext.stack.pop(), callContext.stack.peek() 110 if x.Slt(y) { 111 y.SetOne() 112 } else { 113 y.Clear() 114 } 115 return nil, nil 116 } 117 118 func opSgt(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 119 x, y := callContext.stack.pop(), callContext.stack.peek() 120 if x.Sgt(y) { 121 y.SetOne() 122 } else { 123 y.Clear() 124 } 125 return nil, nil 126 } 127 128 func opEq(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 129 x, y := callContext.stack.pop(), callContext.stack.peek() 130 if x.Eq(y) { 131 y.SetOne() 132 } else { 133 y.Clear() 134 } 135 return nil, nil 136 } 137 138 func opIszero(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 139 x := callContext.stack.peek() 140 if x.IsZero() { 141 x.SetOne() 142 } else { 143 x.Clear() 144 } 145 return nil, nil 146 } 147 148 func opAnd(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 149 x, y := callContext.stack.pop(), callContext.stack.peek() 150 y.And(&x, y) 151 return nil, nil 152 } 153 154 func opOr(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 155 x, y := callContext.stack.pop(), callContext.stack.peek() 156 y.Or(&x, y) 157 return nil, nil 158 } 159 160 func opXor(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 161 x, y := callContext.stack.pop(), callContext.stack.peek() 162 y.Xor(&x, y) 163 return nil, nil 164 } 165 166 func opByte(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 167 th, val := callContext.stack.pop(), callContext.stack.peek() 168 val.Byte(&th) 169 return nil, nil 170 } 171 172 func opAddmod(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 173 x, y, z := callContext.stack.pop(), callContext.stack.pop(), callContext.stack.peek() 174 if z.IsZero() { 175 z.Clear() 176 } else { 177 z.AddMod(&x, &y, z) 178 } 179 return nil, nil 180 } 181 182 func opMulmod(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 183 x, y, z := callContext.stack.pop(), callContext.stack.pop(), callContext.stack.peek() 184 z.MulMod(&x, &y, z) 185 return nil, nil 186 } 187 188 // opSHL implements Shift Left 189 // The SHL instruction (shift left) pops 2 values from the stack, first arg1 and then arg2, 190 // and pushes on the stack arg2 shifted to the left by arg1 number of bits. 191 func opSHL(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 192 // Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards 193 shift, value := callContext.stack.pop(), callContext.stack.peek() 194 if shift.LtUint64(256) { 195 value.Lsh(value, uint(shift.Uint64())) 196 } else { 197 value.Clear() 198 } 199 return nil, nil 200 } 201 202 // opSHR implements Logical Shift Right 203 // The SHR instruction (logical shift right) pops 2 values from the stack, first arg1 and then arg2, 204 // and pushes on the stack arg2 shifted to the right by arg1 number of bits with zero fill. 205 func opSHR(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 206 // Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards 207 shift, value := callContext.stack.pop(), callContext.stack.peek() 208 if shift.LtUint64(256) { 209 value.Rsh(value, uint(shift.Uint64())) 210 } else { 211 value.Clear() 212 } 213 return nil, nil 214 } 215 216 // opSAR implements Arithmetic Shift Right 217 // The SAR instruction (arithmetic shift right) pops 2 values from the stack, first arg1 and then arg2, 218 // and pushes on the stack arg2 shifted to the right by arg1 number of bits with sign extension. 219 func opSAR(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 220 shift, value := callContext.stack.pop(), callContext.stack.peek() 221 if shift.GtUint64(256) { 222 if value.Sign() >= 0 { 223 value.Clear() 224 } else { 225 // Max negative shift: all bits set 226 value.SetAllOne() 227 } 228 return nil, nil 229 } 230 n := uint(shift.Uint64()) 231 value.SRsh(value, n) 232 return nil, nil 233 } 234 235 func opSha3(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 236 offset, size := callContext.stack.pop(), callContext.stack.peek() 237 data := callContext.memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64())) 238 239 if interpreter.hasher == nil { 240 interpreter.hasher = sha3.New256().(keccakState) 241 } else { 242 interpreter.hasher.Reset() 243 } 244 interpreter.hasher.Write(data) 245 interpreter.hasher.Read(interpreter.hasherBuf[:]) 246 247 cvm := interpreter.cvm 248 if cvm.vmConfig.EnablePreimageRecording { 249 cvm.StateDB.AddPreimage(interpreter.hasherBuf, data) 250 } 251 252 size.SetBytes(interpreter.hasherBuf[:]) 253 return nil, nil 254 } 255 func opAddress(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 256 callContext.stack.push(new(uint256.Int).SetBytes(callContext.contract.Address().Bytes())) 257 return nil, nil 258 } 259 260 func opBalance(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 261 slot := callContext.stack.peek() 262 address := common.Address(slot.Bytes22()) 263 slot.SetFromBig(interpreter.cvm.StateDB.GetBalance(address)) 264 return nil, nil 265 } 266 267 func opOrigin(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 268 callContext.stack.push(new(uint256.Int).SetBytes(interpreter.cvm.Origin.Bytes())) 269 return nil, nil 270 } 271 func opCaller(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 272 callContext.stack.push(new(uint256.Int).SetBytes(callContext.contract.Caller().Bytes())) 273 return nil, nil 274 } 275 276 func opCallValue(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 277 v, _ := uint256.FromBig(callContext.contract.value) 278 callContext.stack.push(v) 279 return nil, nil 280 } 281 282 func opCallDataLoad(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 283 x := callContext.stack.peek() 284 if offset, overflow := x.Uint64WithOverflow(); !overflow { 285 data := getData(callContext.contract.Input, offset, 32) 286 x.SetBytes(data) 287 } else { 288 x.Clear() 289 } 290 return nil, nil 291 } 292 293 func opCallDataSize(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 294 callContext.stack.push(new(uint256.Int).SetUint64(uint64(len(callContext.contract.Input)))) 295 return nil, nil 296 } 297 298 func opCallDataCopy(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 299 var ( 300 memOffset = callContext.stack.pop() 301 dataOffset = callContext.stack.pop() 302 length = callContext.stack.pop() 303 ) 304 dataOffset64, overflow := dataOffset.Uint64WithOverflow() 305 if overflow { 306 dataOffset64 = 0xffffffffffffffff 307 } 308 // These values are checked for overflow during energy cost calculation 309 memOffset64 := memOffset.Uint64() 310 length64 := length.Uint64() 311 callContext.memory.Set(memOffset64, length64, getData(callContext.contract.Input, dataOffset64, length64)) 312 313 return nil, nil 314 } 315 316 func opReturnDataSize(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 317 callContext.stack.push(new(uint256.Int).SetUint64(uint64(len(interpreter.returnData)))) 318 return nil, nil 319 } 320 321 func opReturnDataCopy(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 322 var ( 323 memOffset = callContext.stack.pop() 324 dataOffset = callContext.stack.pop() 325 length = callContext.stack.pop() 326 ) 327 328 offset64, overflow := dataOffset.Uint64WithOverflow() 329 if overflow { 330 return nil, ErrReturnDataOutOfBounds 331 } 332 // we can reuse dataOffset now (aliasing it for clarity) 333 var end = dataOffset 334 end.Add(&dataOffset, &length) 335 end64, overflow := end.Uint64WithOverflow() 336 if overflow || uint64(len(interpreter.returnData)) < end64 { 337 return nil, ErrReturnDataOutOfBounds 338 } 339 callContext.memory.Set(memOffset.Uint64(), length.Uint64(), interpreter.returnData[offset64:end64]) 340 return nil, nil 341 } 342 343 func opExtCodeSize(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 344 slot := callContext.stack.peek() 345 slot.SetUint64(uint64(interpreter.cvm.StateDB.GetCodeSize(slot.Bytes22()))) 346 return nil, nil 347 } 348 349 func opCodeSize(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 350 l := new(uint256.Int) 351 l.SetUint64(uint64(len(callContext.contract.Code))) 352 callContext.stack.push(l) 353 return nil, nil 354 } 355 356 func opCodeCopy(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 357 var ( 358 memOffset = callContext.stack.pop() 359 codeOffset = callContext.stack.pop() 360 length = callContext.stack.pop() 361 ) 362 uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow() 363 if overflow { 364 uint64CodeOffset = 0xffffffffffffffff 365 } 366 codeCopy := getData(callContext.contract.Code, uint64CodeOffset, length.Uint64()) 367 callContext.memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy) 368 369 return nil, nil 370 } 371 372 func opExtCodeCopy(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 373 var ( 374 stack = callContext.stack 375 a = stack.pop() 376 memOffset = stack.pop() 377 codeOffset = stack.pop() 378 length = stack.pop() 379 ) 380 uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow() 381 if overflow { 382 uint64CodeOffset = 0xffffffffffffffff 383 } 384 addr := common.Address(a.Bytes22()) 385 codeCopy := getData(interpreter.cvm.StateDB.GetCode(addr), uint64CodeOffset, length.Uint64()) 386 callContext.memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy) 387 388 return nil, nil 389 } 390 391 // opExtCodeHash returns the code hash of a specified account. 392 // There are several cases when the function is called, while we can relay everything 393 // to `state.GetCodeHash` function to ensure the correctness. 394 // 395 // (1) Caller tries to get the code hash of a normal contract account, state 396 // 397 // should return the relative code hash and set it as the result. 398 // 399 // (2) Caller tries to get the code hash of a non-existent account, state should 400 // 401 // return common.Hash{} and zero will be set as the result. 402 // 403 // (3) Caller tries to get the code hash for an account without contract code, 404 // 405 // state should return emptyCodeHash(0xc5d246...) as the result. 406 // 407 // (4) Caller tries to get the code hash of a precompiled account, the result 408 // 409 // should be zero or emptyCodeHash. 410 // 411 // It is worth noting that in order to avoid unnecessary create and clean, 412 // all precompile accounts on mainnet have been transferred 1 ore, so the return 413 // here should be emptyCodeHash. 414 // If the precompile account is not transferred any amount on a private or 415 // customized chain, the return value will be zero. 416 // 417 // (5) Caller tries to get the code hash for an account which is marked as suicided 418 // 419 // in the current transaction, the code hash of this account should be returned. 420 // 421 // (6) Caller tries to get the code hash for an account which is marked as deleted, 422 // 423 // this account should be regarded as a non-existent account and zero should be returned. 424 func opExtCodeHash(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 425 slot := callContext.stack.peek() 426 address := common.Address(slot.Bytes22()) 427 if interpreter.cvm.StateDB.Empty(address) { 428 slot.Clear() 429 } else { 430 slot.SetBytes(interpreter.cvm.StateDB.GetCodeHash(address).Bytes()) 431 } 432 return nil, nil 433 } 434 435 func opEnergyprice(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 436 v, _ := uint256.FromBig(interpreter.cvm.EnergyPrice) 437 callContext.stack.push(v) 438 return nil, nil 439 } 440 441 func opBlockhash(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 442 num := callContext.stack.peek() 443 num64, overflow := num.Uint64WithOverflow() 444 if overflow { 445 num.Clear() 446 return nil, nil 447 } 448 var upper, lower uint64 449 upper = interpreter.cvm.Context.BlockNumber.Uint64() 450 if upper < 257 { 451 lower = 0 452 } else { 453 lower = upper - 256 454 } 455 if num64 >= lower && num64 < upper { 456 num.SetBytes(interpreter.cvm.Context.GetHash(num64).Bytes()) 457 } else { 458 num.Clear() 459 } 460 return nil, nil 461 } 462 463 func opCoinbase(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 464 callContext.stack.push(new(uint256.Int).SetBytes(interpreter.cvm.Context.Coinbase.Bytes())) 465 return nil, nil 466 } 467 468 func opTimestamp(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 469 v, _ := uint256.FromBig(interpreter.cvm.Context.Time) 470 callContext.stack.push(v) 471 return nil, nil 472 } 473 474 func opNumber(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 475 v, _ := uint256.FromBig(interpreter.cvm.Context.BlockNumber) 476 callContext.stack.push(v) 477 return nil, nil 478 } 479 480 func opDifficulty(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 481 v, _ := uint256.FromBig(interpreter.cvm.Context.Difficulty) 482 callContext.stack.push(v) 483 return nil, nil 484 } 485 486 func opEnergyLimit(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 487 callContext.stack.push(new(uint256.Int).SetUint64(interpreter.cvm.Context.EnergyLimit)) 488 return nil, nil 489 } 490 491 func opPop(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 492 callContext.stack.pop() 493 return nil, nil 494 } 495 496 func opMload(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 497 v := callContext.stack.peek() 498 offset := int64(v.Uint64()) 499 v.SetBytes(callContext.memory.GetPtr(offset, 32)) 500 return nil, nil 501 } 502 503 func opMstore(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 504 // pop value of the stack 505 mStart, val := callContext.stack.pop(), callContext.stack.pop() 506 callContext.memory.Set32(mStart.Uint64(), &val) 507 return nil, nil 508 } 509 510 func opMstore8(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 511 off, val := callContext.stack.pop(), callContext.stack.pop() 512 callContext.memory.store[off.Uint64()] = byte(val.Uint64()) 513 return nil, nil 514 } 515 516 func opSload(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 517 loc := callContext.stack.peek() 518 hash := common.Hash(loc.Bytes32()) 519 val := interpreter.cvm.StateDB.GetState(callContext.contract.Address(), hash) 520 loc.SetBytes(val.Bytes()) 521 return nil, nil 522 } 523 524 func opSstore(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 525 loc := callContext.stack.pop() 526 val := callContext.stack.pop() 527 interpreter.cvm.StateDB.SetState(callContext.contract.Address(), 528 loc.Bytes32(), val.Bytes32()) 529 return nil, nil 530 } 531 532 func opJump(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 533 pos := callContext.stack.pop() 534 if !callContext.contract.validJumpdest(&pos) { 535 return nil, ErrInvalidJump 536 } 537 *pc = pos.Uint64() 538 return nil, nil 539 } 540 541 func opJumpi(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 542 pos, cond := callContext.stack.pop(), callContext.stack.pop() 543 if !cond.IsZero() { 544 if !callContext.contract.validJumpdest(&pos) { 545 return nil, ErrInvalidJump 546 } 547 *pc = pos.Uint64() 548 } else { 549 *pc++ 550 } 551 return nil, nil 552 } 553 554 func opJumpdest(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 555 return nil, nil 556 } 557 558 func opBeginSub(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 559 return nil, ErrInvalidSubroutineEntry 560 } 561 562 func opJumpSub(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 563 if len(callContext.rstack.data) >= 1023 { 564 return nil, ErrReturnStackExceeded 565 } 566 pos := callContext.stack.pop() 567 if !pos.IsUint64() { 568 return nil, ErrInvalidJump 569 } 570 posU64 := pos.Uint64() 571 if !callContext.contract.validJumpSubdest(posU64) { 572 return nil, ErrInvalidJump 573 } 574 callContext.rstack.push(uint32(*pc)) 575 *pc = posU64 + 1 576 return nil, nil 577 } 578 579 func opReturnSub(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 580 if len(callContext.rstack.data) == 0 { 581 return nil, ErrInvalidRetsub 582 } 583 // Other than the check that the return stack is not empty, there is no 584 // need to validate the pc from 'returns', since we only ever push valid 585 //values onto it via jumpsub. 586 *pc = uint64(callContext.rstack.pop()) + 1 587 return nil, nil 588 } 589 590 func opPc(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 591 callContext.stack.push(new(uint256.Int).SetUint64(*pc)) 592 return nil, nil 593 } 594 595 func opMsize(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 596 callContext.stack.push(new(uint256.Int).SetUint64(uint64(callContext.memory.Len()))) 597 return nil, nil 598 } 599 600 func opEnergy(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 601 callContext.stack.push(new(uint256.Int).SetUint64(callContext.contract.Energy)) 602 return nil, nil 603 } 604 605 func opCreate(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 606 var ( 607 value = callContext.stack.pop() 608 offset, size = callContext.stack.pop(), callContext.stack.pop() 609 input = callContext.memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64())) 610 energy = callContext.contract.Energy 611 ) 612 energy -= energy / 64 613 // reuse size int for stackvalue 614 stackvalue := size 615 616 callContext.contract.UseEnergy(energy) 617 //TODO: use uint256.Int instead of converting with toBig() 618 var bigVal = big0 619 if !value.IsZero() { 620 bigVal = value.ToBig() 621 } 622 623 res, addr, returnEnergy, suberr := interpreter.cvm.Create(callContext.contract, input, energy, bigVal) 624 // Push item on the stack based on the returned error. If the ruleset is 625 // homestead we must check for CodeStoreOutOfEnergyError (homestead only 626 // rule) and treat as an error, if the ruleset is frontier we must 627 // ignore this error and pretend the operation was successful. 628 if suberr == ErrCodeStoreOutOfEnergy { 629 stackvalue.Clear() 630 } else if suberr != nil && suberr != ErrCodeStoreOutOfEnergy { 631 stackvalue.Clear() 632 } else { 633 stackvalue.SetBytes(addr.Bytes()) 634 } 635 callContext.stack.push(&stackvalue) 636 callContext.contract.Energy += returnEnergy 637 638 if suberr == ErrExecutionReverted { 639 return res, nil 640 } 641 return nil, nil 642 } 643 644 func opCreate2(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 645 var ( 646 endowment = callContext.stack.pop() 647 offset, size = callContext.stack.pop(), callContext.stack.pop() 648 salt = callContext.stack.pop() 649 input = callContext.memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64())) 650 energy = callContext.contract.Energy 651 ) 652 653 // Apply CIP150 654 energy -= energy / 64 655 callContext.contract.UseEnergy(energy) 656 // reuse size int for stackvalue 657 stackvalue := size 658 //TODO: use uint256.Int instead of converting with toBig() 659 bigEndowment := big0 660 if !endowment.IsZero() { 661 bigEndowment = endowment.ToBig() 662 } 663 res, addr, returnEnergy, suberr := interpreter.cvm.Create2(callContext.contract, input, energy, 664 bigEndowment, &salt) 665 // Push item on the stack based on the returned error. 666 if suberr != nil { 667 stackvalue.Clear() 668 } else { 669 stackvalue.SetBytes(addr.Bytes()) 670 } 671 callContext.stack.push(&stackvalue) 672 callContext.contract.Energy += returnEnergy 673 674 if suberr == ErrExecutionReverted { 675 return res, nil 676 } 677 return nil, nil 678 } 679 680 func opCall(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 681 stack := callContext.stack 682 // Pop energy. The actual energy in interpreter.cvm.callEnergyTemp. 683 // We can use this as a temporary value 684 temp := stack.pop() 685 energy := interpreter.cvm.callEnergyTemp 686 // Pop other call parameters. 687 addr, value, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop() 688 toAddr := common.Address(addr.Bytes22()) 689 // Get the arguments from the memory. 690 args := callContext.memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64())) 691 692 var bigVal = big0 693 //TODO: use uint256.Int instead of converting with toBig() 694 // By using big0 here, we save an alloc for the most common case (non-core-transferring contract calls), 695 // but it would make more sense to extend the usage of uint256.Int 696 if !value.IsZero() { 697 energy += params.CallStipend 698 bigVal = value.ToBig() 699 } 700 701 ret, returnEnergy, err := interpreter.cvm.Call(callContext.contract, toAddr, args, energy, bigVal) 702 703 if err != nil { 704 temp.Clear() 705 } else { 706 temp.SetOne() 707 } 708 stack.push(&temp) 709 if err == nil || err == ErrExecutionReverted { 710 callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) 711 } 712 callContext.contract.Energy += returnEnergy 713 714 return ret, nil 715 } 716 717 func opCallCode(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 718 // Pop energy. The actual energy is in interpreter.cvm.callEnergyTemp. 719 stack := callContext.stack 720 // We use it as a temporary value 721 temp := stack.pop() 722 energy := interpreter.cvm.callEnergyTemp 723 // Pop other call parameters. 724 addr, value, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop() 725 toAddr := common.Address(addr.Bytes22()) 726 // Get arguments from the memory. 727 args := callContext.memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64())) 728 729 //TODO: use uint256.Int instead of converting with toBig() 730 var bigVal = big0 731 if !value.IsZero() { 732 energy += params.CallStipend 733 bigVal = value.ToBig() 734 } 735 736 ret, returnEnergy, err := interpreter.cvm.CallCode(callContext.contract, toAddr, args, energy, bigVal) 737 if err != nil { 738 temp.Clear() 739 } else { 740 temp.SetOne() 741 } 742 stack.push(&temp) 743 if err == nil || err == ErrExecutionReverted { 744 callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) 745 } 746 callContext.contract.Energy += returnEnergy 747 748 return ret, nil 749 } 750 751 func opDelegateCall(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 752 stack := callContext.stack 753 // Pop energy. The actual energy is in interpreter.cvm.callEnergyTemp. 754 // We use it as a temporary value 755 temp := stack.pop() 756 energy := interpreter.cvm.callEnergyTemp 757 // Pop other call parameters. 758 addr, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop() 759 toAddr := common.Address(addr.Bytes22()) 760 // Get arguments from the memory. 761 args := callContext.memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64())) 762 763 ret, returnEnergy, err := interpreter.cvm.DelegateCall(callContext.contract, toAddr, args, energy) 764 if err != nil { 765 temp.Clear() 766 } else { 767 temp.SetOne() 768 } 769 stack.push(&temp) 770 if err == nil || err == ErrExecutionReverted { 771 callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) 772 } 773 callContext.contract.Energy += returnEnergy 774 775 return ret, nil 776 } 777 778 func opStaticCall(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 779 // Pop energy. The actual energy is in interpreter.cvm.callEnergyTemp. 780 stack := callContext.stack 781 // We use it as a temporary value 782 temp := stack.pop() 783 energy := interpreter.cvm.callEnergyTemp 784 // Pop other call parameters. 785 addr, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop() 786 toAddr := common.Address(addr.Bytes22()) 787 // Get arguments from the memory. 788 args := callContext.memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64())) 789 790 ret, returnEnergy, err := interpreter.cvm.StaticCall(callContext.contract, toAddr, args, energy) 791 if err != nil { 792 temp.Clear() 793 } else { 794 temp.SetOne() 795 } 796 stack.push(&temp) 797 if err == nil || err == ErrExecutionReverted { 798 callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) 799 } 800 callContext.contract.Energy += returnEnergy 801 802 return ret, nil 803 } 804 805 func opReturn(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 806 offset, size := callContext.stack.pop(), callContext.stack.pop() 807 ret := callContext.memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64())) 808 809 return ret, nil 810 } 811 812 func opRevert(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 813 offset, size := callContext.stack.pop(), callContext.stack.pop() 814 ret := callContext.memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64())) 815 816 return ret, nil 817 } 818 819 func opStop(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 820 return nil, nil 821 } 822 823 func opSuicide(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 824 beneficiary := callContext.stack.pop() 825 balance := interpreter.cvm.StateDB.GetBalance(callContext.contract.Address()) 826 interpreter.cvm.StateDB.AddBalance(beneficiary.Bytes22(), balance) 827 interpreter.cvm.StateDB.Suicide(callContext.contract.Address()) 828 return nil, nil 829 } 830 831 // following functions are used by the instruction jump table 832 833 // make log instruction function 834 func makeLog(size int) executionFunc { 835 return func(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 836 topics := make([]common.Hash, size) 837 stack := callContext.stack 838 mStart, mSize := stack.pop(), stack.pop() 839 for i := 0; i < size; i++ { 840 addr := stack.pop() 841 topics[i] = addr.Bytes32() 842 } 843 844 d := callContext.memory.GetCopy(int64(mStart.Uint64()), int64(mSize.Uint64())) 845 interpreter.cvm.StateDB.AddLog(&types.Log{ 846 Address: callContext.contract.Address(), 847 Topics: topics, 848 Data: d, 849 // This is a non-consensus field, but assigned here because 850 // core/state doesn't know the current block number. 851 BlockNumber: interpreter.cvm.Context.BlockNumber.Uint64(), 852 }) 853 854 return nil, nil 855 } 856 } 857 858 // opPush1 is a specialized version of pushN 859 func opPush1(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 860 var ( 861 codeLen = uint64(len(callContext.contract.Code)) 862 integer = new(uint256.Int) 863 ) 864 *pc += 1 865 if *pc < codeLen { 866 callContext.stack.push(integer.SetUint64(uint64(callContext.contract.Code[*pc]))) 867 } else { 868 callContext.stack.push(integer.Clear()) 869 } 870 return nil, nil 871 } 872 873 // make push instruction function 874 func makePush(size uint64, pushByteSize int) executionFunc { 875 return func(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 876 codeLen := len(callContext.contract.Code) 877 878 startMin := codeLen 879 if int(*pc+1) < startMin { 880 startMin = int(*pc + 1) 881 } 882 883 endMin := codeLen 884 if startMin+pushByteSize < endMin { 885 endMin = startMin + pushByteSize 886 } 887 888 integer := new(uint256.Int) 889 callContext.stack.push(integer.SetBytes(common.RightPadBytes( 890 callContext.contract.Code[startMin:endMin], pushByteSize))) 891 892 *pc += size 893 return nil, nil 894 } 895 } 896 897 // make dup instruction function 898 func makeDup(size int64) executionFunc { 899 return func(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 900 callContext.stack.dup(int(size)) 901 return nil, nil 902 } 903 } 904 905 // make swap instruction function 906 func makeSwap(size int64) executionFunc { 907 // switch n + 1 otherwise n would be swapped with n 908 size++ 909 return func(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 910 callContext.stack.swap(int(size)) 911 return nil, nil 912 } 913 }