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

Make code sizes a characteristic of the EVM version #7250

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- A full and up to date implementation of EOF for Prague [#7169](https://github.com/hyperledger/besu/pull/7169)
- Add Subnet-Based Peer Permissions. [#7168](https://github.com/hyperledger/besu/pull/7168)
- Reduce lock contention on transaction pool when building a block [#7180](https://github.com/hyperledger/besu/pull/7180)
- Refactored how code, initcode, and max stack size are configured in forks. [#7245](https://github.com/hyperledger/besu/pull/7245)

### Bug fixes
- Validation errors ignored in accounts-allowlist and empty list [#7138](https://github.com/hyperledger/besu/issues/7138)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import static picocli.CommandLine.ScopeType.INHERIT;

import org.hyperledger.besu.BesuInfo;
import org.hyperledger.besu.evm.EvmSpecVersion;
import org.hyperledger.besu.evmtool.benchmarks.AltBN128Benchmark;
import org.hyperledger.besu.evmtool.benchmarks.BenchmarkExecutor;
import org.hyperledger.besu.evmtool.benchmarks.ECRecoverBenchmark;
Expand Down Expand Up @@ -64,12 +63,6 @@ enum Benchmark {
negatable = true)
Boolean nativeCode;

@Option(
names = {"--fork"},
paramLabel = "<String>",
description = "Fork to evaluate, when it impacts gas costing.")
String fork = EvmSpecVersion.defaultVersion().getName();

@Parameters(description = "One or more of ${COMPLETION-CANDIDATES}.")
EnumSet<Benchmark> benchmarks = EnumSet.noneOf(Benchmark.class);

Expand All @@ -91,7 +84,7 @@ public void run() {
var benchmarksToRun = benchmarks.isEmpty() ? EnumSet.allOf(Benchmark.class) : benchmarks;
for (var benchmark : benchmarksToRun) {
System.out.println("Benchmarks for " + benchmark);
benchmark.benchmarkExecutor.runBenchmark(output, nativeCode, fork);
benchmark.benchmarkExecutor.runBenchmark(output, nativeCode, parentCommand.getFork());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,36 +17,41 @@
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.hyperledger.besu.evmtool.CodeValidateSubCommand.COMMAND_NAME;

import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.referencetests.ReferenceTestProtocolSchedules;
import org.hyperledger.besu.evm.Code;
import org.hyperledger.besu.evm.code.CodeFactory;
import org.hyperledger.besu.evm.code.CodeV1Validation;
import org.hyperledger.besu.evm.EVM;
import org.hyperledger.besu.evm.EvmSpecVersion;
import org.hyperledger.besu.evm.code.CodeInvalid;
import org.hyperledger.besu.evm.code.EOFLayout;
import org.hyperledger.besu.util.LogConfigurator;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import org.apache.tuweni.bytes.Bytes;
import picocli.CommandLine;
import picocli.CommandLine.ParentCommand;

@SuppressWarnings({"ConstantValue", "DataFlowIssue"})
@CommandLine.Command(
name = COMMAND_NAME,
description = "Validates EVM code for fuzzing",
mixinStandardHelpOptions = true,
versionProvider = VersionProvider.class)
public class CodeValidateSubCommand implements Runnable {
public static final String COMMAND_NAME = "code-validate";
private final InputStream input;
private final PrintStream output;

@ParentCommand EvmToolCommand parentCommand;

private final EVM evm;

@CommandLine.Option(
names = {"--file"},
Expand All @@ -60,41 +65,46 @@ public class CodeValidateSubCommand implements Runnable {
@SuppressWarnings("unused")
public CodeValidateSubCommand() {
// PicoCLI requires this
this(System.in, System.out);
this(null);
}

CodeValidateSubCommand(final InputStream input, final PrintStream output) {
this.input = input;
this.output = output;
CodeValidateSubCommand(final EvmToolCommand parentCommand) {
this.parentCommand = parentCommand;
String fork = EvmSpecVersion.PRAGUE.getName();
if (parentCommand != null && parentCommand.hasFork()) {
fork = parentCommand.getFork();
}
ProtocolSpec protocolSpec = ReferenceTestProtocolSchedules.create().geSpecByName(fork);
evm = protocolSpec.getEvm();
}

@Override
public void run() {
LogConfigurator.setLevel("", "OFF");
if (cliCode.isEmpty() && codeFile == null) {
try (BufferedReader in = new BufferedReader(new InputStreamReader(input, UTF_8))) {
try (BufferedReader in = new BufferedReader(new InputStreamReader(parentCommand.in, UTF_8))) {
checkCodeFromBufferedReader(in);
} catch (IOException e) {
throw new RuntimeException(e);
}
} else {
if (codeFile != null) {
try (BufferedReader in = new BufferedReader(new FileReader(codeFile, UTF_8))) {
checkCodeFromBufferedReader(in);
} catch (IOException e) {
throw new RuntimeException(e);
}
} else if (codeFile != null) {
try (BufferedReader in = new BufferedReader(new FileReader(codeFile, UTF_8))) {
checkCodeFromBufferedReader(in);
} catch (IOException e) {
throw new RuntimeException(e);
}
} else {
for (String code : cliCode) {
output.print(considerCode(code));
parentCommand.out.print(considerCode(code));
}
}
parentCommand.out.flush();
}

private void checkCodeFromBufferedReader(final BufferedReader in) {
try {
for (String code = in.readLine(); code != null; code = in.readLine()) {
output.print(considerCode(code));
parentCommand.out.print(considerCode(code));
}
} catch (IOException e) {
throw new RuntimeException(e);
Expand All @@ -114,24 +124,22 @@ public String considerCode(final String hexCode) {
return "";
}

EOFLayout layout = EOFLayout.parseEOF(codeBytes);
EOFLayout layout = evm.parseEOF(codeBytes);
if (!layout.isValid()) {
return "err: layout - " + layout.invalidReason() + "\n";
}

String error = CodeV1Validation.validate(layout);
if (error != null) {
return "err: " + error + "\n";
Code code = evm.getCodeUncached(codeBytes);
if (code instanceof CodeInvalid codeInvalid) {
return "err: " + codeInvalid.getInvalidReason();
} else {
return "OK "
+ IntStream.range(0, code.getCodeSectionCount())
.mapToObj(code::getCodeSection)
.map(cs -> code.getBytes().slice(cs.getEntryPoint(), cs.getLength()))
.map(Bytes::toUnprefixedHexString)
.collect(Collectors.joining(","))
+ "\n";
}

Code code = CodeFactory.createCode(codeBytes, 1);

return "OK "
+ IntStream.range(0, code.getCodeSectionCount())
.mapToObj(code::getCodeSection)
.map(cs -> layout.container().slice(cs.getEntryPoint(), cs.getLength()))
.map(Bytes::toUnprefixedHexString)
.collect(Collectors.joining(","))
+ "\n";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
import static org.hyperledger.besu.evmtool.EOFTestSubCommand.COMMAND_NAME;

import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.referencetests.EOFTestCaseSpec;
import org.hyperledger.besu.ethereum.referencetests.EOFTestCaseSpec.TestResult;
import org.hyperledger.besu.ethereum.referencetests.ReferenceTestProtocolSchedules;
import org.hyperledger.besu.evm.EVM;
import org.hyperledger.besu.evm.EvmSpecVersion;
import org.hyperledger.besu.evm.code.CodeFactory;
import org.hyperledger.besu.evm.code.CodeInvalid;
import org.hyperledger.besu.evm.code.CodeV1;
import org.hyperledger.besu.evm.code.CodeV1Validation;
import org.hyperledger.besu.evm.code.EOFLayout;
import org.hyperledger.besu.util.LogConfigurator;

Expand Down Expand Up @@ -57,16 +57,14 @@ public class EOFTestSubCommand implements Runnable {
// picocli does it magically
@CommandLine.Parameters private final List<Path> eofTestFiles = new ArrayList<>();

@CommandLine.Option(
names = {"--fork-name"},
description = "Limit execution to one fork.")
private String forkName = null;

@CommandLine.Option(
names = {"--test-name"},
description = "Limit execution to one test.")
private String testVectorName = null;

EVM evm;
String fork = null;

public EOFTestSubCommand() {
this(null);
}
Expand All @@ -82,6 +80,14 @@ public void run() {
SignatureAlgorithmFactory.setDefaultInstance();
final ObjectMapper eofTestMapper = JsonUtils.createObjectMapper();

if (parentCommand.hasFork()) {
fork = parentCommand.getFork();
}
ProtocolSpec protocolSpec =
ReferenceTestProtocolSchedules.create()
.geSpecByName(fork == null ? EvmSpecVersion.PRAGUE.getName() : fork);
evm = protocolSpec.getEvm();

final JavaType javaType =
eofTestMapper
.getTypeFactory()
Expand Down Expand Up @@ -146,7 +152,8 @@ private void executeEOFTest(final String fileName, final Map<String, EOFTestCase
String code = testVector.getValue().code();
for (var testResult : testVector.getValue().results().entrySet()) {
String expectedForkName = testResult.getKey();
if (forkName != null && !forkName.equals(expectedForkName)) {
if (fork != null && !fork.equals(expectedForkName)) {
System.out.println("Wrong fork - " + fork + " != " + expectedForkName);
continue;
}
TestResult expectedResult = testResult.getValue();
Expand Down Expand Up @@ -210,16 +217,10 @@ public TestResult considerCode(final String hexCode) {
return failed("layout - " + layout.invalidReason());
}

var code = CodeFactory.createCode(codeBytes, 1);
var code = evm.getCodeUncached(codeBytes);
if (!code.isValid()) {
return failed("validate " + ((CodeInvalid) code).getInvalidReason());
}
if (code instanceof CodeV1 codeV1) {
var result = CodeV1Validation.validate(codeV1.getEofLayout());
if (result != null) {
return (failed("deep validate error: " + result));
}
}

return passed();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,14 @@ private static void addForkHelp(final CommandLine subCommandLine) {
subCommandLine.setHelpSectionKeys(keys);
}

public String getFork() {
return daggerOptions.provideFork().orElse(EvmSpecVersion.defaultVersion().getName());
}

public boolean hasFork() {
return daggerOptions.provideFork().isPresent();
}

@Override
public void run() {
LogConfigurator.setLevel("", "OFF");
Expand All @@ -340,8 +348,7 @@ public void run() {
.build();

int remainingIters = this.repeat;
final ProtocolSpec protocolSpec =
component.getProtocolSpec().apply(BlockHeaderBuilder.createDefault().buildBlockHeader());
final ProtocolSpec protocolSpec = component.getProtocolSpec();
final Transaction tx =
new Transaction.Builder()
.nonce(0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,13 @@
package org.hyperledger.besu.evmtool;

import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.evm.EVM;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.metrics.MetricsConfigurationModule;
import org.hyperledger.besu.metrics.MetricsSystemModule;

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

import dagger.Component;
Expand All @@ -40,7 +39,9 @@
})
public interface EvmToolComponent {

Function<BlockHeader, ProtocolSpec> getProtocolSpec();
ProtocolSpec getProtocolSpec();

EVM getEVM();

WorldUpdater getWorldUpdater();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters;
import org.hyperledger.besu.evm.EvmSpecVersion;
import org.hyperledger.besu.evm.internal.EvmConfiguration;

import java.math.BigInteger;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
Expand Down Expand Up @@ -68,13 +70,15 @@ ProtocolSchedule provideProtocolSchedule(
}
}

if (fork.isPresent()) {
var schedules = createSchedules();
var schedule = schedules.get(fork.map(String::toLowerCase).get());
if (schedule != null) {
return schedule.get();
}
var schedules = createSchedules();
var schedule =
schedules.get(
fork.orElse(EvmSpecVersion.defaultVersion().getName())
.toLowerCase(Locale.getDefault()));
if (schedule != null) {
return schedule.get();
}

return MainnetProtocolSchedule.fromConfig(
configOptions, evmConfiguration, MiningParameters.newDefault(), new BadBlockManager());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@

import static org.hyperledger.besu.evmtool.PrettyPrintSubCommand.COMMAND_NAME;

import org.hyperledger.besu.evm.code.CodeV1Validation;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.referencetests.ReferenceTestProtocolSchedules;
import org.hyperledger.besu.evm.EVM;
import org.hyperledger.besu.evm.EvmSpecVersion;
import org.hyperledger.besu.evm.code.CodeInvalid;
import org.hyperledger.besu.evm.code.EOFLayout;
import org.hyperledger.besu.util.LogConfigurator;

Expand Down Expand Up @@ -63,14 +67,20 @@ public void run() {
"Pretty printing of legacy EVM is not supported. Patches welcome!");

} else {
EOFLayout layout = EOFLayout.parseEOF(container);
String fork = EvmSpecVersion.PRAGUE.getName();
if (parentCommand.hasFork()) {
fork = parentCommand.getFork();
}
ProtocolSpec protocolSpec = ReferenceTestProtocolSchedules.create().geSpecByName(fork);
EVM evm = protocolSpec.getEvm();
EOFLayout layout = evm.parseEOF(container);
if (layout.isValid()) {
String validation = CodeV1Validation.validate(layout);
if (validation == null || force) {
var validatedCode = evm.getCodeUncached(container);
if (validatedCode.isValid() || force) {
layout.prettyPrint(parentCommand.out);
}
if (validation != null) {
parentCommand.out.println("EOF code is invalid - " + validation);
if (validatedCode instanceof CodeInvalid codeInvalid) {
parentCommand.out.println("EOF code is invalid - " + codeInvalid.getInvalidReason());
}
} else {
parentCommand.out.println("EOF layout is invalid - " + layout.invalidReason());
Expand Down
Loading
Loading