github.com/core-coin/go-core@v1.1.7/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/go-core/common" 21 "github.com/core-coin/go-core/core/types" 22 "github.com/core-coin/go-core/params" 23 "github.com/core-coin/uint256" 24 "golang.org/x/crypto/sha3" 25 ) 26 27 func opAdd(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 28 x, y := callContext.stack.pop(), callContext.stack.peek() 29 y.Add(&x, y) 30 return nil, nil 31 } 32 33 func opSub(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 34 x, y := callContext.stack.pop(), callContext.stack.peek() 35 y.Sub(&x, y) 36 return nil, nil 37 } 38 39 func opMul(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 40 x, y := callContext.stack.pop(), callContext.stack.peek() 41 y.Mul(&x, y) 42 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 callContext.stack, first arg1 and then arg2, 190 // and pushes on the callContext.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 callContext.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 200 return nil, nil 201 } 202 203 // opSHR implements Logical Shift Right 204 // The SHR instruction (logical shift right) pops 2 values from the callContext.stack, first arg1 and then arg2, 205 // and pushes on the callContext.stack arg2 shifted to the right by arg1 number of bits with zero fill. 206 func opSHR(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 207 // Note, second operand is left in the callContext.stack; accumulate result into it, and no need to push it afterwards 208 shift, value := callContext.stack.pop(), callContext.stack.peek() 209 if shift.LtUint64(256) { 210 value.Rsh(value, uint(shift.Uint64())) 211 } else { 212 value.Clear() 213 } 214 215 return nil, nil 216 } 217 218 // opSAR implements Arithmetic Shift Right 219 // The SAR instruction (arithmetic shift right) pops 2 values from the callContext.stack, first arg1 and then arg2, 220 // and pushes on the callContext.stack arg2 shifted to the right by arg1 number of bits with sign extension. 221 func opSAR(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 222 // Note, S256 returns (potentially) a new bigint, so we're popping, not peeking this one 223 shift, value := callContext.stack.pop(), callContext.stack.peek() 224 if shift.GtUint64(256) { 225 if value.Sign() >= 0 { 226 value.Clear() 227 } else { 228 // Max negative shift: all bits set 229 value.SetAllOne() 230 } 231 return nil, nil 232 } 233 n := uint(shift.Uint64()) 234 value.SRsh(value, n) 235 236 return nil, nil 237 } 238 239 func opSha3(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 240 offset, size := callContext.stack.pop(), callContext.stack.peek() 241 data := callContext.memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64())) 242 243 if interpreter.hasher == nil { 244 interpreter.hasher = sha3.New256().(keccakState) 245 } else { 246 interpreter.hasher.Reset() 247 } 248 interpreter.hasher.Write(data) 249 interpreter.hasher.Read(interpreter.hasherBuf[:]) 250 251 cvm := interpreter.cvm 252 if cvm.vmConfig.EnablePreimageRecording { 253 cvm.StateDB.AddPreimage(interpreter.hasherBuf, data) 254 } 255 size.SetBytes(interpreter.hasherBuf[:]) 256 return nil, nil 257 } 258 259 func opAddress(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 260 callContext.stack.push(new(uint256.Int).SetBytes(callContext.contract.Address().Bytes())) 261 return nil, nil 262 } 263 264 func opBalance(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 265 slot := callContext.stack.peek() 266 address := common.Address(slot.Bytes22()) 267 slot.SetFromBig(interpreter.cvm.StateDB.GetBalance(address)) 268 return nil, nil 269 } 270 271 func opOrigin(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 272 callContext.stack.push(new(uint256.Int).SetBytes(interpreter.cvm.Origin.Bytes())) 273 return nil, nil 274 } 275 276 func opCaller(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 277 callContext.stack.push(new(uint256.Int).SetBytes(callContext.contract.Caller().Bytes())) 278 return nil, nil 279 } 280 281 func opCallValue(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 282 v, _ := uint256.FromBig(callContext.contract.value) 283 callContext.stack.push(v) 284 return nil, nil 285 } 286 287 func opCallDataLoad(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 288 x := callContext.stack.peek() 289 if offset, overflow := x.Uint64WithOverflow(); !overflow { 290 data := getData(callContext.contract.Input, offset, 32) 291 x.SetBytes(data) 292 } else { 293 x.Clear() 294 } 295 return nil, nil 296 } 297 298 func opCallDataSize(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 299 callContext.stack.push(new(uint256.Int).SetUint64(uint64(len(callContext.contract.Input)))) 300 return nil, nil 301 } 302 303 func opCallDataCopy(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 304 var ( 305 memOffset = callContext.stack.pop() 306 dataOffset = callContext.stack.pop() 307 length = callContext.stack.pop() 308 ) 309 dataOffset64, overflow := dataOffset.Uint64WithOverflow() 310 if overflow { 311 dataOffset64 = 0xffffffffffffffff 312 } 313 // These values are checked for overflow during energy cost calculation 314 memOffset64 := memOffset.Uint64() 315 length64 := length.Uint64() 316 callContext.memory.Set(memOffset64, length64, getData(callContext.contract.Input, dataOffset64, length64)) 317 return nil, nil 318 } 319 320 func opReturnDataSize(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 321 callContext.stack.push(new(uint256.Int).SetUint64(uint64(len(interpreter.returnData)))) 322 return nil, nil 323 } 324 325 func opReturnDataCopy(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 326 var ( 327 memOffset = callContext.stack.pop() 328 dataOffset = callContext.stack.pop() 329 length = callContext.stack.pop() 330 ) 331 332 offset64, overflow := dataOffset.Uint64WithOverflow() 333 if overflow { 334 return nil, ErrReturnDataOutOfBounds 335 } 336 // we can reuse dataOffset now (aliasing it for clarity) 337 var end = dataOffset 338 end.Add(&dataOffset, &length) 339 end64, overflow := end.Uint64WithOverflow() 340 if overflow || uint64(len(interpreter.returnData)) < end64 { 341 return nil, ErrReturnDataOutOfBounds 342 } 343 callContext.memory.Set(memOffset.Uint64(), length.Uint64(), interpreter.returnData[offset64:end64]) 344 return nil, nil 345 } 346 347 func opExtCodeSize(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 348 slot := callContext.stack.peek() 349 slot.SetUint64(uint64(interpreter.cvm.StateDB.GetCodeSize(common.Address(slot.Bytes22())))) 350 351 return nil, nil 352 } 353 354 func opCodeSize(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 355 l := new(uint256.Int) 356 l.SetUint64(uint64(len(callContext.contract.Code))) 357 callContext.stack.push(l) 358 359 return nil, nil 360 } 361 362 func opCodeCopy(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 363 var ( 364 memOffset = callContext.stack.pop() 365 codeOffset = callContext.stack.pop() 366 length = callContext.stack.pop() 367 ) 368 uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow() 369 if overflow { 370 uint64CodeOffset = 0xffffffffffffffff 371 } 372 codeCopy := getData(callContext.contract.Code, uint64CodeOffset, length.Uint64()) 373 callContext.memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy) 374 375 return nil, nil 376 } 377 378 func opExtCodeCopy(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 379 var ( 380 a = callContext.stack.pop() 381 memOffset = callContext.stack.pop() 382 codeOffset = callContext.stack.pop() 383 length = callContext.stack.pop() 384 ) 385 uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow() 386 if overflow { 387 uint64CodeOffset = 0xffffffffffffffff 388 } 389 addr := common.Address(a.Bytes22()) 390 codeCopy := getData(interpreter.cvm.StateDB.GetCode(addr), uint64CodeOffset, length.Uint64()) 391 callContext.memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy) 392 393 return nil, nil 394 } 395 396 // opExtCodeHash returns the code hash of a specified account. 397 // There are several cases when the function is called, while we can relay everything 398 // to `state.GetCodeHash` function to ensure the correctness. 399 // (1) Caller tries to get the code hash of a normal callContext.contract account, state 400 // should return the relative code hash and set it as the result. 401 // 402 // (2) Caller tries to get the code hash of a non-existent account, state should 403 // return common.Hash{} and zero will be set as the result. 404 // 405 // (3) Caller tries to get the code hash for an account without callContext.contract code, 406 // state should return emptyCodeHash(0xc5d246...) as the result. 407 // 408 // (4) Caller tries to get the code hash of a precompiled account, the result 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 // in the current transaction, the code hash of this account should be returned. 419 // 420 // (6) Caller tries to get the code hash for an account which is marked as deleted, 421 // this account should be regarded as a non-existent account and zero should be returned. 422 func opExtCodeHash(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 423 slot := callContext.stack.peek() 424 address := common.Address(slot.Bytes22()) 425 if interpreter.cvm.StateDB.Empty(address) { 426 slot.Clear() 427 } else { 428 slot.SetBytes(interpreter.cvm.StateDB.GetCodeHash(address).Bytes()) 429 } 430 return nil, nil 431 } 432 433 func opEnergyprice(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 434 v, _ := uint256.FromBig(interpreter.cvm.EnergyPrice) 435 callContext.stack.push(v) 436 return nil, nil 437 } 438 439 func opBlockhash(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 440 num := callContext.stack.peek() 441 num64, overflow := num.Uint64WithOverflow() 442 if overflow { 443 num.Clear() 444 return nil, nil 445 } 446 var upper, lower uint64 447 upper = interpreter.cvm.BlockNumber.Uint64() 448 if upper < 257 { 449 lower = 0 450 } else { 451 lower = upper - 256 452 } 453 if num64 >= lower && num64 < upper { 454 num.SetBytes(interpreter.cvm.GetHash(num64).Bytes()) 455 } else { 456 num.Clear() 457 } 458 return nil, nil 459 } 460 461 func opCoinbase(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 462 callContext.stack.push(new(uint256.Int).SetBytes(interpreter.cvm.Coinbase.Bytes())) 463 return nil, nil 464 } 465 466 func opTimestamp(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 467 v, _ := uint256.FromBig(interpreter.cvm.Time) 468 callContext.stack.push(v) 469 return nil, nil 470 } 471 472 func opNumber(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 473 v, _ := uint256.FromBig(interpreter.cvm.BlockNumber) 474 callContext.stack.push(v) 475 return nil, nil 476 } 477 478 func opDifficulty(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 479 v, _ := uint256.FromBig(interpreter.cvm.Difficulty) 480 callContext.stack.push(v) 481 return nil, nil 482 } 483 484 func opEnergyLimit(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 485 callContext.stack.push(new(uint256.Int).SetUint64(interpreter.cvm.EnergyLimit)) 486 return nil, nil 487 } 488 489 func opPop(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 490 callContext.stack.pop() 491 return nil, nil 492 } 493 494 func opMload(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 495 v := callContext.stack.peek() 496 offset := int64(v.Uint64()) 497 v.SetBytes(callContext.memory.GetPtr(offset, 32)) 498 return nil, nil 499 } 500 501 func opMstore(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 502 // pop value of the callContext.stack 503 mStart, val := callContext.stack.pop(), callContext.stack.pop() 504 callContext.memory.Set32(mStart.Uint64(), &val) 505 return nil, nil 506 } 507 508 func opMstore8(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 509 off, val := callContext.stack.pop(), callContext.stack.pop() 510 callContext.memory.store[off.Uint64()] = byte(val.Uint64()) 511 return nil, nil 512 } 513 514 func opSload(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 515 loc := callContext.stack.peek() 516 hash := common.Hash(loc.Bytes32()) 517 val := interpreter.cvm.StateDB.GetState(callContext.contract.Address(), hash) 518 loc.SetBytes(val.Bytes()) 519 return nil, nil 520 } 521 522 func opSstore(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 523 loc := callContext.stack.pop() 524 val := callContext.stack.pop() 525 interpreter.cvm.StateDB.SetState(callContext.contract.Address(), 526 common.Hash(loc.Bytes32()), common.Hash(val.Bytes32())) 527 return nil, nil 528 } 529 530 func opJump(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 531 pos := callContext.stack.pop() 532 if !callContext.contract.validJumpdest(&pos) { 533 return nil, ErrInvalidJump 534 } 535 *pc = pos.Uint64() 536 537 return nil, nil 538 } 539 540 func opJumpi(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 541 pos, cond := callContext.stack.pop(), callContext.stack.pop() 542 if !cond.IsZero() { 543 if !callContext.contract.validJumpdest(&pos) { 544 return nil, ErrInvalidJump 545 } 546 *pc = pos.Uint64() 547 } else { 548 *pc++ 549 } 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 613 energy -= energy / 64 614 // reuse size int for callContext.stackvalue 615 stackvalue := size 616 617 callContext.contract.UseEnergy(energy) 618 //TODO: use uint256.Int instead of converting with toBig() 619 var bigVal = big0 620 if !value.IsZero() { 621 bigVal = value.ToBig() 622 } 623 624 res, addr, returnEnergy, suberr := interpreter.cvm.Create(callContext.contract, input, energy, bigVal) 625 // Push item on the callContext.stack based on the returned error. We must 626 // ignore this error and pretend the operation was successful. 627 if suberr == ErrCodeStoreOutOfEnergy { 628 stackvalue.Clear() 629 } else if suberr != nil && suberr != ErrCodeStoreOutOfEnergy { 630 stackvalue.Clear() 631 } else { 632 stackvalue.SetBytes(addr.Bytes()) 633 } 634 callContext.stack.push(&stackvalue) 635 callContext.contract.Energy += returnEnergy 636 637 if suberr == ErrExecutionReverted { 638 return res, nil 639 } 640 return nil, nil 641 } 642 643 func opCreate2(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 644 var ( 645 endowment = callContext.stack.pop() 646 offset, size = callContext.stack.pop(), callContext.stack.pop() 647 salt = callContext.stack.pop() 648 input = callContext.memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64())) 649 energy = callContext.contract.Energy 650 ) 651 652 // Apply CIP150 653 energy -= energy / 64 654 callContext.contract.UseEnergy(energy) 655 // reuse size int for callContext.stackvalue 656 stackvalue := size 657 //TODO: use uint256.Int instead of converting with toBig() 658 bigEndowment := big0 659 if !endowment.IsZero() { 660 bigEndowment = endowment.ToBig() 661 } 662 res, addr, returnEnergy, suberr := interpreter.cvm.Create2(callContext.contract, input, energy, 663 bigEndowment, &salt) 664 // Push item on the callContext.stack based on the returned error. 665 if suberr != nil { 666 stackvalue.Clear() 667 } else { 668 stackvalue.SetBytes(addr.Bytes()) 669 } 670 callContext.stack.push(&stackvalue) 671 callContext.contract.Energy += returnEnergy 672 673 if suberr == ErrExecutionReverted { 674 return res, nil 675 } 676 return nil, nil 677 } 678 679 func opCall(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 680 // Pop energy. The actual energy in interpreter.cvm.callEnergyTemp. 681 // We can use this as a temporary value 682 temp := callContext.stack.pop() 683 energy := interpreter.cvm.callEnergyTemp 684 // Pop other call parameters. 685 addr, value, inOffset, inSize, retOffset, retSize := callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop() 686 toAddr := common.Address(addr.Bytes22()) 687 // Get the arguments from the callContext.memory. 688 args := callContext.memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64())) 689 690 var bigVal = big0 691 //TODO: use uint256.Int instead of converting with toBig() 692 // By using big0 here, we save an alloc for the most common case (non-ether-transferring contract calls), 693 // but it would make more sense to extend the usage of uint256.Int 694 if !value.IsZero() { 695 energy += params.CallStipend 696 bigVal = value.ToBig() 697 } 698 699 ret, returnEnergy, err := interpreter.cvm.Call(callContext.contract, toAddr, args, energy, bigVal) 700 if err != nil { 701 temp.Clear() 702 } else { 703 temp.SetOne() 704 } 705 callContext.stack.push(&temp) 706 if err == nil || err == ErrExecutionReverted { 707 callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) 708 } 709 callContext.contract.Energy += returnEnergy 710 return ret, nil 711 } 712 713 func opCallCode(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 714 // Pop energy. The actual energy is in interpreter.cvm.callEnergyTemp. 715 // We use it as a temporary value 716 temp := callContext.stack.pop() 717 energy := interpreter.cvm.callEnergyTemp 718 // Pop other call parameters. 719 addr, value, inOffset, inSize, retOffset, retSize := callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop() 720 toAddr := common.Address(addr.Bytes22()) 721 // Get arguments from the callContext.memory. 722 args := callContext.memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64())) 723 724 //TODO: use uint256.Int instead of converting with toBig() 725 var bigVal = big0 726 if !value.IsZero() { 727 energy += params.CallStipend 728 bigVal = value.ToBig() 729 } 730 731 ret, returnEnergy, err := interpreter.cvm.CallCode(callContext.contract, toAddr, args, energy, bigVal) 732 if err != nil { 733 temp.Clear() 734 } else { 735 temp.SetOne() 736 } 737 callContext.stack.push(&temp) 738 if err == nil || err == ErrExecutionReverted { 739 callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) 740 } 741 callContext.contract.Energy += returnEnergy 742 return ret, nil 743 } 744 745 func opDelegateCall(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 746 // Pop energy. The actual energy is in interpreter.cvm.callEnergyTemp. 747 // We use it as a temporary value 748 temp := callContext.stack.pop() 749 energy := interpreter.cvm.callEnergyTemp 750 // Pop other call parameters. 751 addr, inOffset, inSize, retOffset, retSize := callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop() 752 toAddr := common.Address(addr.Bytes22()) 753 // Get arguments from the callContext.memory. 754 args := callContext.memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64())) 755 756 ret, returnEnergy, err := interpreter.cvm.DelegateCall(callContext.contract, toAddr, args, energy) 757 if err != nil { 758 temp.Clear() 759 } else { 760 temp.SetOne() 761 } 762 callContext.stack.push(&temp) 763 if err == nil || err == ErrExecutionReverted { 764 callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) 765 } 766 callContext.contract.Energy += returnEnergy 767 return ret, nil 768 } 769 770 func opStaticCall(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 771 // Pop energy. The actual energy is in interpreter.cvm.callEnergyTemp. 772 // We use it as a temporary value 773 temp := callContext.stack.pop() 774 energy := interpreter.cvm.callEnergyTemp 775 // Pop other call parameters. 776 addr, inOffset, inSize, retOffset, retSize := callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop() 777 toAddr := common.Address(addr.Bytes22()) 778 // Get arguments from the callContext.memory. 779 args := callContext.memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64())) 780 781 ret, returnEnergy, err := interpreter.cvm.StaticCall(callContext.contract, toAddr, args, energy) 782 if err != nil { 783 temp.Clear() 784 } else { 785 temp.SetOne() 786 } 787 callContext.stack.push(&temp) 788 if err == nil || err == ErrExecutionReverted { 789 callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) 790 } 791 callContext.contract.Energy += returnEnergy 792 return ret, nil 793 } 794 795 func opReturn(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 796 offset, size := callContext.stack.pop(), callContext.stack.pop() 797 ret := callContext.memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64())) 798 return ret, nil 799 } 800 801 func opRevert(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 802 offset, size := callContext.stack.pop(), callContext.stack.pop() 803 ret := callContext.memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64())) 804 return ret, nil 805 } 806 807 func opStop(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 808 return nil, nil 809 } 810 811 func opSuicide(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 812 beneficiary := callContext.stack.pop() 813 balance := interpreter.cvm.StateDB.GetBalance(callContext.contract.Address()) 814 interpreter.cvm.StateDB.AddBalance(common.Address(beneficiary.Bytes22()), balance) 815 816 interpreter.cvm.StateDB.Suicide(callContext.contract.Address()) 817 return nil, nil 818 } 819 820 // following functions are used by the instruction jump table 821 822 // make log instruction function 823 func makeLog(size int) executionFunc { 824 return func(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 825 topics := make([]common.Hash, size) 826 mStart, mSize := callContext.stack.pop(), callContext.stack.pop() 827 for i := 0; i < size; i++ { 828 addr := callContext.stack.pop() 829 topics[i] = common.Hash(addr.Bytes32()) 830 } 831 832 d := callContext.memory.GetCopy(int64(mStart.Uint64()), int64(mSize.Uint64())) 833 interpreter.cvm.StateDB.AddLog(&types.Log{ 834 Address: callContext.contract.Address(), 835 Topics: topics, 836 Data: d, 837 // This is a non-consensus field, but assigned here because 838 // core/state doesn't know the current block number. 839 BlockNumber: interpreter.cvm.BlockNumber.Uint64(), 840 }) 841 842 return nil, nil 843 } 844 } 845 846 // opPush1 is a specialized version of pushN 847 func opPush1(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 848 var ( 849 codeLen = uint64(len(callContext.contract.Code)) 850 integer = new(uint256.Int) 851 ) 852 *pc += 1 853 if *pc < codeLen { 854 callContext.stack.push(integer.SetUint64(uint64(callContext.contract.Code[*pc]))) 855 } else { 856 callContext.stack.push(integer.Clear()) 857 } 858 return nil, nil 859 } 860 861 // make push instruction function 862 func makePush(size uint64, pushByteSize int) executionFunc { 863 return func(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 864 codeLen := len(callContext.contract.Code) 865 866 startMin := codeLen 867 if int(*pc+1) < startMin { 868 startMin = int(*pc + 1) 869 } 870 871 endMin := codeLen 872 if startMin+pushByteSize < endMin { 873 endMin = startMin + pushByteSize 874 } 875 876 integer := new(uint256.Int) 877 callContext.stack.push(integer.SetBytes(common.RightPadBytes( 878 callContext.contract.Code[startMin:endMin], pushByteSize))) 879 880 *pc += size 881 return nil, nil 882 } 883 } 884 885 // make dup instruction function 886 func makeDup(size int64) executionFunc { 887 return func(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 888 callContext.stack.dup(int(size)) 889 return nil, nil 890 } 891 } 892 893 // make swap instruction function 894 func makeSwap(size int64) executionFunc { 895 // switch n + 1 otherwise n would be swapped with n 896 size++ 897 return func(pc *uint64, interpreter *CVMInterpreter, callContext *callCtx) ([]byte, error) { 898 callContext.stack.swap(int(size)) 899 return nil, nil 900 } 901 }