From 42b3cd42917413519dd6127be4b1cd84a8de5fb9 Mon Sep 17 00:00:00 2001 From: 7at <44062322+itfat@users.noreply.github.com> Date: Mon, 28 Oct 2024 10:19:28 +0500 Subject: [PATCH 1/2] Fix evmtool JSON Error Field to Return Hex String Instead of Long Null String on REVERT (#7774) Signed-off-by: 7at Co-authored-by: Sally MacFarlane --- .../besu/evmtool/EvmToolCommand.java | 4 +-- .../besu/evmtool/trace/revert.json | 2 +- .../besu/evm/tracing/StandardJsonTracer.java | 35 +------------------ .../besu/evm/toy/EvmToyCommand.java | 5 +-- 4 files changed, 4 insertions(+), 42 deletions(-) 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 f9d7c0db47..2574d4b8e3 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 @@ -529,9 +529,7 @@ public class EvmToolCommand implements Runnable { messageFrame .getExceptionalHaltReason() .ifPresent(haltReason -> out.println(haltReason)); - messageFrame - .getRevertReason() - .ifPresent(bytes -> out.println(new String(bytes.toArrayUnsafe(), UTF_8))); + messageFrame.getRevertReason().ifPresent(bytes -> out.println(bytes.toHexString())); } } } diff --git a/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/trace/revert.json b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/trace/revert.json index 4798d5da70..32ee526fdd 100644 --- a/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/trace/revert.json +++ b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/trace/revert.json @@ -12,7 +12,7 @@ {"pc":7,"op":82,"gas":"0x2540be3fa","gasCost":"0x6","memSize":0,"stack":["0x4e6f7065","0x0"],"depth":1,"refund":0,"opName":"MSTORE"}, {"pc":8,"op":96,"gas":"0x2540be3f4","gasCost":"0x3","memSize":32,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"}, {"pc":10,"op":96,"gas":"0x2540be3f1","gasCost":"0x3","memSize":32,"stack":["0x4"],"depth":1,"refund":0,"opName":"PUSH1"}, - {"pc":12,"op":253,"gas":"0x2540be3ee","gasCost":"0x0","memSize":32,"stack":["0x4","0x1c"],"depth":1,"refund":0,"opName":"REVERT","error":"Nope"}, + {"pc":12,"op":253,"gas":"0x2540be3ee","gasCost":"0x0","memSize":32,"stack":["0x4","0x1c"],"depth":1,"refund":0,"opName":"REVERT","error":"0x4e6f7065"}, {"stateRoot":"0x405bbd98da2aca6dff77f79e0b270270c48d6a3e07b76db675b20e454b50bbcb","output":"0x4e6f7065","gasUsed":"0x12","pass":true,"fork":"Cancun"} ] } \ No newline at end of file diff --git a/evm/src/main/java/org/hyperledger/besu/evm/tracing/StandardJsonTracer.java b/evm/src/main/java/org/hyperledger/besu/evm/tracing/StandardJsonTracer.java index baf052ba4e..8071fa942f 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/tracing/StandardJsonTracer.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/tracing/StandardJsonTracer.java @@ -14,8 +14,6 @@ */ package org.hyperledger.besu.evm.tracing; -import static com.google.common.base.Strings.padStart; - import org.hyperledger.besu.evm.code.OpcodeInfo; import org.hyperledger.besu.evm.frame.ExceptionalHaltReason; import org.hyperledger.besu.evm.frame.MessageFrame; @@ -224,7 +222,7 @@ public class StandardJsonTracer implements OperationTracer { .append("\""); } else if (messageFrame.getRevertReason().isPresent()) { sb.append(",\"error\":\"") - .append(quoteEscape(messageFrame.getRevertReason().orElse(Bytes.EMPTY))) + .append(messageFrame.getRevertReason().get().toHexString()) .append("\""); } @@ -232,37 +230,6 @@ public class StandardJsonTracer implements OperationTracer { out.println(sb); } - private static String quoteEscape(final Bytes bytes) { - final StringBuilder result = new StringBuilder(bytes.size()); - for (final byte b : bytes.toArrayUnsafe()) { - final int c = Byte.toUnsignedInt(b); - // list from RFC-4627 section 2 - if (c == '"') { - result.append("\\\""); - } else if (c == '\\') { - result.append("\\\\"); - } else if (c == '/') { - result.append("\\/"); - } else if (c == '\b') { - result.append("\\b"); - } else if (c == '\f') { - result.append("\\f"); - } else if (c == '\n') { - result.append("\\n"); - } else if (c == '\r') { - result.append("\\r"); - } else if (c == '\t') { - result.append("\\t"); - } else if (c <= 0x1F) { - result.append("\\u"); - result.append(padStart(Integer.toHexString(c), 4, '0')); - } else { - result.append((char) b); - } - } - return result.toString(); - } - @Override public void tracePrecompileCall( final MessageFrame frame, final long gasRequirement, final Bytes output) { 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 fcf26c3c56..9a5c3cd1ea 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 @@ -32,7 +32,6 @@ import org.hyperledger.besu.evm.worldstate.WorldUpdater; import java.io.PrintStream; import java.math.BigInteger; -import java.nio.charset.StandardCharsets; import java.util.Deque; import java.util.List; @@ -208,9 +207,7 @@ public class EvmToyCommand implements Runnable { out.println(messageFrame.getExceptionalHaltReason().get()); } if (messageFrame.getRevertReason().isPresent()) { - out.println( - new String( - messageFrame.getRevertReason().get().toArrayUnsafe(), StandardCharsets.UTF_8)); + out.println(messageFrame.getRevertReason().get().toHexString()); } } if (messageFrameStack.isEmpty()) { From f855d5b72fb5e44977d995f48872cdb976333711 Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Tue, 29 Oct 2024 10:30:33 +1000 Subject: [PATCH 2/2] EIP-7742: Add target_blob_count to block header (#7808) Signed-off-by: Simon Dudley --- .../besu/tests/acceptance/dsl/BlockUtils.java | 1 + .../ExecutionEnginePragueAcceptanceTest.java | 3 +++ .../AbstractBftBesuControllerBuilderTest.java | 1 + .../CliqueBesuControllerBuilderTest.java | 1 + .../besu/services/BesuEventsImplTest.java | 2 +- .../besu/config/GenesisConfigFile.java | 11 ++++++++++ .../api/jsonrpc/JsonRpcResponseKey.java | 3 ++- .../api/jsonrpc/JsonRpcResponseUtils.java | 6 ++++++ .../engine/AbstractEngineNewPayload.java | 1 + .../jsonrpc/internal/results/BlockResult.java | 7 +++++++ .../internal/methods/EthGasPriceTest.java | 1 + .../methods/EthMaxPriorityFeePerGasTest.java | 1 + ...neExchangeTransitionConfigurationTest.java | 1 + .../query/BlockchainQueriesLogCacheTest.java | 1 + .../cache/TransactionLogBloomCacherTest.java | 2 ++ .../besu/ethereum/chain/GenesisState.java | 7 +++++++ .../besu/ethereum/core/BlockHeader.java | 14 ++++++++++++- .../ethereum/core/BlockHeaderBuilder.java | 20 ++++++++++++++++--- .../ethereum/core/ProcessableBlockHeader.java | 17 +++++++++++++++- .../ethereum/core/SealableBlockHeader.java | 7 +++++-- .../ethereum/core/BlockHeaderTestFixture.java | 8 ++++++++ .../besu/ethereum/chain/GenesisStateTest.java | 12 +++++++---- .../diffbased/bonsai/LogRollingTests.java | 2 ++ .../besu/ethereum/chain/genesis_prague.json | 3 ++- .../eth/messages/MessageWrapperTest.java | 1 + .../backwardsync/ChainForTestCreator.java | 3 +++ .../BlockchainReferenceTestCaseSpec.java | 1 + .../referencetests/ReferenceTestEnv.java | 1 + plugin-api/build.gradle | 2 +- .../plugin/data/ProcessableBlockHeader.java | 12 +++++++++++ 30 files changed, 137 insertions(+), 15 deletions(-) diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/BlockUtils.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/BlockUtils.java index 3a4ca71002..29f60dd74a 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/BlockUtils.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/BlockUtils.java @@ -58,6 +58,7 @@ public class BlockUtils { null, null, null, + null, blockHeaderFunctions); } } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEnginePragueAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEnginePragueAcceptanceTest.java index 966c02bebd..f38a192d4d 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEnginePragueAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEnginePragueAcceptanceTest.java @@ -20,8 +20,11 @@ import java.util.stream.Stream; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.provider.Arguments; +// TODO SLD +@Disabled("TODO SLD - Enable when Prague spec is finalized") public class ExecutionEnginePragueAcceptanceTest extends AbstractJsonRpcTest { private static final String GENESIS_FILE = "/jsonrpc/engine/prague/genesis.json"; private static final String TEST_CASE_PATH = "/jsonrpc/engine/prague/test-cases/"; diff --git a/besu/src/test/java/org/hyperledger/besu/controller/AbstractBftBesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/AbstractBftBesuControllerBuilderTest.java index 621ae8a98c..1d9843dc5d 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/AbstractBftBesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/AbstractBftBesuControllerBuilderTest.java @@ -193,6 +193,7 @@ public abstract class AbstractBftBesuControllerBuilderTest { null, null, null, + null, getBlockHeaderFunctions()); final Block block1 = new Block(header1, BlockBody.empty()); diff --git a/besu/src/test/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilderTest.java index e9e93de9b9..d73907ced7 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilderTest.java @@ -222,6 +222,7 @@ public class CliqueBesuControllerBuilderTest { null, null, null, + null, new CliqueBlockHeaderFunctions()); final Block block1 = new Block(header1, BlockBody.empty()); diff --git a/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java b/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java index 478ce4ebc4..ddf68ba14b 100644 --- a/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java +++ b/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java @@ -219,7 +219,7 @@ public class BesuEventsImplTest { mock(EthPeer.class), new org.hyperledger.besu.ethereum.core.BlockHeader( null, null, null, null, null, null, null, null, 1, 1, 1, 1, null, null, null, 1, null, - null, null, null, null, null)); + null, null, null, null, null, null)); } private void clearSyncTarget() { diff --git a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java index 8938e5143c..eae9bc3d10 100644 --- a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java +++ b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java @@ -265,6 +265,17 @@ public class GenesisConfigFile { "0x0000000000000000000000000000000000000000000000000000000000000000"); } + /** + * Gets target blob count. + * + * @return the target blob count + */ + public Optional getTargetBlobCount() { + // TODO SLD EIP-7742 not sure if we should use a default value here or enforce any + // "pragueAtGenesis" genesis file (used in devnets) to have this value + return JsonUtil.getValueAsString(genesisRoot, "targetblobcount"); + } + /** * Gets coinbase. * diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseKey.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseKey.java index bf5d12804b..045b4ad02d 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseKey.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseKey.java @@ -38,5 +38,6 @@ public enum JsonRpcResponseKey { TRANSACTION_ROOT, BASEFEE, WITHDRAWALS_ROOT, - REQUESTS_HASH + REQUESTS_HASH, + TARGET_BLOB_COUNT } diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseUtils.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseUtils.java index d72db974b0..7e5e08aa7b 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseUtils.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseUtils.java @@ -63,6 +63,7 @@ import java.util.Optional; import com.fasterxml.jackson.databind.JsonNode; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.units.bigints.UInt256; +import org.apache.tuweni.units.bigints.UInt64; public class JsonRpcResponseUtils { @@ -106,6 +107,10 @@ public class JsonRpcResponseUtils { values.containsKey(WITHDRAWALS_ROOT) ? hash(values.get(WITHDRAWALS_ROOT)) : null; final Hash requestsHash = values.containsKey(REQUESTS_HASH) ? hash(values.get(REQUESTS_HASH)) : null; + final UInt64 targetBlobCount = + values.containsKey(JsonRpcResponseKey.TARGET_BLOB_COUNT) + ? UInt64.fromHexString(values.get(JsonRpcResponseKey.TARGET_BLOB_COUNT)) + : null; final List ommers = new ArrayList<>(); final BlockHeader header = @@ -131,6 +136,7 @@ public class JsonRpcResponseUtils { null, // ToDo 4844: set with the value of excess_blob_gas field null, // TODO 4788: set with the value of the parent beacon block root field requestsHash, + targetBlobCount, blockHeaderFunctions); return new JsonRpcSuccessResponse( diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java index 308940f16a..8562e140f5 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java @@ -279,6 +279,7 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet : BlobGas.fromHexString(blockParam.getExcessBlobGas()), maybeParentBeaconBlockRoot.orElse(null), maybeRequests.map(BodyValidation::requestsHash).orElse(null), + null, // TODO SLD EIP-7742 wiring in future PR headerFunctions); // ensure the block hash matches the blockParam hash diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResult.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResult.java index ed0b64d742..25e6763eda 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResult.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResult.java @@ -88,6 +88,7 @@ public class BlockResult implements JsonRpcResult { private final String blobGasUsed; private final String excessBlobGas; private final String parentBeaconBlockRoot; + private final String targetBlobCount; public BlockResult( final BlockHeader header, @@ -138,6 +139,7 @@ public class BlockResult implements JsonRpcResult { this.excessBlobGas = header.getExcessBlobGas().map(Quantity::create).orElse(null); this.parentBeaconBlockRoot = header.getParentBeaconBlockRoot().map(Bytes32::toHexString).orElse(null); + this.targetBlobCount = header.getTargetBlobCount().map(Quantity::create).orElse(null); } @JsonGetter(value = "number") @@ -275,4 +277,9 @@ public class BlockResult implements JsonRpcResult { public String getParentBeaconBlockRoot() { return parentBeaconBlockRoot; } + + @JsonGetter(value = "targetBlobCount") + public String getTargetBlobCount() { + return targetBlobCount; + } } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGasPriceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGasPriceTest.java index e428286444..8c7cba99c4 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGasPriceTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGasPriceTest.java @@ -372,6 +372,7 @@ public class EthGasPriceTest { null, null, null, + null, null), new BlockBody( IntStream.range(0, txsNum) diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGasTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGasTest.java index 886c8a1d03..d29a10a114 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGasTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGasTest.java @@ -207,6 +207,7 @@ public class EthMaxPriorityFeePerGasTest { null, null, null, + null, null), new BlockBody( IntStream.range(0, txsNum) diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineExchangeTransitionConfigurationTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineExchangeTransitionConfigurationTest.java index f1575f81ab..4c9dbef7d2 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineExchangeTransitionConfigurationTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineExchangeTransitionConfigurationTest.java @@ -254,6 +254,7 @@ public class EngineExchangeTransitionConfigurationTest { null, null, null, + null, new BlockHeaderFunctions() { @Override public Hash hash(final BlockHeader header) { diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueriesLogCacheTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueriesLogCacheTest.java index c0420163de..4b96317329 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueriesLogCacheTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueriesLogCacheTest.java @@ -120,6 +120,7 @@ public class BlockchainQueriesLogCacheTest { null, null, null, + null, new MainnetBlockHeaderFunctions()); testHash = fakeHeader.getHash(); final BlockBody fakeBody = new BlockBody(Collections.emptyList(), Collections.emptyList()); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/cache/TransactionLogBloomCacherTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/cache/TransactionLogBloomCacherTest.java index 5772a04a49..293c0b176e 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/cache/TransactionLogBloomCacherTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/cache/TransactionLogBloomCacherTest.java @@ -108,6 +108,7 @@ public class TransactionLogBloomCacherTest { null, null, null, + null, new MainnetBlockHeaderFunctions()); testHash = fakeHeader.getHash(); when(blockchain.getBlockHeader(anyLong())).thenReturn(Optional.of(fakeHeader)); @@ -283,6 +284,7 @@ public class TransactionLogBloomCacherTest { null, null, null, + null, new MainnetBlockHeaderFunctions()); testHash = fakeHeader.getHash(); when(blockchain.getBlockHeader(number)).thenReturn(Optional.of(fakeHeader)); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java index 2ee997f8cc..b27023776f 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java @@ -48,6 +48,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.units.bigints.UInt64; public final class GenesisState { @@ -218,6 +219,12 @@ public final class GenesisState { .parentBeaconBlockRoot( (isCancunAtGenesis(genesis) ? parseParentBeaconBlockRoot(genesis) : null)) .requestsHash(isPragueAtGenesis(genesis) ? Hash.EMPTY_REQUESTS_HASH : null) + .targetBlobCount( + isPragueAtGenesis(genesis) + // TODO SLD EIP-7742 Currently defaulting to null due to dependency on web3j + // BlockHeader in CodeDelegationTransactionAcceptanceTest + ? genesis.getTargetBlobCount().map(UInt64::fromHexString).orElse(null) + : null) .buildBlockHeader(); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java index 6bd1a2aa58..830a80ccce 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java @@ -28,6 +28,7 @@ import java.util.function.Supplier; import com.google.common.base.Suppliers; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.units.bigints.UInt64; /** A mined Ethereum block header. */ public class BlockHeader extends SealableBlockHeader @@ -65,6 +66,7 @@ public class BlockHeader extends SealableBlockHeader final BlobGas excessBlobGas, final Bytes32 parentBeaconBlockRoot, final Hash requestsHash, + final UInt64 targetBlobCount, final BlockHeaderFunctions blockHeaderFunctions) { super( parentHash, @@ -86,7 +88,8 @@ public class BlockHeader extends SealableBlockHeader blobGasUsed, excessBlobGas, parentBeaconBlockRoot, - requestsHash); + requestsHash, + targetBlobCount); this.nonce = nonce; this.hash = Suppliers.memoize(() -> blockHeaderFunctions.hash(this)); this.parsedExtraData = Suppliers.memoize(() -> blockHeaderFunctions.parseExtraData(this)); @@ -187,6 +190,9 @@ public class BlockHeader extends SealableBlockHeader if (requestsHash == null) break; out.writeBytes(requestsHash); + + if (targetBlobCount == null) break; + out.writeUInt64Scalar(targetBlobCount); } while (false); out.endList(); } @@ -219,6 +225,7 @@ public class BlockHeader extends SealableBlockHeader !input.isEndOfCurrentList() ? BlobGas.of(input.readUInt64Scalar()) : null; final Bytes32 parentBeaconBlockRoot = !input.isEndOfCurrentList() ? input.readBytes32() : null; final Hash requestsHash = !input.isEndOfCurrentList() ? Hash.wrap(input.readBytes32()) : null; + final UInt64 targetBlobCount = !input.isEndOfCurrentList() ? input.readUInt64Scalar() : null; input.leaveList(); return new BlockHeader( parentHash, @@ -242,6 +249,7 @@ public class BlockHeader extends SealableBlockHeader excessBlobGas, parentBeaconBlockRoot, requestsHash, + targetBlobCount, blockHeaderFunctions); } @@ -295,6 +303,9 @@ public class BlockHeader extends SealableBlockHeader if (requestsHash != null) { sb.append("requestsHash=").append(requestsHash); } + if (targetBlobCount != null) { + sb.append("targetBlobCount=").append(targetBlobCount); + } return sb.append("}").toString(); } @@ -329,6 +340,7 @@ public class BlockHeader extends SealableBlockHeader .getRequestsHash() .map(h -> Hash.fromHexString(h.toHexString())) .orElse(null), + pluginBlockHeader.getTargetBlobCount().orElse(null), blockHeaderFunctions); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeaderBuilder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeaderBuilder.java index a024d53cd2..b98f820112 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeaderBuilder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeaderBuilder.java @@ -30,6 +30,7 @@ import java.util.OptionalLong; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.units.bigints.UInt64; /** A utility class for building block headers. */ public class BlockHeaderBuilder { @@ -76,6 +77,7 @@ public class BlockHeaderBuilder { private Long blobGasUsed = null; private BlobGas excessBlobGas = null; private Bytes32 parentBeaconBlockRoot = null; + private UInt64 targetBlobCount = null; public static BlockHeaderBuilder create() { return new BlockHeaderBuilder(); @@ -124,7 +126,8 @@ public class BlockHeaderBuilder { .blobGasUsed(header.getBlobGasUsed().orElse(null)) .excessBlobGas(header.getExcessBlobGas().orElse(null)) .parentBeaconBlockRoot(header.getParentBeaconBlockRoot().orElse(null)) - .requestsHash(header.getRequestsHash().orElse(null)); + .requestsHash(header.getRequestsHash().orElse(null)) + .targetBlobCount(header.getTargetBlobCount().orElse(null)); } public static BlockHeaderBuilder fromBuilder(final BlockHeaderBuilder fromBuilder) { @@ -149,6 +152,7 @@ public class BlockHeaderBuilder { .excessBlobGas(fromBuilder.excessBlobGas) .parentBeaconBlockRoot(fromBuilder.parentBeaconBlockRoot) .requestsHash(fromBuilder.requestsHash) + .targetBlobCount(fromBuilder.targetBlobCount) .blockHeaderFunctions(fromBuilder.blockHeaderFunctions); toBuilder.nonce = fromBuilder.nonce; return toBuilder; @@ -179,6 +183,7 @@ public class BlockHeaderBuilder { excessBlobGas, parentBeaconBlockRoot, requestsHash, + targetBlobCount, blockHeaderFunctions); } @@ -194,7 +199,8 @@ public class BlockHeaderBuilder { timestamp, baseFee, mixHashOrPrevRandao, - parentBeaconBlockRoot); + parentBeaconBlockRoot, + targetBlobCount); } public SealableBlockHeader buildSealableBlockHeader() { @@ -220,7 +226,8 @@ public class BlockHeaderBuilder { blobGasUsed, excessBlobGas, parentBeaconBlockRoot, - requestsHash); + requestsHash, + targetBlobCount); } private void validateBlockHeader() { @@ -260,6 +267,7 @@ public class BlockHeaderBuilder { baseFee(processableBlockHeader.getBaseFee().orElse(null)); processableBlockHeader.getPrevRandao().ifPresent(this::prevRandao); processableBlockHeader.getParentBeaconBlockRoot().ifPresent(this::parentBeaconBlockRoot); + processableBlockHeader.getTargetBlobCount().ifPresent(this::targetBlobCount); return this; } @@ -285,6 +293,7 @@ public class BlockHeaderBuilder { sealableBlockHeader.getExcessBlobGas().ifPresent(this::excessBlobGas); sealableBlockHeader.getParentBeaconBlockRoot().ifPresent(this::parentBeaconBlockRoot); requestsHash(sealableBlockHeader.getRequestsHash().orElse(null)); + sealableBlockHeader.getTargetBlobCount().ifPresent(this::targetBlobCount); return this; } @@ -418,4 +427,9 @@ public class BlockHeaderBuilder { this.parentBeaconBlockRoot = parentBeaconBlockRoot; return this; } + + public BlockHeaderBuilder targetBlobCount(final UInt64 targetBlobCount) { + this.targetBlobCount = targetBlobCount; + return this; + } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/ProcessableBlockHeader.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/ProcessableBlockHeader.java index 036a33af97..7e037dff3a 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/ProcessableBlockHeader.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/ProcessableBlockHeader.java @@ -23,6 +23,7 @@ import java.util.Optional; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.units.bigints.UInt64; /** A block header capable of being processed. */ public class ProcessableBlockHeader @@ -46,6 +47,8 @@ public class ProcessableBlockHeader protected final Bytes32 mixHashOrPrevRandao; // parentBeaconBlockRoot is included for Cancun protected final Bytes32 parentBeaconBlockRoot; + // TODO SLD Quantity or UInt64Value instead? + protected final UInt64 targetBlobCount; protected ProcessableBlockHeader( final Hash parentHash, @@ -56,7 +59,8 @@ public class ProcessableBlockHeader final long timestamp, final Wei baseFee, final Bytes32 mixHashOrPrevRandao, - final Bytes32 parentBeaconBlockRoot) { + final Bytes32 parentBeaconBlockRoot, + final UInt64 targetBlobCount) { this.parentHash = parentHash; this.coinbase = coinbase; this.difficulty = difficulty; @@ -66,6 +70,7 @@ public class ProcessableBlockHeader this.baseFee = baseFee; this.mixHashOrPrevRandao = mixHashOrPrevRandao; this.parentBeaconBlockRoot = parentBeaconBlockRoot; + this.targetBlobCount = targetBlobCount; } /** @@ -178,6 +183,16 @@ public class ProcessableBlockHeader return Optional.ofNullable(parentBeaconBlockRoot); } + /** + * Returns the target blob count if available. + * + * @return the target blob count if available. + */ + @Override + public Optional getTargetBlobCount() { + return Optional.ofNullable(targetBlobCount); + } + public String toLogString() { return getNumber() + " (time: " + getTimestamp() + ")"; } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/SealableBlockHeader.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/SealableBlockHeader.java index 1934c8f8c0..962178e504 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/SealableBlockHeader.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/SealableBlockHeader.java @@ -24,6 +24,7 @@ import java.util.Optional; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.units.bigints.UInt64; /** A block header capable of being sealed. */ public class SealableBlockHeader extends ProcessableBlockHeader { @@ -69,7 +70,8 @@ public class SealableBlockHeader extends ProcessableBlockHeader { final Long blobGasUsed, final BlobGas excessBlobGas, final Bytes32 parentBeaconBlockRoot, - final Hash requestsHash) { + final Hash requestsHash, + final UInt64 targetBlobCount) { super( parentHash, coinbase, @@ -79,7 +81,8 @@ public class SealableBlockHeader extends ProcessableBlockHeader { timestamp, baseFee, mixHashOrPrevRandao, - parentBeaconBlockRoot); + parentBeaconBlockRoot, + targetBlobCount); this.ommersHash = ommersHash; this.stateRoot = stateRoot; this.transactionsRoot = transactionsRoot; diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockHeaderTestFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockHeaderTestFixture.java index 99cf2407b8..b0b9aa6497 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockHeaderTestFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockHeaderTestFixture.java @@ -25,6 +25,7 @@ import java.util.Optional; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.units.bigints.UInt64; public class BlockHeaderTestFixture { @@ -55,6 +56,7 @@ public class BlockHeaderTestFixture { private Optional excessBlobGas = Optional.empty(); private Optional blobGasUsed = Optional.empty(); private Optional parentBeaconBlockRoot = Optional.empty(); + private Optional targetBlobCount = Optional.empty(); public BlockHeader buildHeader() { final BlockHeaderBuilder builder = BlockHeaderBuilder.create(); @@ -80,6 +82,7 @@ public class BlockHeaderTestFixture { blobGasUsed.ifPresent(builder::blobGasUsed); requestsHash.ifPresent(builder::requestsHash); parentBeaconBlockRoot.ifPresent(builder::parentBeaconBlockRoot); + targetBlobCount.ifPresent(builder::targetBlobCount); builder.blockHeaderFunctions(blockHeaderFunctions); return builder.buildBlockHeader(); @@ -201,4 +204,9 @@ public class BlockHeaderTestFixture { this.parentBeaconBlockRoot = parentBeaconBlockRoot; return this; } + + public BlockHeaderTestFixture targetBlobCount(final UInt64 targetBlobCount) { + this.targetBlobCount = Optional.of(targetBlobCount); + return this; + } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/GenesisStateTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/GenesisStateTest.java index ba03634708..83c0f1a4c4 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/GenesisStateTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/GenesisStateTest.java @@ -31,6 +31,7 @@ import java.util.stream.Stream; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.units.bigints.UInt256; +import org.apache.tuweni.units.bigints.UInt64; import org.bouncycastle.util.encoders.Hex; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; @@ -287,10 +288,6 @@ final class GenesisStateTest { GenesisStateTest.class.getResource("genesis_prague.json"), ProtocolScheduleFixture.MAINNET); final BlockHeader header = genesisState.getBlock().getHeader(); - assertThat(header.getHash()) - .isEqualTo( - Hash.fromHexString( - "0x554807b22674e6d335f734485993857bbad7a9543affb0663a10c14d78135ec7")); assertThat(header.getGasLimit()).isEqualTo(0x2fefd8); assertThat(header.getGasUsed()).isZero(); assertThat(header.getNumber()).isZero(); @@ -331,6 +328,13 @@ final class GenesisStateTest { .isEqualTo( Hash.fromHexString( "0x6036c41849da9c076ed79654d434017387a88fb833c2856b32e18218b3341c5f")); + assertThat(header.getTargetBlobCount().isPresent()).isTrue(); + assertThat(header.getTargetBlobCount().get()).isEqualTo(UInt64.ONE); + + assertThat(header.getHash()) + .isEqualTo( + Hash.fromHexString( + "0xdbc64edecb3a432e48cbd270b4a248ffc611b5f3dd666c8a10d546672cae17bd")); } @Test diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/LogRollingTests.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/LogRollingTests.java index e43d464474..6a70cb20e2 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/LogRollingTests.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/LogRollingTests.java @@ -99,6 +99,7 @@ class LogRollingTests { null, null, null, + null, new MainnetBlockHeaderFunctions()); private static final BlockHeader headerTwo = new BlockHeader( @@ -123,6 +124,7 @@ class LogRollingTests { null, null, null, + null, new MainnetBlockHeaderFunctions()); @BeforeEach diff --git a/ethereum/core/src/test/resources/org/hyperledger/besu/ethereum/chain/genesis_prague.json b/ethereum/core/src/test/resources/org/hyperledger/besu/ethereum/chain/genesis_prague.json index d99071b328..f9aa3ff466 100644 --- a/ethereum/core/src/test/resources/org/hyperledger/besu/ethereum/chain/genesis_prague.json +++ b/ethereum/core/src/test/resources/org/hyperledger/besu/ethereum/chain/genesis_prague.json @@ -4073,5 +4073,6 @@ "number": "0x0", "gasUsed": "0x0", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": "0x3b9aca00" + "baseFeePerGas": "0x3b9aca00", + "targetBlobCount": "0x1" } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/MessageWrapperTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/MessageWrapperTest.java index 2b020cd4ac..0256b09653 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/MessageWrapperTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/MessageWrapperTest.java @@ -398,6 +398,7 @@ public class MessageWrapperTest { null, null, null, + null, new MainnetBlockHeaderFunctions()); } } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/ChainForTestCreator.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/ChainForTestCreator.java index c15f3aa1dc..e6fab81102 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/ChainForTestCreator.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/ChainForTestCreator.java @@ -61,6 +61,7 @@ public class ChainForTestCreator { null, null, null, + null, new MainnetBlockHeaderFunctions()); } @@ -89,6 +90,7 @@ public class ChainForTestCreator { blockHeader.getExcessBlobGas().orElse(null), blockHeader.getParentBeaconBlockRoot().orElse(null), blockHeader.getRequestsHash().orElse(null), + blockHeader.getTargetBlobCount().orElse(null), new MainnetBlockHeaderFunctions()); } @@ -139,6 +141,7 @@ public class ChainForTestCreator { null, null, null, + null, new MainnetBlockHeaderFunctions()); } } diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java index bc60c7ddd0..7ab0091090 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java @@ -195,6 +195,7 @@ public class BlockchainReferenceTestCaseSpec { excessBlobGas != null ? BlobGas.fromHexString(excessBlobGas) : null, parentBeaconBlockRoot != null ? Bytes32.fromHexString(parentBeaconBlockRoot) : null, requestsHash != null ? Hash.fromHexString(requestsHash) : null, + null, // TODO SLD EIP-7742 use targetBlobCount when reference tests are updated new BlockHeaderFunctions() { @Override public Hash hash(final BlockHeader header) { diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java index 26c124472b..25c0cd2484 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java @@ -146,6 +146,7 @@ public class ReferenceTestEnv extends BlockHeader { currentExcessBlobGas == null ? null : BlobGas.of(Long.decode(currentExcessBlobGas)), beaconRoot == null ? null : Bytes32.fromHexString(beaconRoot), null, // requestsHash + null, // TODO SLD EIP-7742 use targetBlobCount when reference tests are updated new MainnetBlockHeaderFunctions()); this.parentDifficulty = parentDifficulty; this.parentBaseFee = parentBaseFee; diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index 0dbca077ab..3632bb5ae1 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -71,7 +71,7 @@ Calculated : ${currentHash} tasks.register('checkAPIChanges', FileStateChecker) { description = "Checks that the API for the Plugin-API project does not change without deliberate thought" files = sourceSets.main.allJava.files - knownHash = 'G3cpM0HGYp4G1u6dN2CRZiEEsgce6jy9rkIlT1blUb4=' + knownHash = 'uNQzVjMa7m1fw3d10NuVOjmzGxmCkgZd88yGFgP3qoY=' } check.dependsOn('checkAPIChanges') diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/ProcessableBlockHeader.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/ProcessableBlockHeader.java index db9bfa942e..c7a1c5b99e 100644 --- a/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/ProcessableBlockHeader.java +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/ProcessableBlockHeader.java @@ -22,6 +22,7 @@ import org.hyperledger.besu.plugin.Unstable; import java.util.Optional; import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.units.bigints.UInt64; /** * The minimum set of data for a BlockHeader, as defined in the getParentBeaconBlockRoot(); + + /** + * The target_blob_count of this header. + * + * @return The target blob count of this header. + */ + @Unstable + // TODO SLD should be Quantity or new subclass of Quantity? + default Optional getTargetBlobCount() { + return Optional.empty(); + } }