From 938058f0890dbde7f01800e2ce651e567f6e6f0c Mon Sep 17 00:00:00 2001 From: Sally MacFarlane Date: Wed, 18 Feb 2026 16:06:45 +1000 Subject: [PATCH] implement testing_buildBlockV1 Signed-off-by: Sally MacFarlane --- .../besu/ethereum/api/jsonrpc/RpcApis.java | 3 +- .../besu/ethereum/api/jsonrpc/RpcMethod.java | 3 +- .../methods/testing/TestingBuildBlockV1.java | 184 ++++++++++++++++++ .../TestingBuildBlockParameter.java | 59 ++++++ .../methods/JsonRpcMethodsFactory.java | 8 +- .../methods/TestingJsonRpcMethods.java | 60 ++++++ .../testing/TestingBuildBlockV1Test.java | 123 ++++++++++++ .../blockcreation/GenericBlockCreator.java | 60 ++++++ 8 files changed, 497 insertions(+), 3 deletions(-) create mode 100644 ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/testing/TestingBuildBlockV1.java create mode 100644 ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/TestingBuildBlockParameter.java create mode 100644 ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TestingJsonRpcMethods.java create mode 100644 ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/testing/TestingBuildBlockV1Test.java create mode 100644 ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/GenericBlockCreator.java diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcApis.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcApis.java index 3bef2f85ec8..a90134dac22 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcApis.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcApis.java @@ -33,7 +33,8 @@ public enum RpcApis { CLIQUE, IBFT, ENGINE, - QBFT; + QBFT, + TESTING; public static final List DEFAULT_RPC_APIS = Arrays.asList("ETH", "NET", "WEB3"); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java index fc40011d366..f813e59ac31 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java @@ -176,7 +176,8 @@ public enum RpcMethod { TX_POOL_BESU_PENDING_TRANSACTIONS("txpool_besuPendingTransactions"), WEB3_CLIENT_VERSION("web3_clientVersion"), WEB3_SHA3("web3_sha3"), - PLUGINS_RELOAD_CONFIG("plugins_reloadPluginConfig"); + PLUGINS_RELOAD_CONFIG("plugins_reloadPluginConfig"), + TESTING_BUILD_BLOCK_V1("testing_buildBlockV1"); private final String methodName; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/testing/TestingBuildBlockV1.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/testing/TestingBuildBlockV1.java new file mode 100644 index 00000000000..ee0aac63ca6 --- /dev/null +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/testing/TestingBuildBlockV1.java @@ -0,0 +1,184 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.testing; + +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.ProtocolContext; +import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePayloadAttributesParameter; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.TestingBuildBlockParameter; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalParameter; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BlobsBundleV1; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.EngineGetPayloadResultV4; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.Quantity; +import org.hyperledger.besu.ethereum.blockcreation.BlockCreator.BlockCreationResult; +import org.hyperledger.besu.ethereum.blockcreation.GenericBlockCreator; +import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.BlockValueCalculator; +import org.hyperledger.besu.ethereum.core.BlockWithReceipts; +import org.hyperledger.besu.ethereum.core.MiningConfiguration; +import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.ethereum.core.Withdrawal; +import org.hyperledger.besu.ethereum.core.encoding.EncodingContext; +import org.hyperledger.besu.ethereum.core.encoding.TransactionDecoder; +import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder; +import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; +import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.util.HexUtils; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.apache.tuweni.bytes.Bytes; + +public class TestingBuildBlockV1 implements JsonRpcMethod { + + private final ProtocolContext protocolContext; + private final ProtocolSchedule protocolSchedule; + private final MiningConfiguration miningConfiguration; + private final TransactionPool transactionPool; + private final EthScheduler ethScheduler; + + public TestingBuildBlockV1( + final ProtocolContext protocolContext, + final ProtocolSchedule protocolSchedule, + final MiningConfiguration miningConfiguration, + final TransactionPool transactionPool, + final EthScheduler ethScheduler) { + this.protocolContext = protocolContext; + this.protocolSchedule = protocolSchedule; + this.miningConfiguration = miningConfiguration; + this.transactionPool = transactionPool; + this.ethScheduler = ethScheduler; + } + + @Override + public String getName() { + return RpcMethod.TESTING_BUILD_BLOCK_V1.getMethodName(); + } + + @Override + public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { + final TestingBuildBlockParameter param; + try { + param = requestContext.getRequiredParameter(0, TestingBuildBlockParameter.class); + } catch (final JsonRpcParameterException e) { + throw new InvalidJsonRpcParameters( + "Invalid testing_buildBlockV1 parameter (index 0)", RpcErrorType.INVALID_PARAMS, e); + } + + final EnginePayloadAttributesParameter payloadAttributes = param.getPayloadAttributes(); + + // Validate parent block exists + final Optional maybeParentHeader = + protocolContext.getBlockchain().getBlockHeader(param.getParentBlockHash()); + if (maybeParentHeader.isEmpty()) { + return new JsonRpcErrorResponse( + requestContext.getRequest().getId(), RpcErrorType.INVALID_BLOCK_HASH_PARAMS); + } + final BlockHeader parentHeader = maybeParentHeader.get(); + + // Decode transactions from hex RLP + final List transactions; + try { + transactions = + param.getTransactions().stream() + .map(Bytes::fromHexString) + .map(bytes -> TransactionDecoder.decodeOpaqueBytes(bytes, EncodingContext.BLOCK_BODY)) + .collect(Collectors.toList()); + } catch (final Exception e) { + return new JsonRpcErrorResponse( + requestContext.getRequest().getId(), RpcErrorType.INVALID_PARAMS); + } + + // Convert withdrawals + final Optional> withdrawals = + Optional.ofNullable(payloadAttributes.getWithdrawals()) + .map( + wps -> + wps.stream() + .map(WithdrawalParameter::toWithdrawal) + .collect(Collectors.toList())); + + // Extra data + final Bytes extraData = param.getExtraData().map(Bytes::fromHexString).orElse(Bytes.EMPTY); + + // Create block creator + final GenericBlockCreator blockCreator = + new GenericBlockCreator( + miningConfiguration, + (__, ___) -> payloadAttributes.getSuggestedFeeRecipient(), + (__) -> extraData, + transactionPool, + protocolContext, + protocolSchedule, + ethScheduler); + + // Build the block + final BlockCreationResult result; + try { + result = + blockCreator.createBlock( + Optional.of(transactions), + Optional.of(Collections.emptyList()), + withdrawals, + Optional.of(payloadAttributes.getPrevRandao()), + Optional.ofNullable(payloadAttributes.getParentBeaconBlockRoot()), + Optional.empty(), + payloadAttributes.getTimestamp(), + false, + parentHeader); + } catch (final Exception e) { + return new JsonRpcErrorResponse( + requestContext.getRequest().getId(), RpcErrorType.INTERNAL_ERROR); + } + + // Format response as EngineGetPayloadResultV4 + final var block = result.getBlock(); + final List txsAsHex = + block.getBody().getTransactions().stream() + .map(tx -> TransactionEncoder.encodeOpaqueBytes(tx, EncodingContext.BLOCK_BODY)) + .map(b -> HexUtils.toFastHex(b, true)) + .collect(Collectors.toList()); + + final BlockWithReceipts blockWithReceipts = + new BlockWithReceipts(block, result.getTransactionSelectionResults().getReceipts()); + final Wei blockValue = BlockValueCalculator.calculateBlockValue(blockWithReceipts); + + final BlobsBundleV1 blobsBundle = new BlobsBundleV1(block.getBody().getTransactions()); + + final EngineGetPayloadResultV4 response = + new EngineGetPayloadResultV4( + block.getHeader(), + txsAsHex, + block.getBody().getWithdrawals(), + Optional.empty(), + Quantity.create(blockValue), + blobsBundle); + + return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), response); + } +} diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/TestingBuildBlockParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/TestingBuildBlockParameter.java new file mode 100644 index 00000000000..e4c2e674d5d --- /dev/null +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/TestingBuildBlockParameter.java @@ -0,0 +1,59 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters; + +import org.hyperledger.besu.datatypes.Hash; + +import java.util.List; +import java.util.Optional; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class TestingBuildBlockParameter { + + private final Hash parentBlockHash; + private final EnginePayloadAttributesParameter payloadAttributes; + private final List transactions; + private final String extraData; + + @JsonCreator + public TestingBuildBlockParameter( + @JsonProperty("parentBlockHash") final String parentBlockHash, + @JsonProperty("payloadAttributes") final EnginePayloadAttributesParameter payloadAttributes, + @JsonProperty("transactions") final List transactions, + @JsonProperty("extraData") final String extraData) { + this.parentBlockHash = Hash.fromHexString(parentBlockHash); + this.payloadAttributes = payloadAttributes; + this.transactions = transactions; + this.extraData = extraData; + } + + public Hash getParentBlockHash() { + return parentBlockHash; + } + + public EnginePayloadAttributesParameter getPayloadAttributes() { + return payloadAttributes; + } + + public List getTransactions() { + return transactions; + } + + public Optional getExtraData() { + return Optional.ofNullable(extraData); + } +} diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java index 404d3646780..59040634602 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java @@ -160,7 +160,13 @@ public Map methods( metricsSystem, ethScheduler), new TxPoolJsonRpcMethods(transactionPool), - new PluginsJsonRpcMethods(namedPlugins)); + new PluginsJsonRpcMethods(namedPlugins), + new TestingJsonRpcMethods( + protocolContext, + protocolSchedule, + miningConfiguration, + transactionPool, + ethScheduler)); for (final JsonRpcMethods apiGroup : availableApiGroups) { enabled.putAll(apiGroup.create(rpcApis)); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TestingJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TestingJsonRpcMethods.java new file mode 100644 index 00000000000..d3bc9c7d69e --- /dev/null +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TestingJsonRpcMethods.java @@ -0,0 +1,60 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.api.jsonrpc.methods; + +import org.hyperledger.besu.ethereum.ProtocolContext; +import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.testing.TestingBuildBlockV1; +import org.hyperledger.besu.ethereum.core.MiningConfiguration; +import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; +import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; + +import java.util.Map; + +public class TestingJsonRpcMethods extends ApiGroupJsonRpcMethods { + + private final ProtocolContext protocolContext; + private final ProtocolSchedule protocolSchedule; + private final MiningConfiguration miningConfiguration; + private final TransactionPool transactionPool; + private final EthScheduler ethScheduler; + + public TestingJsonRpcMethods( + final ProtocolContext protocolContext, + final ProtocolSchedule protocolSchedule, + final MiningConfiguration miningConfiguration, + final TransactionPool transactionPool, + final EthScheduler ethScheduler) { + this.protocolContext = protocolContext; + this.protocolSchedule = protocolSchedule; + this.miningConfiguration = miningConfiguration; + this.transactionPool = transactionPool; + this.ethScheduler = ethScheduler; + } + + @Override + protected String getApiGroup() { + return RpcApis.TESTING.name(); + } + + @Override + protected Map create() { + return mapOf( + new TestingBuildBlockV1( + protocolContext, protocolSchedule, miningConfiguration, transactionPool, ethScheduler)); + } +} diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/testing/TestingBuildBlockV1Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/testing/TestingBuildBlockV1Test.java new file mode 100644 index 00000000000..51eb73866de --- /dev/null +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/testing/TestingBuildBlockV1Test.java @@ -0,0 +1,123 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.testing; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.ethereum.ProtocolContext; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; +import org.hyperledger.besu.ethereum.chain.MutableBlockchain; +import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; +import org.hyperledger.besu.ethereum.core.MiningConfiguration; +import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; +import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; + +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +class TestingBuildBlockV1Test { + + @Mock private ProtocolContext protocolContext; + @Mock private ProtocolSchedule protocolSchedule; + @Mock private MiningConfiguration miningConfiguration; + @Mock private TransactionPool transactionPool; + @Mock private EthScheduler ethScheduler; + @Mock private MutableBlockchain blockchain; + + private TestingBuildBlockV1 method; + + @BeforeEach + void setUp() { + when(protocolContext.getBlockchain()).thenReturn(blockchain); + method = + new TestingBuildBlockV1( + protocolContext, protocolSchedule, miningConfiguration, transactionPool, ethScheduler); + } + + @Test + void shouldReturnCorrectMethodName() { + assertThat(method.getName()).isEqualTo("testing_buildBlockV1"); + } + + @Test + void shouldReturnErrorWhenParentBlockNotFound() { + when(blockchain.getBlockHeader(any(Hash.class))).thenReturn(Optional.empty()); + + final JsonRpcResponse response = + method.response(requestWithParentHash(Hash.ZERO.toHexString())); + + assertThat(response).isInstanceOf(JsonRpcErrorResponse.class); + final JsonRpcErrorResponse errorResponse = (JsonRpcErrorResponse) response; + assertThat(errorResponse.getError().getCode()) + .isEqualTo(RpcErrorType.INVALID_BLOCK_HASH_PARAMS.getCode()); + } + + @Test + void shouldReturnErrorForInvalidTransactionRlp() { + final BlockHeader parentHeader = new BlockHeaderTestFixture().buildHeader(); + when(blockchain.getBlockHeader(any(Hash.class))).thenReturn(Optional.of(parentHeader)); + + final JsonRpcResponse response = + method.response( + requestWithTransactions(parentHeader.getHash().toHexString(), List.of("0xINVALIDRLP"))); + + assertThat(response).isInstanceOf(JsonRpcErrorResponse.class); + final JsonRpcErrorResponse errorResponse = (JsonRpcErrorResponse) response; + assertThat(errorResponse.getError().getCode()).isEqualTo(RpcErrorType.INVALID_PARAMS.getCode()); + } + + private JsonRpcRequestContext requestWithParentHash(final String parentHash) { + return requestWithTransactions(parentHash, Collections.emptyList()); + } + + private JsonRpcRequestContext requestWithTransactions( + final String parentHash, final List transactions) { + final Map payloadAttributes = new LinkedHashMap<>(); + payloadAttributes.put("timestamp", "0x1"); + payloadAttributes.put("prevRandao", Hash.ZERO.toHexString()); + payloadAttributes.put("suggestedFeeRecipient", "0x0000000000000000000000000000000000000000"); + payloadAttributes.put("withdrawals", Collections.emptyList()); + + final Map param = new LinkedHashMap<>(); + param.put("parentBlockHash", parentHash); + param.put("payloadAttributes", payloadAttributes); + param.put("transactions", transactions); + + return new JsonRpcRequestContext( + new JsonRpcRequest("2.0", "testing_buildBlockV1", new Object[] {param})); + } +} diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/GenericBlockCreator.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/GenericBlockCreator.java new file mode 100644 index 00000000000..27758263446 --- /dev/null +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/GenericBlockCreator.java @@ -0,0 +1,60 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.blockcreation; + +import org.hyperledger.besu.ethereum.ProtocolContext; +import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; +import org.hyperledger.besu.ethereum.core.Difficulty; +import org.hyperledger.besu.ethereum.core.MiningConfiguration; +import org.hyperledger.besu.ethereum.core.SealableBlockHeader; +import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; +import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; + +/** + * A consensus-agnostic block creator that produces blocks with zero difficulty and zero nonce. + * Suitable for testing and block building outside of any specific consensus mechanism. + */ +public class GenericBlockCreator extends AbstractBlockCreator { + + public GenericBlockCreator( + final MiningConfiguration miningConfiguration, + final MiningBeneficiaryCalculator miningBeneficiaryCalculator, + final ExtraDataCalculator extraDataCalculator, + final TransactionPool transactionPool, + final ProtocolContext protocolContext, + final ProtocolSchedule protocolSchedule, + final EthScheduler ethScheduler) { + super( + miningConfiguration, + miningBeneficiaryCalculator, + extraDataCalculator, + transactionPool, + protocolContext, + protocolSchedule, + ethScheduler); + } + + @Override + protected BlockHeader createFinalBlockHeader(final SealableBlockHeader sealableBlockHeader) { + return BlockHeaderBuilder.create() + .difficulty(Difficulty.ZERO) + .populateFrom(sealableBlockHeader) + .nonce(0L) + .blockHeaderFunctions(blockHeaderFunctions) + .buildBlockHeader(); + } +}