Coverage Summary for Class: VM (org.ethereum.vm)

Class Method, % Line, %
VM 43.9% (43/98) 33.2% (369/1113)
VM$1 0% (0/1) 0% (0/1)
Total 43.4% (43/99) 33.1% (369/1114)


1 /* 2  * This file is part of RskJ 3  * Copyright (C) 2017 RSK Labs Ltd. 4  * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>) 5  * 6  * This program is free software: you can redistribute it and/or modify 7  * it under the terms of the GNU Lesser General Public License as published by 8  * the Free Software Foundation, either version 3 of the License, or 9  * (at your option) any later version. 10  * 11  * This program is distributed in the hope that it will be useful, 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14  * GNU Lesser General Public License for more details. 15  * 16  * You should have received a copy of the GNU Lesser General Public License 17  * along with this program. If not, see <http://www.gnu.org/licenses/>. 18  */ 19  20 package org.ethereum.vm; 21  22 import co.rsk.config.VmConfig; 23 import co.rsk.core.RskAddress; 24 import co.rsk.crypto.Keccak256; 25 import org.bouncycastle.util.BigIntegers; 26 import org.ethereum.config.blockchain.upgrades.ActivationConfig; 27 import org.ethereum.core.Repository; 28 import org.ethereum.crypto.HashUtil; 29 import org.ethereum.crypto.Keccak256Helper; 30 import org.ethereum.util.ByteUtil; 31 import org.ethereum.vm.MessageCall.MsgType; 32 import org.ethereum.vm.program.Program; 33 import org.ethereum.vm.program.Stack; 34 import org.slf4j.Logger; 35 import org.slf4j.LoggerFactory; 36  37 import java.math.BigInteger; 38 import java.util.ArrayList; 39 import java.util.Iterator; 40 import java.util.List; 41  42 import static org.ethereum.config.blockchain.upgrades.ConsensusRule.*; 43 import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY; 44 import static org.ethereum.vm.OpCode.CALL; 45  46  47 /** 48  * The Ethereum Virtual Machine (EVM) is responsible for initialization 49  * and executing a transaction on a contract. 50  * 51  * It is a quasi-Turing-complete machine; the quasi qualification 52  * comes from the fact that the computation is intrinsically bounded 53  * through a parameter, gas, which limits the total amount of computation done. 54  * 55  * The EVM is a simple stack-based architecture. The word size of the machine 56  * (and thus size of stack item) is 256-bit. This was chosen to facilitate 57  * the SHA3-256 hash scheme and elliptic-curve computations. The memory model 58  * is a simple word-addressed byte array. The stack has an unlimited size. 59  * The machine also has an independent storage model; this is similar in concept 60  * to the memory but rather than a byte array, it is a word-addressable word array. 61  * 62  * Unlike memory, which is volatile, storage is non volatile and is 63  * maintained as part of the system state. All locations in both storage 64  * and memory are well-defined initially as zero. 65  * 66  * The machine does not follow the standard von Neumann architecture. 67  * Rather than storing program code in generally-accessible memory or storage, 68  * it is stored separately in a virtual ROM interactable only though 69  * a specialised instruction. 70  * 71  * The machine can have exceptional execution for several reasons, 72  * including stack underflows and invalid instructions. These unambiguously 73  * and validly result in immediate halting of the machine with all state changes 74  * left intact. The one piece of exceptional execution that does not leave 75  * state changes intact is the out-of-gas (OOG) exception. 76  * 77  * Here, the machine halts immediately and reports the issue to 78  * the execution agent (either the transaction processor or, recursively, 79  * the spawning execution environment) and which will deal with it separately. 80  * 81  * @author Roman Mandeleil 82  * @since 01.06.2014 83  */ 84 public class VM { 85  86  private static final Logger logger = LoggerFactory.getLogger("VM"); 87  private static final Logger dumpLogger = LoggerFactory.getLogger("dump"); 88  private static final String logString = "{} Op: [{}] Gas: [{}] Deep: [{}] Hint: [{}]"; 89  private static final boolean computeGas = true; // for performance comp 90  91  /* Keeps track of the number of steps performed in this VM */ 92  private int vmCounter = 0; 93  94  private static VMHook vmHook; 95  96  private final VmConfig vmConfig; 97  private final PrecompiledContracts precompiledContracts; 98  99  // Execution variables 100  private Program program; 101  private Stack stack; 102  private OpCode op; 103  private long oldMemSize ; 104  105  private String hint ; 106  107  private long memWords; // parameters for logging 108  private long gasCost; 109  private long gasBefore; // only for tracing 110  private boolean isLogEnabled; 111  112  public VM(VmConfig vmConfig, PrecompiledContracts precompiledContracts) { 113  this.vmConfig = vmConfig; 114  this.precompiledContracts = precompiledContracts; 115  isLogEnabled = logger.isInfoEnabled(); 116  } 117  118  private void checkSizeArgument(long size) { 119  if (size > Program.MAX_MEMORY) { // Force exception 120  throw Program.ExceptionHelper.notEnoughOpGas(program, op, Long.MAX_VALUE, program.getRemainingGas()); 121  } 122  } 123  124  private long calcMemGas(long oldMemSize, long newMemSize, long copySize) { 125  long currentGasCost = 0; 126  127  // Avoid overflows 128  checkSizeArgument(newMemSize); 129  130  // memory gas calc 131  // newMemSize has only 30 significant digits. 132  // Because of quadratic cost, we'll limit the maximim memSize to 30 bits = 2^30 = 1 GB. 133  134  // This comparison assumes (oldMemSize % 32 == 0) 135  if (newMemSize > oldMemSize) { // optimization to avoid div/mul 136  long memoryUsage = (newMemSize+31) / 32 * 32; // rounds up 137  138  if (memoryUsage > oldMemSize) { 139  memWords = (memoryUsage / 32); // 25 sig digits 140  long memWordsOld = (oldMemSize / 32); 141  long memGas; 142  143  // MemWords*MemWords has 50 sig digits, so this cannot overflow 144  memGas = GasCost.subtract( 145  GasCost.add( 146  GasCost.multiply(GasCost.MEMORY, memWords), 147  GasCost.multiply(memWords, memWords) / 512 148  ), 149  GasCost.add( 150  GasCost.multiply(GasCost.MEMORY, memWordsOld), 151  GasCost.multiply(memWordsOld, memWordsOld) / 512 152  ) 153  ); 154  currentGasCost = GasCost.add(currentGasCost, memGas); 155  } 156  } 157  158  // copySize is invalid if newMemSize > 2^63, but it only gets here if newMemSize is <= 2^30 159  if (copySize > 0) { 160  long copyGas = GasCost.multiply(GasCost.COPY_GAS, GasCost.add(copySize, 31) / 32); 161  currentGasCost = GasCost.add(currentGasCost, copyGas); 162  } 163  164  return currentGasCost; 165  } 166  167  public void step(Program aprogram) { 168  steps(aprogram,1); 169  } 170  171  public int getVmCounter() { // for profiling only 172  return vmCounter; 173  } 174  175  public void resetVmCounter() { // for profiling only 176  vmCounter =0; 177  } 178  179  protected void checkOpcode() { 180  if (op == null) { 181  throw Program.ExceptionHelper.invalidOpCode(program); 182  } 183  if (op.scriptVersion() > program.getScriptVersion()) { 184  throw Program.ExceptionHelper.invalidOpCode(program); 185  } 186  187  } 188  189  public static long limitedAddToMaxLong(long left, long right) { 190  try { 191  return Math.addExact(left, right); 192  } catch (ArithmeticException e) { 193  return Long.MAX_VALUE; 194  } 195  } 196  197  protected void spendOpCodeGas() { 198  if (!computeGas) { 199  return; 200  } 201  202  program.spendGas(gasCost, op.name()); 203  } 204  205  protected void doSTOP() { 206  if (computeGas) { 207  gasCost = GasCost.STOP; 208  spendOpCodeGas(); 209  } 210  211  // EXECUTION PHASE 212  program.setHReturn(EMPTY_BYTE_ARRAY); 213  program.stop(); 214  } 215  216  protected void doADD() { 217  spendOpCodeGas(); 218  // EXECUTION PHASE 219  DataWord word1 = program.stackPop(); 220  DataWord word2 = program.stackPop(); 221  222  if (isLogEnabled) { 223  hint = word1.value() + " + " + word2.value(); 224  } 225  226  program.stackPush(word1.add(word2)); 227  program.step(); 228  229  } 230  231  protected void doMUL() { 232  spendOpCodeGas(); 233  // EXECUTION PHASE 234  DataWord word1 = program.stackPop(); 235  DataWord word2 = program.stackPop(); 236  237  if (isLogEnabled) { 238  hint = word1.value() + " * " + word2.value(); 239  } 240  241  program.stackPush(word1.mul(word2)); 242  program.step(); 243  } 244  245  protected void doSUB() { 246  spendOpCodeGas(); 247  // EXECUTION PHASE 248  DataWord word1 = program.stackPop(); 249  DataWord word2 = program.stackPop(); 250  251  if (isLogEnabled) { 252  hint = word1.value() + " - " + word2.value(); 253  } 254  255  program.stackPush(word1.sub(word2)); 256  program.step(); 257  } 258  259  protected void doDIV() { 260  spendOpCodeGas(); 261  // EXECUTION PHASE 262  DataWord word1 = program.stackPop(); 263  DataWord word2 = program.stackPop(); 264  265  if (isLogEnabled) { 266  hint = word1.value() + " / " + word2.value(); 267  } 268  269  program.stackPush(word1.div(word2)); 270  program.step(); 271  } 272  273  protected void doSDIV() { 274  spendOpCodeGas(); 275  // EXECUTION PHASE 276  DataWord word1 = program.stackPop(); 277  DataWord word2 = program.stackPop(); 278  279  if (isLogEnabled) { 280  hint = word1.sValue() + " / " + word2.sValue(); 281  } 282  283  program.stackPush(word1.sDiv(word2)); 284  program.step(); 285  } 286  287  protected void doMOD() { 288  spendOpCodeGas(); 289  // EXECUTION PHASE 290  DataWord word1 = program.stackPop(); 291  DataWord word2 = program.stackPop(); 292  293  if (isLogEnabled) { 294  hint = word1.value() + " % " + word2.value(); 295  } 296  297  program.stackPush(word1.mod(word2)); 298  program.step(); 299  } 300  301  protected void doSMOD() { 302  spendOpCodeGas(); 303  // EXECUTION PHASE 304  DataWord word1 = program.stackPop(); 305  DataWord word2 = program.stackPop(); 306  307  if (isLogEnabled) { 308  hint = word1.sValue() + " #% " + word2.sValue(); 309  } 310  311  program.stackPush(word1.sMod(word2)); 312  program.step(); 313  } 314  315  protected void doEXP() { 316  if (computeGas) { 317  DataWord exp = stack.get(stack.size() - 2); 318  int bytesOccupied = exp.bytesOccupied(); 319  gasCost = GasCost.calculateTotal(GasCost.EXP_GAS, GasCost.EXP_BYTE_GAS, bytesOccupied); 320  } 321  spendOpCodeGas(); 322  // EXECUTION PHASE 323  DataWord word1 = program.stackPop(); 324  DataWord word2 = program.stackPop(); 325  326  if (isLogEnabled) { 327  hint = word1.value() + " ** " + word2.value(); 328  } 329  330  program.stackPush(word1.exp(word2)); 331  program.step(); 332  } 333  334  protected void doSIGNEXTEND() { 335  spendOpCodeGas(); 336  // EXECUTION PHASE 337  DataWord word1 = program.stackPop(); 338  long k = Program.limitToMaxLong(word1); 339  340  if (k<32) { 341  DataWord word2 = program.stackPop(); 342  if (isLogEnabled) { 343  hint = word1 + " " + word2.value(); 344  } 345  346  program.stackPush(word2.signExtend((byte) k)); 347  } 348  349  program.step(); 350  } 351  352  protected void doNOT() { 353  spendOpCodeGas(); 354  // EXECUTION PHASE 355  DataWord word1 = program.stackPop().bnot(); 356  357  if (isLogEnabled) { 358  hint = "" + word1.value(); 359  } 360  361  program.stackPush(word1); 362  program.step(); 363  } 364  365  protected void doLT() { 366  spendOpCodeGas(); 367  // EXECUTION PHASE 368  // TODO: can be improved by not using BigInteger 369  DataWord word1 = program.stackPop(); 370  DataWord word2 = program.stackPop(); 371  372  if (isLogEnabled) { 373  hint = word1.value() + " < " + word2.value(); 374  } 375  376  // TODO: We should compare the performance of BigInteger comparison with DataWord comparison: 377  if (word1.compareTo(word2) < 0) { 378  program.stackPush(DataWord.ONE); 379  } else { 380  program.stackPush(DataWord.ZERO); 381  } 382  program.step(); 383  } 384  385  protected void doSLT() { 386  spendOpCodeGas(); 387  // EXECUTION PHASE 388  // TODO: can be improved by not using BigInteger 389  DataWord word1 = program.stackPop(); 390  DataWord word2 = program.stackPop(); 391  392  if (isLogEnabled) { 393  hint = word1.sValue() + " < " + word2.sValue(); 394  } 395  396  if (word1.sValue().compareTo(word2.sValue()) < 0) { 397  program.stackPush(DataWord.ONE); 398  } else { 399  program.stackPush(DataWord.ZERO); 400  } 401  program.step(); 402  } 403  404  protected void doSGT() { 405  spendOpCodeGas(); 406  // EXECUTION PHASE 407  // TODO: can be improved by not using BigInteger 408  DataWord word1 = program.stackPop(); 409  DataWord word2 = program.stackPop(); 410  411  if (isLogEnabled) { 412  hint = word1.sValue() + " > " + word2.sValue(); 413  } 414  415  if (word1.sValue().compareTo(word2.sValue()) > 0) { 416  program.stackPush(DataWord.ONE); 417  } else { 418  program.stackPush(DataWord.ZERO); 419  } 420  program.step(); 421  } 422  423  protected void doGT() { 424  spendOpCodeGas(); 425  // EXECUTION PHASE 426  // TODO: can be improved by not using BigInteger 427  DataWord word1 = program.stackPop(); 428  DataWord word2 = program.stackPop(); 429  430  if (isLogEnabled) { 431  hint = word1.value() + " > " + word2.value(); 432  } 433  434  if (word1.value().compareTo(word2.value()) > 0) { 435  program.stackPush(DataWord.ONE); 436  } else { 437  program.stackPush(DataWord.ZERO); 438  } 439  440  program.step(); 441  } 442  443  protected void doEQ() { 444  spendOpCodeGas(); 445  // EXECUTION PHASE 446  DataWord word1 = program.stackPop(); 447  DataWord word2 = program.stackPop(); 448  449  if (isLogEnabled) { 450  hint = word1.value() + " == " + word2.value(); 451  } 452  453  if (word1.equalValue(word2)) { 454  program.stackPush(DataWord.ONE); 455  } else { 456  program.stackPush(DataWord.ZERO); 457  } 458  459  program.step(); 460  } 461  462  protected void doISZERO() { 463  spendOpCodeGas(); 464  // EXECUTION PHASE 465  DataWord word1 = program.stackPop(); 466  467  DataWord result = word1.isZero() ? DataWord.ONE : DataWord.ZERO; 468  469  if (isLogEnabled) { 470  hint = "" + result.value(); 471  } 472  473  program.stackPush(result); 474  program.step(); 475  } 476  477  protected void doAND(){ 478  spendOpCodeGas(); 479  // EXECUTION PHASE 480  DataWord word1 = program.stackPop(); 481  DataWord word2 = program.stackPop(); 482  483  if (isLogEnabled) { 484  hint = word1.value() + " && " + word2.value(); 485  } 486  487  program.stackPush(word1.and(word2)); 488  program.step(); 489  } 490  491  protected void doOR(){ 492  spendOpCodeGas(); 493  // EXECUTION PHASE 494  DataWord word1 = program.stackPop(); 495  DataWord word2 = program.stackPop(); 496  497  if (isLogEnabled) { 498  hint = word1.value() + " || " + word2.value(); 499  } 500  501  program.stackPush(word1.or(word2)); 502  program.step(); 503  } 504  505  protected void doXOR(){ 506  spendOpCodeGas(); 507  // EXECUTION PHASE 508  DataWord word1 = program.stackPop(); 509  DataWord word2 = program.stackPop(); 510  511  if (isLogEnabled) { 512  hint = word1.value() + " ^ " + word2.value(); 513  } 514  515  program.stackPush(word1.xor(word2)); 516  program.step(); 517  } 518  519  protected void doBYTE() { 520  spendOpCodeGas(); 521  // EXECUTION PHASE 522  DataWord word1 = program.stackPop(); 523  DataWord word2 = program.stackPop(); 524  final DataWord result; 525  long wvalue = Program.limitToMaxLong(word1); 526  if (wvalue<32) { 527  byte tmp = word2.getData()[(int) wvalue]; 528  byte[] newdata = new byte[32]; 529  newdata[31] = tmp; 530  result = DataWord.valueOf(newdata); 531  } else { 532  result = DataWord.ZERO; 533  } 534  535  if (isLogEnabled) { 536  hint = "" + result.value(); 537  } 538  539  program.stackPush(result); 540  program.step(); 541  } 542  543  protected void doSHL() { 544  spendOpCodeGas(); 545  // EXECUTION PHASE 546  DataWord word1 = program.stackPop(); 547  DataWord word2 = program.stackPop(); 548  549  if (isLogEnabled) { 550  hint = word1.value() + " << " + word2.value(); 551  } 552  553  program.stackPush(word2.shiftLeft(word1)); 554  program.step(); 555  556  } 557  558  protected void doSHR() { 559  spendOpCodeGas(); 560  // EXECUTION PHASE 561  DataWord word1 = program.stackPop(); 562  DataWord word2 = program.stackPop(); 563  564  if (isLogEnabled) { 565  hint = word1.value() + " >> " + word2.value(); 566  } 567  568  program.stackPush(word2.shiftRight(word1)); 569  program.step(); 570  571  } 572  573  protected void doSAR() { 574  spendOpCodeGas(); 575  // EXECUTION PHASE 576  DataWord word1 = program.stackPop(); 577  DataWord word2 = program.stackPop(); 578  579  if (isLogEnabled) { 580  hint = word1.value() + " >> " + word2.value(); 581  } 582  583  program.stackPush(word2.shiftRightSigned(word1)); 584  program.step(); 585  586  } 587  588  protected void doADDMOD() { 589  spendOpCodeGas(); 590  // EXECUTION PHASE 591  DataWord word1 = program.stackPop(); 592  DataWord word2 = program.stackPop(); 593  DataWord word3 = program.stackPop(); 594  program.stackPush(word1.addmod(word2, word3)); 595  program.step(); 596  } 597  598  protected void doMULMOD() { 599  spendOpCodeGas(); 600  // EXECUTION PHASE 601  DataWord word1 = program.stackPop(); 602  DataWord word2 = program.stackPop(); 603  DataWord word3 = program.stackPop(); 604  program.stackPush(word1.mulmod(word2, word3)); 605  program.step(); 606  } 607  608  protected void doSHA3() { 609  DataWord size; 610  long sizeLong; 611  long newMemSize ; 612  if (computeGas) { 613  gasCost = GasCost.SHA3; 614  size = stack.get(stack.size() - 2); 615  sizeLong = Program.limitToMaxLong(size); 616  checkSizeArgument(sizeLong); 617  newMemSize = memNeeded(stack.peek(), sizeLong); 618  long chunkUsed = (sizeLong + 31) / 32; 619  gasCost = GasCost.calculateTotal(gasCost, GasCost.SHA3_WORD, chunkUsed); 620  gasCost = GasCost.add(gasCost, calcMemGas(oldMemSize, newMemSize, 0)); 621  622  spendOpCodeGas(); 623  } 624  // EXECUTION PHASE 625  DataWord memOffsetData = program.stackPop(); 626  DataWord lengthData = program.stackPop(); 627  byte[] buffer = program.memoryChunk(memOffsetData.intValue(), lengthData.intValue()); 628  629  byte[] encoded = HashUtil.keccak256(buffer); 630  DataWord word = DataWord.valueOf(encoded); 631  632  if (isLogEnabled) { 633  hint = word.toString(); 634  } 635  636  program.stackPush(word); 637  program.step(); 638  } 639  640  protected void doADDRESS() { 641  spendOpCodeGas(); 642  // EXECUTION PHASE 643  DataWord address = program.getOwnerAddress(); 644  645  if (isLogEnabled) { 646  hint = "address: " + ByteUtil.toHexString(address.getLast20Bytes()); 647  } 648  649  program.stackPush(address); 650  program.step(); 651  } 652  653  protected void doBALANCE() { 654  if (computeGas) { 655  gasCost = GasCost.BALANCE; 656  spendOpCodeGas(); 657  } 658  // EXECUTION PHASE 659  DataWord address = program.stackPop(); 660  DataWord balance = program.getBalance(address); // TODO: should not allocate 661  662  if (isLogEnabled) { 663  hint = "address: " 664  + ByteUtil.toHexString(address.getLast20Bytes()) 665  + " balance: " + balance.toString(); 666  } 667  668  program.stackPush(balance); 669  program.step(); 670  } 671  672  protected void doORIGIN(){ 673  spendOpCodeGas(); 674  // EXECUTION PHASE 675  DataWord originAddress = program.getOriginAddress(); 676  677  if (isLogEnabled) { 678  hint = "address: " + ByteUtil.toHexString(originAddress.getLast20Bytes()); 679  } 680  681  program.stackPush(originAddress); 682  program.step(); 683  } 684  685  protected void doCALLER() { 686  spendOpCodeGas(); 687  // EXECUTION PHASE 688  DataWord callerAddress = program.getCallerAddress(); 689  690  if (isLogEnabled) { 691  hint = "address: " + ByteUtil.toHexString(callerAddress.getLast20Bytes()); 692  } 693  694  program.stackPush(callerAddress); 695  program.step(); 696  } 697  698  protected void doCALLVALUE() { 699  spendOpCodeGas(); 700  // EXECUTION PHASE 701  DataWord callValue = program.getCallValue(); 702  703  if (isLogEnabled) { 704  hint = "value: " + callValue; 705  } 706  707  program.stackPush(callValue); 708  program.step(); 709  } 710  711  protected void doCALLDATALOAD() { 712  spendOpCodeGas(); 713  // EXECUTION PHASE 714  DataWord dataOffs = program.stackPop(); 715  DataWord value = program.getDataValue(dataOffs); 716  717  if (isLogEnabled) { 718  hint = "data: " + value; 719  } 720  721  program.stackPush(value); 722  program.step(); 723  } 724  725  protected void doCALLDATASIZE() { 726  spendOpCodeGas(); 727  // EXECUTION PHASE 728  DataWord dataSize = program.getDataSize(); 729  730  if (isLogEnabled) { 731  hint = "size: " + dataSize.value(); 732  } 733  734  program.stackPush(dataSize); 735  program.step(); 736  } 737  738  protected void doCALLDATACOPY() { 739  if (computeGas) { 740  gasCost = GasCost.add(gasCost, computeDataCopyGas()); 741  spendOpCodeGas(); 742  } 743  // EXECUTION PHASE 744  DataWord memOffsetData = program.stackPop(); 745  DataWord dataOffsetData = program.stackPop(); 746  DataWord lengthData = program.stackPop(); 747  748  byte[] msgData = program.getDataCopy(dataOffsetData, lengthData); 749  750  if (isLogEnabled) { 751  hint = "data: " + ByteUtil.toHexString(msgData); 752  } 753  754  program.memorySave(memOffsetData.intValue(), msgData); 755  program.step(); 756  } 757  758  private long computeDataCopyGas() { 759  DataWord size = stack.get(stack.size() - 3); 760  long copySize = Program.limitToMaxLong(size); 761  checkSizeArgument(copySize); 762  long newMemSize = memNeeded(stack.peek(), copySize); 763  return calcMemGas(oldMemSize, newMemSize, copySize); 764  } 765  766  protected void doCODESIZE() { 767  if (computeGas) { 768  if (op == OpCode.EXTCODESIZE) { 769  gasCost = GasCost.EXT_CODE_SIZE; 770  } 771  spendOpCodeGas(); 772  } 773  // EXECUTION PHASE 774  DataWord codeLength; 775  if (op == OpCode.CODESIZE) { 776  codeLength = DataWord.valueOf(program.getCode().length); // during initialization it will return the initialization code size 777  } else { 778  DataWord address = program.stackPop(); 779  codeLength = DataWord.valueOf(program.getCodeLengthAt(address)); 780  ActivationConfig.ForBlock activations = program.getActivations(); 781  if (activations.isActive(RSKIP90)) { 782  PrecompiledContracts.PrecompiledContract precompiledContract = precompiledContracts.getContractForAddress(activations, address); 783  if (precompiledContract != null) { 784  codeLength = DataWord.valueOf(BigIntegers.asUnsignedByteArray(DataWord.MAX_VALUE)); 785  } 786  } 787  } 788  if (isLogEnabled) { 789  hint = "size: " + codeLength; 790  } 791  program.stackPush(codeLength); 792  program.step(); 793  } 794  795  protected void doEXTCODEHASH() { 796  if (computeGas) { 797  gasCost = GasCost.EXT_CODE_HASH; 798  spendOpCodeGas(); 799  } 800  801  //EXECUTION PHASE 802  DataWord address = program.stackPop(); 803  804  ActivationConfig.ForBlock activations = program.getActivations(); 805  PrecompiledContracts.PrecompiledContract precompiledContract = precompiledContracts.getContractForAddress(activations, address); 806  boolean isPrecompiledContract = precompiledContract != null; 807  808  if (isPrecompiledContract) { 809  byte[] emptyHash = Keccak256Helper.keccak256(EMPTY_BYTE_ARRAY); 810  program.stackPush(DataWord.valueOf(emptyHash)); 811  812  if (isLogEnabled) { 813  hint = "hash: " + ByteUtil.toHexString(emptyHash); 814  } 815  } else { 816  Keccak256 codeHash = program.getCodeHashAt(address,activations.isActive(RSKIP169)); 817  //If account does not exist, 0 is pushed in stack 818  if (codeHash.equals(Keccak256.ZERO_HASH)) { 819  program.stackPush(DataWord.ZERO); 820  } else { 821  DataWord word = DataWord.valueOf(codeHash.getBytes()); 822  program.stackPush(word); 823  } 824  825  if (isLogEnabled) { 826  hint = "hash: " + codeHash.toHexString(); 827  } 828  } 829  830  program.step(); 831  } 832  833  protected void doCODECOPY() { 834  DataWord size; 835  long newMemSize ; 836  long copySize; 837  if (computeGas) { 838  839  if (op == OpCode.EXTCODECOPY) { 840  gasCost = GasCost.EXT_CODE_COPY; 841  size = stack.get(stack.size() - 4); 842  copySize = Program.limitToMaxLong(size); 843  checkSizeArgument(copySize); 844  newMemSize = memNeeded(stack.get(stack.size() - 2), copySize); 845  gasCost = GasCost.add(gasCost, calcMemGas(oldMemSize, newMemSize, copySize)); 846  } else { 847  size = stack.get(stack.size() - 3); 848  copySize = Program.limitToMaxLong(size); 849  checkSizeArgument(copySize); 850  newMemSize = memNeeded(stack.peek(), copySize); 851  gasCost = GasCost.add(gasCost, calcMemGas(oldMemSize, newMemSize, copySize)); 852  } 853  spendOpCodeGas(); 854  } 855  // EXECUTION PHASE 856  // case OpCodes.opCODECOPY: 857  // case OpCodes.opEXTCODECOPY 858  859  byte[] fullCode = EMPTY_BYTE_ARRAY; 860  if (op == OpCode.CODECOPY) { 861  fullCode = program.getCode(); 862  } 863  864  if (op == OpCode.EXTCODECOPY) { 865  DataWord address = program.stackPop(); 866  fullCode = program.getCodeAt(address); 867  } 868  869  DataWord memOffsetDW = program.stackPop(); 870  DataWord codeOffsetDW = program.stackPop(); 871  DataWord lengthDataDW = program.stackPop(); 872  873  // Here size/offsets fit in ints are assumed: this is consistent with 874  // maximum memory size, which is 1 GB (program.MAX_MEMORY) 875  int memOffset = memOffsetDW .intValueSafe(); 876  int codeOffset = codeOffsetDW.intValueSafe(); // where to start reading 877  int lengthData = lengthDataDW.intValueSafe(); // amount of bytes to copy 878  879  int sizeToBeCopied; 880  if ((long) codeOffset + lengthData > fullCode.length) { 881  // if user wants to read more info from code what actual code has then.. 882  // if all code that users wants lies after code has ended.. 883  if (codeOffset >=fullCode.length) { 884  sizeToBeCopied=0; // do not copy anything 885  } else { 886  sizeToBeCopied = fullCode.length - codeOffset; // copy only the remaining 887  } 888  889  } else 890  // Code is longer, so limit by user length value 891  { 892  sizeToBeCopied =lengthData; 893  } 894  895  // The part not copied must be filled with zeros, so here we allocate 896  // enough space to contain filling also. 897  byte[] codeCopy = new byte[lengthData]; 898  899  if (codeOffset < fullCode.length) { 900  System.arraycopy(fullCode, codeOffset, codeCopy, 0, sizeToBeCopied); 901  } 902  903  if (isLogEnabled) { 904  hint = "code: " + ByteUtil.toHexString(codeCopy); 905  } 906  907  // TODO: an optimization to avoid double-copying would be to override programSave 908  // to receive a byte[] buffer and a length, and to create another method memoryZero(offset,length) 909  // to fill the gap. 910  program.memorySave(memOffset, codeCopy); 911  912  program.step(); 913  } 914  915  protected void doRETURNDATASIZE() { 916  spendOpCodeGas(); 917  DataWord dataSize = program.getReturnDataBufferSize(); 918  if (isLogEnabled) { 919  hint = "size: " + dataSize.value(); 920  } 921  program.stackPush(dataSize); 922  program.step(); 923  } 924  925  protected void doRETURNDATACOPY() { 926  if (computeGas) { 927  gasCost = GasCost.add(gasCost, computeDataCopyGas()); 928  spendOpCodeGas(); 929  } 930  931  DataWord memOffsetData = program.stackPop(); 932  DataWord dataOffsetData = program.stackPop(); 933  DataWord lengthData = program.stackPop(); 934  935  byte[] msgData = program.getReturnDataBufferData(dataOffsetData, lengthData) 936  .orElseThrow(() -> { 937  long returnDataSize = program.getReturnDataBufferSize().longValueSafe(); 938  return new RuntimeException(String.format( 939  "Illegal RETURNDATACOPY arguments: offset (%s) + size (%s) > RETURNDATASIZE (%d)", 940  dataOffsetData, lengthData, returnDataSize)); 941  }); 942  943  if (isLogEnabled) { 944  hint = "data: " + ByteUtil.toHexString(msgData); 945  } 946  947  program.memorySave(memOffsetData.intValueSafe(), msgData); 948  program.step(); 949  } 950  951  protected void doGASPRICE(){ 952  spendOpCodeGas(); 953  // EXECUTION PHASE 954  DataWord gasPrice = program.getGasPrice(); 955  956  if (isLogEnabled) { 957  hint = "price: " + gasPrice.toString(); 958  } 959  960  program.stackPush(gasPrice); 961  program.step(); 962  } 963  964  protected void doTXINDEX() { 965  spendOpCodeGas(); 966  // EXECUTION PHASE 967  968  DataWord transactionIndex = program.getTransactionIndex(); 969  970  if (isLogEnabled) { 971  hint = "transactionIndex: " + transactionIndex; 972  } 973  974  program.stackPush(transactionIndex); 975  program.step(); 976  } 977  978  protected void doBLOCKHASH() { 979  spendOpCodeGas(); 980  // EXECUTION PHASE 981  982  DataWord blockIndexDW = program.stackPop(); 983  984  DataWord blockHash = program.getBlockHash(blockIndexDW); 985  986  if (isLogEnabled) { 987  hint = "blockHash: " + blockHash; 988  } 989  990  program.stackPush(blockHash); 991  program.step(); 992  } 993  994  protected void doCOINBASE() { 995  spendOpCodeGas(); 996  // EXECUTION PHASE 997  DataWord coinbase = program.getCoinbase(); 998  999  if (isLogEnabled) { 1000  hint = "coinbase: " + ByteUtil.toHexString(coinbase.getLast20Bytes()); 1001  } 1002  1003  program.stackPush(coinbase); 1004  program.step(); 1005  } 1006  1007  protected void doTIMESTAMP() { 1008  spendOpCodeGas(); 1009  // EXECUTION PHASE 1010  DataWord timestamp = program.getTimestamp(); 1011  1012  if (isLogEnabled) { 1013  hint = "timestamp: " + timestamp.value(); 1014  } 1015  1016  program.stackPush(timestamp); 1017  program.step(); 1018  } 1019  1020  protected void doNUMBER(){ 1021  spendOpCodeGas(); 1022  // EXECUTION PHASE 1023  DataWord number = program.getNumber(); 1024  1025  if (isLogEnabled) { 1026  hint = "number: " + number.value(); 1027  } 1028  1029  program.stackPush(number); 1030  program.step(); 1031  } 1032  1033  protected void doDIFFICULTY() { 1034  spendOpCodeGas(); 1035  // EXECUTION PHASE 1036  DataWord difficulty = program.getDifficulty(); 1037  1038  if (isLogEnabled) { 1039  hint = "difficulty: " + difficulty; 1040  } 1041  1042  program.stackPush(difficulty); 1043  program.step(); 1044  } 1045  1046  protected void doGASLIMIT() { 1047  spendOpCodeGas(); 1048  // EXECUTION PHASE 1049  DataWord gaslimit = program.getGasLimit(); 1050  1051  if (isLogEnabled) { 1052  hint = "gaslimit: " + gaslimit; 1053  } 1054  1055  program.stackPush(gaslimit); 1056  program.step(); 1057  } 1058  1059  protected void doCHAINID() { 1060  spendOpCodeGas(); 1061  // EXECUTION PHASE 1062  DataWord chainId = DataWord.valueOf(vmConfig.getChainId()); 1063  1064  if (isLogEnabled) { 1065  hint = "chainId: " + chainId; 1066  } 1067  1068  program.stackPush(chainId); 1069  program.step(); 1070  } 1071  1072  protected void doSELFBALANCE(){ 1073  spendOpCodeGas(); 1074  // EXECUTION PHASE 1075  DataWord balance = program.getBalance(program.getOwnerAddress()); 1076  1077  if (isLogEnabled) { 1078  hint = "selfBalance: " + balance; 1079  } 1080  1081  program.stackPush(balance); 1082  program.step(); 1083  } 1084  1085  protected void doPOP(){ 1086  spendOpCodeGas(); 1087  // EXECUTION PHASE 1088  program.stackPop(); 1089  program.step(); 1090  } 1091  1092  protected void doDUP() { 1093  spendOpCodeGas(); 1094  // EXECUTION PHASE 1095  int n = op.val() - OpCode.DUP1.val() + 1; 1096  DataWord word1 = stack.get(stack.size() - n); 1097  program.stackPush(word1); 1098  program.step(); 1099  } 1100  1101  protected void doDUPN() { 1102  spendOpCodeGas(); 1103  // EXECUTION PHASE 1104  program.step(); 1105  1106  int n = stack.pop().intValueCheck() + 1; 1107  1108  program.verifyStackSize(n); 1109  program.verifyStackOverflow(n, n + 1); 1110  1111  DataWord word1 = stack.get(stack.size() - n); 1112  program.stackPush(word1); 1113  program.step(); 1114  } 1115  1116  protected void doSWAP(){ 1117  spendOpCodeGas(); 1118  // EXECUTION PHASE 1119  int n = op.val() - OpCode.SWAP1.val() + 2; 1120  1121  stack.swap(stack.size() - 1, stack.size() - n); 1122  program.step(); 1123  } 1124  1125  protected void doSWAPN(){ 1126  spendOpCodeGas(); 1127  // EXECUTION PHASE 1128  program.step(); 1129  1130  int n = stack.pop().intValueCheck() + 2; 1131  1132  program.verifyStackSize(n); 1133  program.verifyStackOverflow(n, n); 1134  1135  stack.swap(stack.size() - 1, stack.size() - n); 1136  program.step(); 1137  } 1138  1139  protected void doLOG(){ 1140  if (program.isStaticCall() && program.getActivations().isActive(RSKIP91)) { 1141  throw Program.ExceptionHelper.modificationException(program); 1142  } 1143  1144  DataWord size; 1145  long sizeLong; 1146  long newMemSize ; 1147  int nTopics = op.val() - OpCode.LOG0.val(); 1148  1149  if (computeGas) { 1150  size = stack.get(stack.size() - 2); 1151  sizeLong = Program.limitToMaxLong(size); 1152  checkSizeArgument(sizeLong); 1153  newMemSize = memNeeded(stack.peek(), sizeLong); 1154  1155  long dataCost = GasCost.multiply(sizeLong, GasCost.LOG_DATA_GAS); 1156  1157  gasCost = GasCost.calculateTotal(GasCost.add(GasCost.LOG_GAS, dataCost), GasCost.LOG_TOPIC_GAS, nTopics); 1158  gasCost = GasCost.add(gasCost, calcMemGas(oldMemSize, newMemSize, 0)); 1159  1160  spendOpCodeGas(); 1161  } 1162  // EXECUTION PHASE 1163  DataWord address = program.getOwnerAddress(); 1164  1165  DataWord memStart = stack.pop(); 1166  DataWord memOffset = stack.pop(); 1167  1168  List<DataWord> topics = new ArrayList<>(); 1169  for (int i = 0; i < nTopics; ++i) { 1170  DataWord topic = stack.pop(); 1171  topics.add(topic); 1172  } 1173  1174  // Int32 address values guaranteed by previous MAX_MEMORY checks 1175  byte[] data = program.memoryChunk(memStart.intValue(), memOffset.intValue()); 1176  1177  LogInfo logInfo = 1178  new LogInfo(address.getLast20Bytes(), topics, data); 1179  1180  if (isLogEnabled) { 1181  hint = logInfo.toString(); 1182  } 1183  1184  program.getResult().addLogInfo(logInfo); 1185  // Log topics taken from the stack are lost and never returned to the DataWord pool 1186  program.step(); 1187  } 1188  1189  protected void doMLOAD(){ 1190  long newMemSize ; 1191  1192  if (computeGas) { 1193  newMemSize = memNeeded(stack.peek(), 32); 1194  gasCost = GasCost.add(gasCost, calcMemGas(oldMemSize, newMemSize, 0)); 1195  spendOpCodeGas(); 1196  } 1197  // EXECUTION PHASE 1198  DataWord addr = program.stackPop(); 1199  DataWord data = program.memoryLoad(addr); 1200  1201  if (isLogEnabled) { 1202  hint = "data: " + data; 1203  } 1204  1205  program.stackPush(data); 1206  program.step(); 1207  } 1208  1209  protected void doMSTORE() { 1210  long newMemSize ; 1211  1212  if (computeGas) { 1213  newMemSize = memNeeded(stack.peek(), 32); 1214  gasCost = GasCost.add(gasCost, calcMemGas(oldMemSize, newMemSize, 0)); 1215  spendOpCodeGas(); 1216  } 1217  // EXECUTION PHASE 1218  DataWord addr = program.stackPop(); 1219  DataWord value = program.stackPop(); 1220  1221  if (isLogEnabled) { 1222  hint = "addr: " + addr + " value: " + value; 1223  } 1224  1225  program.memorySave(addr, value); 1226  program.step(); 1227  } 1228  1229  protected void doMSTORE8(){ 1230  long newMemSize ; 1231  1232  if (computeGas) { 1233  newMemSize = memNeeded(stack.peek(), 1); 1234  gasCost = GasCost.add(gasCost, calcMemGas(oldMemSize, newMemSize, 0)); 1235  1236  spendOpCodeGas(); 1237  } 1238  // EXECUTION PHASE 1239  DataWord addr = program.stackPop(); 1240  DataWord value = program.stackPop(); 1241  byte[] byteVal = {value.getData()[31]}; 1242  //TODO: non-standard single byte memory storage, this should be documented 1243  program.memorySave(addr.intValue(), byteVal); 1244  program.step(); 1245  } 1246  1247  protected void doSLOAD() { 1248  if (computeGas) { 1249  gasCost = GasCost.SLOAD; 1250  spendOpCodeGas(); 1251  } 1252  // EXECUTION PHASE 1253  DataWord key = program.stackPop(); 1254  DataWord val = program.storageLoad(key); 1255  1256  if (isLogEnabled) { 1257  hint = "key: " + key + " value: " + val; 1258  } 1259  1260  if (val == null) { 1261  val = DataWord.ZERO; 1262  } 1263  1264  program.stackPush(val); 1265  // key could be returned to the pool, but storageLoad semantics should be checked 1266  // to make sure storageLoad always gets a copy, not a reference. 1267  program.step(); 1268  } 1269  1270  protected void doSSTORE() { 1271  if (program.isStaticCall() && program.getActivations().isActive(RSKIP91)) { 1272  throw Program.ExceptionHelper.modificationException(program); 1273  } 1274  1275  if (computeGas) { 1276  DataWord newValue = stack.get(stack.size() - 2); 1277  DataWord oldValue = program.storageLoad(stack.peek()); 1278  1279  // From null to non-zero 1280  if (oldValue == null && !newValue.isZero()) { 1281  gasCost = GasCost.SET_SSTORE; 1282  } 1283  1284  // from non-zero to zero 1285  else if (oldValue != null && newValue.isZero()) { 1286  // todo: GASREFUND counter policyn 1287  1288  // refund step cost policy. 1289  program.futureRefundGas(GasCost.REFUND_SSTORE); 1290  gasCost = GasCost.CLEAR_SSTORE; 1291  } else 1292  // from zero to zero, or from non-zero to non-zero 1293  { 1294  gasCost = GasCost.RESET_SSTORE; 1295  } 1296  1297  spendOpCodeGas(); 1298  } 1299  // EXECUTION PHASE 1300  DataWord addr = program.stackPop(); 1301  DataWord value = program.stackPop(); 1302  1303  if (isLogEnabled) { 1304  hint = "[" + program.getOwnerAddress() + "] key: " + addr + " value: " + value; 1305  } 1306  1307  program.storageSave(addr, value); 1308  program.step(); 1309  } 1310  1311  protected void doJUMP(){ 1312  spendOpCodeGas(); 1313  // EXECUTION PHASE 1314  DataWord pos = program.stackPop(); 1315  int nextPC = program.verifyJumpDest(pos); 1316  1317  if (isLogEnabled) { 1318  hint = "~> " + nextPC; 1319  } 1320  1321  program.setPC(nextPC); 1322  } 1323  1324  protected void doJUMPI(){ 1325  spendOpCodeGas(); 1326  // EXECUTION PHASE 1327  DataWord pos = program.stackPop(); 1328  DataWord cond = program.stackPop(); 1329  1330  if (!cond.isZero()) { 1331  int nextPC = program.verifyJumpDest(pos); 1332  1333  if (isLogEnabled) { 1334  hint = "~> " + nextPC; 1335  } 1336  1337  program.setPC(nextPC); 1338  1339  } else { 1340  program.step(); 1341  } 1342  } 1343  1344  protected void doPC(){ 1345  spendOpCodeGas(); 1346  // EXECUTION PHASE 1347  int pc = program.getPC(); 1348  DataWord pcWord = DataWord.valueOf(pc); 1349  1350  if (isLogEnabled) { 1351  hint = pcWord.toString(); 1352  } 1353  1354  program.stackPush(pcWord); 1355  program.step(); 1356  } 1357  1358  protected void doMSIZE(){ 1359  spendOpCodeGas(); 1360  // EXECUTION PHASE 1361  int memSize = program.getMemSize(); 1362  DataWord wordMemSize = DataWord.valueOf(memSize); 1363  1364  if (isLogEnabled) { 1365  hint = Integer.toString(memSize); 1366  } 1367  1368  program.stackPush(wordMemSize); 1369  program.step(); 1370  } 1371  1372  protected void doGAS(){ 1373  spendOpCodeGas(); 1374  // EXECUTION PHASE 1375  DataWord gas = DataWord.valueOf(program.getRemainingGas()); 1376  1377  if (isLogEnabled) { 1378  hint = "" + gas; 1379  } 1380  1381  program.stackPush(gas); 1382  program.step(); 1383  } 1384  1385  protected void doPUSH(){ 1386  spendOpCodeGas(); 1387  // EXECUTION PHASE 1388  program.step(); 1389  int nPush = op.val() - OpCode.PUSH1.val() + 1; 1390  1391  DataWord data = program.sweepGetDataWord(nPush); 1392  1393  if (isLogEnabled) { 1394  hint = "" + ByteUtil.toHexString(data.getData()); 1395  } 1396  1397  program.stackPush(data); 1398  } 1399  1400  protected void doJUMPDEST() 1401  { 1402  spendOpCodeGas(); 1403  // EXECUTION PHASE 1404  program.step(); 1405  } 1406  1407  protected void doCREATE(){ 1408  if (program.isStaticCall() && program.getActivations().isActive(RSKIP91)) { 1409  throw Program.ExceptionHelper.modificationException(program); 1410  } 1411  1412  DataWord size; 1413  long sizeLong; 1414  long newMemSize ; 1415  1416  if (computeGas) { 1417  gasCost = GasCost.CREATE; 1418  size = stack.get(stack.size() - 3); 1419  sizeLong = Program.limitToMaxLong(size); 1420  checkSizeArgument(sizeLong); 1421  newMemSize = memNeeded(stack.get(stack.size() - 2), sizeLong); 1422  gasCost = GasCost.add(gasCost, calcMemGas(oldMemSize, newMemSize, 0)); 1423  1424  spendOpCodeGas(); 1425  } 1426  // EXECUTION PHASE 1427  DataWord value = program.stackPop(); 1428  DataWord inOffset = program.stackPop(); 1429  DataWord inSize = program.stackPop(); 1430  1431  if (isLogEnabled) { 1432  logger.info(logString, String.format("%5s", "[" + program.getPC() + "]"), 1433  String.format("%-12s", op.name()), 1434  program.getRemainingGas(), 1435  program.getCallDeep(), hint); 1436  } 1437  1438  program.createContract(value, inOffset, inSize); 1439  program.step(); 1440  } 1441  1442  protected void doCREATE2(){ 1443  if (program.isStaticCall()) { 1444  throw Program.ExceptionHelper.modificationException(program); 1445  } 1446  1447  if (computeGas){ 1448  long codeSize = stack.get(stack.size() - 3).longValueSafe(); 1449  gasCost = GasCost.calculateTotal( 1450  GasCost.add( 1451  GasCost.CREATE, 1452  calcMemGas(oldMemSize, memNeeded(stack.get(stack.size() - 2), codeSize), 0) 1453  ), 1454  GasCost.SHA3_WORD, 1455  GasCost.add(codeSize, 31) / 32 1456  ); 1457  spendOpCodeGas(); 1458  } 1459  1460  DataWord value = program.stackPop(); 1461  DataWord inOffset = program.stackPop(); 1462  DataWord inSize = program.stackPop(); 1463  DataWord salt = program.stackPop(); 1464  1465  if (logger.isInfoEnabled()) { 1466  logger.info(logString, String.format("%5s", "[" + program.getPC() + "]"), 1467  String.format("%-12s", op.name()), 1468  program.getRemainingGas(), 1469  program.getCallDeep(), hint); 1470  } 1471  1472  program.createContract2(value, inOffset, inSize, salt); 1473  1474  program.step(); 1475  } 1476  1477  protected void doCALL(){ 1478  DataWord gas = program.stackPop(); 1479  DataWord codeAddress = program.stackPop(); 1480  1481  ActivationConfig.ForBlock activations = program.getActivations(); 1482  1483  MessageCall msg = getMessageCall(gas, codeAddress, activations); 1484  1485  PrecompiledContracts.PrecompiledContract precompiledContract = precompiledContracts.getContractForAddress(activations, codeAddress); 1486  1487  if (precompiledContract != null) { 1488  program.callToPrecompiledAddress(msg, precompiledContract); 1489  } else { 1490  program.callToAddress(msg); 1491  } 1492  1493  program.step(); 1494  } 1495  1496  private MessageCall getMessageCall(DataWord gas, DataWord codeAddress, ActivationConfig.ForBlock activations) { 1497  DataWord value = calculateCallValue(activations); 1498  1499  if (program.isStaticCall() && op == CALL && !value.isZero()) { 1500  throw Program.ExceptionHelper.modificationException(program); 1501  } 1502  1503  DataWord inDataOffs = program.stackPop(); 1504  DataWord inDataSize = program.stackPop(); 1505  1506  DataWord outDataOffs = program.stackPop(); 1507  DataWord outDataSize = program.stackPop(); 1508  1509  if (computeGas) { 1510  gasCost = computeCallGas(codeAddress, value, inDataOffs, inDataSize, outDataOffs, outDataSize); 1511  } 1512  1513  // gasCost doesn't include the calleeGas at this point 1514  // because we want to throw gasOverflow instead of notEnoughSpendingGas 1515  long requiredGas = gasCost; 1516  if (requiredGas > program.getRemainingGas()) { 1517  throw Program.ExceptionHelper.gasOverflow(program, BigInteger.valueOf(program.getRemainingGas()), BigInteger.valueOf(requiredGas)); 1518  } 1519  long remainingGas = GasCost.subtract(program.getRemainingGas(), requiredGas); 1520  long minimumTransferGas = calculateGetMinimumTransferGas(value, remainingGas); 1521  1522  long userSpecifiedGas = Program.limitToMaxLong(gas); 1523  long specifiedGasPlusMin = activations.isActive(RSKIP150) ? 1524  GasCost.add(userSpecifiedGas, minimumTransferGas) : 1525  userSpecifiedGas + minimumTransferGas; 1526  1527  // If specified gas is higher than available gas then move all remaining gas to callee. 1528  // This will have one possibly undesired behavior: if the specified gas is higher than the remaining gas, 1529  // the callee will receive less gas than the parent expected. 1530  long calleeGas = Math.min(remainingGas, specifiedGasPlusMin); 1531  1532  if (computeGas) { 1533  gasCost = GasCost.add(gasCost, calleeGas); 1534  spendOpCodeGas(); 1535  } 1536  1537  if (isLogEnabled) { 1538  hint = "addr: " + ByteUtil.toHexString(codeAddress.getLast20Bytes()) 1539  + " gas: " + calleeGas 1540  + " inOff: " + inDataOffs.shortHex() 1541  + " inSize: " + inDataSize.shortHex(); 1542  logger.info(logString, String.format("%5s", "[" + program.getPC() + "]"), 1543  String.format("%-12s", op.name()), 1544  program.getRemainingGas(), 1545  program.getCallDeep(), hint); 1546  } 1547  1548  program.memoryExpand(outDataOffs, outDataSize); 1549  1550  return new MessageCall( 1551  MsgType.fromOpcode(op), 1552  DataWord.valueOf(calleeGas), codeAddress, value, inDataOffs, inDataSize, 1553  outDataOffs, outDataSize); 1554  } 1555  1556  private DataWord calculateCallValue(ActivationConfig.ForBlock activations) { 1557  DataWord value; 1558  if (activations.isActive(RSKIP103)) { 1559  // value is always zero in a DELEGATECALL or STATICCALL operation 1560  value = op == OpCode.DELEGATECALL || op == OpCode.STATICCALL ? DataWord.ZERO : program.stackPop(); 1561  } else { 1562  // value is always zero in a DELEGATECALL operation 1563  value = op == OpCode.DELEGATECALL ? DataWord.ZERO : program.stackPop(); 1564  } 1565  return value; 1566  } 1567  1568  private long calculateGetMinimumTransferGas(DataWord value, long remainingGas) { 1569  // We give the callee a basic stipend whenever we transfer value, 1570  // basically to avoid problems when invoking a contract's default function. 1571  long minimumTransferGas = 0; 1572  1573  if (!value.isZero()) { 1574  1575  minimumTransferGas = GasCost.add(minimumTransferGas, GasCost.STIPEND_CALL); 1576  if (remainingGas < minimumTransferGas) { 1577  throw Program.ExceptionHelper.notEnoughSpendingGas(program, op.name(), minimumTransferGas); 1578  } 1579  } 1580  1581  return minimumTransferGas; 1582  } 1583  1584  private long computeCallGas(DataWord codeAddress, 1585  DataWord value, 1586  DataWord inDataOffs, 1587  DataWord inDataSize, 1588  DataWord outDataOffs, 1589  DataWord outDataSize) { 1590  long callGas = GasCost.CALL; 1591  1592  //check to see if account does not exist and is not a precompiled contract 1593  if (op == OpCode.CALL && !program.getStorage().isExist(new RskAddress(codeAddress))) { 1594  callGas = GasCost.add(callGas, GasCost.NEW_ACCT_CALL); 1595  } 1596  // RSKIP103: we don't need to check static call nor delegate call since value will always be zero 1597  if (!value.isZero()) { 1598  callGas = GasCost.add(callGas, GasCost.VT_CALL); 1599  } 1600  1601  long inSizeLong = Program.limitToMaxLong(inDataSize); 1602  long outSizeLong = Program.limitToMaxLong(outDataSize); 1603  1604  long in = memNeeded(inDataOffs, inSizeLong); // in offset+size 1605  long out = memNeeded(outDataOffs, outSizeLong); // out offset+size 1606  long newMemSize = Long.max(in, out); 1607  callGas = GasCost.add(callGas, calcMemGas(oldMemSize, newMemSize, 0)); 1608  return callGas; 1609  } 1610  1611  protected void doREVERT(){ 1612  doRETURN(); 1613  program.getResult().setRevert(); 1614  } 1615  1616  protected void doRETURN(){ 1617  DataWord size; 1618  long sizeLong; 1619  long newMemSize ; 1620  1621  size = stack.get(stack.size() - 2); 1622  1623  if (computeGas) { 1624  gasCost = GasCost.RETURN; 1625  sizeLong = Program.limitToMaxLong(size); 1626  checkSizeArgument(sizeLong); 1627  newMemSize = memNeeded(stack.peek(), sizeLong); 1628  gasCost = GasCost.add(gasCost, calcMemGas(oldMemSize, newMemSize, 0)); 1629  spendOpCodeGas(); 1630  } 1631  // EXECUTION PHASE 1632  DataWord offset = program.stackPop(); 1633  program.stackPop(); // pops size 1634  1635  byte[] hReturn = program.memoryChunk(offset.intValue(), size.intValue()); 1636  program.setHReturn(hReturn); 1637  1638  if (isLogEnabled) { 1639  hint = "data: " + ByteUtil.toHexString(hReturn) 1640  + " offset: " + offset.value() 1641  + " size: " + size.value(); 1642  } 1643  1644  program.step(); 1645  program.stop(); 1646  } 1647  1648  protected void doSUICIDE(){ 1649  if (program.isStaticCall() && program.getActivations().isActive(RSKIP91)) { 1650  throw Program.ExceptionHelper.modificationException(program); 1651  } 1652  1653  if (computeGas) { 1654  gasCost = GasCost.SUICIDE; 1655  DataWord suicideAddressWord = stack.get(stack.size() - 1); 1656  if (!program.getStorage().isExist(new RskAddress(suicideAddressWord))) { 1657  gasCost = GasCost.add(gasCost, GasCost.NEW_ACCT_SUICIDE); 1658  } 1659  spendOpCodeGas(); 1660  } 1661  // EXECUTION PHASE 1662  DataWord address = program.stackPop(); 1663  program.suicide(address); 1664  1665  if (isLogEnabled) { 1666  hint = "address: " + ByteUtil.toHexString(program.getOwnerAddress().getLast20Bytes()); 1667  } 1668  1669  program.stop(); 1670  } 1671  1672  protected void executeOpcode() { 1673  // Execute operation 1674  ActivationConfig.ForBlock activations = program.getActivations(); 1675  switch (op.val()) { 1676  /** 1677  * Stop and Arithmetic Operations 1678  */ 1679  case OpCodes.OP_STOP: doSTOP(); 1680  break; 1681  case OpCodes.OP_ADD: doADD(); 1682  break; 1683  case OpCodes.OP_MUL: doMUL(); 1684  break; 1685  case OpCodes.OP_SUB: doSUB(); 1686  break; 1687  case OpCodes.OP_DIV: doDIV(); 1688  break; 1689  case OpCodes.OP_SDIV: doSDIV(); 1690  break; 1691  case OpCodes.OP_MOD: doMOD(); 1692  break; 1693  case OpCodes.OP_SMOD: doSMOD(); 1694  break; 1695  case OpCodes.OP_EXP: doEXP(); 1696  break; 1697  case OpCodes.OP_SIGNEXTEND: doSIGNEXTEND(); 1698  break; 1699  case OpCodes.OP_NOT: doNOT(); 1700  break; 1701  case OpCodes.OP_LT: doLT(); 1702  break; 1703  case OpCodes.OP_SLT: doSLT(); 1704  break; 1705  case OpCodes.OP_SGT: doSGT(); 1706  break; 1707  case OpCodes.OP_GT: doGT(); 1708  break; 1709  case OpCodes.OP_EQ: doEQ(); 1710  break; 1711  case OpCodes.OP_ISZERO: doISZERO(); 1712  break; 1713  /** 1714  * Bitwise Logic Operations 1715  */ 1716  case OpCodes.OP_AND: doAND(); 1717  break; 1718  case OpCodes.OP_OR: doOR(); 1719  break; 1720  case OpCodes.OP_XOR: doXOR(); 1721  break; 1722  case OpCodes.OP_BYTE: doBYTE(); 1723  break; 1724  case OpCodes.OP_ADDMOD: doADDMOD(); 1725  break; 1726  case OpCodes.OP_MULMOD: doMULMOD(); 1727  break; 1728  case OpCodes.OP_SHL: 1729  if (!activations.isActive(RSKIP120)) { 1730  throw Program.ExceptionHelper.invalidOpCode(program); 1731  } 1732  doSHL(); 1733  break; 1734  case OpCodes.OP_SHR: 1735  if (!activations.isActive(RSKIP120)) { 1736  throw Program.ExceptionHelper.invalidOpCode(program); 1737  } 1738  doSHR(); 1739  break; 1740  case OpCodes.OP_SAR: 1741  if (!activations.isActive(RSKIP120)) { 1742  throw Program.ExceptionHelper.invalidOpCode(program); 1743  } 1744  doSAR(); 1745  break; 1746  /** 1747  * SHA3 1748  */ 1749  case OpCodes.OP_SHA_3: doSHA3(); 1750  break; 1751  1752  /** 1753  * Environmental Information 1754  */ 1755  case OpCodes.OP_ADDRESS: doADDRESS(); 1756  break; 1757  case OpCodes.OP_BALANCE: doBALANCE(); 1758  break; 1759  case OpCodes.OP_ORIGIN: doORIGIN(); 1760  break; 1761  case OpCodes.OP_CALLER: doCALLER(); 1762  break; 1763  case OpCodes.OP_CALLVALUE: doCALLVALUE(); 1764  break; 1765  case OpCodes.OP_CALLDATALOAD: doCALLDATALOAD(); 1766  break; 1767  case OpCodes.OP_CALLDATASIZE: doCALLDATASIZE(); 1768  break; 1769  case OpCodes.OP_CALLDATACOPY: doCALLDATACOPY(); 1770  break; 1771  case OpCodes.OP_CODESIZE: 1772  case OpCodes.OP_EXTCODESIZE: doCODESIZE(); 1773  break; 1774  case OpCodes.OP_CODECOPY: 1775  case OpCodes.OP_EXTCODECOPY: doCODECOPY(); 1776  break; 1777  1778  1779  case OpCodes.OP_EXTCODEHASH: 1780  if (!activations.isActive(RSKIP140)) { 1781  throw Program.ExceptionHelper.invalidOpCode(program); 1782  } 1783  doEXTCODEHASH(); 1784  break; 1785  case OpCodes.OP_RETURNDATASIZE: doRETURNDATASIZE(); 1786  break; 1787  case OpCodes.OP_RETURNDATACOPY: doRETURNDATACOPY(); 1788  break; 1789  case OpCodes.OP_GASPRICE: doGASPRICE(); 1790  break; 1791  1792  /** 1793  * Block Information 1794  */ 1795  case OpCodes.OP_BLOCKHASH: doBLOCKHASH(); 1796  break; 1797  case OpCodes.OP_COINBASE: doCOINBASE(); 1798  break; 1799  case OpCodes.OP_TIMESTAMP: doTIMESTAMP(); 1800  break; 1801  case OpCodes.OP_NUMBER: doNUMBER(); 1802  break; 1803  case OpCodes.OP_DIFFICULTY: doDIFFICULTY(); 1804  break; 1805  case OpCodes.OP_GASLIMIT: doGASLIMIT(); 1806  break; 1807  case OpCodes.OP_CHAINID: 1808  if (!activations.isActive(RSKIP152)) { 1809  throw Program.ExceptionHelper.invalidOpCode(program); 1810  } 1811  doCHAINID(); 1812  break; 1813  case OpCodes.OP_SELFBALANCE: 1814  if (!activations.isActive(RSKIP151)) { 1815  throw Program.ExceptionHelper.invalidOpCode(program); 1816  } 1817  doSELFBALANCE(); 1818  break; 1819  case OpCodes.OP_TXINDEX: 1820  if (activations.isActive(RSKIP191)) { 1821  throw Program.ExceptionHelper.invalidOpCode(program); 1822  } 1823  1824  doTXINDEX(); 1825  1826  break; 1827  1828  case OpCodes.OP_POP: doPOP(); 1829  break; 1830  case OpCodes.OP_DUP_1: 1831  case OpCodes.OP_DUP_2: 1832  case OpCodes.OP_DUP_3: 1833  case OpCodes.OP_DUP_4: 1834  case OpCodes.OP_DUP_5: 1835  case OpCodes.OP_DUP_6: 1836  case OpCodes.OP_DUP_7: 1837  case OpCodes.OP_DUP_8: 1838  case OpCodes.OP_DUP_9: 1839  case OpCodes.OP_DUP_10: 1840  case OpCodes.OP_DUP_11: 1841  case OpCodes.OP_DUP_12: 1842  case OpCodes.OP_DUP_13: 1843  case OpCodes.OP_DUP_14: 1844  case OpCodes.OP_DUP_15: 1845  case OpCodes.OP_DUP_16: doDUP(); 1846  break; 1847  case OpCodes.OP_SWAP_1: 1848  case OpCodes.OP_SWAP_2: 1849  case OpCodes.OP_SWAP_3: 1850  case OpCodes.OP_SWAP_4: 1851  case OpCodes.OP_SWAP_5: 1852  case OpCodes.OP_SWAP_6: 1853  case OpCodes.OP_SWAP_7: 1854  case OpCodes.OP_SWAP_8: 1855  case OpCodes.OP_SWAP_9: 1856  case OpCodes.OP_SWAP_10: 1857  case OpCodes.OP_SWAP_11: 1858  case OpCodes.OP_SWAP_12: 1859  case OpCodes.OP_SWAP_13: 1860  case OpCodes.OP_SWAP_14: 1861  case OpCodes.OP_SWAP_15: 1862  case OpCodes.OP_SWAP_16: doSWAP(); 1863  break; 1864  case OpCodes.OP_SWAPN: 1865  if (activations.isActive(RSKIP191)) { 1866  throw Program.ExceptionHelper.invalidOpCode(program); 1867  } 1868  1869  doSWAPN(); 1870  1871  break; 1872  1873  case OpCodes.OP_LOG_0: 1874  case OpCodes.OP_LOG_1: 1875  case OpCodes.OP_LOG_2: 1876  case OpCodes.OP_LOG_3: 1877  case OpCodes.OP_LOG_4: doLOG(); 1878  break; 1879  case OpCodes.OP_MLOAD: doMLOAD(); 1880  break; 1881  case OpCodes.OP_MSTORE: doMSTORE(); 1882  break; 1883  case OpCodes.OP_MSTORE_8: doMSTORE8(); 1884  break; 1885  case OpCodes.OP_SLOAD: doSLOAD(); 1886  break; 1887  case OpCodes.OP_SSTORE: doSSTORE(); 1888  break; 1889  case OpCodes.OP_JUMP: doJUMP(); 1890  break; 1891  case OpCodes.OP_JUMPI: doJUMPI(); 1892  break; 1893  case OpCodes.OP_PC: doPC(); 1894  break; 1895  case OpCodes.OP_MSIZE: doMSIZE(); 1896  break; 1897  case OpCodes.OP_GAS: doGAS(); 1898  break; 1899  1900  case OpCodes.OP_PUSH_1: 1901  case OpCodes.OP_PUSH_2: 1902  case OpCodes.OP_PUSH_3: 1903  case OpCodes.OP_PUSH_4: 1904  case OpCodes.OP_PUSH_5: 1905  case OpCodes.OP_PUSH_6: 1906  case OpCodes.OP_PUSH_7: 1907  case OpCodes.OP_PUSH_8: 1908  case OpCodes.OP_PUSH_9: 1909  case OpCodes.OP_PUSH_10: 1910  case OpCodes.OP_PUSH_11: 1911  case OpCodes.OP_PUSH_12: 1912  case OpCodes.OP_PUSH_13: 1913  case OpCodes.OP_PUSH_14: 1914  case OpCodes.OP_PUSH_15: 1915  case OpCodes.OP_PUSH_16: 1916  case OpCodes.OP_PUSH_17: 1917  case OpCodes.OP_PUSH_18: 1918  case OpCodes.OP_PUSH_19: 1919  case OpCodes.OP_PUSH_20: 1920  case OpCodes.OP_PUSH_21: 1921  case OpCodes.OP_PUSH_22: 1922  case OpCodes.OP_PUSH_23: 1923  case OpCodes.OP_PUSH_24: 1924  case OpCodes.OP_PUSH_25: 1925  case OpCodes.OP_PUSH_26: 1926  case OpCodes.OP_PUSH_27: 1927  case OpCodes.OP_PUSH_28: 1928  case OpCodes.OP_PUSH_29: 1929  case OpCodes.OP_PUSH_30: 1930  case OpCodes.OP_PUSH_31: 1931  case OpCodes.OP_PUSH_32: doPUSH(); 1932  break; 1933  case OpCodes.OP_JUMPDEST: doJUMPDEST(); 1934  break; 1935  case OpCodes.OP_CREATE: doCREATE(); 1936  break; 1937  case OpCodes.OP_CREATE2: 1938  if (!activations.isActive(RSKIP125)) { 1939  throw Program.ExceptionHelper.invalidOpCode(program); 1940  } 1941  doCREATE2(); 1942  break; 1943  case OpCodes.OP_CALL: 1944  case OpCodes.OP_CALLCODE: 1945  case OpCodes.OP_DELEGATECALL: 1946  doCALL(); 1947  break; 1948  case OpCodes.OP_STATICCALL: 1949  if (!activations.isActive(RSKIP91)) { 1950  throw Program.ExceptionHelper.invalidOpCode(program); 1951  } 1952  doCALL(); 1953  break; 1954  case OpCodes.OP_RETURN: doRETURN(); 1955  break; 1956  case OpCodes.OP_REVERT: doREVERT(); 1957  break; 1958  case OpCodes.OP_SUICIDE: doSUICIDE(); 1959  break; 1960  case OpCodes.OP_DUPN: 1961  if (activations.isActive(RSKIP191)) { 1962  throw Program.ExceptionHelper.invalidOpCode(program); 1963  } 1964  1965  doDUPN(); 1966  1967  break; 1968  case OpCodes.OP_HEADER: 1969  //fallthrough to default case until implementation's ready 1970  1971  default: 1972  // It should never execute this line. 1973  // We rise an exception to prevent DoS attacks that halt the node, in case of a bug. 1974  throw Program.ExceptionHelper.invalidOpCode(program); 1975  } 1976  } 1977  1978  protected void logOpCode() { 1979  if (isLogEnabled && !op.equals(OpCode.CALL) 1980  && !op.equals(OpCode.CALLCODE) 1981  && !op.equals(OpCode.CREATE)) { 1982  logger.info(logString, String.format("%5s", "[" + program.getPC() + "]"), 1983  String.format("%-12s", 1984  op.name()), program.getRemainingGas(), 1985  program.getCallDeep(), hint); 1986  } 1987  } 1988  1989  public void steps(Program aprogram, long steps) { 1990  program = aprogram; 1991  stack = program.getStack(); 1992  1993  try { 1994  1995  for(long s=0;s<steps;s++) { 1996  if (program.isStopped()) { 1997  break; 1998  } 1999  2000  if (vmConfig.vmTrace()) { 2001  program.saveOpTrace(); 2002  } 2003  2004  op = OpCode.code(program.getCurrentOp()); 2005  2006  checkOpcode(); 2007  program.setLastOp(op.val()); 2008  program.verifyStackSize(op.require()); 2009  program.verifyStackOverflow(op.require(), op.ret()); //Check not exceeding stack limits 2010  2011  //TODO: There is no need to compute oldMemSize for arithmetic opcodes. 2012  //But this three initializations and memory computations could be done 2013  //in opcodes requiring memory access only. 2014  oldMemSize = program.getMemSize(); 2015  2016  2017  if (isLogEnabled) { 2018  hint = ""; 2019  } 2020  2021  gasCost = op.getTier().asInt(); 2022  2023  if (vmConfig.dumpBlock() >= 0) { 2024  gasBefore = program.getRemainingGas(); 2025  memWords = 0; // parameters for logging 2026  } 2027  2028  // Log debugging line for VM 2029  if (vmConfig.dumpBlock() >= 0 && program.getNumber().intValue() == vmConfig.dumpBlock()) { 2030  this.dumpLine(op, gasBefore, gasCost , memWords, program); 2031  } 2032  2033  if (vmHook != null) { 2034  vmHook.step(program, op); 2035  } 2036  executeOpcode(); 2037  2038  if (vmConfig.vmTrace()) { 2039  program.saveOpGasCost(gasCost); 2040  } 2041  2042  logOpCode(); 2043  vmCounter++; 2044  } // for 2045  } catch (RuntimeException e) { 2046  logger.error("VM halted", e); 2047  program.spendAllGas(); 2048  program.resetFutureRefund(); 2049  program.stop(); 2050  throw e; 2051  } finally { 2052  if (isLogEnabled) { // this must be prevented because it's slow! 2053  program.fullTrace(); 2054  } 2055  } 2056  } 2057  2058  public void initDebugData() { 2059  gasBefore = 0; 2060  memWords = 0; 2061  } 2062  2063  public void play(Program program) { 2064  try { 2065  if (vmHook != null) { 2066  vmHook.startPlay(program); 2067  } 2068  2069  initDebugData(); 2070  this.steps(program,Long.MAX_VALUE); 2071  2072  if (vmHook != null) { 2073  vmHook.stopPlay(program); 2074  } 2075  2076  } catch (RuntimeException e) { 2077  program.setRuntimeFailure(e); 2078  } 2079  } 2080  2081  public static void setVmHook(VMHook vmHook) { 2082  VM.vmHook = vmHook; 2083  } 2084  2085  /** 2086  * Utility to calculate new total memory size needed for an operation. 2087  * <br/> Basically just offset + size, unless size is 0, in which case the result is also 0. 2088  * 2089  * @param offset starting position of the memory 2090  * @param size number of bytes needed 2091  * @return offset + size, unless size is 0. In that case memNeeded is also 0. 2092  */ 2093  2094  private static long memNeeded(DataWord offset, long size) { 2095  return (size==0)? 0 : limitedAddToMaxLong(Program.limitToMaxLong(offset.value()),size); 2096  } 2097  2098  /* 2099  * Dumping the VM state at the current operation in various styles 2100  * - standard Not Yet Implemented 2101  * - standard+ (owner address, program counter, operation, gas left) 2102  * - pretty (stack, memory, storage, level, contract, 2103  * vmCounter, internalSteps, operation 2104  gasBefore, gasCost, memWords) 2105  */ 2106  private void dumpLine(OpCode op, long gasBefore, long gasCost, long memWords, Program program) { 2107  Repository storage = program.getStorage(); 2108  RskAddress ownerAddress = new RskAddress(program.getOwnerAddress()); 2109  if ("standard+".equals(vmConfig.dumpStyle())) { 2110  switch (op) { 2111  case STOP: 2112  case RETURN: 2113  case SUICIDE: 2114  Iterator<DataWord> keysIterator = storage.getStorageKeys(ownerAddress); 2115  while (keysIterator.hasNext()) { 2116  DataWord key = keysIterator.next(); 2117  DataWord value = storage.getStorageValue(ownerAddress, key); 2118  dumpLogger.trace("{} {}", 2119  ByteUtil.toHexString(key.getNoLeadZeroesData()), 2120  ByteUtil.toHexString(value.getNoLeadZeroesData())); 2121  } 2122  break; 2123  default: 2124  break; 2125  } 2126  String addressString = ByteUtil.toHexString(program.getOwnerAddress().getLast20Bytes()); 2127  String pcString = ByteUtil.toHexString(DataWord.valueOf(program.getPC()).getNoLeadZeroesData()); 2128  String opString = ByteUtil.toHexString(new byte[]{op.val()}); 2129  String gasString = Long.toHexString(program.getRemainingGas()); 2130  2131  dumpLogger.trace("{} {} {} {}", addressString, pcString, opString, gasString); 2132  } else if ("pretty".equals(vmConfig.dumpStyle())) { 2133  dumpLogger.trace("-------------------------------------------------------------------------"); 2134  dumpLogger.trace(" STACK"); 2135  program.getStack().forEach(item -> dumpLogger.trace("{}", item)); 2136  dumpLogger.trace(" MEMORY"); 2137  String memoryString = program.memoryToString(); 2138  if (!"".equals(memoryString)) { 2139  dumpLogger.trace("{}", memoryString); 2140  } 2141  2142  dumpLogger.trace(" STORAGE"); 2143  Iterator<DataWord> keysIterator = storage.getStorageKeys(ownerAddress); 2144  while (keysIterator.hasNext()) { 2145  DataWord key = keysIterator.next(); 2146  DataWord value = storage.getStorageValue(ownerAddress, key); 2147  dumpLogger.trace("{}: {}", 2148  key.shortHex(), 2149  value.shortHex()); 2150  } 2151  2152  int level = program.getCallDeep(); 2153  String contract = ByteUtil.toHexString(program.getOwnerAddress().getLast20Bytes()); 2154  String internalSteps = String.format("%4s", Integer.toHexString(program.getPC())).replace(' ', '0').toUpperCase(); 2155  dumpLogger.trace("{} | {} | #{} | {} : {} | {} | -{} | {}x32", 2156  level, contract, vmCounter, internalSteps, op, 2157  gasBefore, gasCost, memWords); 2158  } 2159  } 2160 }