Add Parity style Statediff (#326)

* State diff

All but balances work at this point.  And it has something to do with
upfront gas costs.

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>

* fix the balances bug

There was also a chained transactions bug. To address this I create a
new WorldUpdater for each iteration of a transaction through the block.
 The current world updater has the new state, the prior the old one.
 Diffs just fall out after that.

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>

* get rid of midBlock state, it's unneeded with the chained updaters.

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>

* remove rootWorld method, old code from a prior attempt.

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>

* remove println

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>

* spotless

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>

* spotless, comments, and cleanup

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>

* spotless keeps missing this.

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>

* javadoc

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>

* fix broken reference tests

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>

* spotless

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>

* tighten access

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>
pull/329/head
Danno Ferrin 5 years ago committed by Abdelhamid Bakhta
parent 1d316196f9
commit f9b0439fdc
  1. 34
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceReplayBlockTransactions.java
  2. 11
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockTracer.java
  3. 61
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/diff/AccountDiff.java
  4. 94
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/diff/DiffNode.java
  5. 128
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/diff/StateDiffGenerator.java
  6. 23
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/diff/StateDiffTrace.java
  7. 2
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/flat/Result.java
  8. 2
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/vm/VmOperation.java
  9. 3
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/TraceJsonRpcHttpBySpecTest.java
  10. 3
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceBlockByHashTest.java
  11. 3
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceBlockByNumberTest.java
  12. 3
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceBlockTest.java
  13. 6
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceTransactionTest.java
  14. 28
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/chain-data/blocks.json
  15. 47
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/chain-data/genesis.json
  16. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/flat/trace_replayBlockTransactions_traceOnly_0x0.json
  17. 2
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/flat/trace_replayBlockTransactions_traceOnly_0x1.json
  18. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/flat/trace_replayBlockTransactions_traceOnly_0x2.json
  19. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/flat/trace_replayBlockTransactions_traceOnly_0x3.json
  20. 14
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/flat/trace_replayBlockTransactions_traceOnly_0x4.json
  21. 3
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/flat/trace_replayBlockTransactions_traceOnly_0x5.json
  22. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/flat/trace_replayBlockTransactions_traceOnly_0x6.json
  23. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/flat/trace_replayBlockTransactions_traceOnly_0x7.json
  24. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/flat/trace_replayBlockTransactions_traceOnly_0x8.json
  25. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/flat/trace_replayBlockTransactions_traceOnly_0x9.json
  26. 19
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/statediff/trace_replayBlockTransactions_diffOnly_0x0.json
  27. 19
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/statediff/trace_replayBlockTransactions_diffOnly_0x1.json
  28. 67
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/statediff/trace_replayBlockTransactions_diffOnly_0x2.json
  29. 67
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/statediff/trace_replayBlockTransactions_diffOnly_0x3.json
  30. 128
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/statediff/trace_replayBlockTransactions_diffOnly_0x4.json
  31. 74
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/statediff/trace_replayBlockTransactions_diffOnly_0x5.json
  32. 79
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/statediff/trace_replayBlockTransactions_diffOnly_0x6.json
  33. 55
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/statediff/trace_replayBlockTransactions_diffOnly_0x7.json
  34. 55
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/statediff/trace_replayBlockTransactions_diffOnly_0x8.json
  35. 55
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/statediff/trace_replayBlockTransactions_diffOnly_0x9.json
  36. 55
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/statediff/trace_replayBlockTransactions_diffOnly_0xA.json
  37. 55
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/statediff/trace_replayBlockTransactions_diffOnly_0xB.json
  38. 55
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/statediff/trace_replayBlockTransactions_diffOnly_0xC.json
  39. 55
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/statediff/trace_replayBlockTransactions_diffOnly_0xD.json
  40. 164
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/statediff/trace_replayBlockTransactions_diffOnly_0xE.json
  41. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/vm-trace/trace_replayBlockTransactions_0x0.json
  42. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/vm-trace/trace_replayBlockTransactions_0x1.json
  43. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/vm-trace/trace_replayBlockTransactions_0x2.json
  44. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/vm-trace/trace_replayBlockTransactions_0x3.json
  45. 34
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/vm-trace/trace_replayBlockTransactions_0x4.json
  46. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/vm-trace/trace_replayBlockTransactions_0x5.json
  47. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/vm-trace/trace_replayBlockTransactions_0x6.json
  48. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/vm-trace/trace_replayBlockTransactions_0x7.json
  49. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/vm-trace/trace_replayBlockTransactions_0x8.json
  50. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/vm-trace/trace_replayBlockTransactions_0x9.json
  51. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/vm-trace/trace_replayBlockTransactions_0xA.json
  52. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/vm-trace/trace_replayBlockTransactions_0xB.json
  53. 0
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/vm-trace/trace_replayBlockTransactions_0xC.json
  54. 2
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/vm-trace/trace_replayBlockTransactions_0xD.json
  55. 524
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/trace/specs/vm-trace/trace_replayBlockTransactions_0xE.json
  56. 17
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/AbstractWorldUpdater.java
  57. 11
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/WorldUpdater.java
  58. 42
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/debug/TraceFrame.java
  59. 1
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/DebugOperationTracer.java
  60. 11
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DefaultMutablePrivateWorldStateUpdater.java
  61. 8
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DefaultMutableWorldState.java

@ -16,14 +16,15 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.TraceTypeParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.TraceTypeParameter.TraceType;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockTrace;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockTracer;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionTrace;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.TraceFormatter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.TraceWriter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.diff.StateDiffGenerator;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.flat.FlatTraceGenerator;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.vm.VmTraceGenerator;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
@ -42,13 +43,13 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
public class TraceReplayBlockTransactions extends AbstractBlockParameterMethod {
private static final Logger LOG = LogManager.getLogger();
private final BlockTracer blockTracer;
private final Supplier<StateDiffGenerator> stateDiffGenerator =
Suppliers.memoize(StateDiffGenerator::new);
public TraceReplayBlockTransactions(
final BlockTracer blockTracer, final BlockchainQueries queries) {
@ -72,13 +73,6 @@ public class TraceReplayBlockTransactions extends AbstractBlockParameterMethod {
final TraceTypeParameter traceTypeParameter =
request.getRequiredParameter(1, TraceTypeParameter.class);
// TODO : method returns an error if any option other than “trace” is supplied.
// remove when others options are implemented
if (traceTypeParameter.getTraceTypes().contains(TraceTypeParameter.TraceType.STATE_DIFF)) {
LOG.warn("Unsupported trace option");
throw new InvalidJsonRpcParameters("Invalid trace types supplied.");
}
if (blockNumber == BlockHeader.GENESIS_BLOCK_NUMBER) {
// Nothing to trace for the genesis block
return emptyResult();
@ -125,10 +119,17 @@ public class TraceReplayBlockTransactions extends AbstractBlockParameterMethod {
final ArrayNode resultArrayNode,
final AtomicInteger traceCounter) {
final ObjectNode resultNode = mapper.createObjectNode();
resultNode.put("transactionHash", transactionTrace.getTransaction().getHash().toHexString());
resultNode.put("output", transactionTrace.getResult().getOutput().toString());
setEmptyArrayIfNotPresent(resultNode, "trace");
setNullNodesIfNotPresent(resultNode, "vmTrace", "stateDiff");
if (traceTypes.contains(TraceType.STATE_DIFF)) {
generateTracesFromTransactionTrace(
trace -> resultNode.putPOJO("stateDiff", trace),
transactionTrace,
(txTrace, ignored) -> stateDiffGenerator.get().generateStateDiff(txTrace),
traceCounter);
}
setNullNodesIfNotPresent(resultNode, "stateDiff");
if (traceTypes.contains(TraceTypeParameter.TraceType.TRACE)) {
generateTracesFromTransactionTrace(
resultNode.putArray("trace")::addPOJO,
@ -136,6 +137,8 @@ public class TraceReplayBlockTransactions extends AbstractBlockParameterMethod {
FlatTraceGenerator::generateFromTransactionTrace,
traceCounter);
}
setEmptyArrayIfNotPresent(resultNode, "trace");
resultNode.put("transactionHash", transactionTrace.getTransaction().getHash().toHexString());
if (traceTypes.contains(TraceTypeParameter.TraceType.VM_TRACE)) {
generateTracesFromTransactionTrace(
trace -> resultNode.putPOJO("vmTrace", trace),
@ -143,6 +146,7 @@ public class TraceReplayBlockTransactions extends AbstractBlockParameterMethod {
(__, ignored) -> new VmTraceGenerator(transactionTrace).generateTraceStream(),
traceCounter);
}
setNullNodesIfNotPresent(resultNode, "vmTrace");
resultArrayNode.add(resultNode);
}

@ -17,6 +17,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockReplay.TransactionAction;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.WorldUpdater;
import org.hyperledger.besu.ethereum.debug.TraceFrame;
import org.hyperledger.besu.ethereum.mainnet.TransactionProcessor;
import org.hyperledger.besu.ethereum.vm.BlockHashLookup;
@ -29,6 +30,8 @@ import java.util.Optional;
public class BlockTracer {
private final BlockReplay blockReplay;
// Either the initial block state or the state of the prior TX, including miner rewards.
private WorldUpdater chainedUpdater;
public BlockTracer(final BlockReplay blockReplay) {
this.blockReplay = blockReplay;
@ -45,10 +48,16 @@ public class BlockTracer {
private TransactionAction<TransactionTrace> prepareReplayAction(
final DebugOperationTracer tracer) {
return (transaction, header, blockchain, mutableWorldState, transactionProcessor) -> {
// if we have no prior updater, it must be the first TX, so use the block's initial state
if (chainedUpdater == null) {
chainedUpdater = mutableWorldState.updater();
}
// create an updater for just this tx
chainedUpdater = chainedUpdater.updater();
final TransactionProcessor.Result result =
transactionProcessor.processTransaction(
blockchain,
mutableWorldState.updater(),
chainedUpdater,
header,
transaction,
header.getCoinbase(),

@ -0,0 +1,61 @@
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.diff;
import java.util.Map;
public final class AccountDiff {
private final DiffNode balance;
private final DiffNode code;
private final DiffNode nonce;
private final Map<String, DiffNode> storage;
AccountDiff(
final DiffNode balance,
final DiffNode code,
final DiffNode nonce,
final Map<String, DiffNode> storage) {
this.balance = balance;
this.code = code;
this.nonce = nonce;
this.storage = storage;
}
public DiffNode getBalance() {
return balance;
}
public DiffNode getCode() {
return code;
}
public DiffNode getNonce() {
return nonce;
}
public Map<String, DiffNode> getStorage() {
return storage;
}
boolean hasDifference() {
return balance.hasDifference()
|| code.hasDifference()
|| nonce.hasDifference()
|| !storage.isEmpty();
}
}

@ -0,0 +1,94 @@
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.diff;
import java.io.IOException;
import java.util.Optional;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
@JsonSerialize(using = DiffNode.Serializer.class)
public final class DiffNode {
private final Optional<String> from;
private final Optional<String> to;
public DiffNode() {
from = Optional.empty();
to = Optional.empty();
}
DiffNode(final String from, final String to) {
this.from = Optional.ofNullable(from);
this.to = Optional.ofNullable(to);
}
DiffNode(final Optional<String> from, final Optional<String> to) {
this.from = from;
this.to = to;
}
boolean hasDifference() {
return from.map(it -> !it.equals(to.get())).orElse(to.isPresent());
}
public static class Serializer extends StdSerializer<DiffNode> {
public Serializer() {
this(null);
}
protected Serializer(final Class<DiffNode> t) {
super(t);
}
@Override
public void serialize(
final DiffNode value, final JsonGenerator gen, final SerializerProvider provider)
throws IOException {
if (value.from.isPresent()) {
if (value.to.isPresent()) {
if (value.from.get().equalsIgnoreCase(value.to.get())) {
gen.writeString("=");
} else {
gen.writeStartObject();
gen.writeObjectFieldStart("*");
gen.writeObjectField("from", value.from.get());
gen.writeObjectField("to", value.to.get());
gen.writeEndObject();
gen.writeEndObject();
}
} else {
gen.writeStartObject();
gen.writeObjectField("-", value.from.get());
gen.writeEndObject();
}
} else {
if (value.to.isPresent()) {
gen.writeStartObject();
gen.writeObjectField("+", value.to.get());
gen.writeEndObject();
} else {
gen.writeString("=");
}
}
}
}
}

@ -0,0 +1,128 @@
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.diff;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionTrace;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.Trace;
import org.hyperledger.besu.ethereum.core.AbstractWorldUpdater;
import org.hyperledger.besu.ethereum.core.AbstractWorldUpdater.UpdateTrackingAccount;
import org.hyperledger.besu.ethereum.core.Account;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.core.WorldUpdater;
import org.hyperledger.besu.ethereum.debug.TraceFrame;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.stream.Stream;
import org.apache.tuweni.units.bigints.UInt256;
public class StateDiffGenerator {
public Stream<Trace> generateStateDiff(final TransactionTrace transactionTrace) {
List<TraceFrame> traceFrames = transactionTrace.getTraceFrames();
if (traceFrames.size() < 1) {
return Stream.empty();
}
// This corresponds to the world state after the TX executed
// It is two deep because of the way we addressed Spurious Dragon.
WorldUpdater transactionUpdater =
traceFrames
.get(0)
.getMessageFrame()
.getWorldState()
.parentUpdater()
.get()
.parentUpdater()
.get();
// This corresponds to the world state prior to the TX execution,
// Either the initial block state or the state of the prior TX
WorldUpdater previousUpdater = transactionUpdater.parentUpdater().get();
StateDiffTrace stateDiffResult = new StateDiffTrace();
for (Account touchedAccount : transactionUpdater.getTouchedAccounts()) {
if (!(touchedAccount instanceof AbstractWorldUpdater.UpdateTrackingAccount)) {
continue;
}
Address accountAddress = touchedAccount.getAddress();
UpdateTrackingAccount<?> updatedAccount =
(UpdateTrackingAccount<?>) transactionUpdater.get(accountAddress);
Account rootAccount = previousUpdater.get(accountAddress);
// calculate storage diff
Map<String, DiffNode> storageDiff = new TreeMap<>();
for (Map.Entry<UInt256, UInt256> entry : updatedAccount.getUpdatedStorage().entrySet()) {
UInt256 originalValue = rootAccount.getStorageValue(entry.getKey());
UInt256 newValue = entry.getValue();
storageDiff.put(
entry.getKey().toHexString(),
new DiffNode(originalValue.toHexString(), newValue.toHexString()));
}
// populate the diff object
AccountDiff accountDiff =
new AccountDiff(
createDiffNode(rootAccount, updatedAccount, StateDiffGenerator::balanceAsHex),
createDiffNode(rootAccount, updatedAccount, StateDiffGenerator::codeAsHex),
createDiffNode(rootAccount, updatedAccount, StateDiffGenerator::nonceAsHex),
storageDiff);
if (accountDiff.hasDifference()) {
stateDiffResult.put(accountAddress.toHexString(), accountDiff);
}
}
// Add deleted accounts
for (Address accountAddress : transactionUpdater.getDeletedAccountAddresses()) {
Account deletedAccount = previousUpdater.get(accountAddress);
AccountDiff accountDiff =
new AccountDiff(
createDiffNode(deletedAccount, null, StateDiffGenerator::balanceAsHex),
createDiffNode(deletedAccount, null, StateDiffGenerator::codeAsHex),
createDiffNode(deletedAccount, null, StateDiffGenerator::nonceAsHex),
Collections.emptyMap());
stateDiffResult.put(accountAddress.toHexString(), accountDiff);
}
return Stream.of(stateDiffResult);
}
private DiffNode createDiffNode(
final Account from, final Account to, final Function<Account, String> func) {
return new DiffNode(Optional.ofNullable(from).map(func), Optional.ofNullable(to).map(func));
}
private static String balanceAsHex(final Account account) {
Wei balance = account.getBalance();
return balance.isZero() ? "0x0" : balance.toShortHexString();
}
private static String codeAsHex(final Account account) {
return account.getCode().toHexString();
}
private static String nonceAsHex(final Account account) {
return "0x" + Long.toHexString(account.getNonce());
}
}

@ -0,0 +1,23 @@
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.diff;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.Trace;
import java.util.TreeMap;
class StateDiffTrace extends TreeMap<String, AccountDiff> implements Trace {}

@ -17,8 +17,10 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.flat;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
@JsonInclude(NON_NULL)
@JsonPropertyOrder({"address", "code", "gasUsed", "output"})
public class Result {
private final String gasUsed;
private final String output;

@ -17,7 +17,9 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.vm;
import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
@JsonPropertyOrder({"cost", "ex", "pc", "sub"})
public class VmOperation {
private long cost;
// Information concerning the execution of the operation.

@ -74,6 +74,7 @@ public class TraceJsonRpcHttpBySpecTest extends AbstractJsonRpcHttpBySpecTest {
@Parameters(name = "{index}: {0}")
public static Object[][] specs() {
return AbstractJsonRpcHttpBySpecTest.findSpecFiles("trace/specs/flat", "trace/specs/vm-trace");
return AbstractJsonRpcHttpBySpecTest.findSpecFiles(
"trace/specs/flat", "trace/specs/vm-trace", "trace/specs/statediff");
}
}

@ -62,6 +62,7 @@ public class DebugTraceBlockByHashTest {
final TraceFrame traceFrame =
new TraceFrame(
null,
12,
"NONE",
Gas.of(45),
@ -77,6 +78,8 @@ public class DebugTraceBlockByHashTest {
0,
Optional.empty(),
Optional.empty(),
Optional.empty(),
false,
Optional.empty());
final TransactionProcessor.Result transaction1Result = mock(TransactionProcessor.Result.class);

@ -67,6 +67,7 @@ public class DebugTraceBlockByNumberTest {
final TraceFrame traceFrame =
new TraceFrame(
null,
12,
"NONE",
Gas.of(45),
@ -82,6 +83,8 @@ public class DebugTraceBlockByNumberTest {
0,
Optional.empty(),
Optional.empty(),
Optional.empty(),
false,
Optional.empty());
final TransactionProcessor.Result transaction1Result = mock(TransactionProcessor.Result.class);

@ -80,6 +80,7 @@ public class DebugTraceBlockTest {
final TraceFrame traceFrame =
new TraceFrame(
null,
12,
"NONE",
Gas.of(45),
@ -95,6 +96,8 @@ public class DebugTraceBlockTest {
0,
Optional.empty(),
Optional.empty(),
Optional.empty(),
false,
Optional.empty());
final TransactionProcessor.Result transaction1Result = mock(TransactionProcessor.Result.class);

@ -79,6 +79,7 @@ public class DebugTraceTransactionTest {
final TraceFrame traceFrame =
new TraceFrame(
null,
12,
"NONE",
Gas.of(45),
@ -94,6 +95,8 @@ public class DebugTraceTransactionTest {
0,
Optional.empty(),
Optional.empty(),
Optional.empty(),
false,
Optional.empty());
final List<TraceFrame> traceFrames = Collections.singletonList(traceFrame);
final TransactionTrace transactionTrace =
@ -129,6 +132,7 @@ public class DebugTraceTransactionTest {
final TraceFrame traceFrame =
new TraceFrame(
null,
12,
"NONE",
Gas.of(45),
@ -144,6 +148,8 @@ public class DebugTraceTransactionTest {
0,
Optional.empty(),
Optional.empty(),
Optional.empty(),
false,
Optional.empty());
final List<TraceFrame> traceFrames = Collections.singletonList(traceFrame);
final TransactionTrace transactionTrace =

@ -54,7 +54,7 @@
{
"number": 5,
"transactions": [
{
{
"comment": "Clear contract storage keys 1 and 2",
"secretKey": "0x8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
"gasLimit": "0xFFFFF2",
@ -165,6 +165,32 @@
"to": "0x0080000000000000000000000000000000000000"
}
]
},
{
"number": "0xE",
"transactions": [
{
"comment": "Increments contract storage 0 by 1",
"secretKey": "0x8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
"gasLimit": "0xFFFFF2",
"gasPrice": "0xEF",
"to": "0x0090000000000000000000000000000000000000"
},
{
"comment": "Increments contract storage 0 by 1",
"secretKey": "0x8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
"gasLimit": "0xFFFFF2",
"gasPrice": "0xEF",
"to": "0x0090000000000000000000000000000000000000"
},
{
"comment": "Increments contract storage 0 by 1",
"secretKey": "0x8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
"gasLimit": "0xFFFFF2",
"gasPrice": "0xEF",
"to": "0x0090000000000000000000000000000000000000"
}
]
}
]
}

@ -1,26 +1,26 @@
{
"config": {
"homesteadBlock": 0,
"daoForkBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"eip160Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"constantinopleFixBlock": 0,
"ethash": {
"fixeddifficulty": 15
},
"chainID": 1982,
"networkID": 1982
"config": {
"homesteadBlock": 0,
"daoForkBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"eip160Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"constantinopleFixBlock": 0,
"ethash": {
"fixeddifficulty": 15
},
"nonce": "0x0000000000000042",
"gasLimit": "0x100000000000",
"difficulty": "0xf",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"chainID": 1982,
"networkID": 1982
},
"nonce": "0x0000000000000042",
"gasLimit": "0x100000000000",
"difficulty": "0xf",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"0010000000000000000000000000000000000000": {
"comment": "Add smart contract that will simply set 2 key-value pairs. Parses tx input into 4 32 byte values: [key1, val1, key2, val2]. Can be used to test constantinople fix.",
"code": "0x6020356000355560603560403555",
@ -66,6 +66,11 @@
"code": "0x7F3940be4289e4c3587d88c1856cc95352461992db0a584c281226faefe560b3017F14c4d2c102bdeb2354bfc3dc96a95e4512cf3a8461e0560e2272dbf884ef390552",
"balance": "0x0"
},
"0090000000000000000000000000000000000000": {
"comment": "Increases storage 0x00 by one. Return the new value",
"code": "0x6000546001018060005360005560016000F3",
"balance": "0x0"
},
"fe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"secretKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",

@ -14,8 +14,8 @@
"jsonrpc": "2.0",
"result": [
{
"transactionHash": "0x4de634fe767d1f6d0512ca0c9c0a054d3a2596f7cdd7c1eea5f93046a740b3c7",
"output": "0x",
"stateDiff": null,
"trace": [
{
"action": {
@ -35,12 +35,12 @@
"type": "call"
}
],
"vmTrace": null,
"stateDiff": null
"transactionHash": "0x4de634fe767d1f6d0512ca0c9c0a054d3a2596f7cdd7c1eea5f93046a740b3c7",
"vmTrace": null
},
{
"transactionHash": "0xf882ec206292910527fd7095e59a1ca027b873296f1eba3886aa1addc4ff0ab9",
"output": "0x",
"stateDiff": null,
"trace": [
{
"action": {
@ -52,7 +52,7 @@
"value": "0x0"
},
"result": {
"gasUsed": "0x9c58",
"gasUsed": "0x2728",
"output": "0x"
},
"subtraces": 0,
@ -60,8 +60,8 @@
"type": "call"
}
],
"vmTrace": null,
"stateDiff": null
"transactionHash": "0xf882ec206292910527fd7095e59a1ca027b873296f1eba3886aa1addc4ff0ab9",
"vmTrace": null
}
],
"id": 415

@ -0,0 +1,19 @@
{
"request": {
"jsonrpc": "2.0",
"method": "trace_replayBlockTransactions",
"params": [
"0x0",
[
"stateDiff"
]
],
"id": 415
},
"response": {
"jsonrpc": "2.0",
"result": [],
"id": 415
},
"statusCode": 200
}

@ -0,0 +1,19 @@
{
"request": {
"jsonrpc": "2.0",
"method": "trace_replayBlockTransactions",
"params": [
"0x1",
[
"stateDiff"
]
],
"id": 415
},
"response": {
"jsonrpc": "2.0",
"result": [],
"id": 415
},
"statusCode": 200
}

@ -0,0 +1,67 @@
{
"request": {
"jsonrpc": "2.0",
"method": "trace_replayBlockTransactions",
"params": [
"0x2",
[
"stateDiff"
]
],
"id": 415
},
"response": {
"jsonrpc": "2.0",
"result": [
{
"output": "0x",
"stateDiff": {
"0x0000000000000000000000000000000000000000": {
"balance": {
"*": {
"from": "0x1bc16d674ec80000",
"to": "0x1bc16d674f149578"
}
},
"code": "=",
"nonce": "=",
"storage": {}
},
"0x0000000000000000000000000000000000000999": {
"balance": {
"+": "0x1"
},
"code": {
"+": "0x"
},
"nonce": {
"+": "0x0"
},
"storage": {}
},
"0x627306090abab3a6e1400e9345bc60c78a8bef57": {
"balance": {
"*": {
"from": "0xf0000000000000000000000",
"to": "0xeffffffffffffffffb36a87"
}
},
"code": "=",
"nonce": {
"*": {
"from": "0x0",
"to": "0x1"
}
},
"storage": {}
}
},
"trace": [],
"transactionHash": "0x28fa8042c7b5835f4f91fc20937f3e70dcf3585c1afe31202bb6075185f9abfe",
"vmTrace": null
}
],
"id": 415
},
"statusCode": 200
}

@ -0,0 +1,67 @@
{
"request": {
"jsonrpc": "2.0",
"method": "trace_replayBlockTransactions",
"params": [
"0x3",
[
"stateDiff"
]
],
"id": 415
},
"response": {
"jsonrpc": "2.0",
"result": [
{
"output": "0x600035ff",
"stateDiff": {
"0x0000000000000000000000000000000000000000": {
"balance": {
"*": {
"from": "0x3782dace9ddc9578",
"to": "0x3782dace9ea423b8"
}
},
"code": "=",
"nonce": "=",
"storage": {}
},
"0x627306090abab3a6e1400e9345bc60c78a8bef57": {
"balance": {
"*": {
"from": "0xeffffffffffffffffb36a87",
"to": "0xefffffffffffffffeebdc47"
}
},
"code": "=",
"nonce": {
"*": {
"from": "0x1",
"to": "0x2"
}
},
"storage": {}
},
"0xf12b5dd4ead5f743c6baa640b0216200e89b60da": {
"balance": {
"+": "0x0"
},
"code": {
"+": "0x600035ff"
},
"nonce": {
"+": "0x1"
},
"storage": {}
}
},
"trace": [],
"transactionHash": "0x8d5477f0aae852c3e9487b0f8e7b9ecf9ccdf23d7934d4b4b7eff40c271031e5",
"vmTrace": null
}
],
"id": 415
},
"statusCode": 200
}

@ -0,0 +1,128 @@
{
"request": {
"jsonrpc": "2.0",
"method": "trace_replayBlockTransactions",
"params": [
"0x4",
[
"stateDiff"
]
],
"id": 415
},
"response": {
"jsonrpc": "2.0",
"result": [
{
"output": "0x",
"stateDiff": {
"0x0000000000000000000000000000000000000000": {
"balance": {
"*": {
"from": "0x53444835ed6c23b8",
"to": "0x53444835ee4d7c58"
}
},
"code": "=",
"nonce": "=",
"storage": {}
},
"0x0010000000000000000000000000000000000000": {
"balance": "=",
"code": "=",
"nonce": "=",
"storage": {
"0x0000000000000000000000000000000000000000000000000000000000000001": {
"*": {
"from": "0x0000000000000000000000000000000000000000000000000000000000000000",
"to": "0x0000000000000000000000000000000000000000000000000000000000000001"
}
},
"0x0000000000000000000000000000000000000000000000000000000000000002": {
"*": {
"from": "0x0000000000000000000000000000000000000000000000000000000000000000",
"to": "0x0000000000000000000000000000000000000000000000000000000000000002"
}
}
}
},
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"balance": {
"*": {
"from": "0xfffffffffffffffffffffffffffffffffffffffff",
"to": "0xfffffffffffffffffffffffffffffffffff1ea75f"
}
},
"code": "=",
"nonce": {
"*": {
"from": "0x0",
"to": "0x1"
}
},
"storage": {}
}
},
"trace": [],
"transactionHash": "0x4de634fe767d1f6d0512ca0c9c0a054d3a2596f7cdd7c1eea5f93046a740b3c7",
"vmTrace": null
},
{
"output": "0x",
"stateDiff": {
"0x0000000000000000000000000000000000000000": {
"balance": {
"*": {
"from": "0x53444835ee4d7c58",
"to": "0x53444835eec16d28"
}
},
"code": "=",
"nonce": "=",
"storage": {}
},
"0x0010000000000000000000000000000000000000": {
"balance": "=",
"code": "=",
"nonce": "=",
"storage": {
"0x0000000000000000000000000000000000000000000000000000000000000001": {
"*": {
"from": "0x0000000000000000000000000000000000000000000000000000000000000001",
"to": "0x0000000000000000000000000000000000000000000000000000000000000003"
}
},
"0x0000000000000000000000000000000000000000000000000000000000000002": {
"*": {
"from": "0x0000000000000000000000000000000000000000000000000000000000000002",
"to": "0x0000000000000000000000000000000000000000000000000000000000000004"
}
}
}
},
"0x627306090abab3a6e1400e9345bc60c78a8bef57": {
"balance": {
"*": {
"from": "0xefffffffffffffffeebdc47",
"to": "0xefffffffffffffffe77eb77"
}
},
"code": "=",
"nonce": {
"*": {
"from": "0x2",
"to": "0x3"
}
},
"storage": {}
}
},
"trace": [],
"transactionHash": "0xf882ec206292910527fd7095e59a1ca027b873296f1eba3886aa1addc4ff0ab9",
"vmTrace": null
}
],
"id": 415
},
"statusCode": 200
}

@ -0,0 +1,74 @@
{
"request": {
"jsonrpc": "2.0",
"method": "trace_replayBlockTransactions",
"params": [
"0x5",
[
"stateDiff"
]
],
"id": 415
},
"response": {
"jsonrpc": "2.0",
"result": [
{
"output": "0x",
"stateDiff": {
"0x0000000000000000000000000000000000000000": {
"balance": {
"*": {
"from": "0x6f05b59d3d896d28",
"to": "0x6f05b59d3dc329d0"
}
},
"code": "=",
"nonce": "=",
"storage": {}
},
"0x0010000000000000000000000000000000000000": {
"balance": "=",
"code": "=",
"nonce": "=",
"storage": {
"0x0000000000000000000000000000000000000000000000000000000000000001": {
"*": {
"from": "0x0000000000000000000000000000000000000000000000000000000000000003",
"to": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
},
"0x0000000000000000000000000000000000000000000000000000000000000002": {
"*": {
"from": "0x0000000000000000000000000000000000000000000000000000000000000004",
"to": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
}
}
},
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"balance": {
"*": {
"from": "0xfffffffffffffffffffffffffffffffffff1ea75f",
"to": "0xffffffffffffffffffffffffffffffffffee4eab7"
}
},
"code": "=",
"nonce": {
"*": {
"from": "0x1",
"to": "0x2"
}
},
"storage": {}
}
},
"trace": [],
"transactionHash": "0xdb2cd5e93dedae66371fc4a95452c746e11f7d2097464707597b8807c889ef5b",
"vmTrace": null
}
],
"id": 415
},
"statusCode": 200
}

@ -0,0 +1,79 @@
{
"request": {
"jsonrpc": "2.0",
"method": "trace_replayBlockTransactions",
"params": [
"0x6",
[
"stateDiff"
]
],
"id": 415
},
"response": {
"jsonrpc": "2.0",
"result": [
{
"output": "0x",
"stateDiff": {
"0x0000000000000000000000000000000000000000": {
"balance": {
"*": {
"from": "0x8ac723048c8b29d0",
"to": "0x8ac723048cee68a2"
}
},
"code": "=",
"nonce": "=",
"storage": {}
},
"0x0000000000000999000000000000000000000000": {
"balance": {
"+": "0x300"
},
"code": {
"+": "0x"
},
"nonce": {
"+": "0x0"
},
"storage": {}
},
"0x0020000000000000000000000000000000000000": {
"balance": {
"-": "0x300"
},
"code": {
"-": "0x600035ff"
},
"nonce": {
"-": "0x0"
},
"storage": {}
},
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"balance": {
"*": {
"from": "0xffffffffffffffffffffffffffffffffffee4eab7",
"to": "0xffffffffffffffffffffffffffffffffffe81abe5"
}
},
"code": "=",
"nonce": {
"*": {
"from": "0x2",
"to": "0x3"
}
},
"storage": {}
}
},
"trace": [],
"transactionHash": "0x91eeabc671e2dd2b1c8ddebb46ba59e8cb3e7d189f80bcc868a9787728c6e59e",
"vmTrace": null
}
],
"id": 415
},
"statusCode": 200
}

@ -0,0 +1,55 @@
{
"request": {
"jsonrpc": "2.0",
"method": "trace_replayBlockTransactions",
"params": [
"0x7",
[
"stateDiff"
]
],
"id": 415
},
"response": {
"jsonrpc": "2.0",
"result": [
{
"output": "0xf000000000000000000000000000000000000000000000000000000000000002",
"stateDiff": {
"0x0000000000000000000000000000000000000000": {
"balance": {
"*": {
"from": "0xa688906bdbb668a2",
"to": "0xa688906bdc04064f"
}
},
"code": "=",
"nonce": "=",
"storage": {}
},
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"balance": {
"*": {
"from": "0xffffffffffffffffffffffffffffffffffe81abe5",
"to": "0xffffffffffffffffffffffffffffffffffe340e38"
}
},
"code": "=",
"nonce": {
"*": {
"from": "0x3",
"to": "0x4"
}
},
"storage": {}
}
},
"trace": [],
"transactionHash": "0x47f4d445ea1812cb1ddd3464ab23d2bfc6ed408a8a9db1c497f94e8e06e85286",
"vmTrace": null
}
],
"id": 415
},
"statusCode": 200
}

@ -0,0 +1,55 @@
{
"request": {
"jsonrpc": "2.0",
"method": "trace_replayBlockTransactions",
"params": [
"0x8",
[
"stateDiff"
]
],
"id": 415
},
"response": {
"jsonrpc": "2.0",
"result": [
{
"output": "0xf000000000000000000000000000000000000000000000000000000000000002",
"stateDiff": {
"0x0000000000000000000000000000000000000000": {
"balance": {
"*": {
"from": "0xc249fdd32acc064f",
"to": "0xc249fdd32b1d145d"
}
},
"code": "=",
"nonce": "=",
"storage": {}
},
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"balance": {
"*": {
"from": "0xffffffffffffffffffffffffffffffffffe340e38",
"to": "0xffffffffffffffffffffffffffffffffffde3002a"
}
},
"code": "=",
"nonce": {
"*": {
"from": "0x4",
"to": "0x5"
}
},
"storage": {}
}
},
"trace": [],
"transactionHash": "0xa29f9d6a4f183f4c22c4857544a9a6b69c48d7bb8a97652be06e50bb69470666",
"vmTrace": null
}
],
"id": 415
},
"statusCode": 200
}

@ -0,0 +1,55 @@
{
"request": {
"jsonrpc": "2.0",
"method": "trace_replayBlockTransactions",
"params": [
"0x9",
[
"stateDiff"
]
],
"id": 415
},
"response": {
"jsonrpc": "2.0",
"result": [
{
"output": "0xf000000000000000000000000000000000000000000000000000000000000002",
"stateDiff": {
"0x0000000000000000000000000000000000000000": {
"balance": {
"*": {
"from": "0xde0b6b3a79e5145d",
"to": "0xde0b6b3a7a3d13fb"
}
},
"code": "=",
"nonce": "=",
"storage": {}
},
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"balance": {
"*": {
"from": "0xffffffffffffffffffffffffffffffffffde3002a",
"to": "0xffffffffffffffffffffffffffffffffffd8b008c"
}
},
"code": "=",
"nonce": {
"*": {
"from": "0x5",
"to": "0x6"
}
},
"storage": {}
}
},
"trace": [],
"transactionHash": "0x4af0ef28fbfcbdee7cc5925797c1b9030b3848c2f63f92737c3fe76b45582af5",
"vmTrace": null
}
],
"id": 415
},
"statusCode": 200
}

@ -0,0 +1,55 @@
{
"request": {
"jsonrpc": "2.0",
"method": "trace_replayBlockTransactions",
"params": [
"0xA",
[
"stateDiff"
]
],
"id": 415
},
"response": {
"jsonrpc": "2.0",
"result": [
{
"output": "0xf000000000000000000000000000000000000000000000000000000000000002",
"stateDiff": {
"0x0000000000000000000000000000000000000000": {
"balance": {
"*": {
"from": "0xf9ccd8a1c90513fb",
"to": "0xf9ccd8a1c9562209"
}
},
"code": "=",
"nonce": "=",
"storage": {}
},
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"balance": {
"*": {
"from": "0xffffffffffffffffffffffffffffffffffd8b008c",
"to": "0xffffffffffffffffffffffffffffffffffd39f27e"
}
},
"code": "=",
"nonce": {
"*": {
"from": "0x6",
"to": "0x7"
}
},
"storage": {}
}
},
"trace": [],
"transactionHash": "0x4ec95b7de430b61fc9a57ed35274fd766b7f5fac5213ab946963eb528deae6b5",
"vmTrace": null
}
],
"id": 415
},
"statusCode": 200
}

@ -0,0 +1,55 @@
{
"request": {
"jsonrpc": "2.0",
"method": "trace_replayBlockTransactions",
"params": [
"0xB",
[
"stateDiff"
]
],
"id": 415
},
"response": {
"jsonrpc": "2.0",
"result": [
{
"output": "0xf000000000000000000000000000000000000000000000000000000000000001",
"stateDiff": {
"0x0000000000000000000000000000000000000000": {
"balance": {
"*": {
"from": "0x1158e4609181e2209",
"to": "0x1158e4609186f3017"
}
},
"code": "=",
"nonce": "=",
"storage": {}
},
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"balance": {
"*": {
"from": "0xffffffffffffffffffffffffffffffffffd39f27e",
"to": "0xffffffffffffffffffffffffffffffffffce8e470"
}
},
"code": "=",
"nonce": {
"*": {
"from": "0x7",
"to": "0x8"
}
},
"storage": {}
}
},
"trace": [],
"transactionHash": "0x6f77512ee9d43474a884c0703c86712fb98dca772fa6e12252786e3e23f196c1",
"vmTrace": null
}
],
"id": 415
},
"statusCode": 200
}

@ -0,0 +1,55 @@
{
"request": {
"jsonrpc": "2.0",
"method": "trace_replayBlockTransactions",
"params": [
"0xC",
[
"stateDiff"
]
],
"id": 415
},
"response": {
"jsonrpc": "2.0",
"result": [
{
"output": "0x",
"stateDiff": {
"0x0000000000000000000000000000000000000000": {
"balance": {
"*": {
"from": "0x1314fb37067373017",
"to": "0x1314fb3706783e191"
}
},
"code": "=",
"nonce": "=",
"storage": {}
},
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"balance": {
"*": {
"from": "0xffffffffffffffffffffffffffffffffffce8e470",
"to": "0xffffffffffffffffffffffffffffffffffc9c32f6"
}
},
"code": "=",
"nonce": {
"*": {
"from": "0x8",
"to": "0x9"
}
},
"storage": {}
}
},
"trace": [],
"transactionHash": "0x12e4a98e63825852a69d7702202a3b593e4059ec913c479443665d590da18724",
"vmTrace": null
}
],
"id": 415
},
"statusCode": 200
}

@ -0,0 +1,55 @@
{
"request": {
"jsonrpc": "2.0",
"method": "trace_replayBlockTransactions",
"params": [
"0xD",
[
"stateDiff"
]
],
"id": 415
},
"response": {
"jsonrpc": "2.0",
"result": [
{
"output": "0x",
"stateDiff": {
"0x0000000000000000000000000000000000000000": {
"balance": {
"*": {
"from": "0x14d1120d7b64be191",
"to": "0x14d1120d8a54bd47f"
}
},
"code": "=",
"nonce": "=",
"storage": {}
},
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"balance": {
"*": {
"from": "0xffffffffffffffffffffffffffffffffffc9c32f6",
"to": "0xfffffffffffffffffffffffffffffffff0d9c4008"
}
},
"code": "=",
"nonce": {
"*": {
"from": "0x9",
"to": "0xa"
}
},
"storage": {}
}
},
"trace": [],
"transactionHash": "0x547c7e2fcdf9f88b03b4f4184d667d6768c669f279785774d0cf42435cab06f1",
"vmTrace": null
}
],
"id": 415
},
"statusCode": 200
}

@ -0,0 +1,164 @@
{
"request": {
"jsonrpc": "2.0",
"method": "trace_replayBlockTransactions",
"params": [
"0xE",
[
"stateDiff"
]
],
"id": 415
},
"response": {
"jsonrpc": "2.0",
"result": [
{
"output": "0x01",
"stateDiff": {
"0x0000000000000000000000000000000000000000": {
"balance": {
"*": {
"from": "0x168d28e3ff413d47f",
"to": "0x168d28e3ff4aa3091"
}
},
"code": "=",
"nonce": "=",
"storage": {}
},
"0x0090000000000000000000000000000000000000": {
"balance": "=",
"code": "=",
"nonce": "=",
"storage": {
"0x0000000000000000000000000000000000000000000000000000000000000000": {
"*": {
"from": "0x0000000000000000000000000000000000000000000000000000000000000000",
"to": "0x0000000000000000000000000000000000000000000000000000000000000001"
}
}
}
},
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"balance": {
"*": {
"from": "0xfffffffffffffffffffffffffffffffff0d9c4008",
"to": "0xfffffffffffffffffffffffffffffffff0d05e3f6"
}
},
"code": "=",
"nonce": {
"*": {
"from": "0xa",
"to": "0xb"
}
},
"storage": {}
}
},
"trace": [],
"transactionHash": "0xe3ebc73c55176c3f2e72b289f8a9cefbcd5b25dcd205db5661f81b0bb974fa73",
"vmTrace": null
},
{
"output": "0x02",
"stateDiff": {
"0x0000000000000000000000000000000000000000": {
"balance": {
"*": {
"from": "0x168d28e3ff4aa3091",
"to": "0x168d28e3ff509d8bb"
}
},
"code": "=",
"nonce": "=",
"storage": {}
},
"0x0090000000000000000000000000000000000000": {
"balance": "=",
"code": "=",
"nonce": "=",
"storage": {
"0x0000000000000000000000000000000000000000000000000000000000000000": {
"*": {
"from": "0x0000000000000000000000000000000000000000000000000000000000000001",
"to": "0x0000000000000000000000000000000000000000000000000000000000000002"
}
}
}
},
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"balance": {
"*": {
"from": "0xfffffffffffffffffffffffffffffffff0d05e3f6",
"to": "0xfffffffffffffffffffffffffffffffff0ca63bcc"
}
},
"code": "=",
"nonce": {
"*": {
"from": "0xb",
"to": "0xc"
}
},
"storage": {}
}
},
"trace": [],
"transactionHash": "0xb4dc55ca4a7c1f72402860c594efaa7da32035003f8e203b7f6a3cf1826685a5",
"vmTrace": null
},
{
"output": "0x03",
"stateDiff": {
"0x0000000000000000000000000000000000000000": {
"balance": {
"*": {
"from": "0x168d28e3ff509d8bb",
"to": "0x168d28e3ff56980e5"
}
},
"code": "=",
"nonce": "=",
"storage": {}
},
"0x0090000000000000000000000000000000000000": {
"balance": "=",
"code": "=",
"nonce": "=",
"storage": {
"0x0000000000000000000000000000000000000000000000000000000000000000": {
"*": {
"from": "0x0000000000000000000000000000000000000000000000000000000000000002",
"to": "0x0000000000000000000000000000000000000000000000000000000000000003"
}
}
}
},
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"balance": {
"*": {
"from": "0xfffffffffffffffffffffffffffffffff0ca63bcc",
"to": "0xfffffffffffffffffffffffffffffffff0c4693a2"
}
},
"code": "=",
"nonce": {
"*": {
"from": "0xc",
"to": "0xd"
}
},
"storage": {}
}
},
"trace": [],
"transactionHash": "0x1a9f6256886437cfa21ee7685dd7a996024bea4d4bf6554b14787a6c9e5b90e6",
"vmTrace": null
}
],
"id": 415
},
"statusCode": 200
}

@ -16,8 +16,7 @@
{
"output": "0x",
"stateDiff": null,
"trace": [
],
"trace": [],
"transactionHash": "0x4de634fe767d1f6d0512ca0c9c0a054d3a2596f7cdd7c1eea5f93046a740b3c7",
"vmTrace": {
"code": "0x6020356000355560603560403555",
@ -78,8 +77,7 @@
"cost": 20000,
"ex": {
"mem": null,
"push": [
],
"push": [],
"store": {
"key": "0x1",
"val": "0x1"
@ -145,8 +143,7 @@
"cost": 20000,
"ex": {
"mem": null,
"push": [
],
"push": [],
"store": {
"key": "0x2",
"val": "0x2"
@ -162,8 +159,7 @@
{
"output": "0x",
"stateDiff": null,
"trace": [
],
"trace": [],
"transactionHash": "0xf882ec206292910527fd7095e59a1ca027b873296f1eba3886aa1addc4ff0ab9",
"vmTrace": {
"code": "0x6020356000355560603560403555",
@ -221,16 +217,15 @@
"sub": null
},
{
"cost": 20000,
"cost": 5000,
"ex": {
"mem": null,
"push": [
],
"push": [],
"store": {
"key": "0x1",
"val": "0x3"
},
"used": 16735422
"used": 16750422
},
"pc": 6,
"sub": null
@ -243,7 +238,7 @@
"0x60"
],
"store": null,
"used": 16735419
"used": 16750419
},
"pc": 7,
"sub": null
@ -256,7 +251,7 @@
"0x4"
],
"store": null,
"used": 16735416
"used": 16750416
},
"pc": 9,
"sub": null
@ -269,7 +264,7 @@
"0x40"
],
"store": null,
"used": 16735413
"used": 16750413
},
"pc": 10,
"sub": null
@ -282,22 +277,21 @@
"0x2"
],
"store": null,
"used": 16735410
"used": 16750410
},
"pc": 12,
"sub": null
},
{
"cost": 20000,
"cost": 5000,
"ex": {
"mem": null,
"push": [
],
"push": [],
"store": {
"key": "0x2",
"val": "0x4"
},
"used": 16715410
"used": 16745410
},
"pc": 13,
"sub": null

@ -0,0 +1,524 @@
{
"request": {
"jsonrpc": "2.0",
"method": "trace_replayBlockTransactions",
"params": [
"0xE",
[
"vmTrace"
]
],
"id": 415
},
"response": {
"jsonrpc": "2.0",
"result": [
{
"output": "0x01",
"stateDiff": null,
"trace": [],
"transactionHash": "0xe3ebc73c55176c3f2e72b289f8a9cefbcd5b25dcd205db5661f81b0bb974fa73",
"vmTrace": {
"code": "0x6000546001018060005360005560016000f3",
"ops": [
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x0"
],
"store": null,
"used": 16756199
},
"pc": 0,
"sub": null
},
{
"cost": 200,
"ex": {
"mem": null,
"push": [
"0x0"
],
"store": null,
"used": 16755999
},
"pc": 2,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x1"
],
"store": null,
"used": 16755996
},
"pc": 3,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x1"
],
"store": null,
"used": 16755993
},
"pc": 5,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x1",
"0x1"
],
"store": null,
"used": 16755990
},
"pc": 6,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x0"
],
"store": null,
"used": 16755987
},
"pc": 7,
"sub": null
},
{
"cost": 6,
"ex": {
"mem": {
"data": "0x01",
"off": 0
},
"push": [],
"store": null,
"used": 16755981
},
"pc": 9,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x0"
],
"store": null,
"used": 16755978
},
"pc": 10,
"sub": null
},
{
"cost": 20000,
"ex": {
"mem": null,
"push": [],
"store": {
"key": "0x0",
"val": "0x1"
},
"used": 16735978
},
"pc": 12,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x1"
],
"store": null,
"used": 16735975
},
"pc": 13,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x0"
],
"store": null,
"used": 16735972
},
"pc": 15,
"sub": null
},
{
"cost": 0,
"ex": {
"mem": null,
"push": [],
"store": null,
"used": 16735972
},
"pc": 17,
"sub": null
}
]
}
},
{
"output": "0x02",
"stateDiff": null,
"trace": [],
"transactionHash": "0xb4dc55ca4a7c1f72402860c594efaa7da32035003f8e203b7f6a3cf1826685a5",
"vmTrace": {
"code": "0x6000546001018060005360005560016000f3",
"ops": [
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x0"
],
"store": null,
"used": 16756199
},
"pc": 0,
"sub": null
},
{
"cost": 200,
"ex": {
"mem": null,
"push": [
"0x1"
],
"store": null,
"used": 16755999
},
"pc": 2,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x1"
],
"store": null,
"used": 16755996
},
"pc": 3,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x2"
],
"store": null,
"used": 16755993
},
"pc": 5,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x2",
"0x2"
],
"store": null,
"used": 16755990
},
"pc": 6,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x0"
],
"store": null,
"used": 16755987
},
"pc": 7,
"sub": null
},
{
"cost": 6,
"ex": {
"mem": {
"data": "0x02",
"off": 0
},
"push": [],
"store": null,
"used": 16755981
},
"pc": 9,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x0"
],
"store": null,
"used": 16755978
},
"pc": 10,
"sub": null
},
{
"cost": 5000,
"ex": {
"mem": null,
"push": [],
"store": {
"key": "0x0",
"val": "0x2"
},
"used": 16750978
},
"pc": 12,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x1"
],
"store": null,
"used": 16750975
},
"pc": 13,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x0"
],
"store": null,
"used": 16750972
},
"pc": 15,
"sub": null
},
{
"cost": 0,
"ex": {
"mem": null,
"push": [],
"store": null,
"used": 16750972
},
"pc": 17,
"sub": null
}
]
}
},
{
"output": "0x03",
"stateDiff": null,
"trace": [],
"transactionHash": "0x1a9f6256886437cfa21ee7685dd7a996024bea4d4bf6554b14787a6c9e5b90e6",
"vmTrace": {
"code": "0x6000546001018060005360005560016000f3",
"ops": [
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x0"
],
"store": null,
"used": 16756199
},
"pc": 0,
"sub": null
},
{
"cost": 200,
"ex": {
"mem": null,
"push": [
"0x2"
],
"store": null,
"used": 16755999
},
"pc": 2,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x1"
],
"store": null,
"used": 16755996
},
"pc": 3,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x3"
],
"store": null,
"used": 16755993
},
"pc": 5,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x3",
"0x3"
],
"store": null,
"used": 16755990
},
"pc": 6,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x0"
],
"store": null,
"used": 16755987
},
"pc": 7,
"sub": null
},
{
"cost": 6,
"ex": {
"mem": {
"data": "0x03",
"off": 0
},
"push": [],
"store": null,
"used": 16755981
},
"pc": 9,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x0"
],
"store": null,
"used": 16755978
},
"pc": 10,
"sub": null
},
{
"cost": 5000,
"ex": {
"mem": null,
"push": [],
"store": {
"key": "0x0",
"val": "0x3"
},
"used": 16750978
},
"pc": 12,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x1"
],
"store": null,
"used": 16750975
},
"pc": 13,
"sub": null
},
{
"cost": 3,
"ex": {
"mem": null,
"push": [
"0x0"
],
"store": null,
"used": 16750972
},
"pc": 15,
"sub": null
},
{
"cost": 0,
"ex": {
"mem": null,
"push": [],
"store": null,
"used": 16750972
},
"pc": 17,
"sub": null
}
]
}
}
],
"id": 415
},
"statusCode": 200
}

@ -22,6 +22,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Optional;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
@ -132,6 +133,15 @@ public abstract class AbstractWorldUpdater<W extends WorldView, A extends Accoun
return world;
}
@Override
public Optional<WorldUpdater> parentUpdater() {
if (world instanceof WorldUpdater) {
return Optional.of((WorldUpdater) world);
} else {
return Optional.empty();
}
}
/**
* The accounts modified in this updater.
*
@ -228,7 +238,7 @@ public abstract class AbstractWorldUpdater<W extends WorldView, A extends Accoun
* with a value of 0 to signify deletion.
*/
@Override
public SortedMap<UInt256, UInt256> getUpdatedStorage() {
public Map<UInt256, UInt256> getUpdatedStorage() {
return updatedStorage;
}
@ -403,6 +413,11 @@ public abstract class AbstractWorldUpdater<W extends WorldView, A extends Accoun
return new ArrayList<>(updatedAccounts());
}
@Override
public Collection<Address> getDeletedAccountAddresses() {
return new ArrayList<>(deletedAccounts());
}
@Override
public void revert() {
deletedAccounts().clear();

@ -15,6 +15,7 @@
package org.hyperledger.besu.ethereum.core;
import java.util.Collection;
import java.util.Optional;
/**
* An object that buffers updates made over a particular {@link WorldView}.
@ -93,6 +94,13 @@ public interface WorldUpdater extends MutableWorldView {
*/
Collection<Account> getTouchedAccounts();
/**
* Returns the account addresses that have been deleted within the scope of this updater.
*
* @return the account addresses that have been deleted within the scope of this updater
*/
Collection<Address> getDeletedAccountAddresses();
/** Removes the changes that were made to this updater. */
void revert();
@ -101,4 +109,7 @@ public interface WorldUpdater extends MutableWorldView {
* of.
*/
void commit();
/** @return The parent WorldUpdater if this wraps another one, empty otherwise */
public Optional<WorldUpdater> parentUpdater();
}

@ -19,6 +19,7 @@ import org.hyperledger.besu.ethereum.core.Gas;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.vm.Code;
import org.hyperledger.besu.ethereum.vm.ExceptionalHaltReason;
import org.hyperledger.besu.ethereum.vm.MessageFrame;
import org.hyperledger.besu.ethereum.vm.internal.MemoryEntry;
import java.util.EnumSet;
@ -32,6 +33,7 @@ import org.apache.tuweni.units.bigints.UInt256;
public class TraceFrame {
private final MessageFrame messageFrame;
private final int pc;
private final String opcode;
private final Gas gasRemaining;
@ -55,6 +57,7 @@ public class TraceFrame {
private final Optional<MemoryEntry> maybeUpdatedMemory;
public TraceFrame(
final MessageFrame messageFrame,
final int pc,
final String opcode,
final Gas gasRemaining,
@ -73,6 +76,7 @@ public class TraceFrame {
final Optional<Map<UInt256, UInt256>> storagePreExecution,
final boolean virtualOperation,
final Optional<MemoryEntry> maybeUpdatedMemory) {
this.messageFrame = messageFrame;
this.pc = pc;
this.opcode = opcode;
this.gasRemaining = gasRemaining;
@ -94,42 +98,8 @@ public class TraceFrame {
this.maybeUpdatedMemory = maybeUpdatedMemory;
}
public TraceFrame(
final int pc,
final String opcode,
final Gas gasRemaining,
final Optional<Gas> gasCost,
final int depth,
final EnumSet<ExceptionalHaltReason> exceptionalHaltReasons,
final Optional<Bytes32[]> stack,
final Optional<Bytes32[]> memory,
final Optional<Map<UInt256, UInt256>> storage,
final Optional<Bytes> revertReason,
final Optional<Map<Address, Wei>> maybeRefunds,
final Optional<Code> maybeCode,
final int stackItemsProduced,
final Optional<Bytes32[]> stackPostExecution,
final Optional<Bytes32[]> memoryPostExecution,
final Optional<Map<UInt256, UInt256>> storagePreExecution) {
this(
pc,
opcode,
gasRemaining,
gasCost,
depth,
exceptionalHaltReasons,
stack,
memory,
storage,
revertReason,
maybeRefunds,
maybeCode,
stackItemsProduced,
stackPostExecution,
memoryPostExecution,
storagePreExecution,
false,
Optional.empty());
public MessageFrame getMessageFrame() {
return messageFrame;
}
public int getPc() {

@ -74,6 +74,7 @@ public class DebugOperationTracer implements OperationTracer {
frame.getRefunds().isEmpty() ? Optional.empty() : Optional.of(frame.getRefunds());
lastFrame =
new TraceFrame(
frame,
pc,
opcode,
gasRemaining,

@ -21,6 +21,7 @@ import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.core.WorldUpdater;
import java.util.Collection;
import java.util.Optional;
public class DefaultMutablePrivateWorldStateUpdater implements WorldUpdater {
@ -73,6 +74,11 @@ public class DefaultMutablePrivateWorldStateUpdater implements WorldUpdater {
return privateWorldUpdater.getTouchedAccounts();
}
@Override
public Collection<Address> getDeletedAccountAddresses() {
return privateWorldUpdater.getDeletedAccountAddresses();
}
@Override
public void revert() {
privateWorldUpdater.revert();
@ -96,4 +102,9 @@ public class DefaultMutablePrivateWorldStateUpdater implements WorldUpdater {
public WorldUpdater updater() {
return this;
}
@Override
public Optional<WorldUpdater> parentUpdater() {
return privateWorldUpdater.parentUpdater();
}
}

@ -37,7 +37,6 @@ import java.util.Map;
import java.util.NavigableMap;
import java.util.Objects;
import java.util.Optional;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.stream.Stream;
@ -362,6 +361,11 @@ public class DefaultMutableWorldState implements MutableWorldState {
return new ArrayList<>(updatedAccounts());
}
@Override
public Collection<Address> getDeletedAccountAddresses() {
return new ArrayList<>(deletedAccounts());
}
@Override
public void revert() {
deletedAccounts().clear();
@ -394,7 +398,7 @@ public class DefaultMutableWorldState implements MutableWorldState {
if (freshState) {
wrapped.updatedStorageTries.remove(updated.getAddress());
}
final SortedMap<UInt256, UInt256> updatedStorage = updated.getUpdatedStorage();
final Map<UInt256, UInt256> updatedStorage = updated.getUpdatedStorage();
if (!updatedStorage.isEmpty()) {
// Apply any storage updates
final MerklePatriciaTrie<Bytes32, Bytes> storageTrie =

Loading…
Cancel
Save