Skip to content

Commit

Permalink
Adding trace options
Browse files Browse the repository at this point in the history
  • Loading branch information
nagarev committed Oct 29, 2021
1 parent e6a1640 commit 3012153
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,13 @@ public String wireProtocolQueueSize() {
public JsonNode traceTransaction(String transactionHash, Map<String, String> traceOptions) {
logger.trace("debug_traceTransaction({}, {})", transactionHash, traceOptions);

if (traceOptions != null && !traceOptions.isEmpty()) {
// TODO: implement the logic that takes into account trace options.
logger.warn("Received {} trace options. For now trace options are being ignored", traceOptions);
TraceOptions options = new TraceOptions(traceOptions);

if (options.getUnsupportedOptions().size() > 0) {
// TODO: implement the logic that takes into account the remaining trace options.
logger.warn(
"Received {} trace options. For now they are being ignored",
options.getUnsupportedOptions());
}

byte[] hash = stringHexToByteArray(transactionHash);
Expand All @@ -86,7 +90,7 @@ public JsonNode traceTransaction(String transactionHash, Map<String, String> tra
Transaction tx = block.getTransactionsList().get(txInfo.getIndex());
txInfo.setTransaction(tx);

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

return programTraceProcessor.getProgramTraceAsJsonNode(tx.getHash());
Expand Down
61 changes: 61 additions & 0 deletions rskj-core/src/main/java/co/rsk/rpc/modules/debug/TraceOptions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* This file is part of RskJ
* Copyright (C) 2017 RSK Labs Ltd.
* (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>)
*
* 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 <http://www.gnu.org/licenses/>.
*/

package co.rsk.rpc.modules.debug;

import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class TraceOptions {

private static final String[] SUPPORTED_OPTIONS = {
"disableStorage", "disableMemory", "disableStack"};
private static final String[] OPTIONAL_FIELDS = {
"disableStorage", "disableMemory", "disableStack"};

private Set<String> disabledFields;
private Set<String> unsupportedOptions;

private TraceOptions() {}

public TraceOptions(Map<String, String> traceOptions) {
disabledFields = Arrays
.stream(OPTIONAL_FIELDS)
.filter(field -> traceOptions
.containsKey(field) && Boolean.parseBoolean(traceOptions.get(field)))
.collect(Collectors.toSet());
unsupportedOptions = traceOptions
.keySet()
.stream()
.filter(key -> Arrays.stream(SUPPORTED_OPTIONS)
.noneMatch(option -> option.equals(key)))
.collect(Collectors.toSet());
}

public Set<String> getDisabledFields() {
return disabledFields;
}

public Set<String> getUnsupportedOptions() {
return unsupportedOptions;
}

}
2 changes: 2 additions & 0 deletions rskj-core/src/main/java/org/ethereum/vm/trace/Op.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

package org.ethereum.vm.trace;

import com.fasterxml.jackson.annotation.JsonFilter;
import org.ethereum.util.ByteUtil;
import org.ethereum.vm.OpCode;
import org.ethereum.vm.program.Memory;
Expand All @@ -29,6 +30,7 @@
import java.util.List;
import java.util.Map;

@JsonFilter("opFilter")
public class Op {

private OpCode op;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
package org.ethereum.vm.trace;

import co.rsk.crypto.Keccak256;
import co.rsk.rpc.modules.debug.TraceOptions;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.*;
import java.util.stream.Collectors;

/**
Expand All @@ -39,6 +39,17 @@ public class ProgramTraceProcessor {

private final Map<Keccak256, ProgramTrace> traces = new HashMap<>();

private static TraceOptions traceOptions = null;

public ProgramTraceProcessor() {
traceOptions = new TraceOptions(Collections.emptyMap());
}

public ProgramTraceProcessor(TraceOptions options) {
this();
traceOptions = options;
}

public void processProgramTrace(ProgramTrace programTrace, Keccak256 txHash) {
this.traces.put(txHash, programTrace);
}
Expand All @@ -63,7 +74,11 @@ public JsonNode getProgramTraceAsJsonNode(Keccak256 txHash) {
return null;
}

return OBJECT_MAPPER.valueToTree(trace);
SimpleFilterProvider filterProvider = new SimpleFilterProvider();
filterProvider.addFilter("opFilter",
SimpleBeanPropertyFilter.serializeAllExcept(traceOptions.getDisabledFields()));

return OBJECT_MAPPER.setFilterProvider(filterProvider).valueToTree(trace);
}

private static ObjectMapper makeObjectMapper() {
Expand Down
116 changes: 116 additions & 0 deletions rskj-core/src/test/java/co/rsk/rpc/modules/debug/TraceOptionsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* This file is part of RskJ
* Copyright (C) 2017 RSK Labs Ltd.
* (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>)
*
* 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 <http://www.gnu.org/licenses/>.
*/

package co.rsk.rpc.modules.debug;

import org.junit.Assert;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

public class TraceOptionsTest {

@Test
public void testTraceOptions_constructedOnlyWithSupportedOptions_unsupportedOptionsMustBeEmpty() {
// Given
Map<String, String> traceOptions = new HashMap<>();
traceOptions.put("disableStorage", "false");
traceOptions.put("disableMemory", "false");
traceOptions.put("disableStack", "false");

// When
TraceOptions options = new TraceOptions(traceOptions);

// Then
Assert.assertEquals(0, options.getUnsupportedOptions().size());
}

@Test
public void testTraceOptions_constructedWithSomeUnsupportedOptions_unsupportedOptionsMustContainTheUnsupportedOptions() {
// Given
Map<String, String> traceOptions = new HashMap<>();
traceOptions.put("disableStorages", "false");
traceOptions.put("disablesMemory", "false");
traceOptions.put("disableStack", "false");

// When
TraceOptions options = new TraceOptions(traceOptions);

// Then
Assert.assertTrue(options.getUnsupportedOptions().contains("disableStorages"));
Assert.assertTrue(options.getUnsupportedOptions().contains("disablesMemory"));
}

@Test
public void testTraceOptions_optionalFieldsSetToTrue_disabledFieldsMustContainGivenFields() {
// Given
Map<String, String> traceOptions = new HashMap<>();
traceOptions.put("disableStorage", "true");
traceOptions.put("disableMemory", "true");
traceOptions.put("disableStack", "true");

// When
TraceOptions options = new TraceOptions(traceOptions);

// Then
Assert.assertEquals(0, options.getUnsupportedOptions().size());
Assert.assertTrue(options.getDisabledFields().contains("disableStorage"));
Assert.assertTrue(options.getDisabledFields().contains("disableMemory"));
Assert.assertTrue(options.getDisabledFields().contains("disableStack"));
}

@Test
public void testTraceOptions_optionalFieldsSetToFalse_disabledFieldsMustNotContainGivenFields() {
// Given
Map<String, String> traceOptions = new HashMap<>();
traceOptions.put("disableStorage", "false");
traceOptions.put("disableMemory", "false");
traceOptions.put("disableStack", "false");

// When
TraceOptions options = new TraceOptions(traceOptions);

// Then
Assert.assertEquals(0, options.getUnsupportedOptions().size());
Assert.assertFalse(options.getDisabledFields().contains("disableStorages"));
Assert.assertFalse(options.getDisabledFields().contains("disableMemory"));
Assert.assertFalse(options.getDisabledFields().contains("disableStack"));
}

@Test
public void testTraceOptions_mixedCase_OK() {
// Given
Map<String, String> traceOptions = new HashMap<>();
traceOptions.put("disableStorage", "false"); // Valid optional field set to false (Must not be added to the disabled fields).
traceOptions.put("disableStack", "true"); // Valid optional field set to true (Must be added to the disabled fields).
traceOptions.put("unsupported_1", "false"); // Unsupported field (Must be added to the unsupported options).
traceOptions.put("unsupported_2", "4"); // Unsupported field (Must be added to the unsupported options).

// When
TraceOptions options = new TraceOptions(traceOptions);

// Then
Assert.assertFalse(options.getDisabledFields().contains("disableStorage"));
Assert.assertTrue(options.getDisabledFields().contains("disableStack"));
Assert.assertTrue(options.getUnsupportedOptions().contains("unsupported_1"));
Assert.assertTrue(options.getUnsupportedOptions().contains("unsupported_2"));
}

}

0 comments on commit 3012153

Please sign in to comment.