From f868ee5965dd0accfdecf8236aa628e65f8f628a Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Mon, 21 Feb 2022 11:35:58 -0700 Subject: [PATCH] Migrate JumpDestCache to CodeCache (#3472) Migrate the jump dest analysis cache into a more generic code cache that lives inside the EVM. This is in preparation for Ethereum Object Formats where a string of code may be treated differently depending on what EVM version is executing the code. Newer versions will also have difference analyses to run that will need different backing data structures. Signed-off-by: Danno Ferrin --- build.gradle | 2 +- .../results/tracing/vm/VmTraceGenerator.java | 2 +- .../mainnet/MainnetTransactionProcessor.java | 12 ++-- .../privacy/PrivateTransactionProcessor.java | 12 ++-- .../core/MessageFrameTestFixture.java | 3 +- .../besu/ethereum/core/TestCodeExecutor.java | 12 +++- .../hyperledger/besu/ethereum/vm/EVMTest.java | 4 +- .../vm/operations/Create2OperationTest.java | 10 +++- .../vm/operations/CreateOperationTest.java | 2 +- .../vm/operations/JumpOperationTest.java | 12 ++-- .../besu/evmtool/EvmToolCommand.java | 3 +- .../java/org/hyperledger/besu/evm/Code.java | 48 +++++++++------- .../java/org/hyperledger/besu/evm/EVM.java | 35 +++--------- .../besu/evm/fluent/EVMExecutor.java | 55 +++++++++---------- .../{JumpDestCache.java => CodeCache.java} | 13 +++-- .../besu/evm/internal/CodeScale.java | 7 ++- .../evm/operation/AbstractCallOperation.java | 11 ++-- .../operation/AbstractCreateOperation.java | 7 +-- .../besu/evm/operation/JumpOperation.java | 2 +- .../besu/evm/operation/JumpiOperation.java | 2 +- .../processor/AbstractMessageProcessor.java | 8 +++ ...pDestCacheTest.java => CodeCacheTest.java} | 15 +++-- .../besu/evm/precompile/Benchmarks.java | 2 +- .../besu/evm/toy/EvmToyCommand.java | 3 +- 24 files changed, 148 insertions(+), 134 deletions(-) rename evm/src/main/java/org/hyperledger/besu/evm/internal/{JumpDestCache.java => CodeCache.java} (82%) rename evm/src/test/java/org/hyperledger/besu/evm/internal/{JumpDestCacheTest.java => CodeCacheTest.java} (71%) diff --git a/build.gradle b/build.gradle index 8cdb4824d94..49d64892da2 100644 --- a/build.gradle +++ b/build.gradle @@ -130,7 +130,7 @@ allprojects { java { // This path needs to be relative to each project target '**/*.java' - targetExclude '**/src/reference-test/**', '**/src/main/generated/**', '**/src/test/generated/**' + targetExclude '**/src/reference-test/**', '**/src/main/generated/**', '**/src/test/generated/**', '**/src/jmh/generated/**' removeUnusedImports() googleJavaFormat('1.10.0') importOrder 'org.hyperledger', 'java', '' diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/vm/VmTraceGenerator.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/vm/VmTraceGenerator.java index 1dd645ca8f5..4d9dccb75e4 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/vm/VmTraceGenerator.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/vm/VmTraceGenerator.java @@ -288,7 +288,7 @@ private void initStep(final TraceFrame frame) { // set smart contract code if (currentTrace != null && "0x".equals(currentTrace.getCode())) { currentTrace.setCode( - currentTraceFrame.getMaybeCode().orElse(new Code()).getBytes().toHexString()); + currentTraceFrame.getMaybeCode().orElse(Code.EMPTY_CODE).getBytes().toHexString()); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java index 1e223723967..e8e1856d8d0 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java @@ -36,7 +36,6 @@ import org.hyperledger.besu.evm.Code; import org.hyperledger.besu.evm.Gas; import org.hyperledger.besu.evm.account.Account; -import org.hyperledger.besu.evm.account.AccountState; import org.hyperledger.besu.evm.account.EvmAccount; import org.hyperledger.besu.evm.account.MutableAccount; import org.hyperledger.besu.evm.frame.MessageFrame; @@ -366,13 +365,16 @@ public TransactionProcessingResult processTransaction( final Address contractAddress = Address.contractAddress(senderAddress, senderMutableAccount.getNonce() - 1L); + final Bytes initCodeBytes = transaction.getPayload(); initialFrame = commonMessageFrameBuilder .type(MessageFrame.Type.CONTRACT_CREATION) .address(contractAddress) .contract(contractAddress) .inputData(Bytes.EMPTY) - .code(new Code(transaction.getPayload(), Hash.EMPTY)) + .code( + contractCreationProcessor.getCodeFromEVM( + Hash.hash(initCodeBytes), initCodeBytes)) .build(); } else { @SuppressWarnings("OptionalGetWithoutIsPresent") // isContractCall tests isPresent @@ -385,9 +387,9 @@ public TransactionProcessingResult processTransaction( .contract(to) .inputData(transaction.getPayload()) .code( - new Code( - maybeContract.map(AccountState::getCode).orElse(Bytes.EMPTY), - maybeContract.map(AccountState::getCodeHash).orElse(Hash.EMPTY))) + maybeContract + .map(c -> messageCallProcessor.getCodeFromEVM(c.getCodeHash(), c.getCode())) + .orElse(Code.EMPTY_CODE)) .build(); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionProcessor.java index 6ea2f1e160f..1f515398f45 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionProcessor.java @@ -29,7 +29,6 @@ import org.hyperledger.besu.evm.Code; import org.hyperledger.besu.evm.Gas; import org.hyperledger.besu.evm.account.Account; -import org.hyperledger.besu.evm.account.AccountState; import org.hyperledger.besu.evm.account.EvmAccount; import org.hyperledger.besu.evm.account.MutableAccount; import org.hyperledger.besu.evm.frame.MessageFrame; @@ -151,13 +150,16 @@ public TransactionProcessingResult processTransaction( previousNonce, privacyGroupId.toString()); + final Bytes initCodeBytes = transaction.getPayload(); initialFrame = commonMessageFrameBuilder .type(MessageFrame.Type.CONTRACT_CREATION) .address(privateContractAddress) .contract(privateContractAddress) .inputData(Bytes.EMPTY) - .code(new Code(transaction.getPayload(), Hash.EMPTY)) + .code( + contractCreationProcessor.getCodeFromEVM( + Hash.hash(initCodeBytes), initCodeBytes)) .build(); } else { final Address to = transaction.getTo().get(); @@ -170,9 +172,9 @@ public TransactionProcessingResult processTransaction( .contract(to) .inputData(transaction.getPayload()) .code( - new Code( - maybeContract.map(AccountState::getCode).orElse(Bytes.EMPTY), - maybeContract.map(AccountState::getCodeHash).orElse(Hash.EMPTY))) + maybeContract + .map(c -> messageCallProcessor.getCodeFromEVM(c.getCodeHash(), c.getCode())) + .orElse(Code.EMPTY_CODE)) .build(); } diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/MessageFrameTestFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/MessageFrameTestFixture.java index 395092cfb60..60bcf08fce8 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/MessageFrameTestFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/MessageFrameTestFixture.java @@ -17,7 +17,6 @@ import static org.hyperledger.besu.evm.frame.MessageFrame.DEFAULT_MAX_STACK_SIZE; import org.hyperledger.besu.datatypes.Address; -import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.vm.BlockHashLookup; @@ -52,7 +51,7 @@ public class MessageFrameTestFixture { private Wei gasPrice = Wei.ZERO; private Wei value = Wei.ZERO; private Bytes inputData = Bytes.EMPTY; - private Code code = new Code(Bytes.EMPTY, Hash.EMPTY); + private Code code = Code.EMPTY_CODE; private final List stackItems = new ArrayList<>(); private Optional blockHeader = Optional.empty(); private int depth = 0; diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TestCodeExecutor.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TestCodeExecutor.java index 5a93faff16c..acc7279bb44 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TestCodeExecutor.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TestCodeExecutor.java @@ -22,6 +22,7 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.evm.Code; +import org.hyperledger.besu.evm.EVM; import org.hyperledger.besu.evm.Gas; import org.hyperledger.besu.evm.account.MutableAccount; import org.hyperledger.besu.evm.frame.MessageFrame; @@ -49,14 +50,19 @@ public TestCodeExecutor(final ProtocolSchedule protocolSchedule) { } public MessageFrame executeCode( - final String code, final long gasLimit, final Consumer accountSetup) { + final String codeHexString, + final long gasLimit, + final Consumer accountSetup) { final ProtocolSpec protocolSpec = fixture.getProtocolSchedule().getByBlockNumber(0); final WorldUpdater worldUpdater = createInitialWorldState(accountSetup, fixture.getStateArchive()); final Deque messageFrameStack = new ArrayDeque<>(); + final EVM evm = protocolSpec.getEvm(); final MessageCallProcessor messageCallProcessor = - new MessageCallProcessor(protocolSpec.getEvm(), new PrecompileContractRegistry()); + new MessageCallProcessor(evm, new PrecompileContractRegistry()); + final Bytes codeBytes = Bytes.fromHexString(codeHexString); + final Code code = evm.getCode(Hash.hash(codeBytes), codeBytes); final Transaction transaction = Transaction.builder() @@ -85,7 +91,7 @@ public MessageFrame executeCode( .inputData(transaction.getPayload()) .sender(SENDER_ADDRESS) .value(transaction.getValue()) - .code(new Code(Bytes.fromHexString(code), Hash.EMPTY)) + .code(code) .blockHeader(blockHeader) .depth(0) .build(); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/EVMTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/EVMTest.java index 420568c42eb..829ee206adb 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/EVMTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/EVMTest.java @@ -50,7 +50,7 @@ public void setup() { @Test public void assertThatEndOfScriptNotExplicitlySetInCodeReturnsAVirtualOperation() { final Bytes noEnd = Bytes.fromHexString("0x60203560003555606035604035556000"); - final Code code = new Code(noEnd, Hash.hash(noEnd)); + final Code code = Code.createLegacyCode(noEnd, Hash.hash(noEnd)); final Operation operation = evm.operationAtOffset(code, code.getSize()); assertThat(operation).isNotNull(); assertThat(operation.isVirtualOperation()).isTrue(); @@ -59,7 +59,7 @@ public void assertThatEndOfScriptNotExplicitlySetInCodeReturnsAVirtualOperation( @Test public void assertThatEndOfScriptExplicitlySetInCodeDoesNotReturnAVirtualOperation() { final Bytes ends = Bytes.fromHexString("0x6020356000355560603560403555600000"); - final Code code = new Code(ends, Hash.hash(ends)); + final Code code = Code.createLegacyCode(ends, Hash.hash(ends)); when(operationRegistry.get(anyByte())).thenReturn(new StopOperation(gasCalculator)); final Operation operation = evm.operationAtOffset(code, code.getSize() - 1); assertThat(operation).isNotNull(); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/operations/Create2OperationTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/operations/Create2OperationTest.java index 94d3d851559..b59ad5d8487 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/operations/Create2OperationTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/operations/Create2OperationTest.java @@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; import org.hyperledger.besu.ethereum.vm.BlockHashLookup; import org.hyperledger.besu.evm.Code; +import org.hyperledger.besu.evm.EVM; import org.hyperledger.besu.evm.Gas; import org.hyperledger.besu.evm.account.MutableAccount; import org.hyperledger.besu.evm.frame.MessageFrame; @@ -56,6 +57,7 @@ public class Create2OperationTest { private final WorldUpdater worldUpdater = mock(WorldUpdater.class); private final WrappedEvmAccount account = mock(WrappedEvmAccount.class); private final MutableAccount mutableAccount = mock(MutableAccount.class); + private final EVM evm = mock(EVM.class); private final Create2Operation operation = new Create2Operation(new ConstantinopleGasCalculator()); @@ -141,7 +143,7 @@ public void setUp() { .sender(Address.fromHexString(sender)) .value(Wei.ZERO) .apparentValue(Wei.ZERO) - .code(new Code(codeBytes, Hash.hash(codeBytes))) + .code(Code.createLegacyCode(codeBytes, Hash.hash(codeBytes))) .depth(1) .completer(__ -> {}) .address(Address.fromHexString(sender)) @@ -164,6 +166,10 @@ public void setUp() { when(mutableAccount.getBalance()).thenReturn(Wei.ZERO); when(worldUpdater.getAccount(any())).thenReturn(account); when(worldUpdater.updater()).thenReturn(worldUpdater); + when(evm.getCode(any(), any())) + .thenAnswer( + invocation -> + Code.createLegacyCode(invocation.getArgument(1), invocation.getArgument(0))); } @Test @@ -174,7 +180,7 @@ public void shouldCalculateAddress() { @Test public void shouldCalculateGasPrice() { - final OperationResult result = operation.execute(messageFrame, null); + final OperationResult result = operation.execute(messageFrame, evm); assertThat(result.getHaltReason()).isEmpty(); assertThat(result.getGasCost()).contains(Gas.of(expectedGas)); } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/operations/CreateOperationTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/operations/CreateOperationTest.java index b411c2e7b45..3873b585c7c 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/operations/CreateOperationTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/operations/CreateOperationTest.java @@ -88,7 +88,7 @@ public void createFromMemoryMutationSafe() { .sender(Address.fromHexString(SENDER)) .value(Wei.ZERO) .apparentValue(Wei.ZERO) - .code(new Code(SIMPLE_CREATE, Hash.hash(SIMPLE_CREATE))) + .code(Code.createLegacyCode(SIMPLE_CREATE, Hash.hash(SIMPLE_CREATE))) .depth(1) .completer(__ -> {}) .address(Address.fromHexString(SENDER)) diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/operations/JumpOperationTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/operations/JumpOperationTest.java index 725c26e5aae..7b526bda753 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/operations/JumpOperationTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/operations/JumpOperationTest.java @@ -96,7 +96,7 @@ public void shouldJumpWhenLocationIsJumpDest() { final MessageFrame frame = createMessageFrameBuilder(Gas.of(10_000)) .pushStackItem(UInt256.fromHexString("0x03")) - .code(new Code(jumpBytes, Hash.hash(jumpBytes))) + .code(Code.createLegacyCode(jumpBytes, Hash.hash(jumpBytes))) .build(); frame.setPC(CURRENT_PC); @@ -111,7 +111,7 @@ public void shouldJumpWhenLocationIsJumpDestAndAtEndOfCode() { final MessageFrame frame = createMessageFrameBuilder(Gas.of(10_000)) .pushStackItem(UInt256.fromHexString("0x03")) - .code(new Code(jumpBytes, Hash.hash(jumpBytes))) + .code(Code.createLegacyCode(jumpBytes, Hash.hash(jumpBytes))) .build(); frame.setPC(CURRENT_PC); @@ -126,7 +126,7 @@ public void shouldHaltWithInvalidJumDestinationWhenLocationIsOutsideOfCodeRange( final MessageFrame frameDestinationGreaterThanCodeSize = createMessageFrameBuilder(Gas.of(100)) .pushStackItem(UInt256.fromHexString("0xFFFFFFFF")) - .code(new Code(jumpBytes, Hash.hash(jumpBytes))) + .code(Code.createLegacyCode(jumpBytes, Hash.hash(jumpBytes))) .build(); frameDestinationGreaterThanCodeSize.setPC(CURRENT_PC); @@ -136,7 +136,7 @@ public void shouldHaltWithInvalidJumDestinationWhenLocationIsOutsideOfCodeRange( final MessageFrame frameDestinationEqualsToCodeSize = createMessageFrameBuilder(Gas.of(100)) .pushStackItem(UInt256.fromHexString("0x04")) - .code(new Code(badJump, Hash.hash(badJump))) + .code(Code.createLegacyCode(badJump, Hash.hash(badJump))) .build(); frameDestinationEqualsToCodeSize.setPC(CURRENT_PC); @@ -154,7 +154,7 @@ public void longContractsValidate() { final MessageFrame longContract = createMessageFrameBuilder(Gas.of(100)) .pushStackItem(UInt256.fromHexString("0x12c")) - .code(new Code(longCode, Hash.hash(longCode))) + .code(Code.createLegacyCode(longCode, Hash.hash(longCode))) .build(); longContract.setPC(255); @@ -166,7 +166,7 @@ public void longContractsValidate() { public void shouldReuseJumpDestMap() { final JumpOperation operation = new JumpOperation(gasCalculator); final Bytes jumpBytes = Bytes.fromHexString("0x6003565b00"); - Code getsCached = spy(new Code(jumpBytes, Hash.hash(jumpBytes))); + Code getsCached = spy(Code.createLegacyCode(jumpBytes, Hash.hash(jumpBytes))); MessageFrame frame = createMessageFrameBuilder(Gas.of(10_000)) .pushStackItem(UInt256.fromHexString("0x03")) diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java index 0ba1adb9d28..1eb34545c72 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java @@ -213,6 +213,7 @@ public void run() { final PrecompileContractRegistry precompileContractRegistry = protocolSpec.getPrecompileContractRegistry(); final EVM evm = protocolSpec.getEvm(); + Code code = evm.getCode(Hash.hash(codeHexString), codeHexString); final Stopwatch stopwatch = Stopwatch.createUnstarted(); long lastTime = 0; do { @@ -242,7 +243,7 @@ public void run() { .inputData(callData) .value(ethValue) .apparentValue(ethValue) - .code(new Code(codeHexString, Hash.hash(codeHexString))) + .code(code) .blockValues(blockHeader) .depth(0) .completer(c -> {}) diff --git a/evm/src/main/java/org/hyperledger/besu/evm/Code.java b/evm/src/main/java/org/hyperledger/besu/evm/Code.java index de8f963b300..8573afbb6e2 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/Code.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/Code.java @@ -19,11 +19,14 @@ import org.hyperledger.besu.evm.operation.PushOperation; import com.google.common.base.MoreObjects; +import com.google.errorprone.annotations.RestrictedApi; import org.apache.tuweni.bytes.Bytes; /** Represents EVM code associated with an account. */ public class Code { + public static final Code EMPTY_CODE = new Code(Bytes.EMPTY, Hash.EMPTY); + /** The bytes representing the code. */ private final Bytes bytes; @@ -42,19 +45,17 @@ public class Code { * @param bytes The byte representation of the code. * @param codeHash the Hash of the bytes in the code. */ - public Code(final Bytes bytes, final Hash codeHash) { + protected Code(final Bytes bytes, final Hash codeHash) { this.bytes = bytes; this.codeHash = codeHash; } - public Code(final Bytes bytecode, final Hash codeHash, final long[] validJumpDestinations) { - this.bytes = bytecode; - this.validJumpDestinations = validJumpDestinations; - this.codeHash = codeHash; - } - - public Code() { - this(Bytes.EMPTY, Hash.EMPTY); + @RestrictedApi( + explanation = "To be used for testing purpose only", + link = "", + allowedOnPath = ".*/src/test/.*") + public static Code createLegacyCode(final Bytes bytes, final Hash codeHash) { + return new Code(bytes, codeHash); } /** @@ -88,24 +89,24 @@ public int getSize() { } public long[] calculateJumpDests() { - int size = getSize(); - long[] bitmap = new long[(size >> 6) + 1]; - byte[] rawCode = getBytes().toArrayUnsafe(); - int length = rawCode.length; + final int size = getSize(); + final long[] bitmap = new long[(size >> 6) + 1]; + final byte[] rawCode = getBytes().toArrayUnsafe(); + final int length = rawCode.length; for (int i = 0; i < length; ) { long thisEntry = 0L; - int entryPos = i >> 6; - int max = Math.min(64, length - (entryPos << 6)); + final int entryPos = i >> 6; + final int max = Math.min(64, length - (entryPos << 6)); int j = i & 0x3F; for (; j < max; i++, j++) { - byte operationNum = rawCode[i]; + final byte operationNum = rawCode[i]; if (operationNum == JumpDestOperation.OPCODE) { thisEntry |= 1L << j; } else if (operationNum > PushOperation.PUSH_BASE) { // not needed - && operationNum <= PushOperation.PUSH_MAX // Java quirk, all bytes are signed, and PUSH32 is 127, which is Byte.MAX_VALUE // so we don't need to check the upper bound as it will never be violated - int multiByteDataLen = operationNum - PushOperation.PUSH_BASE; + final int multiByteDataLen = operationNum - PushOperation.PUSH_BASE; j += multiByteDataLen; i += multiByteDataLen; } @@ -129,7 +130,16 @@ public Hash getCodeHash() { return codeHash; } - public long[] getValidJumpDestinations() { - return validJumpDestinations; + public boolean isJumpDestInvalid(final int jumpDestination) { + if (jumpDestination < 0 || jumpDestination >= getSize()) { + return true; + } + if (validJumpDestinations == null || validJumpDestinations.length == 0) { + validJumpDestinations = calculateJumpDests(); + } + + final long targetLong = validJumpDestinations[jumpDestination >>> 6]; + final long targetBit = 1L << (jumpDestination & 0x3F); + return (targetLong & targetBit) == 0L; } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/EVM.java b/evm/src/main/java/org/hyperledger/besu/evm/EVM.java index dbc312af8b2..fbd277bd292 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/EVM.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/EVM.java @@ -19,10 +19,10 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.frame.MessageFrame.State; import org.hyperledger.besu.evm.gascalculator.GasCalculator; +import org.hyperledger.besu.evm.internal.CodeCache; import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.FixedStack.OverflowException; import org.hyperledger.besu.evm.internal.FixedStack.UnderflowException; -import org.hyperledger.besu.evm.internal.JumpDestCache; import org.hyperledger.besu.evm.operation.InvalidOperation; import org.hyperledger.besu.evm.operation.Operation; import org.hyperledger.besu.evm.operation.Operation.OperationResult; @@ -51,7 +51,7 @@ public class EVM { private final OperationRegistry operations; private final GasCalculator gasCalculator; private final Operation endOfScriptStop; - private final JumpDestCache jumpDestCache; + private final CodeCache codeCache; public EVM( final OperationRegistry operations, @@ -60,7 +60,7 @@ public EVM( this.operations = operations; this.gasCalculator = gasCalculator; this.endOfScriptStop = new VirtualOperation(new StopOperation(gasCalculator)); - this.jumpDestCache = new JumpDestCache(evmConfiguration); + this.codeCache = new CodeCache(evmConfiguration); } public GasCalculator getGasCalculator() { @@ -142,29 +142,12 @@ public Operation operationAtOffset(final Code code, final int offset) { } } - /** - * Determine whether a specified destination is a valid jump target. - * - * @param jumpDestination The destination we're checking for validity. - * @param code The code within which we are looking for the destination. - * @return Whether or not this location is a valid jump destination. - */ - public boolean isValidJumpDestination(final int jumpDestination, final Code code) { - if (jumpDestination < 0 || jumpDestination >= code.getSize()) return false; - long[] validJumpDestinations = code.getValidJumpDestinations(); - if (validJumpDestinations == null || validJumpDestinations.length == 0) { - validJumpDestinations = jumpDestCache.getIfPresent(code.getCodeHash()); - if (validJumpDestinations == null) { - validJumpDestinations = code.calculateJumpDests(); - if (code.getCodeHash() != null && !code.getCodeHash().equals(Hash.EMPTY)) { - jumpDestCache.put(code.getCodeHash(), validJumpDestinations); - } else { - LOG.debug("not caching jumpdest for unhashed contract code"); - } - } + public Code getCode(final Hash codeHash, final Bytes codeBytes) { + Code result = codeCache.getIfPresent(codeHash); + if (result == null) { + result = new Code(codeBytes, codeHash); + codeCache.put(codeHash, result); } - long targetLong = validJumpDestinations[jumpDestination >>> 6]; - long targetBit = 1L << (jumpDestination & 0x3F); - return (targetLong & targetBit) != 0L; + return result; } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java b/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java index fac5b613f9c..c86bb2be015 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.evm.fluent; +import static com.google.common.base.Preconditions.checkNotNull; + import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; @@ -48,8 +50,8 @@ public class EVMExecutor { + private final EVM evm; private PrecompileContractRegistry precompileContractRegistry; - private EVM evm; private boolean commitWorldState = false; private WorldUpdater worldUpdater = new SimpleWorld(); private Gas gas = Gas.MAX_VALUE; @@ -58,7 +60,7 @@ public class EVMExecutor { private Wei gasPriceGWei = Wei.ZERO; private Bytes callData = Bytes.EMPTY; private Wei ethValue = Wei.ZERO; - private Code code = new Code(Bytes.EMPTY, Hash.EMPTY); + private Code code = Code.EMPTY_CODE; private BlockValues blockValues = new SimpleBlockValues(); private OperationTracer tracer = OperationTracer.NO_TRACING; private boolean requireDeposit = true; @@ -71,15 +73,17 @@ public class EVMExecutor { private MessageCallProcessor messageCallProcessor = null; private ContractCreationProcessor contractCreationProcessor = null; + private EVMExecutor(final EVM evm) { + checkNotNull(evm, "evm must not be null"); + this.evm = evm; + } + public static EVMExecutor evm(final EVM evm) { - EVMExecutor executor = new EVMExecutor(); - executor.evm = evm; - return executor; + return new EVMExecutor(evm); } public static EVMExecutor frontier(final EvmConfiguration evmConfiguration) { - EVMExecutor executor = new EVMExecutor(); - executor.evm = MainnetEVMs.frontier(evmConfiguration); + final EVMExecutor executor = new EVMExecutor(MainnetEVMs.frontier(evmConfiguration)); executor.precompileContractRegistry = MainnetPrecompiledContracts.frontier(executor.evm.getGasCalculator()); executor.contractValidationRules = List.of(); @@ -89,8 +93,7 @@ public static EVMExecutor frontier(final EvmConfiguration evmConfiguration) { } public static EVMExecutor homestead(final EvmConfiguration evmConfiguration) { - EVMExecutor executor = new EVMExecutor(); - executor.evm = MainnetEVMs.homestead(evmConfiguration); + final EVMExecutor executor = new EVMExecutor(MainnetEVMs.homestead(evmConfiguration)); executor.precompileContractRegistry = MainnetPrecompiledContracts.frontier(executor.evm.getGasCalculator()); executor.contractValidationRules = List.of(); @@ -99,8 +102,7 @@ public static EVMExecutor homestead(final EvmConfiguration evmConfiguration) { } public static EVMExecutor spuriousDragon(final EvmConfiguration evmConfiguration) { - EVMExecutor executor = new EVMExecutor(); - executor.evm = MainnetEVMs.spuriousDragon(evmConfiguration); + final EVMExecutor executor = new EVMExecutor(MainnetEVMs.spuriousDragon(evmConfiguration)); executor.precompileContractRegistry = MainnetPrecompiledContracts.frontier(executor.evm.getGasCalculator()); executor.contractValidationRules = List.of(MaxCodeSizeRule.of(0x6000)); @@ -108,8 +110,7 @@ public static EVMExecutor spuriousDragon(final EvmConfiguration evmConfiguration } public static EVMExecutor tangerineWhistle(final EvmConfiguration evmConfiguration) { - EVMExecutor executor = new EVMExecutor(); - executor.evm = MainnetEVMs.tangerineWhistle(evmConfiguration); + final EVMExecutor executor = new EVMExecutor(MainnetEVMs.tangerineWhistle(evmConfiguration)); executor.precompileContractRegistry = MainnetPrecompiledContracts.frontier(executor.evm.getGasCalculator()); executor.contractValidationRules = List.of(MaxCodeSizeRule.of(0x6000)); @@ -117,8 +118,7 @@ public static EVMExecutor tangerineWhistle(final EvmConfiguration evmConfigurati } public static EVMExecutor byzantium(final EvmConfiguration evmConfiguration) { - EVMExecutor executor = new EVMExecutor(); - executor.evm = MainnetEVMs.byzantium(evmConfiguration); + final EVMExecutor executor = new EVMExecutor(MainnetEVMs.byzantium(evmConfiguration)); executor.precompileContractRegistry = MainnetPrecompiledContracts.byzantium(executor.evm.getGasCalculator()); executor.contractValidationRules = List.of(MaxCodeSizeRule.of(0x6000)); @@ -126,8 +126,7 @@ public static EVMExecutor byzantium(final EvmConfiguration evmConfiguration) { } public static EVMExecutor constantinople(final EvmConfiguration evmConfiguration) { - EVMExecutor executor = new EVMExecutor(); - executor.evm = MainnetEVMs.constantinople(evmConfiguration); + final EVMExecutor executor = new EVMExecutor(MainnetEVMs.constantinople(evmConfiguration)); executor.precompileContractRegistry = MainnetPrecompiledContracts.byzantium(executor.evm.getGasCalculator()); executor.contractValidationRules = List.of(MaxCodeSizeRule.of(0x6000)); @@ -135,8 +134,7 @@ public static EVMExecutor constantinople(final EvmConfiguration evmConfiguration } public static EVMExecutor petersburg(final EvmConfiguration evmConfiguration) { - EVMExecutor executor = new EVMExecutor(); - executor.evm = MainnetEVMs.petersburg(evmConfiguration); + final EVMExecutor executor = new EVMExecutor(MainnetEVMs.petersburg(evmConfiguration)); executor.precompileContractRegistry = MainnetPrecompiledContracts.byzantium(executor.evm.getGasCalculator()); executor.contractValidationRules = List.of(MaxCodeSizeRule.of(0x6000)); @@ -144,8 +142,7 @@ public static EVMExecutor petersburg(final EvmConfiguration evmConfiguration) { } public static EVMExecutor istanbul(final EvmConfiguration evmConfiguration) { - EVMExecutor executor = new EVMExecutor(); - executor.evm = MainnetEVMs.istanbul(evmConfiguration); + final EVMExecutor executor = new EVMExecutor(MainnetEVMs.istanbul(evmConfiguration)); executor.precompileContractRegistry = MainnetPrecompiledContracts.istanbul(executor.evm.getGasCalculator()); executor.contractValidationRules = List.of(MaxCodeSizeRule.of(0x6000)); @@ -153,8 +150,7 @@ public static EVMExecutor istanbul(final EvmConfiguration evmConfiguration) { } public static EVMExecutor berlin(final EvmConfiguration evmConfiguration) { - EVMExecutor executor = new EVMExecutor(); - executor.evm = MainnetEVMs.berlin(evmConfiguration); + final EVMExecutor executor = new EVMExecutor(MainnetEVMs.berlin(evmConfiguration)); executor.precompileContractRegistry = MainnetPrecompiledContracts.istanbul(executor.evm.getGasCalculator()); executor.contractValidationRules = List.of(MaxCodeSizeRule.of(0x6000)); @@ -162,8 +158,7 @@ public static EVMExecutor berlin(final EvmConfiguration evmConfiguration) { } public static EVMExecutor london(final EvmConfiguration evmConfiguration) { - EVMExecutor executor = new EVMExecutor(); - executor.evm = MainnetEVMs.istanbul(evmConfiguration); + final EVMExecutor executor = new EVMExecutor(MainnetEVMs.london(evmConfiguration)); executor.precompileContractRegistry = MainnetPrecompiledContracts.istanbul(executor.evm.getGasCalculator()); return executor; @@ -198,7 +193,7 @@ public Bytes execute( public Bytes execute( final Bytes codeBytes, final Bytes inputData, final Wei value, final Address receiver) { - this.code = new Code(codeBytes, Hash.EMPTY); + this.code = evm.getCode(Hash.hash(codeBytes), codeBytes); this.callData = inputData; this.ethValue = value; this.receiver = receiver; @@ -206,10 +201,10 @@ public Bytes execute( } public Bytes execute() { - MessageCallProcessor mcp = thisMessageCallProcessor(); - ContractCreationProcessor ccp = thisContractCreationProcessor(); + final MessageCallProcessor mcp = thisMessageCallProcessor(); + final ContractCreationProcessor ccp = thisContractCreationProcessor(); final Deque messageFrameStack = new ArrayDeque<>(); - MessageFrame initialMessageFrame = + final MessageFrame initialMessageFrame = MessageFrame.builder() .type(MessageFrame.Type.MESSAGE_CALL) .messageFrameStack(messageFrameStack) @@ -302,7 +297,7 @@ public EVMExecutor code(final Code code) { } public EVMExecutor code(final Bytes codeBytes, final Hash hash) { - this.code = new Code(codeBytes, hash); + this.code = evm.getCode(hash, codeBytes); return this; } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/internal/JumpDestCache.java b/evm/src/main/java/org/hyperledger/besu/evm/internal/CodeCache.java similarity index 82% rename from evm/src/main/java/org/hyperledger/besu/evm/internal/JumpDestCache.java rename to evm/src/main/java/org/hyperledger/besu/evm/internal/CodeCache.java index 1b3acf64f52..f74f510e4ae 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/internal/JumpDestCache.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/internal/CodeCache.java @@ -16,20 +16,21 @@ package org.hyperledger.besu.evm.internal; import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.evm.Code; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; -public class JumpDestCache { +public class CodeCache { - private final Cache cache; + private final Cache cache; private final long weightLimit; - public JumpDestCache(final EvmConfiguration config) { + public CodeCache(final EvmConfiguration config) { this(config.getJumpDestCacheWeightBytes()); } - private JumpDestCache(final long maxWeightBytes) { + private CodeCache(final long maxWeightBytes) { this.weightLimit = maxWeightBytes; this.cache = Caffeine.newBuilder().maximumWeight(maxWeightBytes).weigher(new CodeScale()).build(); @@ -43,11 +44,11 @@ public void cleanUp() { this.cache.cleanUp(); } - public long[] getIfPresent(final Hash codeHash) { + public Code getIfPresent(final Hash codeHash) { return cache.getIfPresent(codeHash); } - public void put(final Hash key, final long[] value) { + public void put(final Hash key, final Code value) { cache.put(key, value); } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/internal/CodeScale.java b/evm/src/main/java/org/hyperledger/besu/evm/internal/CodeScale.java index 62f9600c96c..cd736c3d572 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/internal/CodeScale.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/internal/CodeScale.java @@ -16,12 +16,13 @@ package org.hyperledger.besu.evm.internal; import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.evm.Code; import com.github.benmanes.caffeine.cache.Weigher; -class CodeScale implements Weigher { +class CodeScale implements Weigher { @Override - public int weigh(final Hash key, final long[] value) { - return (value.length * 8) + key.size(); + public int weigh(final Hash key, final Code code) { + return ((code.getSize() * 9 + 7) / 8) + key.size(); } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java index be4bdb8011b..03f6345272f 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java @@ -15,7 +15,6 @@ package org.hyperledger.besu.evm.operation; import org.hyperledger.besu.datatypes.Address; -import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.evm.Code; import org.hyperledger.besu.evm.EVM; @@ -185,6 +184,11 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { final Bytes inputData = frame.readMutableMemory(inputDataOffset(frame), inputDataLength(frame)); + final Code code = + contract == null + ? Code.EMPTY_CODE + : evm.getCode(contract.getCodeHash(), contract.getCode()); + final MessageFrame childFrame = MessageFrame.builder() .type(MessageFrame.Type.MESSAGE_CALL) @@ -199,10 +203,7 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { .sender(sender(frame)) .value(value(frame)) .apparentValue(apparentValue(frame)) - .code( - new Code( - contract != null ? contract.getCode() : Bytes.EMPTY, - contract != null ? contract.getCodeHash() : Hash.EMPTY)) + .code(code) .blockValues(frame.getBlockValues()) .depth(frame.getMessageStackDepth() + 1) .isStatic(isStatic(frame)) diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java index 08c627fc60b..df3d4f53daa 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java @@ -19,7 +19,6 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; -import org.hyperledger.besu.evm.Code; import org.hyperledger.besu.evm.EVM; import org.hyperledger.besu.evm.Gas; import org.hyperledger.besu.evm.account.MutableAccount; @@ -76,7 +75,7 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { if (value.compareTo(account.getBalance()) > 0 || frame.getMessageStackDepth() >= 1024) { fail(frame); } else { - spawnChildMessage(frame); + spawnChildMessage(frame, evm); } } @@ -95,7 +94,7 @@ private void fail(final MessageFrame frame) { frame.pushStackItem(UInt256.ZERO); } - private void spawnChildMessage(final MessageFrame frame) { + private void spawnChildMessage(final MessageFrame frame, final EVM evm) { // memory cost needs to be calculated prior to memory expansion final Gas cost = cost(frame); frame.decrementRemainingGas(cost); @@ -129,7 +128,7 @@ private void spawnChildMessage(final MessageFrame frame) { .sender(frame.getRecipientAddress()) .value(value) .apparentValue(value) - .code(new Code(inputData, Hash.EMPTY)) + .code(evm.getCode(Hash.hash(inputData), inputData)) .blockValues(frame.getBlockValues()) .depth(frame.getMessageStackDepth() + 1) .completer(child -> complete(frame, child)) diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/JumpOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/JumpOperation.java index a769da3e4b9..f2855cd9fe1 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/JumpOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/JumpOperation.java @@ -48,7 +48,7 @@ public Operation.OperationResult executeFixedCostOperation( return invalidJumpResponse; } final Code code = frame.getCode(); - if (!evm.isValidJumpDestination(jumpDestination, code)) { + if (code.isJumpDestInvalid(jumpDestination)) { return invalidJumpResponse; } else { frame.setPC(jumpDestination); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/JumpiOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/JumpiOperation.java index 9c4aa8e28bc..29f43effaa8 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/JumpiOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/JumpiOperation.java @@ -53,7 +53,7 @@ public OperationResult executeFixedCostOperation(final MessageFrame frame, final return invalidJumpResponse; } final Code code = frame.getCode(); - if (!evm.isValidJumpDestination(jumpDestination, code)) { + if (code.isJumpDestInvalid(jumpDestination)) { return invalidJumpResponse; } frame.setPC(jumpDestination); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/processor/AbstractMessageProcessor.java b/evm/src/main/java/org/hyperledger/besu/evm/processor/AbstractMessageProcessor.java index 3dd298e07fe..b2f0f64b5ff 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/processor/AbstractMessageProcessor.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/processor/AbstractMessageProcessor.java @@ -15,6 +15,8 @@ package org.hyperledger.besu.evm.processor; import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.evm.Code; import org.hyperledger.besu.evm.EVM; import org.hyperledger.besu.evm.ModificationNotAllowedException; import org.hyperledger.besu.evm.account.Account; @@ -26,6 +28,8 @@ import java.util.Collection; import java.util.stream.Collectors; +import org.apache.tuweni.bytes.Bytes; + /** * A skeletal class for instantiating message processors. * @@ -193,4 +197,8 @@ public void process(final MessageFrame frame, final OperationTracer operationTra completedFailed(frame); } } + + public Code getCodeFromEVM(final Hash codeHash, final Bytes codeBytes) { + return evm.getCode(codeHash, codeBytes); + } } diff --git a/evm/src/test/java/org/hyperledger/besu/evm/internal/JumpDestCacheTest.java b/evm/src/test/java/org/hyperledger/besu/evm/internal/CodeCacheTest.java similarity index 71% rename from evm/src/test/java/org/hyperledger/besu/evm/internal/JumpDestCacheTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/internal/CodeCacheTest.java index a590e7c6279..37ae1e41159 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/internal/JumpDestCacheTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/internal/CodeCacheTest.java @@ -24,19 +24,18 @@ import org.apache.tuweni.bytes.Bytes; import org.junit.Test; -public class JumpDestCacheTest { +public class CodeCacheTest { private final String op = Bytes.of(JumpDestOperation.OPCODE).toUnprefixedHexString(); @Test public void testScale() { - Bytes contractBytes = + final Bytes contractBytes = Bytes.fromHexString("0xDEAD" + op + "BEEF" + op + "B0B0" + op + "C0DE" + op + "FACE"); - // 3rd bit, 6th bit, 9th bit, 12th bit - long[] jumpDests = {4 + 32 + 256 + 2048}; - CodeScale scale = new CodeScale(); - Code contractCode = new Code(contractBytes, Hash.hash(contractBytes), jumpDests); - int weight = scale.weigh(contractCode.getCodeHash(), contractCode.getValidJumpDestinations()); - assertThat(weight).isEqualTo(contractCode.getCodeHash().size() + jumpDests.length * 8); + final CodeScale scale = new CodeScale(); + final Code contractCode = Code.createLegacyCode(contractBytes, Hash.hash(contractBytes)); + final int weight = scale.weigh(contractCode.getCodeHash(), contractCode); + assertThat(weight) + .isEqualTo(contractCode.getCodeHash().size() + (contractBytes.size() * 9 + 7) / 8); } } diff --git a/evm/src/test/java/org/hyperledger/besu/evm/precompile/Benchmarks.java b/evm/src/test/java/org/hyperledger/besu/evm/precompile/Benchmarks.java index a985bd3309c..0ecd568c83e 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/precompile/Benchmarks.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/precompile/Benchmarks.java @@ -66,7 +66,7 @@ public class Benchmarks { .sender(Address.ZERO) .value(Wei.ZERO) .apparentValue(Wei.ZERO) - .code(new Code(Bytes.EMPTY, org.hyperledger.besu.datatypes.Hash.EMPTY)) + .code(Code.EMPTY_CODE) .depth(1) .completer(__ -> {}) .address(Address.ZERO) diff --git a/evm/src/test/java/org/hyperledger/besu/evm/toy/EvmToyCommand.java b/evm/src/test/java/org/hyperledger/besu/evm/toy/EvmToyCommand.java index 243e211fe3c..89ed4c7cce7 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/toy/EvmToyCommand.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/toy/EvmToyCommand.java @@ -144,6 +144,7 @@ public void run() { int repeat = this.repeat; final EVM evm = MainnetEVMs.berlin(EvmConfiguration.DEFAULT); + final Code code = evm.getCode(Hash.hash(codeBytes), codeBytes); final PrecompileContractRegistry precompileContractRegistry = new PrecompileContractRegistry(); MainnetPrecompiledContracts.populateForIstanbul( precompileContractRegistry, evm.getGasCalculator()); @@ -172,7 +173,7 @@ public void run() { .inputData(callData) .value(ethValue) .apparentValue(ethValue) - .code(new Code(codeBytes, Hash.hash(codeBytes))) + .code(code) .blockValues(new ToyBlockValues()) .depth(0) .completer(c -> {})