Skip to content

Commit

Permalink
Adding support to tracer parameter into debug_tracer module
Browse files Browse the repository at this point in the history
  • Loading branch information
asoto-iov committed Nov 4, 2024
1 parent 31fdae2 commit 9c80357
Show file tree
Hide file tree
Showing 20 changed files with 646 additions and 163 deletions.
16 changes: 8 additions & 8 deletions rskj-core/src/main/java/co/rsk/RskContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@
import co.rsk.rpc.*;
import co.rsk.rpc.modules.debug.DebugModule;
import co.rsk.rpc.modules.debug.DebugModuleImpl;
import co.rsk.rpc.modules.debug.trace.CallTracer;
import co.rsk.rpc.modules.debug.trace.RskTracer;
import co.rsk.rpc.modules.debug.trace.TraceProvider;
import co.rsk.rpc.modules.eth.*;
import co.rsk.rpc.modules.eth.subscribe.BlockHeaderNotificationEmitter;
import co.rsk.rpc.modules.eth.subscribe.LogsNotificationEmitter;
Expand Down Expand Up @@ -811,16 +814,13 @@ public synchronized ConfigCapabilities getConfigCapabilities() {

public synchronized DebugModule getDebugModule() {
checkIfNotClosed();
RskTracer rskTracer = new RskTracer(getBlockStore(), getReceiptStore(),
getBlockExecutor(), getWeb3InformationRetriever());

CallTracer callTracer = new CallTracer();
TraceProvider traceProvider = new TraceProvider(Arrays.asList(callTracer, rskTracer));
if (debugModule == null) {
debugModule = new DebugModuleImpl(
getBlockStore(),
getReceiptStore(),
getNodeMessageHandler(),
getBlockExecutor(),
getTxQuotaChecker(),
getWeb3InformationRetriever()
);
debugModule = new DebugModuleImpl(traceProvider,getNodeMessageHandler(),getTxQuotaChecker());
}

return debugModule;
Expand Down
13 changes: 7 additions & 6 deletions rskj-core/src/main/java/co/rsk/rpc/Web3DebugModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import co.rsk.net.handler.quota.TxQuota;
import co.rsk.rpc.modules.debug.DebugModule;
import com.fasterxml.jackson.databind.JsonNode;
import org.ethereum.rpc.parameters.DebugTracerParam;

import java.util.Map;

Expand All @@ -32,19 +33,19 @@ default String debug_wireProtocolQueueSize() {
}

default JsonNode debug_traceTransaction(String transactionHash) throws Exception {
return debug_traceTransaction(transactionHash, null);
return getDebugModule().traceTransaction(transactionHash);
}

default JsonNode debug_traceTransaction(String transactionHash, Map<String, String> traceOptions) throws Exception {
return getDebugModule().traceTransaction(transactionHash, traceOptions);
default JsonNode debug_traceTransaction(String transactionHash, DebugTracerParam traceParams) throws Exception {
return getDebugModule().traceTransaction(transactionHash, traceParams.getTraceOptions(), traceParams.getTracerType());
}

default JsonNode debug_traceBlockByHash(String blockHash) throws Exception {
return debug_traceBlockByHash(blockHash, null);
return getDebugModule().traceBlockByHash(blockHash);
}

default JsonNode debug_traceBlockByHash(String blockHash, Map<String, String> traceOptions) throws Exception {
return getDebugModule().traceBlockByHash(blockHash, traceOptions);
default JsonNode debug_traceBlockByHash(String blockHash, DebugTracerParam debugTracerParam) throws Exception {
return getDebugModule().traceBlockByHash(blockHash, debugTracerParam.getTraceOptions(), debugTracerParam.getTracerType());
}

default JsonNode debug_traceBlockByNumber(String bnOrId) throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package co.rsk.rpc.modules.debug;

import co.rsk.net.handler.quota.TxQuota;
import co.rsk.rpc.modules.debug.trace.TracerType;
import com.fasterxml.jackson.databind.JsonNode;

import java.util.Map;
Expand All @@ -27,11 +28,16 @@ public interface DebugModule {

String wireProtocolQueueSize();

JsonNode traceTransaction(String transactionHash, Map<String, String> traceOptions) throws Exception;
JsonNode traceTransaction(String transactionHash) throws Exception;

JsonNode traceBlockByHash(String blockHash, Map<String, String> traceOptions) throws Exception;
JsonNode traceTransaction(String transactionHash, TraceOptions traceOptions, TracerType tracerType) throws Exception;

JsonNode traceBlockByHash(String blockHash, TraceOptions traceOptions, TracerType tracerType) throws Exception;
JsonNode traceBlockByHash(String blockHash) throws Exception;

JsonNode traceBlockByNumber(String bnOrId, Map<String, String> traceOptions) throws Exception;

JsonNode traceBlockByNumber(String bnOrId, Map<String, String> traceOptions, TracerType tracerType) throws Exception;

TxQuota accountTransactionQuota(String address);
}
143 changes: 57 additions & 86 deletions rskj-core/src/main/java/co/rsk/rpc/modules/debug/DebugModuleImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,128 +19,97 @@
package co.rsk.rpc.modules.debug;

import co.rsk.core.RskAddress;
import co.rsk.core.bc.BlockExecutor;
import co.rsk.crypto.Keccak256;
import co.rsk.net.MessageHandler;
import co.rsk.net.handler.quota.TxQuota;
import co.rsk.net.handler.quota.TxQuotaChecker;
import co.rsk.rpc.Web3InformationRetriever;
import co.rsk.rpc.modules.debug.trace.DebugTracer;
import co.rsk.rpc.modules.debug.trace.TraceProvider;
import co.rsk.rpc.modules.debug.trace.TracerType;
import co.rsk.util.HexUtils;
import co.rsk.util.StringUtils;
import com.fasterxml.jackson.databind.JsonNode;
import org.ethereum.core.Block;
import org.ethereum.core.Transaction;
import org.ethereum.db.BlockStore;
import org.ethereum.db.ReceiptStore;
import org.ethereum.db.TransactionInfo;
import org.ethereum.vm.trace.ProgramTraceProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.Optional;

public class DebugModuleImpl implements DebugModule {
//this could be configurable
public static final TracerType DEFAULT_TRACER_TYPE = TracerType.RSK_TRACER;
private static final Logger logger = LoggerFactory.getLogger("web3");

private final BlockStore blockStore;
private final ReceiptStore receiptStore;

private final TraceProvider traceProvider;
private final MessageHandler messageHandler;
private final BlockExecutor blockExecutor;

private final TxQuotaChecker txQuotaChecker;
private final Web3InformationRetriever web3InformationRetriever;

public DebugModuleImpl(
BlockStore blockStore,
ReceiptStore receiptStore,
MessageHandler messageHandler,
BlockExecutor blockExecutor,
TxQuotaChecker txQuotaChecker,
Web3InformationRetriever web3InformationRetriever) {
this.blockStore = blockStore;
this.receiptStore = receiptStore;

public DebugModuleImpl(TraceProvider traceProvider, MessageHandler messageHandler, TxQuotaChecker txQuotaChecker) {
this.traceProvider = traceProvider;
this.messageHandler = messageHandler;
this.blockExecutor = blockExecutor;
this.txQuotaChecker = txQuotaChecker;
this.web3InformationRetriever = web3InformationRetriever;
}


@Override
public String wireProtocolQueueSize() {
long n = messageHandler.getMessageQueueSize();
return HexUtils.toQuantityJsonHex(n);
}

@Override
public JsonNode traceTransaction(String transactionHash, Map<String, String> traceOptions) {
logger.trace("debug_traceTransaction for txHash: {}", StringUtils.trim(transactionHash));

TraceOptions options = toTraceOptions(traceOptions);
public TxQuota accountTransactionQuota(String address) {
logger.trace("debug_accountTransactionQuota({})", StringUtils.trim(address));
RskAddress rskAddress = new RskAddress(address);
return txQuotaChecker.getTxQuota(rskAddress);
}

byte[] hash = HexUtils.stringHexToByteArray(transactionHash);
TransactionInfo txInfo = receiptStore.getInMainChain(hash, blockStore).orElse(null);
@Override
public JsonNode traceTransaction(String transactionHash) {
return traceTransaction(transactionHash, new TraceOptions(), null);
}

if (txInfo == null) {
logger.trace("No transaction info for txHash: {}", StringUtils.trim(transactionHash));
return null;
@Override
public JsonNode traceTransaction(String transactionHash, TraceOptions traceOptions, TracerType tracerType) {
if (tracerType == null) {
tracerType = DEFAULT_TRACER_TYPE;
}

Block block = blockStore.getBlockByHash(txInfo.getBlockHash());
Block parent = blockStore.getBlockByHash(block.getParentHash().getBytes());
Transaction tx = block.getTransactionsList().get(txInfo.getIndex());
txInfo.setTransaction(tx);

ProgramTraceProcessor programTraceProcessor = new ProgramTraceProcessor(options);
blockExecutor.traceBlock(programTraceProcessor, 0, block, parent.getHeader(), false, false);

return programTraceProcessor.getProgramTraceAsJsonNode(tx.getHash());
if (traceOptions == null) {
traceOptions = new TraceOptions();
}
DebugTracer tracer = traceProvider.getTracer(tracerType);
logger.trace("debug_traceTransaction for txHash: {}", StringUtils.trim(transactionHash));
return tracer.traceTransaction(transactionHash, traceOptions);
}

@Override
public JsonNode traceBlockByHash(String blockHash, Map<String, String> traceOptions) {
public JsonNode traceBlockByHash(String blockHash, TraceOptions traceOptions, TracerType tracerType) {
if (tracerType == null) {
tracerType = DEFAULT_TRACER_TYPE;
}
if (traceOptions == null) {
traceOptions = new TraceOptions();
}
logger.trace("debug_traceBlockByHash for blockHash: {}", StringUtils.trim(blockHash));
DebugTracer tracer = traceProvider.getTracer(tracerType);
return tracer.traceBlockByHash(blockHash, traceOptions);
}

TraceOptions options = toTraceOptions(traceOptions);
@Override
public JsonNode traceBlockByHash(String blockHash) throws Exception {
return traceBlockByHash(blockHash, new TraceOptions(), null);
}

byte[] bHash = HexUtils.stringHexToByteArray(blockHash);
Block block = blockStore.getBlockByHash(bHash);
if (block == null) {
logger.trace("No block is found for blockHash: {}", StringUtils.trim(blockHash));
return null;
}

return traceBlock(block, options);
@Override
public JsonNode traceBlockByNumber(String bnOrId, Map<String, String> traceOptions) throws Exception {
return traceBlockByNumber(bnOrId, traceOptions, DEFAULT_TRACER_TYPE);
}

@Override
public JsonNode traceBlockByNumber(String bnOrId, Map<String, String> traceOptions) {
public JsonNode traceBlockByNumber(String bnOrId, Map<String, String> traceOptions, TracerType tracerType) throws Exception {
logger.trace("debug_traceBlockByNumber for bnOrId: {}", StringUtils.trim(bnOrId));

DebugTracer tracer = traceProvider.getTracer(tracerType);
TraceOptions options = toTraceOptions(traceOptions);

Block block = web3InformationRetriever.getBlock(bnOrId).orElse(null);
if (block == null) {
logger.trace("No block is found for bnOrId: {}", StringUtils.trim(bnOrId));
return null;
}

return traceBlock(block, options);
}

private JsonNode traceBlock(Block block, TraceOptions options) {
Block parent = blockStore.getBlockByHash(block.getParentHash().getBytes());

ProgramTraceProcessor programTraceProcessor = new ProgramTraceProcessor(options);
blockExecutor.traceBlock(programTraceProcessor, 0, block, parent.getHeader(), false, false);

List<Keccak256> txHashes = block.getTransactionsList().stream()
.map(Transaction::getHash)
.collect(Collectors.toList());

return programTraceProcessor.getProgramTracesAsJsonNode(txHashes);
return tracer.traceBlockByNumber(bnOrId, options);
}

private TraceOptions toTraceOptions(Map<String, String> traceOptions) {
Expand All @@ -154,10 +123,12 @@ private TraceOptions toTraceOptions(Map<String, String> traceOptions) {
return options;
}

@Override
public TxQuota accountTransactionQuota(String address) {
logger.trace("debug_accountTransactionQuota({})", StringUtils.trim(address));
RskAddress rskAddress = new RskAddress(address);
return this.txQuotaChecker.getTxQuota(rskAddress);
private TracerType getTracerType(Map<String, String> options) {
if (options.containsKey("tracer")) {
Optional.ofNullable(TracerType.getTracerType(options.get("tracer")))
.orElseThrow(() -> new IllegalArgumentException("Invalid tracer type: " + options.get("tracer")));
}
return DEFAULT_TRACER_TYPE;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,13 @@ public enum DisableOption {
this.option = option;
this.value = value;
}

public static DisableOption getDisableOption(String option) {
for (DisableOption disableOption : DisableOption.values()) {
if (disableOption.option.equalsIgnoreCase(option)) {
return disableOption;
}
}
return null;
}
}
Loading

0 comments on commit 9c80357

Please sign in to comment.