diff --git a/rskj-core/src/main/java/co/rsk/RskContext.java b/rskj-core/src/main/java/co/rsk/RskContext.java index 9e32bc6be8e..ccc43519be2 100644 --- a/rskj-core/src/main/java/co/rsk/RskContext.java +++ b/rskj-core/src/main/java/co/rsk/RskContext.java @@ -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; @@ -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; diff --git a/rskj-core/src/main/java/co/rsk/rpc/Web3DebugModule.java b/rskj-core/src/main/java/co/rsk/rpc/Web3DebugModule.java index c59feddf07f..2e49fd3eb56 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/Web3DebugModule.java +++ b/rskj-core/src/main/java/co/rsk/rpc/Web3DebugModule.java @@ -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; @@ -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 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 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 { diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/debug/DebugModule.java b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/DebugModule.java index 4b7c3e2ce30..6d499084423 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/debug/DebugModule.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/DebugModule.java @@ -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; @@ -27,11 +28,16 @@ public interface DebugModule { String wireProtocolQueueSize(); - JsonNode traceTransaction(String transactionHash, Map traceOptions) throws Exception; + JsonNode traceTransaction(String transactionHash) throws Exception; - JsonNode traceBlockByHash(String blockHash, Map 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 traceOptions) throws Exception; + JsonNode traceBlockByNumber(String bnOrId, Map traceOptions, TracerType tracerType) throws Exception; + TxQuota accountTransactionQuota(String address); } diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/debug/DebugModuleImpl.java b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/DebugModuleImpl.java index 62be8e6e55c..2d1d9007940 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/debug/DebugModuleImpl.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/DebugModuleImpl.java @@ -19,55 +19,36 @@ 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(); @@ -75,72 +56,60 @@ public String wireProtocolQueueSize() { } @Override - public JsonNode traceTransaction(String transactionHash, Map 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 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 traceOptions) throws Exception { + return traceBlockByNumber(bnOrId, traceOptions, DEFAULT_TRACER_TYPE); } @Override - public JsonNode traceBlockByNumber(String bnOrId, Map traceOptions) { + public JsonNode traceBlockByNumber(String bnOrId, Map 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 txHashes = block.getTransactionsList().stream() - .map(Transaction::getHash) - .collect(Collectors.toList()); - - return programTraceProcessor.getProgramTracesAsJsonNode(txHashes); + return tracer.traceBlockByNumber(bnOrId, options); } private TraceOptions toTraceOptions(Map traceOptions) { @@ -154,10 +123,12 @@ private TraceOptions toTraceOptions(Map 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 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; } + } diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/debug/DisableOption.java b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/DisableOption.java index 6fac1c24916..94987d8bc5d 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/debug/DisableOption.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/DisableOption.java @@ -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; + } } diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/debug/TraceOptions.java b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/TraceOptions.java index b5d3fa3cc40..819dd6da0fb 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/debug/TraceOptions.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/TraceOptions.java @@ -19,42 +19,76 @@ package co.rsk.rpc.modules.debug; +import co.rsk.rpc.modules.debug.trace.TracerType; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +import java.io.IOException; +import java.io.Serial; import java.util.*; -import java.util.stream.Collectors; +@JsonDeserialize(using = TraceOptions.Deserializer.class) public class TraceOptions { - private final List supportedOptions; private final Set disabledFields; private final Set unsupportedOptions; + private boolean onlyTopCall; + private boolean diffMode; + private TracerType tracerType; public TraceOptions() { - supportedOptions = Arrays.stream(DisableOption.values()).map(option -> option.option) - .collect(Collectors.toList()); - this.disabledFields = new HashSet<>(); this.unsupportedOptions = new HashSet<>(); } public TraceOptions(Map traceOptions) { this(); + if (traceOptions == null) { + return; + } + traceOptions.forEach(this::addOption); + } + + public final void addOption(String key, String value) { + switch (key) { + case "onlyTopCall" -> onlyTopCall = Boolean.parseBoolean(value); + case "diffMode" -> diffMode = Boolean.parseBoolean(value); + default -> addDisableOption(key, value); + } + } - if (traceOptions == null || traceOptions.isEmpty()) return; - // Disabled Fields Parsing - for (DisableOption disableOption : DisableOption.values()) { - if (Boolean.parseBoolean(traceOptions.get(disableOption.option))) { - this.disabledFields.add(disableOption.value); + + private void addDisableOption(String key, String value) { + DisableOption disableOption = DisableOption.getDisableOption(key); + if (disableOption != null) { + if (Boolean.parseBoolean(value)) { + disabledFields.add(disableOption.value); } + } else { + unsupportedOptions.add(key); } + } + - // Unsupported Options + public void setOnlyTopCall(boolean onlyTopCall) { + this.onlyTopCall = onlyTopCall; + } + + public void setDiffMode(boolean diffMode) { + this.diffMode = diffMode; + } - traceOptions.keySet() - .stream() - .filter(key -> supportedOptions.stream().noneMatch(option -> option.equals(key))) - .forEach(unsupportedOptions::add); + public boolean isOnlyTopCall() { + return onlyTopCall; + } + + public boolean isDiffMode() { + return diffMode; } public Set getDisabledFields() { @@ -65,4 +99,37 @@ public Set getUnsupportedOptions() { return Collections.unmodifiableSet(unsupportedOptions); } + public TracerType getTracerType() { + return tracerType; + } + + public static class Deserializer extends StdDeserializer { + @Serial + private static final long serialVersionUID = 4222943114560623356L; + + public Deserializer() { + this(null); + } + + public Deserializer(Class vc) { + super(vc); + } + + @Override + public TraceOptions deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + JsonNode node = jp.getCodec().readTree(jp); + TraceOptions traceOptions = new TraceOptions(); + Iterator> fields = node.fields(); + while (fields.hasNext()) { + Map.Entry entry = fields.next(); + if ("tracerConfig".equalsIgnoreCase(entry.getKey())) { + JsonNode tracerConfigNode = entry.getValue(); + tracerConfigNode.fields().forEachRemaining(tracerConfigEntry + -> traceOptions.addOption(tracerConfigEntry.getKey(), tracerConfigEntry.getValue().asText())); + } + traceOptions.addOption(entry.getKey(), entry.getValue().asText()); + } + return traceOptions; + } + } } diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/debug/trace/CallTracer.java b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/trace/CallTracer.java new file mode 100644 index 00000000000..9b60881a474 --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/trace/CallTracer.java @@ -0,0 +1,48 @@ +/* + * This file is part of RskJ + * Copyright (C) 2024 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package co.rsk.rpc.modules.debug.trace; + +import co.rsk.rpc.modules.debug.TraceOptions; +import com.fasterxml.jackson.databind.JsonNode; + +public class CallTracer implements DebugTracer { + + public static final String UNSUPPORTED_OPERATION = "Operation not supported by this tracer."; + + @Override + public JsonNode traceTransaction(String transactionHash, TraceOptions traceOptions) { + throw new UnsupportedOperationException(UNSUPPORTED_OPERATION); + } + + @Override + public JsonNode traceBlockByHash(String blockHash, TraceOptions traceOptions) { + throw new UnsupportedOperationException(UNSUPPORTED_OPERATION); + + } + + @Override + public JsonNode traceBlockByNumber(String bnOrId, TraceOptions traceOptions) { + throw new UnsupportedOperationException(UNSUPPORTED_OPERATION); + + } + + @Override + public TracerType getTracerType() { + return TracerType.CALL_TRACER; + } +} diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/debug/trace/DebugTracer.java b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/trace/DebugTracer.java new file mode 100644 index 00000000000..bf938f7b0f9 --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/trace/DebugTracer.java @@ -0,0 +1,31 @@ +/* + * This file is part of RskJ + * Copyright (C) 2024 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package co.rsk.rpc.modules.debug.trace; + +import co.rsk.rpc.modules.debug.TraceOptions; +import com.fasterxml.jackson.databind.JsonNode; + +public interface DebugTracer { + JsonNode traceTransaction(String transactionHash, TraceOptions traceOptions); + + JsonNode traceBlockByHash(String blockHash, TraceOptions traceOptions); + + JsonNode traceBlockByNumber(String bnOrId, TraceOptions traceOptions); + + TracerType getTracerType(); +} diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/debug/trace/RskTracer.java b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/trace/RskTracer.java new file mode 100644 index 00000000000..0dd923e9bad --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/trace/RskTracer.java @@ -0,0 +1,123 @@ +/* + * This file is part of RskJ + * Copyright (C) 2024 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package co.rsk.rpc.modules.debug.trace; + +import co.rsk.core.bc.BlockExecutor; +import co.rsk.crypto.Keccak256; +import co.rsk.rpc.Web3InformationRetriever; +import co.rsk.rpc.modules.debug.TraceOptions; +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.stream.Collectors; + +public class RskTracer implements DebugTracer { + + private static final Logger logger = LoggerFactory.getLogger("web3"); + private final ReceiptStore receiptStore; + private final BlockStore blockStore; + private final BlockExecutor blockExecutor; + private final Web3InformationRetriever web3InformationRetriever; + + public RskTracer( + BlockStore blockStore, + ReceiptStore receiptStore, + BlockExecutor blockExecutor, + Web3InformationRetriever web3InformationRetriever) { + this.blockStore = blockStore; + this.receiptStore = receiptStore; + this.blockExecutor = blockExecutor; + this.web3InformationRetriever = web3InformationRetriever; + } + + @Override + public JsonNode traceTransaction(String transactionHash, TraceOptions traceOptions) { + logger.trace("debug_traceTransaction for txHash: {}", StringUtils.trim(transactionHash)); + + + byte[] hash = HexUtils.stringHexToByteArray(transactionHash); + TransactionInfo txInfo = receiptStore.getInMainChain(hash, blockStore).orElse(null); + + if (txInfo == null) { + logger.trace("No transaction info for txHash: {}", StringUtils.trim(transactionHash)); + return null; + } + + 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(traceOptions); + blockExecutor.traceBlock(programTraceProcessor, 0, block, parent.getHeader(), false, false); + + return programTraceProcessor.getProgramTraceAsJsonNode(tx.getHash()); + } + + @Override + public JsonNode traceBlockByHash(String blockHash, TraceOptions traceOptions) { + + 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, traceOptions); + } + + @Override + public JsonNode traceBlockByNumber(String bnOrId, TraceOptions 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, traceOptions); + } + + @Override + public TracerType getTracerType() { + return TracerType.RSK_TRACER; + } + + 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 txHashes = block.getTransactionsList().stream() + .map(Transaction::getHash) + .collect(Collectors.toList()); + + return programTraceProcessor.getProgramTracesAsJsonNode(txHashes); + } +} diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/debug/trace/TraceProvider.java b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/trace/TraceProvider.java new file mode 100644 index 00000000000..bd180c5726d --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/trace/TraceProvider.java @@ -0,0 +1,41 @@ +/* + * This file is part of RskJ + * Copyright (C) 2024 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package co.rsk.rpc.modules.debug.trace; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class TraceProvider { + + + private final Map tracers; + + public TraceProvider(List tracers) { + this.tracers = tracers.stream().collect(Collectors.toMap(DebugTracer::getTracerType, Function.identity())); + } + + + public DebugTracer getTracer(TracerType tracerType) { + return Optional.ofNullable(tracers.get(tracerType)) + .orElseThrow(() -> new IllegalArgumentException("Requested Tracer is not available." + tracerType.getTracerName())); + } + +} diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/debug/trace/TracerConfig.java b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/trace/TracerConfig.java new file mode 100644 index 00000000000..61b56138792 --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/trace/TracerConfig.java @@ -0,0 +1,25 @@ +package co.rsk.rpc.modules.debug.trace; + +public class TracerConfig { + + public TracerConfig(boolean onlyTopCall, boolean diffMode) { + this.onlyTopCall = onlyTopCall; + this.diffMode = diffMode; + } + public TracerConfig() { + this(false, false); + } + private boolean onlyTopCall; + private boolean diffMode; + + public boolean isOnlyTopCall() { + return onlyTopCall; + } + + public boolean isDiffMode() { + return diffMode; + } + + + +} diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/debug/trace/TracerType.java b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/trace/TracerType.java new file mode 100644 index 00000000000..862ea970239 --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/debug/trace/TracerType.java @@ -0,0 +1,43 @@ +/* + * This file is part of RskJ + * Copyright (C) 2024 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package co.rsk.rpc.modules.debug.trace; + +public enum TracerType { + CALL_TRACER("callTracer"), RSK_TRACER("rskTracer"); + + private final String tracerName; + TracerType(String tracerName) { + this.tracerName = tracerName; + } + + public static TracerType getTracerType(String tracerName) { + for (TracerType tracerType : TracerType.values()) { + if (tracerType.getTracerName().equalsIgnoreCase(tracerName)) { + return tracerType; + } + } + return null; + } + public String getTracerName() { + return tracerName; + } + + public TracerType getDefault() { + return RSK_TRACER; + } +} diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/DebugTracerParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/DebugTracerParam.java new file mode 100644 index 00000000000..716d551beab --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/DebugTracerParam.java @@ -0,0 +1,79 @@ +package org.ethereum.rpc.parameters; + +import co.rsk.rpc.modules.debug.TraceOptions; +import co.rsk.rpc.modules.debug.trace.TracerType; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +import java.io.IOException; +import java.io.Serial; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; + +@JsonDeserialize(using = DebugTracerParam.Deserializer.class) + +public class DebugTracerParam { + private final TracerType tracerType; + private final TraceOptions traceOptions; + + public DebugTracerParam(TracerType tracerType, TraceOptions traceOptions) { + this.tracerType = tracerType; + this.traceOptions = traceOptions; + } + + public TracerType getTracerType() { + return tracerType; + } + + public TraceOptions getTraceOptions() { + return traceOptions; + } + + public static class Deserializer extends StdDeserializer { + @Serial + private static final long serialVersionUID = 4222943114560623356L; + + public Deserializer() { + this(null); + } + + public Deserializer(Class vc) { + super(vc); + } + + @Override + public DebugTracerParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + JsonNode node; + try { + node = jp.getCodec().readTree(jp); + } catch (Exception e) { + throw new IllegalArgumentException("Can not deserialize parameters", e); + } + TracerType tracerType = null; + TraceOptions traceOptions = new TraceOptions(); + Iterator> fields = node.fields(); + while (fields.hasNext()) { + Map.Entry entry = fields.next(); + if ("tracerConfig".equalsIgnoreCase(entry.getKey())) { + JsonNode tracerConfigNode = entry.getValue(); + tracerConfigNode.fields().forEachRemaining(tracerConfigEntry + -> traceOptions.addOption(tracerConfigEntry.getKey(), tracerConfigEntry.getValue().asText())); + }else if("tracer".equalsIgnoreCase(entry.getKey())) { + tracerType = getTracerType(entry.getValue().asText()); + }else { + traceOptions.addOption(entry.getKey(), entry.getValue().asText()); + } + } + return new DebugTracerParam(tracerType, traceOptions); + } + + private TracerType getTracerType(String tracerType) { + return Optional.ofNullable(TracerType.getTracerType(tracerType)).orElseThrow(() + -> new IllegalArgumentException("Invalid tracer type: " + tracerType)); + } + } +} diff --git a/rskj-core/src/main/resources/reference.conf b/rskj-core/src/main/resources/reference.conf index a7d71a2b4db..1b1495a56ae 100644 --- a/rskj-core/src/main/resources/reference.conf +++ b/rskj-core/src/main/resources/reference.conf @@ -469,7 +469,7 @@ rpc { }, debug { version: "1.0", - enabled: "false" + enabled: "true" }, trace { version: "1.0", diff --git a/rskj-core/src/test/java/co/rsk/mine/TransactionModuleTest.java b/rskj-core/src/test/java/co/rsk/mine/TransactionModuleTest.java index f158eb2bcd2..5f5d1b1400c 100644 --- a/rskj-core/src/test/java/co/rsk/mine/TransactionModuleTest.java +++ b/rskj-core/src/test/java/co/rsk/mine/TransactionModuleTest.java @@ -35,6 +35,9 @@ import co.rsk.rpc.Web3RskImpl; import co.rsk.rpc.modules.debug.DebugModule; import co.rsk.rpc.modules.debug.DebugModuleImpl; +import co.rsk.rpc.modules.debug.trace.DebugTracer; +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.personal.PersonalModuleWalletEnabled; import co.rsk.rpc.modules.txpool.TxPoolModule; @@ -82,6 +85,7 @@ import java.math.BigInteger; import java.time.Clock; +import java.util.List; import static org.mockito.Mockito.mock; @@ -650,7 +654,9 @@ repositoryLocator, new EthModuleWalletEnabled(wallet, transactionPool, signature config.getCallGasCap() ); TxPoolModule txPoolModule = new TxPoolModuleImpl(transactionPool, new ReceivedTxSignatureCache()); - DebugModule debugModule = new DebugModuleImpl(null, null, Web3Mocks.getMockMessageHandler(), null, null, null); + DebugTracer debugTracer = new RskTracer(null, null, null, null); + TraceProvider traceProvider = new TraceProvider(List.of(debugTracer)); + DebugModule debugModule = new DebugModuleImpl(traceProvider, Web3Mocks.getMockMessageHandler(), null); ChannelManager channelManager = new SimpleChannelManager(); return new Web3RskImpl( diff --git a/rskj-core/src/test/java/co/rsk/rpc/modules/debug/DebugModuleImplTest.java b/rskj-core/src/test/java/co/rsk/rpc/modules/debug/DebugModuleImplTest.java index bdcb437179c..67d2f069f8d 100644 --- a/rskj-core/src/test/java/co/rsk/rpc/modules/debug/DebugModuleImplTest.java +++ b/rskj-core/src/test/java/co/rsk/rpc/modules/debug/DebugModuleImplTest.java @@ -19,10 +19,14 @@ package co.rsk.rpc.modules.debug; import co.rsk.core.RskAddress; +import co.rsk.core.bc.BlockExecutor; 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.RskTracer; +import co.rsk.rpc.modules.debug.trace.TraceProvider; import co.rsk.test.World; import co.rsk.test.dsl.DslParser; import co.rsk.test.dsl.WorldDslProcessor; @@ -44,10 +48,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; +import java.util.*; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -69,8 +70,7 @@ void setup() { messageHandlerMock = Web3Mocks.getMockMessageHandler(); txQuotaCheckerMock = mock(TxQuotaChecker.class); web3InformationRetrieverMock = mock(Web3InformationRetriever.class); - - mockedDebugModule = new DebugModuleImpl(blockStoreMock, receiptStoreMock, messageHandlerMock, Web3Mocks.getMockBlockExecutor(), txQuotaCheckerMock, web3InformationRetrieverMock); + mockedDebugModule = getDebugModule(blockStoreMock, Web3Mocks.getMockBlockExecutor(), receiptStoreMock, messageHandlerMock, txQuotaCheckerMock, web3InformationRetrieverMock); } @Test @@ -101,7 +101,7 @@ void debug_traceTransaction_retrieveUnknownTransactionAsNull() { when(receiptStoreMock.getInMainChain(hash, blockStoreMock)).thenReturn(Optional.empty()); - JsonNode result = mockedDebugModule.traceTransaction("0x00", null); + JsonNode result = mockedDebugModule.traceTransaction("0x00"); Assertions.assertNull(result); } @@ -117,9 +117,9 @@ void debug_traceTransaction_retrieveSimpleContractCreationTrace() throws Excepti Transaction transaction = world.getTransactionByName("tx01"); - DebugModuleImpl debugModule = new DebugModuleImpl(world.getBlockStore(), receiptStore, messageHandlerMock, world.getBlockExecutor(), null, null); + DebugModuleImpl debugModule = getDebugModule(world.getBlockStore(), world.getBlockExecutor(), receiptStore, messageHandlerMock, null, null); - JsonNode result = debugModule.traceTransaction(transaction.getHash().toJsonString(), null); + JsonNode result = debugModule.traceTransaction(transaction.getHash().toJsonString()); Assertions.assertNotNull(result); Assertions.assertTrue(result.isObject()); @@ -143,9 +143,9 @@ void debug_traceTransaction_retrieveEmptyContractCreationTrace() throws Exceptio Transaction transaction = world.getTransactionByName("tx01"); - DebugModuleImpl debugModule = new DebugModuleImpl(world.getBlockStore(), receiptStore, messageHandlerMock, world.getBlockExecutor(), null, null); + DebugModuleImpl debugModule = getDebugModule(world.getBlockStore(), world.getBlockExecutor(), receiptStore, messageHandlerMock, null, null); - JsonNode result = debugModule.traceTransaction(transaction.getHash().toJsonString(), null); + JsonNode result = debugModule.traceTransaction(transaction.getHash().toJsonString()); Assertions.assertNotNull(result); Assertions.assertTrue(result.isObject()); @@ -168,9 +168,9 @@ void debug_traceTransaction_retrieveSimpleContractInvocationTrace() throws Excep Transaction transaction = world.getTransactionByName("tx02"); - DebugModuleImpl debugModule = new DebugModuleImpl(world.getBlockStore(), receiptStore, messageHandlerMock, world.getBlockExecutor(), null, null); + DebugModuleImpl debugModule = getDebugModule(world.getBlockStore(), world.getBlockExecutor(), receiptStore, messageHandlerMock, null, null); - JsonNode result = debugModule.traceTransaction(transaction.getHash().toJsonString(), null); + JsonNode result = debugModule.traceTransaction(transaction.getHash().toJsonString()); Assertions.assertNotNull(result); Assertions.assertTrue(result.isObject()); @@ -194,9 +194,9 @@ void debug_traceTransaction_retrieveSimpleAccountTransfer() throws Exception { Transaction transaction = world.getTransactionByName("tx01"); - DebugModuleImpl debugModule = new DebugModuleImpl(world.getBlockStore(), receiptStore, messageHandlerMock, world.getBlockExecutor(), null, null); + DebugModuleImpl debugModule = getDebugModule(world.getBlockStore(), world.getBlockExecutor(), receiptStore, messageHandlerMock, null, null); - JsonNode result = debugModule.traceTransaction(transaction.getHash().toJsonString(), null); + JsonNode result = debugModule.traceTransaction(transaction.getHash().toJsonString()); Assertions.assertNotNull(result); Assertions.assertTrue(result.isObject()); @@ -219,28 +219,29 @@ void debug_traceTransaction_retrieveSimpleAccountTransferWithTraceOptions() thro Transaction transaction = world.getTransactionByName("tx01"); - DebugModuleImpl debugModule = new DebugModuleImpl(world.getBlockStore(), receiptStore, messageHandlerMock, world.getBlockExecutor(), null, null); + DebugModuleImpl debugModule = getDebugModule(world.getBlockStore(), world.getBlockExecutor(), receiptStore, messageHandlerMock, null, null); - JsonNode resultWithNoOptions = debugModule.traceTransaction(transaction.getHash().toJsonString(), null); - JsonNode resultWithEmptyOptions = debugModule.traceTransaction(transaction.getHash().toJsonString(), Collections.emptyMap()); + JsonNode resultWithNoOptions = debugModule.traceTransaction(transaction.getHash().toJsonString()); + TraceOptions traceOptions = new TraceOptions(Collections.emptyMap()); + JsonNode resultWithEmptyOptions = debugModule.traceTransaction(transaction.getHash().toJsonString(), traceOptions, null); Assertions.assertEquals(resultWithNoOptions, resultWithEmptyOptions); - Map traceOptions = new HashMap<>(); - traceOptions.put("disableStorage", "true"); - - JsonNode resultWithNonEmptyOptions = debugModule.traceTransaction(transaction.getHash().toJsonString(), traceOptions); + Map traceOptionMap = new HashMap<>(); + traceOptionMap.put("disableStorage", "true"); + TraceOptions traceOptions2 = new TraceOptions(traceOptionMap); + JsonNode resultWithNonEmptyOptions = debugModule.traceTransaction(transaction.getHash().toJsonString(), traceOptions2, null); Assertions.assertEquals(resultWithNoOptions, resultWithNonEmptyOptions); } @Test - void debug_traceBlockByHash_retrieveUnknownBlockAsNull() throws Exception { + void debug_traceBlockByHash_retrieveUnknownBlockAsNull() { byte[] hash = HexUtils.stringHexToByteArray("0x00"); when(blockStoreMock.getBlockByHash(hash)).thenReturn(null); - JsonNode result = mockedDebugModule.traceBlockByHash("0x00", null); + JsonNode result = mockedDebugModule.traceBlockByHash("0x00", null, null); Assertions.assertNull(result); } @@ -256,9 +257,10 @@ void debug_traceBlockByHash_retrieveSimpleContractsCreationTrace() throws Except Block block = world.getBlockByName("b01"); - DebugModuleImpl debugModule = new DebugModuleImpl(world.getBlockStore(), receiptStore, messageHandlerMock, world.getBlockExecutor(), null, null); + DebugModuleImpl debugModule = getDebugModule(world.getBlockStore(), world.getBlockExecutor(), receiptStore, messageHandlerMock, null, null); + - JsonNode result = debugModule.traceBlockByHash(block.getHash().toJsonString(), null); + JsonNode result = debugModule.traceBlockByHash(block.getHash().toJsonString(), null, null); Assertions.assertNotNull(result); Assertions.assertTrue(result.isArray()); @@ -297,7 +299,7 @@ void debug_traceBlockByNumber_retrieveSimpleContractsCreationTrace() throws Exce String blockNumber = HexUtils.toQuantityJsonHex(block.getNumber()); when(web3InformationRetrieverMock.getBlock(blockNumber)).thenReturn(Optional.of(block)); - DebugModuleImpl debugModule = new DebugModuleImpl(world.getBlockStore(), receiptStore, messageHandlerMock, world.getBlockExecutor(), null, web3InformationRetrieverMock); + DebugModuleImpl debugModule = getDebugModule(world.getBlockStore(), world.getBlockExecutor(), receiptStore, messageHandlerMock, null, web3InformationRetrieverMock); JsonNode result = debugModule.traceBlockByNumber(blockNumber, null); @@ -327,15 +329,15 @@ void debug_traceTransaction_retrieveSimpleContractInvocationTrace_traceOptions_d Transaction transaction = world.getTransactionByName("tx02"); - DebugModuleImpl debugModule = new DebugModuleImpl(world.getBlockStore(), receiptStore, messageHandlerMock, world.getBlockExecutor(), null, null); + DebugModuleImpl debugModule = getDebugModule(world.getBlockStore(), world.getBlockExecutor(), receiptStore, messageHandlerMock, null, null); - Map traceOptions = new HashMap<>(); - traceOptions.put("disableStack", "true"); - traceOptions.put("disableMemory", "true"); - traceOptions.put("disableStorage", "true"); - - JsonNode witnessResult = debugModule.traceTransaction(transaction.getHash().toJsonString(), null); - JsonNode result = debugModule.traceTransaction(transaction.getHash().toJsonString(), traceOptions); + Map traceOptionsMap = new HashMap<>(); + traceOptionsMap.put("disableStack", "true"); + traceOptionsMap.put("disableMemory", "true"); + traceOptionsMap.put("disableStorage", "true"); + TraceOptions traceOptions = new TraceOptions(traceOptionsMap); + JsonNode witnessResult = debugModule.traceTransaction(transaction.getHash().toJsonString()); + JsonNode result = debugModule.traceTransaction(transaction.getHash().toJsonString(), traceOptions, null); // Sanity Check @@ -406,4 +408,10 @@ void debug_accountTransactionQuota_whenNonExistingAddress_returnsNull() { Assertions.assertNull(txQuotaRetrieved); } + + private DebugModuleImpl getDebugModule(BlockStore bockStore, BlockExecutor blockExecutor, ReceiptStore receiptStore, MessageHandler messageHandler, TxQuotaChecker txQuotaChecker, Web3InformationRetriever web3InformationRetriever) { + DebugTracer tracer = new RskTracer(bockStore, receiptStore, blockExecutor, web3InformationRetriever); + TraceProvider traceProvider = new TraceProvider(List.of(tracer)); + return new DebugModuleImpl(traceProvider, messageHandler, txQuotaChecker); + } } diff --git a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java index 426e0488cf1..05934b848d4 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java @@ -32,6 +32,9 @@ import co.rsk.rpc.Web3RskImpl; import co.rsk.rpc.modules.debug.DebugModule; import co.rsk.rpc.modules.debug.DebugModuleImpl; +import co.rsk.rpc.modules.debug.trace.DebugTracer; +import co.rsk.rpc.modules.debug.trace.RskTracer; +import co.rsk.rpc.modules.debug.trace.TraceProvider; import co.rsk.rpc.modules.eth.EthModule; import co.rsk.rpc.modules.eth.EthModuleWalletEnabled; import co.rsk.rpc.modules.personal.PersonalModule; @@ -1079,8 +1082,9 @@ null, new EthModuleWalletEnabled(wallet, transactionPool, signatureCache), null, config.getCallGasCap() ); TxPoolModule txPoolModule = new TxPoolModuleImpl(transactionPool, signatureCache); - DebugModule debugModule = new DebugModuleImpl(null, null, Web3Mocks.getMockMessageHandler(), null, null, null); - blocksBloomStore = new BlocksBloomStore(2, 0, new HashMapDB()); + DebugTracer debugTracer = new RskTracer(null, null, null, null); + TraceProvider traceProvider = new TraceProvider(List.of(debugTracer)); + DebugModule debugModule = new DebugModuleImpl(traceProvider, Web3Mocks.getMockMessageHandler(), null); blocksBloomStore = new BlocksBloomStore(2, 0, new HashMapDB()); return new Web3RskImpl( eth, blockChain, diff --git a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplScoringTest.java b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplScoringTest.java index e6122a4e356..596462c072d 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplScoringTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplScoringTest.java @@ -27,6 +27,9 @@ import co.rsk.rpc.Web3RskImpl; import co.rsk.rpc.modules.debug.DebugModule; import co.rsk.rpc.modules.debug.DebugModuleImpl; +import co.rsk.rpc.modules.debug.trace.DebugTracer; +import co.rsk.rpc.modules.debug.trace.RskTracer; +import co.rsk.rpc.modules.debug.trace.TraceProvider; import co.rsk.rpc.modules.eth.EthModule; import co.rsk.rpc.modules.eth.EthModuleWalletEnabled; import co.rsk.rpc.modules.personal.PersonalModule; @@ -51,6 +54,7 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Collections; +import java.util.List; /** * Created by ajlopez on 12/07/2017. @@ -400,7 +404,9 @@ null, new EthModuleWalletEnabled(wallet, world.getTransactionPool(), world.getBl config.getCallGasCap() ); TxPoolModule tpm = new TxPoolModuleImpl(Web3Mocks.getMockTransactionPool(), new ReceivedTxSignatureCache()); - DebugModule dm = new DebugModuleImpl(null, null, Web3Mocks.getMockMessageHandler(), null, null, null); + DebugTracer debugTracer = new RskTracer(null, null, null, null); + TraceProvider traceProvider = new TraceProvider(List.of(debugTracer)); + DebugModule dm = new DebugModuleImpl(traceProvider, Web3Mocks.getMockMessageHandler(), null); return new Web3RskImpl( rsk, world.getBlockChain(), diff --git a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplSnapshotTest.java b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplSnapshotTest.java index 49a4cabb19c..8140c5d2358 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplSnapshotTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplSnapshotTest.java @@ -29,6 +29,9 @@ import co.rsk.mine.gas.provider.FixedMinGasPriceProvider; import co.rsk.rpc.modules.debug.DebugModule; import co.rsk.rpc.modules.debug.DebugModuleImpl; +import co.rsk.rpc.modules.debug.trace.DebugTracer; +import co.rsk.rpc.modules.debug.trace.RskTracer; +import co.rsk.rpc.modules.debug.trace.TraceProvider; import co.rsk.rpc.modules.evm.EvmModule; import co.rsk.rpc.modules.evm.EvmModuleImpl; import co.rsk.rpc.modules.personal.PersonalModule; @@ -174,8 +177,9 @@ private Web3Impl createWeb3(SimpleEthereum ethereum) { ); PersonalModule pm = new PersonalModuleWalletDisabled(); TxPoolModule tpm = new TxPoolModuleImpl(Web3Mocks.getMockTransactionPool(), new ReceivedTxSignatureCache()); - DebugModule dm = new DebugModuleImpl(null, null, Web3Mocks.getMockMessageHandler(), null, null, null); - + DebugTracer debugTracer = new RskTracer(null, null, null, null); + TraceProvider traceProvider = new TraceProvider(List.of(debugTracer)); + DebugModule dm = new DebugModuleImpl(traceProvider, Web3Mocks.getMockMessageHandler(), null); ethereum.blockchain = blockchain; return new Web3Impl( diff --git a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java index 9c498a3a35a..decc6c37fec 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java @@ -42,6 +42,9 @@ import co.rsk.rpc.Web3RskImpl; import co.rsk.rpc.modules.debug.DebugModule; import co.rsk.rpc.modules.debug.DebugModuleImpl; +import co.rsk.rpc.modules.debug.trace.DebugTracer; +import co.rsk.rpc.modules.debug.trace.RskTracer; +import co.rsk.rpc.modules.debug.trace.TraceProvider; import co.rsk.rpc.modules.eth.EthModule; import co.rsk.rpc.modules.eth.EthModuleTransactionBase; import co.rsk.rpc.modules.eth.EthModuleWalletEnabled; @@ -749,7 +752,9 @@ void eth_mining() { MinerClient minerClient = new SimpleMinerClient(); PersonalModule personalModule = new PersonalModuleWalletDisabled(); TxPoolModule txPoolModule = new TxPoolModuleImpl(Web3Mocks.getMockTransactionPool(), signatureCache); - DebugModule debugModule = new DebugModuleImpl(null, null, Web3Mocks.getMockMessageHandler(), null, null, null); + DebugTracer debugTracer = new RskTracer(null, null, null, null); + TraceProvider traceProvider = new TraceProvider(List.of(debugTracer)); + DebugModule debugModule = new DebugModuleImpl(traceProvider, Web3Mocks.getMockMessageHandler(), null); Web3 web3 = new Web3Impl( ethMock, blockchain, @@ -2773,7 +2778,9 @@ null, new EthModuleWalletEnabled(wallet, transactionPool, signatureCache), null, config.getCallGasCap() ); TxPoolModule txPoolModule = new TxPoolModuleImpl(Web3Mocks.getMockTransactionPool(), signatureCache); - DebugModule debugModule = new DebugModuleImpl(null, null, Web3Mocks.getMockMessageHandler(), null, null, null); + DebugTracer debugTracer = new RskTracer(null, null, null, null); + TraceProvider traceProvider = new TraceProvider(List.of(debugTracer)); + DebugModule debugModule = new DebugModuleImpl(traceProvider, Web3Mocks.getMockMessageHandler(), null); MinerClient minerClient = new SimpleMinerClient(); ChannelManager channelManager = new SimpleChannelManager(); return new Web3RskImpl( @@ -2891,7 +2898,9 @@ private Web3Impl createWeb3( config.getCallGasCap() ); TxPoolModule txPoolModule = new TxPoolModuleImpl(transactionPool, signatureCache); - DebugModule debugModule = new DebugModuleImpl(null, null, Web3Mocks.getMockMessageHandler(), null, null, null); + DebugTracer debugTracer = new RskTracer(null, null, null, null); + TraceProvider traceProvider = new TraceProvider(List.of(debugTracer)); + DebugModule debugModule = new DebugModuleImpl(traceProvider, Web3Mocks.getMockMessageHandler(), null); RskModule rskModule = new RskModuleImpl(blockchain, blockStore, receiptStore, retriever, flusher, nodeStopper); MinerClient minerClient = new SimpleMinerClient(); ChannelManager channelManager = new SimpleChannelManager(); @@ -2954,7 +2963,9 @@ private Web3Impl createWeb3CallNoReturn( config.getGasEstimationCap(), config.getCallGasCap()); TxPoolModule txPoolModule = new TxPoolModuleImpl(transactionPool, signatureCache); - DebugModule debugModule = new DebugModuleImpl(null, null, Web3Mocks.getMockMessageHandler(), null, null, null); + DebugTracer debugTracer = new RskTracer(null, null, null, null); + TraceProvider traceProvider = new TraceProvider(List.of(debugTracer)); + DebugModule debugModule = new DebugModuleImpl(traceProvider, Web3Mocks.getMockMessageHandler(), null); RskModule rskModule = new RskModuleImpl(blockchain, blockStore, receiptStore, retriever, mock(Flusher.class)); MinerClient minerClient = new SimpleMinerClient(); ChannelManager channelManager = new SimpleChannelManager();