Coverage Summary for Class: TraceModuleImpl (co.rsk.rpc.modules.trace)

Class Class, % Method, % Line, %
TraceModuleImpl 0% (0/1) 0% (0/7) 0% (0/60)


1 /* 2  * This file is part of RskJ 3  * Copyright (C) 2018 RSK Labs Ltd. 4  * 5  * This program is free software: you can redistribute it and/or modify 6  * it under the terms of the GNU Lesser General Public License as published by 7  * the Free Software Foundation, either version 3 of the License, or 8  * (at your option) any later version. 9  * 10  * This program is distributed in the hope that it will be useful, 11  * but WITHOUT ANY WARRANTY; without even the implied warranty of 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13  * GNU Lesser General Public License for more details. 14  * 15  * You should have received a copy of the GNU Lesser General Public License 16  * along with this program. If not, see <http://www.gnu.org/licenses/>. 17  */ 18  19 package co.rsk.rpc.modules.trace; 20  21 import co.rsk.config.VmConfig; 22 import co.rsk.core.bc.BlockExecutor; 23 import com.fasterxml.jackson.databind.JsonNode; 24 import com.fasterxml.jackson.databind.ObjectMapper; 25 import org.ethereum.core.Block; 26 import org.ethereum.core.Blockchain; 27 import org.ethereum.core.Transaction; 28 import org.ethereum.db.BlockStore; 29 import org.ethereum.db.ReceiptStore; 30 import org.ethereum.db.TransactionInfo; 31 import org.ethereum.rpc.exception.RskJsonRpcRequestException; 32 import org.ethereum.vm.trace.ProgramTraceProcessor; 33 import org.ethereum.vm.trace.Serializers; 34 import org.ethereum.vm.trace.SummarizedProgramTrace; 35 import org.slf4j.Logger; 36 import org.slf4j.LoggerFactory; 37  38 import java.util.ArrayList; 39 import java.util.List; 40  41 import static org.ethereum.rpc.TypeConverter.stringHexToBigInteger; 42 import static org.ethereum.rpc.TypeConverter.stringHexToByteArray; 43  44 public class TraceModuleImpl implements TraceModule { 45  private static final Logger logger = LoggerFactory.getLogger("web3"); 46  47  private final Blockchain blockchain; 48  private final BlockStore blockStore; 49  private final ReceiptStore receiptStore; 50  51  private final BlockExecutor blockExecutor; 52  53  public TraceModuleImpl( 54  Blockchain blockchain, 55  BlockStore blockStore, 56  ReceiptStore receiptStore, 57  BlockExecutor blockExecutor) { 58  this.blockchain = blockchain; 59  this.blockStore = blockStore; 60  this.receiptStore = receiptStore; 61  this.blockExecutor = blockExecutor; 62  } 63  64  @Override 65  public JsonNode traceTransaction(String transactionHash) throws Exception { 66  logger.trace("trace_transaction({})", transactionHash); 67  68  byte[] hash = stringHexToByteArray(transactionHash); 69  TransactionInfo txInfo = this.receiptStore.getInMainChain(hash, this.blockStore); 70  71  if (txInfo == null) { 72  logger.trace("No transaction info for {}", transactionHash); 73  return null; 74  } 75  76  Block block = this.blockchain.getBlockByHash(txInfo.getBlockHash()); 77  Block parent = this.blockchain.getBlockByHash(block.getParentHash().getBytes()); 78  Transaction tx = block.getTransactionsList().get(txInfo.getIndex()); 79  txInfo.setTransaction(tx); 80  81  ProgramTraceProcessor programTraceProcessor = new ProgramTraceProcessor(); 82  this.blockExecutor.traceBlock(programTraceProcessor, VmConfig.LIGHT_TRACE, block, parent.getHeader(), false, false); 83  84  SummarizedProgramTrace programTrace = (SummarizedProgramTrace)programTraceProcessor.getProgramTrace(tx.getHash()); 85  86  if (programTrace == null) { 87  return null; 88  } 89  90  List<TransactionTrace> traces = TraceTransformer.toTraces(programTrace, txInfo, block.getNumber()); 91  ObjectMapper mapper = Serializers.createMapper(true); 92  return mapper.valueToTree(traces); 93  } 94  95  @Override 96  public JsonNode traceBlock(String blockArgument) throws Exception { 97  logger.trace("trace_block({})", blockArgument); 98  99  Block block = this.getByJsonArgument(blockArgument); 100  101  if (block == null) { 102  logger.trace("No block for {}", blockArgument); 103  return null; 104  } 105  106  Block parent = this.blockchain.getBlockByHash(block.getParentHash().getBytes()); 107  108  List<TransactionTrace> blockTraces = new ArrayList<>(); 109  110  if (block.getNumber() != 0) { 111  ProgramTraceProcessor programTraceProcessor = new ProgramTraceProcessor(); 112  this.blockExecutor.traceBlock(programTraceProcessor, VmConfig.LIGHT_TRACE, block, parent.getHeader(), false, false); 113  114  for (Transaction tx : block.getTransactionsList()) { 115  TransactionInfo txInfo = receiptStore.getInMainChain(tx.getHash().getBytes(), this.blockStore); 116  txInfo.setTransaction(tx); 117  118  SummarizedProgramTrace programTrace = (SummarizedProgramTrace) programTraceProcessor.getProgramTrace(tx.getHash()); 119  120  if (programTrace == null) { 121  return null; 122  } 123  124  List<TransactionTrace> traces = TraceTransformer.toTraces(programTrace, txInfo, block.getNumber()); 125  126  blockTraces.addAll(traces); 127  } 128  } 129  130  ObjectMapper mapper = Serializers.createMapper(true); 131  132  return mapper.valueToTree(blockTraces); 133  } 134  135  private Block getByJsonArgument(String arg) { 136  if (arg.length() < 20) { 137  return this.getByJsonBlockId(arg); 138  } 139  else { 140  return this.getByJsonBlockHash(arg); 141  } 142  } 143  144  private Block getByJsonBlockHash(String arg) { 145  byte[] hash = stringHexToByteArray(arg); 146  147  return this.blockchain.getBlockByHash(hash); 148  } 149  150  private Block getByJsonBlockId(String id) { 151  if ("earliest".equalsIgnoreCase(id)) { 152  return this.blockchain.getBlockByNumber(0); 153  } else if ("latest".equalsIgnoreCase(id)) { 154  return this.blockchain.getBestBlock(); 155  } else if ("pending".equalsIgnoreCase(id)) { 156  throw RskJsonRpcRequestException.unimplemented("The method don't support 'pending' as a parameter yet"); 157  } else { 158  try { 159  long blockNumber = stringHexToBigInteger(id).longValue(); 160  return this.blockchain.getBlockByNumber(blockNumber); 161  } catch (NumberFormatException | StringIndexOutOfBoundsException e) { 162  throw RskJsonRpcRequestException.invalidParamError("invalid blocknumber " + id); 163  } 164  } 165  } 166 }