Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add post-run allocation output to EVMTool #4709

Merged
merged 5 commits into from
Dec 23, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# Changelog
## 23.1
## 23.1.0-beta

### Breaking Changes
- GoQuorum-compatible privacy is deprecated and will be removed in 23.4
- IBFT 1.0 is deprecated and will be removed in 23.4

### Additions and Improvements
- Added post-execution state logging option to EVM Tool [#4709](https://github.com/hyperledger/besu/pull/4709)

## 22.10.4

### Additions and Improvements
Expand Down Expand Up @@ -59,7 +62,7 @@ https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.10.2/besu-22.10.2
- Support for ephemeral testnet Shandong, for EOF testing. [#4599](https://github.com/hyperledger/besu/pull/4599)
- Improve performance of block processing by parallelizing some parts during the "commit" step [#4635](https://github.com/hyperledger/besu/pull/4635)
- Upgrade RocksDB version from 7.6.0 to 7.7.3
- Added new RPC endpoints `debug_setHead` & `debug_replayBlock [4580](https://github.com/hyperledger/besu/pull/4580)
- Added new RPC endpoints `debug_setHead` & `debug_replayBlock [#4580](https://github.com/hyperledger/besu/pull/4580)
- Upgrade OpenTelemetry to version 1.19.0 [#3675](https://github.com/hyperledger/besu/pull/3675)
- Implement Eth/67 sub-protocol [#4596](https://github.com/hyperledger/besu/issues/4596)
- Backward sync log UX improvements [#4655](https://github.com/hyperledger/besu/pull/4655)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.hyperledger.besu.evm.processor.MessageCallProcessor;
import org.hyperledger.besu.evm.tracing.OperationTracer;
import org.hyperledger.besu.evm.tracing.StandardJsonTracer;
import org.hyperledger.besu.evm.worldstate.WorldState;
import org.hyperledger.besu.util.Log4j2ConfiguratorUtil;

import java.io.BufferedWriter;
Expand All @@ -47,13 +48,18 @@
import java.io.PrintWriter;
import java.time.Instant;
import java.util.ArrayDeque;
import java.util.Comparator;
import java.util.Deque;
import java.util.Optional;
import java.util.stream.Collectors;

import com.google.common.base.Joiner;
import com.google.common.base.Stopwatch;
import io.vertx.core.json.JsonObject;
import org.apache.logging.log4j.Level;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import picocli.CommandLine;
Expand Down Expand Up @@ -130,6 +136,12 @@ void setBytes(final String optionValue) {
scope = INHERIT)
final Boolean showJsonResults = false;

@Option(
names = {"--json-alloc"},
description = "Output the final allocations after a run.",
scope = INHERIT)
final Boolean showJsonAlloc = false;

@Option(
names = {"--nomemory"},
description = "Disable showing the full memory output for each op.",
Expand All @@ -151,6 +163,7 @@ void setBytes(final String optionValue) {
description = "Number of times to repeat for benchmarking.")
private final Integer repeat = 0;

static final Joiner STORAGE_JOINER = Joiner.on(",\n");
private final EvmToolCommandOptionsModule daggerOptions = new EvmToolCommandOptionsModule();
private PrintWriter out =
new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out, UTF_8)), true);
Expand Down Expand Up @@ -313,10 +326,62 @@ public void run() {
}
lastTime = stopwatch.elapsed().toNanos();
stopwatch.reset();
if (showJsonAlloc && lastLoop) {
updater.commit();
WorldState worldState = component.getWorldState();
dumpWorldState(worldState, out);
}
shemnon marked this conversation as resolved.
Show resolved Hide resolved
} while (remainingIters-- > 0);

} catch (final IOException e) {
LOG.error("Unable to create Genesis module", e);
}
}

public static void dumpWorldState(final WorldState worldState, final PrintWriter out) {
out.println("{");
worldState
.streamAccounts(Bytes32.ZERO, Integer.MAX_VALUE)
.sorted(Comparator.comparing(o -> o.getAddress().get().toHexString()))
.forEach(
account -> {
out.println(
" \"" + account.getAddress().map(Address::toHexString).orElse("-") + "\": {");
if (account.getCode() != null && account.getCode().size() > 0) {
out.println(" \"code\": \"" + account.getCode().toHexString() + "\",");
}
var storageEntries = account.storageEntriesFrom(Bytes32.ZERO, Integer.MAX_VALUE);
if (!storageEntries.isEmpty()) {
out.println(" \"storage\": {");
out.println(
STORAGE_JOINER.join(
storageEntries.values().stream()
.map(
accountStorageEntry ->
" \""
+ accountStorageEntry
.getKey()
.map(UInt256::toHexString)
.orElse("-")
+ "\": \""
+ accountStorageEntry.getValue().toHexString()
+ "\"")
.collect(Collectors.toList())));
out.println(" },");
}
out.print(" \"balance\": \"" + account.getBalance().toShortHexString() + "\"");
if (account.getNonce() > 0) {
out.println(",");
out.println(
" \"nonce\": \""
+ Bytes.ofUnsignedLong(account.getNonce()).toShortHexString()
+ "\"");
} else {
out.println();
}
out.println(" },");
});
out.println("}");
out.flush();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import java.nio.file.Path;
import javax.inject.Named;
import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;
Expand Down Expand Up @@ -71,6 +72,7 @@ String provideKeyValueStorageName() {
final Path dataPath = getDefaultBesuDataPath(this);

@Provides
@Singleton
BesuConfiguration provideBesuConfiguration() {
return new BesuConfigurationImpl(dataPath, dataPath.resolve(BesuController.DATABASE_PATH));
}
Expand All @@ -83,6 +85,7 @@ BesuConfiguration provideBesuConfiguration() {
private final BlockParameter blockParameter = BlockParameter.PENDING;

@Provides
@Singleton
BlockParameter provideBlockParameter() {
return blockParameter;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package org.hyperledger.besu.evmtool;

import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;

Expand All @@ -40,5 +41,7 @@ public interface EvmToolComponent {

WorldUpdater getWorldUpdater();

MutableWorldState getWorldState();

Blockchain getBlockchain();
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.plugin.services.MetricsSystem;

import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;

Expand All @@ -28,6 +30,7 @@
public class MetricsSystemModule {

@Provides
@Singleton
MetricsSystem getMetricsSystem() {
return MetricsSystemFactory.create(MetricsConfiguration.builder().build());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;

import java.util.function.Function;
import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;
Expand All @@ -28,6 +29,7 @@
public class ProtocolModule {

@Provides
@Singleton
Function<Integer, ProtocolSpec> getProtocolSpec(final ProtocolSchedule protocolSchedule) {
return protocolSchedule::getByBlockNumber;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.hyperledger.besu.evmtool;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.hyperledger.besu.ethereum.referencetests.ReferenceTestProtocolSchedules.shouldClearEmptyAccounts;
import static org.hyperledger.besu.evmtool.StateTestSubCommand.COMMAND_NAME;

Expand Down Expand Up @@ -45,12 +46,14 @@
import org.hyperledger.besu.util.Log4j2ConfiguratorUtil;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -124,8 +127,7 @@ public void run() {
try {
if (stateTestFiles.isEmpty()) {
// if no state tests were specified use standard input to get filenames
final BufferedReader in =
new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
final BufferedReader in = new BufferedReader(new InputStreamReader(input, UTF_8));
while (true) {
final String fileName = in.readLine();
if (fileName == null) {
Expand Down Expand Up @@ -166,10 +168,10 @@ private void executeStateTest(final Map<String, GeneralStateTestCaseSpec> genera

private void traceTestSpecs(final String test, final List<GeneralStateTestCaseEipSpec> specs) {
Log4j2ConfiguratorUtil.setLevel(
"org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder", Level.OFF);
"org.hyperledger.besu.ethereum.mainnet.AbstractProtocolScheduleBuilder", Level.OFF);
final var referenceTestProtocolSchedules = ReferenceTestProtocolSchedules.create();
Log4j2ConfiguratorUtil.setLevel(
"org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder", null);
"org.hyperledger.besu.ethereum.mainnet.AbstractProtocolScheduleBuilder", null);

final OperationTracer tracer = // You should have picked Mercy.
parentCommand.showJsonResults
Expand All @@ -184,7 +186,9 @@ private void traceTestSpecs(final String test, final List<GeneralStateTestCaseEi

final ObjectNode summaryLine = objectMapper.createObjectNode();
if (transaction == null) {
// Check the world state root hash.
if (parentCommand.showJsonAlloc || parentCommand.showJsonResults) {
output.println("{\"error\":\"Transaction was invalid, trace and alloc unavailable.\"}");
}
summaryLine.put("test", test);
summaryLine.put("fork", spec.getFork());
summaryLine.put("d", spec.getDataIndex());
Expand Down Expand Up @@ -271,6 +275,12 @@ private void traceTestSpecs(final String test, final List<GeneralStateTestCaseEi
"validationError",
"Exception '" + spec.getExpectException() + "' was expected but did not occur");
}

if (parentCommand.showJsonAlloc) {
EvmToolCommand.dumpWorldState(
worldState,
new PrintWriter(new BufferedWriter(new OutputStreamWriter(output, UTF_8))));
}
}

output.println(summaryLine);
Expand Down