diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ethereum/CodeDelegationTransactionAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ethereum/CodeDelegationTransactionAcceptanceTest.java index ee896ccd278..9e469518261 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ethereum/CodeDelegationTransactionAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ethereum/CodeDelegationTransactionAcceptanceTest.java @@ -58,7 +58,7 @@ public class CodeDelegationTransactionAcceptanceTest extends AcceptanceTestBase public static final Bytes TRANSACTION_SPONSOR_PRIVATE_KEY = Bytes.fromHexString("3a4ff6d22d7502ef2452368165422861c01a0f72f851793b372b87888dc3c453"); - private final Account otherAccount = accounts.createAccount("otherAccount"); + private final Account otherAccount = accounts.getPrimaryBenefactor(); private BesuNode besuNode; private PragueAcceptanceTestHelper testHelper; @@ -85,7 +85,6 @@ void tearDown() { */ @Test public void shouldTransferAllEthOfAuthorizerToSponsor() throws IOException { - // 7702 transaction final CodeDelegation authorization = org.hyperledger.besu.ethereum.core.CodeDelegation.builder() diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ethereum/PragueAcceptanceTestHelper.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ethereum/PragueAcceptanceTestHelper.java index 754e28165c8..183eb45c88d 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ethereum/PragueAcceptanceTestHelper.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ethereum/PragueAcceptanceTestHelper.java @@ -20,6 +20,7 @@ import org.hyperledger.besu.tests.acceptance.dsl.transaction.eth.EthTransactions; import java.io.IOException; +import java.io.InputStream; import java.util.Optional; import com.fasterxml.jackson.databind.JsonNode; @@ -92,11 +93,21 @@ public void buildNewBlock() throws IOException { assertThat(newBlockHash).isNotEmpty(); } + final String targetBlobsPerBlock = "0x3"; final Call newPayloadRequest = createEngineCall( createNewPayloadRequest( - executionPayload.toString(), parentBeaconBlockRoot, executionRequests.toString())); + executionPayload.toString(), + parentBeaconBlockRoot, + executionRequests.toString(), + targetBlobsPerBlock)); try (final Response newPayloadResponse = newPayloadRequest.execute()) { + final InputStream responseStr = newPayloadResponse.body().byteStream(); + JsonNode jsonNode = mapper.readTree(responseStr); + if (jsonNode.has("error")) { + throw new AssertionError( + "Unexpected engine_newPayload error: " + jsonNode.get("error").get("message").asText()); + } assertThat(newPayloadResponse.code()).isEqualTo(200); } @@ -148,7 +159,9 @@ private String createForkChoiceRequest(final String parentBlockHash, final Long + " \"prevRandao\": \"0x0000000000000000000000000000000000000000000000000000000000000000\"," + " \"suggestedFeeRecipient\": \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\"," + " \"withdrawals\": []," - + " \"parentBeaconBlockRoot\": \"0x0000000000000000000000000000000000000000000000000000000000000000\"" + + " \"parentBeaconBlockRoot\": \"0x0000000000000000000000000000000000000000000000000000000000000000\"," + + " \"targetBlobsPerBlock\": \"0x3\"," + + " \"maxBlobsPerBlock\": \"0x6\"" + " }"; } @@ -171,7 +184,8 @@ private String createGetPayloadRequest(final String payloadId) { private String createNewPayloadRequest( final String executionPayload, final String parentBeaconBlockRoot, - final String executionRequests) { + final String executionRequests, + final String targetBlobsPerBlock) { return "{" + " \"jsonrpc\": \"2.0\"," + " \"method\": \"engine_newPayloadV4\"," @@ -183,7 +197,11 @@ private String createNewPayloadRequest( + "\"" + "," + executionRequests - + "]," + + "," + + "\"" + + targetBlobsPerBlock + + "\"" + + "]," // end params + " \"id\": 67" + "}"; } diff --git a/acceptance-tests/tests/src/test/resources/dev/dev_prague.json b/acceptance-tests/tests/src/test/resources/dev/dev_prague.json index 942edc4e70a..cff3c405e5e 100644 --- a/acceptance-tests/tests/src/test/resources/dev/dev_prague.json +++ b/acceptance-tests/tests/src/test/resources/dev/dev_prague.json @@ -110,5 +110,6 @@ "number":"0x0", "gasUsed":"0x0", "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas":"0x7" + "baseFeePerGas":"0x7", + "targetBlobsPerBlock":"0x1" } \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/cancun/test-cases/block-production/10_cancun_build_on_genesis.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/cancun/test-cases/block-production/10_cancun_build_on_genesis.json index 5dea701a33f..e269c045ec6 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/cancun/test-cases/block-production/10_cancun_build_on_genesis.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/cancun/test-cases/block-production/10_cancun_build_on_genesis.json @@ -1,5 +1,95 @@ { - "request" : {"jsonrpc":"2.0","id":5,"method":"engine_forkchoiceUpdatedV3","params":[{"headBlockHash":"0x33235e7b7a78302cdb54e5ddba66c7ae49b01c1f5498bb00cd0c8ed5206784bf","safeBlockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","finalizedBlockHash":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"timestamp":"0x1236","prevRandao":"0xc13da06dc53836ca0766057413b9683eb9a8773bbb8fcc5691e41c25b56dda1d","suggestedFeeRecipient":"0x0000000000000000000000000000000000000000","withdrawals":[{"index":"0xb","validatorIndex":"0x0","address":"0x0000000000000000000000000000000000000000","amount":"0x64"},{"index":"0xc","validatorIndex":"0x1","address":"0x0100000000000000000000000000000000000000","amount":"0x64"},{"index":"0xd","validatorIndex":"0x2","address":"0x0200000000000000000000000000000000000000","amount":"0x64"},{"index":"0xe","validatorIndex":"0x3","address":"0x0300000000000000000000000000000000000000","amount":"0x64"},{"index":"0xf","validatorIndex":"0x4","address":"0x0400000000000000000000000000000000000000","amount":"0x64"},{"index":"0x10","validatorIndex":"0x5","address":"0x0500000000000000000000000000000000000000","amount":"0x64"},{"index":"0x11","validatorIndex":"0x6","address":"0x0600000000000000000000000000000000000000","amount":"0x64"},{"index":"0x12","validatorIndex":"0x7","address":"0x0700000000000000000000000000000000000000","amount":"0x64"},{"index":"0x13","validatorIndex":"0x8","address":"0x0800000000000000000000000000000000000000","amount":"0x64"},{"index":"0x14","validatorIndex":"0x9","address":"0x0900000000000000000000000000000000000000","amount":"0x64"}],"parentBeaconBlockRoot":"0x062367f0b23e2d49ad5e770d9ad17b83c0c1c625c3f9a290cd9572b3fc6cfc9e"}]}, - "response" : {"jsonrpc":"2.0","id":5,"result":{"payloadStatus":{"status":"VALID","latestValidHash":"0x33235e7b7a78302cdb54e5ddba66c7ae49b01c1f5498bb00cd0c8ed5206784bf","validationError":null},"payloadId":"0x29e12df730769ab6"}}, - "statusCode" : 200 + "request": { + "jsonrpc": "2.0", + "id": 5, + "method": "engine_forkchoiceUpdatedV3", + "params": [ + { + "headBlockHash": "0x33235e7b7a78302cdb54e5ddba66c7ae49b01c1f5498bb00cd0c8ed5206784bf", + "safeBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "timestamp": "0x1236", + "prevRandao": "0xc13da06dc53836ca0766057413b9683eb9a8773bbb8fcc5691e41c25b56dda1d", + "suggestedFeeRecipient": "0x0000000000000000000000000000000000000000", + "withdrawals": [ + { + "index": "0xb", + "validatorIndex": "0x0", + "address": "0x0000000000000000000000000000000000000000", + "amount": "0x64" + }, + { + "index": "0xc", + "validatorIndex": "0x1", + "address": "0x0100000000000000000000000000000000000000", + "amount": "0x64" + }, + { + "index": "0xd", + "validatorIndex": "0x2", + "address": "0x0200000000000000000000000000000000000000", + "amount": "0x64" + }, + { + "index": "0xe", + "validatorIndex": "0x3", + "address": "0x0300000000000000000000000000000000000000", + "amount": "0x64" + }, + { + "index": "0xf", + "validatorIndex": "0x4", + "address": "0x0400000000000000000000000000000000000000", + "amount": "0x64" + }, + { + "index": "0x10", + "validatorIndex": "0x5", + "address": "0x0500000000000000000000000000000000000000", + "amount": "0x64" + }, + { + "index": "0x11", + "validatorIndex": "0x6", + "address": "0x0600000000000000000000000000000000000000", + "amount": "0x64" + }, + { + "index": "0x12", + "validatorIndex": "0x7", + "address": "0x0700000000000000000000000000000000000000", + "amount": "0x64" + }, + { + "index": "0x13", + "validatorIndex": "0x8", + "address": "0x0800000000000000000000000000000000000000", + "amount": "0x64" + }, + { + "index": "0x14", + "validatorIndex": "0x9", + "address": "0x0900000000000000000000000000000000000000", + "amount": "0x64" + } + ], + "parentBeaconBlockRoot": "0x062367f0b23e2d49ad5e770d9ad17b83c0c1c625c3f9a290cd9572b3fc6cfc9e" + } + ] + }, + "response": { + "jsonrpc": "2.0", + "id": 5, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0x33235e7b7a78302cdb54e5ddba66c7ae49b01c1f5498bb00cd0c8ed5206784bf", + "validationError": null + }, + "payloadId": "0x744ab0889222f836" + } + }, + "statusCode": 200 } \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/cancun/test-cases/block-production/12_cancun_get_built_block.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/cancun/test-cases/block-production/12_cancun_get_built_block.json index 8cbdd626427..bbc4860f1d3 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/cancun/test-cases/block-production/12_cancun_get_built_block.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/cancun/test-cases/block-production/12_cancun_get_built_block.json @@ -1,5 +1,5 @@ { - "request" : {"jsonrpc":"2.0","id":2,"method":"engine_getPayloadV3","params":["0x29e12df730769ab6"]}, + "request" : {"jsonrpc":"2.0","id":2,"method":"engine_getPayloadV3","params":["0x744ab0889222f836"]}, "response" : { "jsonrpc" : "2.0", "id" : 2, diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/06_shanghai_prepare_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/06_shanghai_prepare_payload.json index 456a9a74264..b171983efd3 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/06_shanghai_prepare_payload.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/06_shanghai_prepare_payload.json @@ -39,7 +39,7 @@ "latestValidHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", "validationError": null }, - "payloadId": "0x0065bd2db6663f59" + "payloadId": "0x48b9f464feba7610" } }, "statusCode" : 200 diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/07_shanghai_prepare_payload_replay_different_withdrawals.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/07_shanghai_prepare_payload_replay_different_withdrawals.json index dcb022e1a62..3bbf1edcd9e 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/07_shanghai_prepare_payload_replay_different_withdrawals.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/07_shanghai_prepare_payload_replay_different_withdrawals.json @@ -39,7 +39,7 @@ "latestValidHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", "validationError": null }, - "payloadId": "0x0065bd2db6663ed9" + "payloadId": "0x48b9f5e4feba7610" } }, "statusCode" : 200 diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/08_shanghai_getPayloadV2.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/08_shanghai_getPayloadV2.json index 072e5146d0a..2d1d7f741d2 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/08_shanghai_getPayloadV2.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/08_shanghai_getPayloadV2.json @@ -3,7 +3,7 @@ "jsonrpc": "2.0", "method": "engine_getPayloadV2", "params": [ - "0x0065bd2db6663ed9" + "0x48b9f5e4feba7610" ], "id": 67 }, diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java index 56c78877a67..6540abbb6e6 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java @@ -32,6 +32,7 @@ import java.util.Optional; import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.units.bigints.UInt64; /** The Merge block creator. */ class MergeBlockCreator extends AbstractBlockCreator { @@ -80,6 +81,7 @@ public BlockCreationResult createBlock( final long timestamp, final Optional> withdrawals, final Optional parentBeaconBlockRoot, + final Optional targetBlobsPerBlock, final BlockHeader parentHeader) { return createBlock( @@ -88,6 +90,7 @@ public BlockCreationResult createBlock( withdrawals, Optional.of(random), parentBeaconBlockRoot, + targetBlobsPerBlock, timestamp, false, parentHeader); diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java index 7570e97d4d6..4fc440748ac 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java @@ -62,6 +62,7 @@ import com.google.common.annotations.VisibleForTesting; import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.units.bigints.UInt64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -257,7 +258,9 @@ public PayloadIdentifier preparePayload( final Bytes32 prevRandao, final Address feeRecipient, final Optional> withdrawals, - final Optional parentBeaconBlockRoot) { + final Optional parentBeaconBlockRoot, + final Optional targetBlobsPerBlock, + final Optional maxBlobsPerBlock) { // we assume that preparePayload is always called sequentially, since the RPC Engine calls // are sequential, if this assumption changes then more synchronization should be added to @@ -270,7 +273,9 @@ public PayloadIdentifier preparePayload( prevRandao, feeRecipient, withdrawals, - parentBeaconBlockRoot); + parentBeaconBlockRoot, + targetBlobsPerBlock, + maxBlobsPerBlock); if (blockCreationTasks.containsKey(payloadIdentifier)) { LOG.debug( @@ -295,6 +300,7 @@ public PayloadIdentifier preparePayload( timestamp, withdrawals, parentBeaconBlockRoot, + targetBlobsPerBlock, parentHeader) .getBlock(); @@ -326,6 +332,7 @@ public PayloadIdentifier preparePayload( mergeBlockCreator, withdrawals, parentBeaconBlockRoot, + targetBlobsPerBlock, parentHeader); return payloadIdentifier; @@ -368,6 +375,7 @@ private void tryToBuildBetterBlock( final MergeBlockCreator mergeBlockCreator, final Optional> withdrawals, final Optional parentBeaconBlockRoot, + final Optional targetBlobsPerBlock, final BlockHeader parentHeader) { final Supplier blockCreator = @@ -378,6 +386,7 @@ private void tryToBuildBetterBlock( timestamp, withdrawals, parentBeaconBlockRoot, + targetBlobsPerBlock, parentHeader); LOG.debug( diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeMiningCoordinator.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeMiningCoordinator.java index 0bbd1f0a69c..9e0c420cf1f 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeMiningCoordinator.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeMiningCoordinator.java @@ -31,6 +31,7 @@ import java.util.concurrent.CompletableFuture; import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.units.bigints.UInt64; /** The interface Merge mining coordinator. */ public interface MergeMiningCoordinator extends MiningCoordinator { @@ -43,6 +44,8 @@ public interface MergeMiningCoordinator extends MiningCoordinator { * @param feeRecipient the fee recipient * @param withdrawals the optional list of withdrawals * @param parentBeaconBlockRoot optional root hash of the parent beacon block + * @param targetBlobsPerBlock optional target blobs per block EIP-7742 + * @param maxBlobsPerBlock optional max blobs per block EIP-7742 * @return the payload identifier */ PayloadIdentifier preparePayload( @@ -51,7 +54,9 @@ PayloadIdentifier preparePayload( final Bytes32 prevRandao, final Address feeRecipient, final Optional> withdrawals, - final Optional parentBeaconBlockRoot); + final Optional parentBeaconBlockRoot, + final Optional targetBlobsPerBlock, + final Optional maxBlobsPerBlock); @Override default boolean isCompatibleWithEngineApi() { diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/PayloadIdentifier.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/PayloadIdentifier.java index c08715897f0..a166766d90e 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/PayloadIdentifier.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/PayloadIdentifier.java @@ -63,6 +63,8 @@ public PayloadIdentifier(final Long payloadId) { * @param feeRecipient the fee recipient * @param withdrawals the withdrawals * @param parentBeaconBlockRoot the parent beacon block root + * @param targetBlobsPerBlock the target blobs per block EIP-7742 + * @param maxBlobsPerBlock the max blobs per block EIP-7742 * @return the payload identifier */ public static PayloadIdentifier forPayloadParams( @@ -71,23 +73,33 @@ public static PayloadIdentifier forPayloadParams( final Bytes32 prevRandao, final Address feeRecipient, final Optional> withdrawals, - final Optional parentBeaconBlockRoot) { + final Optional parentBeaconBlockRoot, + final Optional targetBlobsPerBlock, + final Optional maxBlobsPerBlock) { - return new PayloadIdentifier( + long payloadId = timestamp ^ ((long) parentHash.toHexString().hashCode()) << 8 ^ ((long) prevRandao.toHexString().hashCode()) << 16 ^ ((long) feeRecipient.toHexString().hashCode()) << 24 ^ (long) - withdrawals - .map( - ws -> - ws.stream() - .sorted(Comparator.comparing(Withdrawal::getIndex)) - .map(Withdrawal::hashCode) - .reduce(1, (a, b) -> a ^ (b * 31))) - .orElse(0) - ^ ((long) parentBeaconBlockRoot.hashCode()) << 40); + withdrawals + .map( + ws -> + ws.stream() + .sorted(Comparator.comparing(Withdrawal::getIndex)) + .map(Withdrawal::hashCode) + .reduce(1, (a, b) -> a ^ (b * 31))) + .orElse(0) + << 32 + ^ ((long) parentBeaconBlockRoot.hashCode()) << 40; + if (targetBlobsPerBlock.isPresent()) { + payloadId ^= ((long) targetBlobsPerBlock.get().hashCode() + 13) << 48; + } + if (maxBlobsPerBlock.isPresent()) { + payloadId ^= ((long) maxBlobsPerBlock.get().hashCode() + 13) << 56; + } + return new PayloadIdentifier(payloadId); } @Override diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/TransitionCoordinator.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/TransitionCoordinator.java index 681c6f334bc..f43483f0d7b 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/TransitionCoordinator.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/TransitionCoordinator.java @@ -34,6 +34,7 @@ import java.util.concurrent.CompletableFuture; import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.units.bigints.UInt64; /** The Transition coordinator. */ public class TransitionCoordinator extends TransitionUtils @@ -147,9 +148,18 @@ public PayloadIdentifier preparePayload( final Bytes32 prevRandao, final Address feeRecipient, final Optional> withdrawals, - final Optional parentBeaconBlockRoot) { + final Optional parentBeaconBlockRoot, + final Optional targetBlobsPerBlock, + final Optional maxBlobsPerBlock) { return mergeCoordinator.preparePayload( - parentHeader, timestamp, prevRandao, feeRecipient, withdrawals, parentBeaconBlockRoot); + parentHeader, + timestamp, + prevRandao, + feeRecipient, + withdrawals, + parentBeaconBlockRoot, + targetBlobsPerBlock, + maxBlobsPerBlock); } @Override diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java index 90c4b6866e4..dd1cfd25717 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java @@ -249,6 +249,8 @@ public void coinbaseShouldMatchSuggestedFeeRecipient() { Bytes32.ZERO, suggestedFeeRecipient, Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); ArgumentCaptor payloadWrapper = ArgumentCaptor.forClass(PayloadWrapper.class); @@ -290,6 +292,7 @@ public void exceptionDuringBuildingBlockShouldNotBeInvalid() anyLong(), eq(Optional.empty()), eq(Optional.empty()), + eq(Optional.empty()), any()); return beingSpiedOn; }; @@ -328,6 +331,8 @@ public void exceptionDuringBuildingBlockShouldNotBeInvalid() Bytes32.random(), suggestedFeeRecipient, Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); blockCreationTask.get(); @@ -366,6 +371,8 @@ public void shouldNotRecordProposedBadBlockToBadBlockManager() Bytes32.ZERO, suggestedFeeRecipient, Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); verify(badBlockManager, never()).addBadBlock(any(), any()); @@ -399,6 +406,8 @@ public void shouldContinueBuildingBlocksUntilFinalizeIsCalled() Bytes32.ZERO, suggestedFeeRecipient, Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); blockCreationTask.get(); @@ -457,6 +466,8 @@ public void blockCreationRepetitionShouldTakeNotLessThanRepetitionMinDuration() Bytes32.ZERO, suggestedFeeRecipient, Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); blockCreationTask.get(); @@ -508,6 +519,8 @@ public void shouldRetryBlockCreationOnRecoverableError() Bytes32.ZERO, suggestedFeeRecipient, Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); blockCreationTask.get(); @@ -561,6 +574,8 @@ public void shouldStopRetryBlockCreationIfTimeExpired() throws InterruptedExcept Bytes32.ZERO, suggestedFeeRecipient, Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); try { @@ -607,6 +622,8 @@ public void shouldStopInProgressBlockCreationIfFinalizedIsCalled() Bytes32.ZERO, suggestedFeeRecipient, Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); waitForBlockCreationInProgress.await(); @@ -661,6 +678,8 @@ public void shouldNotStartAnotherBlockCreationJobIfCalledAgainWithTheSamePayload Bytes32.ZERO, suggestedFeeRecipient, Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); final CompletableFuture task1 = blockCreationTask; @@ -672,6 +691,8 @@ public void shouldNotStartAnotherBlockCreationJobIfCalledAgainWithTheSamePayload Bytes32.ZERO, suggestedFeeRecipient, Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); assertThat(payloadId1).isEqualTo(payloadId2); @@ -713,6 +734,8 @@ public void shouldCancelPreviousBlockCreationJobIfCalledAgainWithNewPayloadId() Bytes32.ZERO, suggestedFeeRecipient, Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); assertThat(coordinator.isBlockCreationCancelled(payloadId1)).isFalse(); @@ -724,6 +747,8 @@ public void shouldCancelPreviousBlockCreationJobIfCalledAgainWithNewPayloadId() Bytes32.ZERO, suggestedFeeRecipient, Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); assertThat(payloadId1).isNotEqualTo(payloadId2); @@ -757,6 +782,8 @@ public void shouldUseExtraDataFromMiningParameters() { Bytes32.ZERO, suggestedFeeRecipient, Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); ArgumentCaptor payloadWrapper = ArgumentCaptor.forClass(PayloadWrapper.class); diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/PayloadIdentifierTest.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/PayloadIdentifierTest.java index cb0352dc7a0..130317ad6ec 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/PayloadIdentifierTest.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/PayloadIdentifierTest.java @@ -53,6 +53,8 @@ public void conversionCoverage() { Bytes32.random(), Address.fromHexString("0x42"), Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); assertThat(new PayloadIdentifier(idTest.getAsBigInteger().longValue())).isEqualTo(idTest); assertThat(new PayloadIdentifier(idTest.getAsBigInteger().longValue())).isEqualTo(idTest); @@ -92,6 +94,8 @@ public void differentWithdrawalAmountsYieldDifferentHash() { prevRandao, Address.fromHexString("0x42"), Optional.of(withdrawals1), + Optional.empty(), + Optional.empty(), Optional.empty()); var idForWithdrawals2 = PayloadIdentifier.forPayloadParams( @@ -100,6 +104,8 @@ public void differentWithdrawalAmountsYieldDifferentHash() { prevRandao, Address.fromHexString("0x42"), Optional.of(withdrawals2), + Optional.empty(), + Optional.empty(), Optional.empty()); assertThat(idForWithdrawals1).isNotEqualTo(idForWithdrawals2); } @@ -138,6 +144,8 @@ public void differentOrderedWithdrawalsYieldSameHash() { prevRandao, Address.fromHexString("0x42"), Optional.of(withdrawals1), + Optional.empty(), + Optional.empty(), Optional.empty()); var idForWithdrawals2 = PayloadIdentifier.forPayloadParams( @@ -146,6 +154,8 @@ public void differentOrderedWithdrawalsYieldSameHash() { prevRandao, Address.fromHexString("0x42"), Optional.of(withdrawals2), + Optional.empty(), + Optional.empty(), Optional.empty()); assertThat(idForWithdrawals1).isEqualTo(idForWithdrawals2); } @@ -160,6 +170,8 @@ public void emptyOptionalAndEmptyListWithdrawalsYieldDifferentHash() { prevRandao, Address.fromHexString("0x42"), Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); var idForWithdrawals2 = PayloadIdentifier.forPayloadParams( @@ -168,6 +180,8 @@ public void emptyOptionalAndEmptyListWithdrawalsYieldDifferentHash() { prevRandao, Address.fromHexString("0x42"), Optional.of(emptyList()), + Optional.empty(), + Optional.empty(), Optional.empty()); assertThat(idForWithdrawals1).isNotEqualTo(idForWithdrawals2); } @@ -175,44 +189,156 @@ public void emptyOptionalAndEmptyListWithdrawalsYieldDifferentHash() { @Test public void emptyOptionalAndNonEmptyParentBeaconBlockRootYieldDifferentHash() { final Bytes32 prevRandao = Bytes32.random(); - var idForWithdrawals1 = + var idForPbbr1 = PayloadIdentifier.forPayloadParams( Hash.ZERO, 1337L, prevRandao, Address.fromHexString("0x42"), Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); - var idForWithdrawals2 = + var idForPbbr2 = PayloadIdentifier.forPayloadParams( Hash.ZERO, 1337L, prevRandao, Address.fromHexString("0x42"), Optional.empty(), - Optional.of(Bytes32.ZERO)); - assertThat(idForWithdrawals1).isNotEqualTo(idForWithdrawals2); + Optional.of(Bytes32.ZERO), + Optional.empty(), + Optional.empty()); + assertThat(idForPbbr1).isNotEqualTo(idForPbbr2); } @Test public void differentParentBeaconBlockRootYieldDifferentHash() { final Bytes32 prevRandao = Bytes32.random(); - var idForWithdrawals1 = + var idForPbbr1 = PayloadIdentifier.forPayloadParams( Hash.ZERO, 1337L, prevRandao, Address.fromHexString("0x42"), Optional.empty(), - Optional.of(Bytes32.fromHexStringLenient("0x1"))); - var idForWithdrawals2 = + Optional.of(Bytes32.fromHexStringLenient("0x1")), + Optional.empty(), + Optional.empty()); + var idForPbbr2 = PayloadIdentifier.forPayloadParams( Hash.ZERO, 1337L, prevRandao, Address.fromHexString("0x42"), Optional.empty(), - Optional.of(Bytes32.ZERO)); - assertThat(idForWithdrawals1).isNotEqualTo(idForWithdrawals2); + Optional.of(Bytes32.ZERO), + Optional.empty(), + Optional.empty()); + assertThat(idForPbbr1).isNotEqualTo(idForPbbr2); + } + + @Test + public void emptyOptionalAndNonEmptyTargetBlobsPerBlockYieldDifferentHash() { + final Bytes32 prevRandao = Bytes32.random(); + var idForTbc1 = + PayloadIdentifier.forPayloadParams( + Hash.ZERO, + 1337L, + prevRandao, + Address.fromHexString("0x42"), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty()); + var idForTbc2 = + PayloadIdentifier.forPayloadParams( + Hash.ZERO, + 1337L, + prevRandao, + Address.fromHexString("0x42"), + Optional.empty(), + Optional.empty(), + Optional.of(UInt64.ZERO), + Optional.empty()); + assertThat(idForTbc1).isNotEqualTo(idForTbc2); + } + + @Test + public void differentTargetBlobsPerBlockYieldDifferentHash() { + final Bytes32 prevRandao = Bytes32.random(); + var idForTbc1 = + PayloadIdentifier.forPayloadParams( + Hash.ZERO, + 1337L, + prevRandao, + Address.fromHexString("0x42"), + Optional.empty(), + Optional.empty(), + Optional.of(UInt64.ZERO), + Optional.empty()); + var idForTbc2 = + PayloadIdentifier.forPayloadParams( + Hash.ZERO, + 1337L, + prevRandao, + Address.fromHexString("0x42"), + Optional.empty(), + Optional.empty(), + Optional.of(UInt64.ONE), + Optional.empty()); + assertThat(idForTbc1).isNotEqualTo(idForTbc2); + } + + @Test + public void emptyOptionalAndNonEmptyMaxBlobsPerBlockYieldDifferentHash() { + final Bytes32 prevRandao = Bytes32.random(); + var idForTbc1 = + PayloadIdentifier.forPayloadParams( + Hash.ZERO, + 1337L, + prevRandao, + Address.fromHexString("0x42"), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty()); + var idForTbc2 = + PayloadIdentifier.forPayloadParams( + Hash.ZERO, + 1337L, + prevRandao, + Address.fromHexString("0x42"), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.of(UInt64.ZERO)); + assertThat(idForTbc1).isNotEqualTo(idForTbc2); + } + + @Test + public void differentMaxBlobsPerBlockYieldDifferentHash() { + final Bytes32 prevRandao = Bytes32.random(); + var idForTbc1 = + PayloadIdentifier.forPayloadParams( + Hash.ZERO, + 1337L, + prevRandao, + Address.fromHexString("0x42"), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.of(UInt64.ZERO)); + var idForTbc2 = + PayloadIdentifier.forPayloadParams( + Hash.ZERO, + 1337L, + prevRandao, + Address.fromHexString("0x42"), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.of(UInt64.ONE)); + assertThat(idForTbc1).isNotEqualTo(idForTbc2); } } 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 f8bc597ff7c..497c104a35e 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 @@ -63,6 +63,7 @@ public enum RpcMethod { ENGINE_FORKCHOICE_UPDATED_V1("engine_forkchoiceUpdatedV1"), ENGINE_FORKCHOICE_UPDATED_V2("engine_forkchoiceUpdatedV2"), ENGINE_FORKCHOICE_UPDATED_V3("engine_forkchoiceUpdatedV3"), + ENGINE_FORKCHOICE_UPDATED_V4("engine_forkchoiceUpdatedV4"), ENGINE_EXCHANGE_TRANSITION_CONFIGURATION("engine_exchangeTransitionConfigurationV1"), ENGINE_GET_CLIENT_VERSION_V1("engine_getClientVersionV1"), ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V1("engine_getPayloadBodiesByHashV1"), diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineForkchoiceUpdated.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineForkchoiceUpdated.java index 727677aa8ed..58bd3554901 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineForkchoiceUpdated.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineForkchoiceUpdated.java @@ -224,7 +224,9 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) payloadAttributes.getPrevRandao(), payloadAttributes.getSuggestedFeeRecipient(), finalWithdrawals, - Optional.ofNullable(payloadAttributes.getParentBeaconBlockRoot()))); + Optional.ofNullable(payloadAttributes.getParentBeaconBlockRoot()), + Optional.ofNullable(payloadAttributes.getTargetBlobsPerBlock()), + Optional.ofNullable(payloadAttributes.getMaxBlobsPerBlock()))); payloadId.ifPresent( pid -> @@ -318,6 +320,10 @@ private void logPayload(final EnginePayloadAttributesParameter payloadAttributes .setMessage(message) .addArgument(() -> payloadAttributes.getParentBeaconBlockRoot().toHexString()); } + if (payloadAttributes.getTargetBlobsPerBlock() != null) { + message += ", targetBlobsPerBlock: {}"; + builder = builder.setMessage(message).addArgument(payloadAttributes::getTargetBlobsPerBlock); + } builder.log(); } 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 ac9dfe221e6..e81e5b0fd2c 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 @@ -76,6 +76,7 @@ import io.vertx.core.json.Json; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.units.bigints.UInt64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -147,12 +148,23 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) e); } + final Optional maybeTargetBlobsPerBlockParam; + try { + maybeTargetBlobsPerBlockParam = requestContext.getOptionalParameter(4, String.class); + } catch (JsonRpcParameterException e) { + throw new InvalidJsonRpcRequestException( + "Invalid target blobs per block parameter (index 4)", + RpcErrorType.INVALID_TARGET_BLOB_COUNT_PARAM, + e); + } + final ValidationResult parameterValidationResult = validateParameters( blockParam, maybeVersionedHashParam, maybeParentBeaconBlockRootParam, - maybeRequestsParam); + maybeRequestsParam, + maybeTargetBlobsPerBlockParam); if (!parameterValidationResult.isValid()) { return new JsonRpcErrorResponse(reqId, parameterValidationResult); } @@ -211,6 +223,18 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) return new JsonRpcErrorResponse(reqId, RpcErrorType.INVALID_EXECUTION_REQUESTS_PARAMS); } + final Optional maybeTargetBlobsPerBlock; + try { + maybeTargetBlobsPerBlock = maybeTargetBlobsPerBlockParam.map(UInt64::fromHexString); + } catch (RuntimeException ex) { + return respondWithInvalid( + reqId, + blockParam, + mergeCoordinator.getLatestValidAncestor(blockParam.getParentHash()).orElse(null), + INVALID, + "Invalid targetBlobsPerBlock"); + } + if (mergeContext.get().isSyncing()) { LOG.debug("We are syncing"); return respondWith(reqId, blockParam, null, SYNCING); @@ -279,7 +303,7 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) : BlobGas.fromHexString(blockParam.getExcessBlobGas()), maybeParentBeaconBlockRoot.orElse(null), maybeRequests.map(BodyValidation::requestsHash).orElse(null), - null, // TODO SLD EIP-7742 wiring in future PR + maybeTargetBlobsPerBlock.orElse(null), headerFunctions); // ensure the block hash matches the blockParam hash @@ -457,7 +481,8 @@ protected ValidationResult validateParameters( final EnginePayloadParameter parameter, final Optional> maybeVersionedHashParam, final Optional maybeBeaconBlockRootParam, - final Optional> maybeRequestsParam) { + final Optional> maybeRequestsParam, + final Optional maybeTargetBlobsPerBlockParam) { return ValidationResult.valid(); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineForkchoiceUpdatedV4.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineForkchoiceUpdatedV4.java new file mode 100644 index 00000000000..22985868d90 --- /dev/null +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineForkchoiceUpdatedV4.java @@ -0,0 +1,118 @@ +/* + * Copyright contributors to Hyperledger 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.engine; + +import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.PRAGUE; + +import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator; +import org.hyperledger.besu.ethereum.ProtocolContext; +import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EngineForkchoiceUpdatedParameter; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePayloadAttributesParameter; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.ethereum.mainnet.ValidationResult; + +import java.util.Optional; + +import io.vertx.core.Vertx; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EngineForkchoiceUpdatedV4 extends AbstractEngineForkchoiceUpdated { + + private static final Logger LOG = LoggerFactory.getLogger(EngineForkchoiceUpdatedV4.class); + protected final Optional pragueMilestone; + + public EngineForkchoiceUpdatedV4( + final Vertx vertx, + final ProtocolSchedule protocolSchedule, + final ProtocolContext protocolContext, + final MergeMiningCoordinator mergeCoordinator, + final EngineCallListener engineCallListener) { + super(vertx, protocolSchedule, protocolContext, mergeCoordinator, engineCallListener); + this.pragueMilestone = protocolSchedule.milestoneFor(PRAGUE); + } + + @Override + public String getName() { + return RpcMethod.ENGINE_FORKCHOICE_UPDATED_V4.getMethodName(); + } + + @Override + protected ValidationResult validateParameter( + final EngineForkchoiceUpdatedParameter fcuParameter, + final Optional maybePayloadAttributes) { + if (fcuParameter.getHeadBlockHash() == null) { + return ValidationResult.invalid( + getInvalidPayloadAttributesError(), "Missing head block hash"); + } else if (fcuParameter.getSafeBlockHash() == null) { + return ValidationResult.invalid( + getInvalidPayloadAttributesError(), "Missing safe block hash"); + } else if (fcuParameter.getFinalizedBlockHash() == null) { + return ValidationResult.invalid( + getInvalidPayloadAttributesError(), "Missing finalized block hash"); + } + if (maybePayloadAttributes.isPresent()) { + if (maybePayloadAttributes.get().getParentBeaconBlockRoot() == null) { + return ValidationResult.invalid( + getInvalidPayloadAttributesError(), "Missing parent beacon block root hash"); + } + if (maybePayloadAttributes.get().getTargetBlobsPerBlock() == null) { + return ValidationResult.invalid( + getInvalidPayloadAttributesError(), "Missing target blobs per block"); + } + if (maybePayloadAttributes.get().getMaxBlobsPerBlock() == null) { + return ValidationResult.invalid( + getInvalidPayloadAttributesError(), "Missing max blobs per block"); + } + } + return ValidationResult.valid(); + } + + @Override + protected ValidationResult validateForkSupported(final long blockTimestamp) { + return ForkSupportHelper.validateForkSupported(PRAGUE, pragueMilestone, blockTimestamp); + } + + @Override + protected Optional isPayloadAttributesValid( + final Object requestId, final EnginePayloadAttributesParameter payloadAttributes) { + if (payloadAttributes.getParentBeaconBlockRoot() == null) { + LOG.error( + "Parent beacon block root hash not present in payload attributes after cancun hardfork"); + return Optional.of(new JsonRpcErrorResponse(requestId, getInvalidPayloadAttributesError())); + } + if (payloadAttributes.getTargetBlobsPerBlock() == null) { + LOG.error("targetBlobsPerBlock not present in payload attributes after prague hardfork"); + return Optional.of(new JsonRpcErrorResponse(requestId, getInvalidPayloadAttributesError())); + } + if (payloadAttributes.getMaxBlobsPerBlock() == null) { + LOG.error("maxBlobsPerBlock not present in payload attributes after prague hardfork"); + return Optional.of(new JsonRpcErrorResponse(requestId, getInvalidPayloadAttributesError())); + } + + if (payloadAttributes.getTimestamp() == 0) { + return Optional.of(new JsonRpcErrorResponse(requestId, getInvalidPayloadAttributesError())); + } + + if (pragueMilestone.isEmpty() || payloadAttributes.getTimestamp() < pragueMilestone.get()) { + return Optional.of(new JsonRpcErrorResponse(requestId, RpcErrorType.UNSUPPORTED_FORK)); + } + + return Optional.empty(); + } +} diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2.java index 8d6bd7e4333..8e1bd9a2145 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2.java @@ -58,7 +58,8 @@ protected ValidationResult validateParameters( final EnginePayloadParameter payloadParameter, final Optional> maybeVersionedHashParam, final Optional maybeBeaconBlockRootParam, - final Optional> maybeRequestsParam) { + final Optional> maybeRequestsParam, + final Optional maybeTargetBlobsPerBlockParam) { if (payloadParameter.getBlobGasUsed() != null) { return ValidationResult.invalid( RpcErrorType.INVALID_BLOB_GAS_USED_PARAMS, "Unexpected blob gas used field present"); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3.java index 8710e436274..ba439c33ee5 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3.java @@ -56,7 +56,8 @@ protected ValidationResult validateParameters( final EnginePayloadParameter payloadParameter, final Optional> maybeVersionedHashParam, final Optional maybeBeaconBlockRootParam, - final Optional> maybeRequestsParam) { + final Optional> maybeRequestsParam, + final Optional maybeTargetBlobsPerBlockParam) { if (payloadParameter.getBlobGasUsed() == null) { return ValidationResult.invalid( RpcErrorType.INVALID_BLOB_GAS_USED_PARAMS, "Missing blob gas used field"); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4.java index 0155e3d721a..c8a4ce7a436 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4.java @@ -56,7 +56,8 @@ protected ValidationResult validateParameters( final EnginePayloadParameter payloadParameter, final Optional> maybeVersionedHashParam, final Optional maybeBeaconBlockRootParam, - final Optional> maybeRequestsParam) { + final Optional> maybeRequestsParam, + final Optional maybeTargetBlobsPerBlockParam) { if (payloadParameter.getBlobGasUsed() == null) { return ValidationResult.invalid( RpcErrorType.INVALID_BLOB_GAS_USED_PARAMS, "Missing blob gas used field"); @@ -73,6 +74,9 @@ protected ValidationResult validateParameters( } else if (maybeRequestsParam.isEmpty()) { return ValidationResult.invalid( RpcErrorType.INVALID_EXECUTION_REQUESTS_PARAMS, "Missing execution requests field"); + } else if (maybeTargetBlobsPerBlockParam.isEmpty()) { + return ValidationResult.invalid( + RpcErrorType.INVALID_TARGET_BLOB_COUNT_PARAM, "Missing targetBlobsPerBlock field"); } else { return ValidationResult.valid(); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EnginePreparePayloadDebug.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EnginePreparePayloadDebug.java index c4bca218031..34a3fcda551 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EnginePreparePayloadDebug.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EnginePreparePayloadDebug.java @@ -114,6 +114,10 @@ Optional generatePayload(final EnginePreparePayloadParameter param.getPrevRandao(), param.getFeeRecipient(), Optional.of(withdrawals), - param.getParentBeaconBlockRoot())); + param.getParentBeaconBlockRoot(), + // TODO SLD EIP-7742 add targetBlobsPerBlock or refactor to inherit from + // EnginePayloadAttributesParameter? + Optional.empty(), + Optional.empty())); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadAttributesParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadAttributesParameter.java index 0168531c4f8..9f3cf9d06d4 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadAttributesParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadAttributesParameter.java @@ -23,6 +23,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import io.vertx.core.json.JsonObject; import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.units.bigints.UInt64; public class EnginePayloadAttributesParameter { @@ -31,6 +32,8 @@ public class EnginePayloadAttributesParameter { final Address suggestedFeeRecipient; final List withdrawals; private final Bytes32 parentBeaconBlockRoot; + private final UInt64 targetBlobsPerBlock; + private final UInt64 maxBlobsPerBlock; @JsonCreator public EnginePayloadAttributesParameter( @@ -38,13 +41,19 @@ public EnginePayloadAttributesParameter( @JsonProperty("prevRandao") final String prevRandao, @JsonProperty("suggestedFeeRecipient") final String suggestedFeeRecipient, @JsonProperty("withdrawals") final List withdrawals, - @JsonProperty("parentBeaconBlockRoot") final String parentBeaconBlockRoot) { + @JsonProperty("parentBeaconBlockRoot") final String parentBeaconBlockRoot, + @JsonProperty("targetBlobsPerBlock") final String targetBlobsPerBlock, + @JsonProperty("maxBlobsPerBlock") final String maxBlobsPerBlock) { this.timestamp = Long.decode(timestamp); this.prevRandao = Bytes32.fromHexString(prevRandao); this.suggestedFeeRecipient = Address.fromHexString(suggestedFeeRecipient); this.withdrawals = withdrawals; this.parentBeaconBlockRoot = parentBeaconBlockRoot == null ? null : Bytes32.fromHexString(parentBeaconBlockRoot); + this.targetBlobsPerBlock = + targetBlobsPerBlock == null ? null : UInt64.fromHexString(targetBlobsPerBlock); + this.maxBlobsPerBlock = + maxBlobsPerBlock == null ? null : UInt64.fromHexString(maxBlobsPerBlock); } public Long getTimestamp() { @@ -63,6 +72,14 @@ public Bytes32 getParentBeaconBlockRoot() { return parentBeaconBlockRoot; } + public UInt64 getTargetBlobsPerBlock() { + return targetBlobsPerBlock; + } + + public UInt64 getMaxBlobsPerBlock() { + return maxBlobsPerBlock; + } + public List getWithdrawals() { return withdrawals; } @@ -81,6 +98,12 @@ public String serialize() { if (parentBeaconBlockRoot != null) { json.put("parentBeaconBlockRoot", parentBeaconBlockRoot.toHexString()); } + if (targetBlobsPerBlock != null) { + json.put("targetBlobsPerBlock", targetBlobsPerBlock.toHexString()); + } + if (maxBlobsPerBlock != null) { + json.put("maxBlobsPerBlock", maxBlobsPerBlock.toHexString()); + } return json.encode(); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePreparePayloadParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePreparePayloadParameter.java index 1485209d593..6bc978ea133 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePreparePayloadParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePreparePayloadParameter.java @@ -34,6 +34,8 @@ public class EnginePreparePayloadParameter { final List withdrawals; private final Optional parentBeaconBlockRoot; + // TODO SLD EIP-7742 add targetBlobsPerBlock or refactor to inherit from + // EnginePayloadAttributesParameter? @JsonCreator public EnginePreparePayloadParameter( @JsonProperty("parentHash") final Optional parentHash, diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/RpcErrorType.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/RpcErrorType.java index fa67fce15bc..f981a96b67d 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/RpcErrorType.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/RpcErrorType.java @@ -63,6 +63,8 @@ public enum RpcErrorType implements RpcMethodError { INVALID_EXCESS_BLOB_GAS_PARAMS( INVALID_PARAMS_ERROR_CODE, "Invalid excess blob gas params (missing or invalid)"), INVALID_EXECUTION_REQUESTS_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid execution requests params"), + INVALID_TARGET_BLOB_COUNT_PARAM( + INVALID_PARAMS_ERROR_CODE, "Invalid target blobs per block param"), INVALID_EXTRA_DATA_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid extra data params"), INVALID_FILTER_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid filter params"), INVALID_GAS_PRICE_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid gas price params"), diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV3.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV3.java index 1f1b19d88a1..44b246c8447 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV3.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV3.java @@ -83,6 +83,8 @@ public static class PayloadResult { private final String baseFeePerGas; private final String excessBlobGas; private final String blobGasUsed; + // TODO Don't think parentBeaconBlockRoot is needed as per the spec + // https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#ExecutionPayloadV3 private final String parentBeaconBlockRoot; protected final List transactions; @@ -207,6 +209,8 @@ public String getBlobGasUseds() { return blobGasUsed; } + // TODO Don't think parentBeaconBlockRoot is needed as per the spec + // https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#ExecutionPayloadV3 @JsonGetter(value = "parentBeaconBlockRoot") public String getParentBeaconBlockRoot() { return parentBeaconBlockRoot; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV4.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV4.java index 017de4653ca..2cc27ecec77 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV4.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV4.java @@ -97,6 +97,8 @@ public static class PayloadResult { private final String baseFeePerGas; private final String excessBlobGas; private final String blobGasUsed; + // TODO Don't think parentBeaconBlockRoot is needed as per the spec + // https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#ExecutionPayloadV3 private final String parentBeaconBlockRoot; protected final List transactions; @@ -221,6 +223,8 @@ public String getBlobGasUsed() { return blobGasUsed; } + // TODO Don't think parentBeaconBlockRoot is needed as per the spec + // https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#ExecutionPayloadV3 @JsonGetter(value = "parentBeaconBlockRoot") public String getParentBeaconBlockRoot() { return parentBeaconBlockRoot; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/ExecutionEngineJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/ExecutionEngineJsonRpcMethods.java index d8d04027f6a..74331711fcd 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/ExecutionEngineJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/ExecutionEngineJsonRpcMethods.java @@ -23,6 +23,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineForkchoiceUpdatedV1; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineForkchoiceUpdatedV2; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineForkchoiceUpdatedV3; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineForkchoiceUpdatedV4; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineGetBlobsV1; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineGetClientVersionV1; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineGetPayloadBodiesByHashV1; @@ -177,23 +178,28 @@ protected Map create() { } if (protocolSchedule.anyMatch(p -> p.spec().getName().equalsIgnoreCase("prague"))) { - executionEngineApisSupported.add( - new EngineGetPayloadV4( - consensusEngineServer, - protocolContext, - mergeCoordinator.get(), - blockResultFactory, - engineQosTimer, - protocolSchedule)); - - executionEngineApisSupported.add( - new EngineNewPayloadV4( - consensusEngineServer, - protocolSchedule, - protocolContext, - mergeCoordinator.get(), - ethPeers, - engineQosTimer)); + executionEngineApisSupported.addAll( + List.of( + new EngineGetPayloadV4( + consensusEngineServer, + protocolContext, + mergeCoordinator.get(), + blockResultFactory, + engineQosTimer, + protocolSchedule), + new EngineNewPayloadV4( + consensusEngineServer, + protocolSchedule, + protocolContext, + mergeCoordinator.get(), + ethPeers, + engineQosTimer), + new EngineForkchoiceUpdatedV4( + consensusEngineServer, + protocolSchedule, + protocolContext, + mergeCoordinator.get(), + engineQosTimer))); } return mapOf(executionEngineApisSupported); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineForkchoiceUpdatedTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineForkchoiceUpdatedTest.java index cdca20cb00e..00f62a28135 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineForkchoiceUpdatedTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineForkchoiceUpdatedTest.java @@ -244,6 +244,8 @@ public void shouldReturnValidWithoutFinalizedWithPayload() { Bytes32.fromHexStringLenient("0xDEADBEEF").toHexString(), Address.ECREC.toString(), null, + null, + null, null); var mockPayloadId = PayloadIdentifier.forPayloadParams( @@ -252,6 +254,8 @@ public void shouldReturnValidWithoutFinalizedWithPayload() { payloadParams.getPrevRandao(), payloadParams.getSuggestedFeeRecipient(), Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); when(mergeCoordinator.preparePayload( @@ -260,6 +264,8 @@ public void shouldReturnValidWithoutFinalizedWithPayload() { payloadParams.getPrevRandao(), Address.ECREC, Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty())) .thenReturn(mockPayloadId); @@ -433,6 +439,8 @@ public void shouldIgnoreUpdateToOldHeadAndNotPreparePayload() { Bytes32.fromHexStringLenient("0xDEADBEEF").toHexString(), Address.ECREC.toString(), null, + null, + null, null); var resp = @@ -444,7 +452,8 @@ public void shouldIgnoreUpdateToOldHeadAndNotPreparePayload() { var forkchoiceRes = (EngineUpdateForkchoiceResult) resp.getResult(); - verify(mergeCoordinator, never()).preparePayload(any(), any(), any(), any(), any(), any()); + verify(mergeCoordinator, never()) + .preparePayload(any(), any(), any(), any(), any(), any(), any(), any()); assertThat(forkchoiceRes.getPayloadStatus().getStatus()).isEqualTo(VALID); assertThat(forkchoiceRes.getPayloadStatus().getError()).isNull(); @@ -470,6 +479,8 @@ public void shouldReturnInvalidIfPayloadTimestampNotGreaterThanHead() { Bytes32.fromHexStringLenient("0xDEADBEEF").toHexString(), Address.ECREC.toString(), emptyList(), + null, + null, null); var resp = @@ -495,6 +506,8 @@ public void shouldReturnInvalidIfWithdrawalsIsNotNull_WhenWithdrawalsProhibited( Bytes32.fromHexStringLenient("0xDEADBEEF").toHexString(), Address.ECREC.toString(), emptyList(), + null, + null, null); var resp = @@ -520,6 +533,8 @@ public void shouldReturnValidIfWithdrawalsIsNull_WhenWithdrawalsProhibited() { Bytes32.fromHexStringLenient("0xDEADBEEF").toHexString(), Address.ECREC.toString(), null, + null, + null, null); var mockPayloadId = @@ -529,6 +544,8 @@ public void shouldReturnValidIfWithdrawalsIsNull_WhenWithdrawalsProhibited() { payloadParams.getPrevRandao(), payloadParams.getSuggestedFeeRecipient(), Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); when(mergeCoordinator.preparePayload( @@ -537,6 +554,8 @@ public void shouldReturnValidIfWithdrawalsIsNull_WhenWithdrawalsProhibited() { payloadParams.getPrevRandao(), Address.ECREC, Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty())) .thenReturn(mockPayloadId); @@ -564,6 +583,8 @@ public void shouldReturnInvalidIfWithdrawalsIsNull_WhenWithdrawalsAllowed() { Bytes32.fromHexStringLenient("0xDEADBEEF").toHexString(), Address.ECREC.toString(), null, + null, + null, null); var resp = @@ -600,6 +621,8 @@ public void shouldReturnValidIfWithdrawalsIsNotNull_WhenWithdrawalsAllowed() { Bytes32.fromHexStringLenient("0xDEADBEEF").toHexString(), Address.ECREC.toString(), withdrawalParameters, + null, + null, null); final Optional> withdrawals = @@ -615,6 +638,8 @@ public void shouldReturnValidIfWithdrawalsIsNotNull_WhenWithdrawalsAllowed() { payloadParams.getPrevRandao(), payloadParams.getSuggestedFeeRecipient(), withdrawals, + Optional.empty(), + Optional.empty(), Optional.empty()); when(mergeCoordinator.preparePayload( @@ -623,6 +648,8 @@ public void shouldReturnValidIfWithdrawalsIsNotNull_WhenWithdrawalsAllowed() { payloadParams.getPrevRandao(), Address.ECREC, withdrawals, + Optional.empty(), + Optional.empty(), Optional.empty())) .thenReturn(mockPayloadId); @@ -649,6 +676,8 @@ public void shouldReturnValidIfProtocolScheduleIsEmpty() { Bytes32.fromHexStringLenient("0xDEADBEEF").toHexString(), Address.ECREC.toString(), null, + null, + null, null); var mockPayloadId = @@ -658,6 +687,8 @@ public void shouldReturnValidIfProtocolScheduleIsEmpty() { payloadParams.getPrevRandao(), payloadParams.getSuggestedFeeRecipient(), Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); when(mergeCoordinator.preparePayload( @@ -666,6 +697,8 @@ public void shouldReturnValidIfProtocolScheduleIsEmpty() { payloadParams.getPrevRandao(), Address.ECREC, Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty())) .thenReturn(mockPayloadId); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayloadTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayloadTest.java index 1cfc51396d4..bb73f41ee61 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayloadTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayloadTest.java @@ -91,6 +91,8 @@ public AbstractEngineGetPayloadTest() { Bytes32.random(), Address.fromHexString("0x42"), Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); protected static final BlockHeader mockHeader = new BlockHeaderTestFixture().prevRandao(Bytes32.random()).buildHeader(); @@ -159,6 +161,8 @@ public void shouldFailForUnknownPayloadId() { Bytes32.random(), Address.fromHexString("0x42"), Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty())); assertThat(resp).isInstanceOf(JsonRpcErrorResponse.class); verify(engineCallListener, times(1)).executionEngineCalled(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineForkchoiceUpdatedV2Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineForkchoiceUpdatedV2Test.java index c3558ef3292..214606dc778 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineForkchoiceUpdatedV2Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineForkchoiceUpdatedV2Test.java @@ -73,6 +73,8 @@ public void shouldReturnUnsupportedForkIfBlockTimestampIsAfterCancunMilestone() Bytes32.fromHexStringLenient("0xDEADBEEF").toHexString(), Address.ECREC.toString(), null, + null, + null, null); final JsonRpcResponse resp = resp(param, Optional.of(payloadParams)); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV3Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV3Test.java index 1fe3b44d451..33eeafd81e8 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV3Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV3Test.java @@ -104,6 +104,8 @@ public void shouldReturnBlockForKnownPayloadId() { Bytes32.random(), Address.fromHexString("0x42"), Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); BlobTestFixture blobTestFixture = new BlobTestFixture(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV4Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV4Test.java index 744600ddca9..c8f3bc448a5 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV4Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV4Test.java @@ -111,6 +111,8 @@ public void shouldReturnBlockForKnownPayloadId() { Bytes32.random(), Address.fromHexString("0x42"), Optional.empty(), + Optional.empty(), + Optional.empty(), Optional.empty()); BlobTestFixture blobTestFixture = new BlobTestFixture(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java index 1810ce94508..66441503078 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java @@ -150,7 +150,8 @@ public void shouldValidVersionedHash_whenListIsEmpty() { payload, Optional.of(List.of()), Optional.of("0x0000000000000000000000000000000000000000000000000000000000000000"), - Optional.of(emptyList())); + Optional.of(emptyList()), + Optional.of("0x3")); assertThat(res.isValid()).isTrue(); } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java index fe7c38917c3..6d262f38cea 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java @@ -17,7 +17,9 @@ import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.ethereum.api.graphql.internal.response.GraphQLError.INVALID_PARAMS; +import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.INVALID; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType.INVALID_EXECUTION_REQUESTS_PARAMS; +import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType.INVALID_TARGET_BLOB_COUNT_PARAM; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; @@ -35,6 +37,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePayloadParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.EnginePayloadStatusResult; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.Request; @@ -50,6 +53,7 @@ import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.units.bigints.UInt64; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -65,6 +69,7 @@ public EngineNewPayloadV4Test() {} new Request(RequestType.DEPOSIT, Bytes.of(1)), new Request(RequestType.WITHDRAWAL, Bytes.of(1)), new Request(RequestType.CONSOLIDATION, Bytes.of(1))); + private static final UInt64 VALID_TARGET_BLOB_COUNT = UInt64.valueOf(3L); @BeforeEach @Override @@ -91,9 +96,7 @@ public void shouldReturnExpectedMethodName() { @Test public void shouldReturnInvalidIfRequestsIsNull_WhenRequestsAllowed() { - var resp = - respWithInvalidRequests( - mockEnginePayload(createValidBlockHeaderForV4(Optional.empty()), emptyList())); + var resp = respWithInvalidRequests(); assertThat(fromErrorResp(resp).getCode()).isEqualTo(INVALID_PARAMS.getCode()); assertThat(fromErrorResp(resp).getMessage()) @@ -129,10 +132,31 @@ public void shouldReturnInvalidIfRequestsIsNotNull_WhenRequestsProhibited() { verify(engineCallListener, times(1)).executionEngineCalled(); } + @Test + public void shouldReturnErrorIfTargetBlobsPerBlockIsMissing() { + var resp = respWithMissingTargetBlobsPerBlock(); + + assertThat(fromErrorResp(resp).getCode()).isEqualTo(INVALID_PARAMS.getCode()); + assertThat(fromErrorResp(resp).getMessage()) + .isEqualTo(INVALID_TARGET_BLOB_COUNT_PARAM.getMessage()); + verify(engineCallListener, times(1)).executionEngineCalled(); + } + + @Test + public void shouldReturnInvalidIfTargetBlobsPerBlockIsInvalid() { + var resp = respWithInvalidTargetBlobsPerBlock(); + final EnginePayloadStatusResult result = fromSuccessResp(resp); + + assertThat(result.getStatusAsString()).isEqualTo(INVALID.name()); + assertThat(result.getError()).isEqualTo("Invalid targetBlobsPerBlock"); + verify(engineCallListener, times(1)).executionEngineCalled(); + } + private BlockHeader createValidBlockHeaderForV4( final Optional> maybeWithdrawals) { return createBlockHeaderFixtureForV3(maybeWithdrawals) .requestsHash(BodyValidation.requestsHash(VALID_REQUESTS)) + .targetBlobsPerBlock(VALID_TARGET_BLOB_COUNT) .buildHeader(); } @@ -173,22 +197,76 @@ protected JsonRpcResponse resp(final EnginePayloadParameter payload) { Object[] params = maybeParentBeaconBlockRoot .map( - bytes32 -> + parentBeaconBlockRootBytes32 -> new Object[] { - payload, emptyList(), bytes32.toHexString(), requestsWithoutRequestId + payload, + emptyList(), + parentBeaconBlockRootBytes32.toHexString(), + requestsWithoutRequestId, + VALID_TARGET_BLOB_COUNT.toHexString() }) .orElseGet(() -> new Object[] {payload}); return method.response( new JsonRpcRequestContext(new JsonRpcRequest("2.0", this.method.getName(), params))); } - protected JsonRpcResponse respWithInvalidRequests(final EnginePayloadParameter payload) { + private JsonRpcResponse respWithInvalidRequests() { + final EnginePayloadParameter payload = + mockEnginePayload(createValidBlockHeaderForV4(Optional.empty()), emptyList()); Object[] params = maybeParentBeaconBlockRoot .map( bytes32 -> new Object[] {payload, emptyList(), bytes32.toHexString() - // empty requests param is invalid + // missing requests param is invalid + }) + .orElseGet(() -> new Object[] {payload}); + return method.response( + new JsonRpcRequestContext(new JsonRpcRequest("2.0", this.method.getName(), params))); + } + + private JsonRpcResponse respWithMissingTargetBlobsPerBlock() { + final EnginePayloadParameter payload = + mockEnginePayload(createValidBlockHeaderForV4(Optional.empty()), emptyList()); + final List requestsWithoutRequestId = + VALID_REQUESTS.stream() + .sorted(Comparator.comparing(Request::getType)) + .map(r -> r.getData().toHexString()) + .toList(); + Object[] params = + maybeParentBeaconBlockRoot + .map( + parentBeaconBlockRootBytes32 -> + new Object[] { + payload, + emptyList(), + parentBeaconBlockRootBytes32.toHexString(), + requestsWithoutRequestId, + // missing targetBlobsPerBlock param + }) + .orElseGet(() -> new Object[] {payload}); + return method.response( + new JsonRpcRequestContext(new JsonRpcRequest("2.0", this.method.getName(), params))); + } + + private JsonRpcResponse respWithInvalidTargetBlobsPerBlock() { + final EnginePayloadParameter payload = + mockEnginePayload(createValidBlockHeaderForV4(Optional.empty()), emptyList()); + final List requestsWithoutRequestId = + VALID_REQUESTS.stream() + .sorted(Comparator.comparing(Request::getType)) + .map(r -> r.getData().toHexString()) + .toList(); + Object[] params = + maybeParentBeaconBlockRoot + .map( + parentBeaconBlockRootBytes32 -> + new Object[] { + payload, + emptyList(), + parentBeaconBlockRootBytes32.toHexString(), + requestsWithoutRequestId, + "invalidTargetBlobsPerBlock" }) .orElseGet(() -> new Object[] {payload}); return method.response( diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadAttributesParameterTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadAttributesParameterTest.java index bec9bd12143..3c558a30e6e 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadAttributesParameterTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadAttributesParameterTest.java @@ -98,13 +98,13 @@ public void serialize_WithdrawalsPresent() { private EnginePayloadAttributesParameter parameterWithdrawalsOmitted() { return new EnginePayloadAttributesParameter( - TIMESTAMP, PREV_RANDAO, SUGGESTED_FEE_RECIPIENT_ADDRESS, null, null); + TIMESTAMP, PREV_RANDAO, SUGGESTED_FEE_RECIPIENT_ADDRESS, null, null, null, null); } private EnginePayloadAttributesParameter parameterWithdrawalsPresent() { final List withdrawals = List.of(WITHDRAWAL_PARAM_1, WITHDRAWAL_PARAM_2); return new EnginePayloadAttributesParameter( - TIMESTAMP, PREV_RANDAO, SUGGESTED_FEE_RECIPIENT_ADDRESS, withdrawals, null); + TIMESTAMP, PREV_RANDAO, SUGGESTED_FEE_RECIPIENT_ADDRESS, withdrawals, null, null, null); } // TODO: add a parent beacon block root test here diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java index 50eb978df1e..1cd10280a39 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java @@ -65,6 +65,7 @@ import com.google.common.collect.Lists; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.units.bigints.UInt64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -148,6 +149,7 @@ public BlockCreationResult createBlock( Optional.empty(), Optional.empty(), Optional.empty(), + Optional.empty(), timestamp, true, parentHeader); @@ -171,6 +173,7 @@ public BlockCreationResult createBlock( maybeWithdrawals, Optional.empty(), Optional.empty(), + Optional.empty(), timestamp, true, parentHeader); @@ -182,6 +185,7 @@ protected BlockCreationResult createBlock( final Optional> maybeWithdrawals, final Optional maybePrevRandao, final Optional maybeParentBeaconBlockRoot, + final Optional maybeTargetBlobsPerBlock, final long timestamp, boolean rewardCoinbase, final BlockHeader parentHeader) { @@ -200,7 +204,8 @@ protected BlockCreationResult createBlock( miningConfiguration, timestamp, maybePrevRandao, - maybeParentBeaconBlockRoot) + maybeParentBeaconBlockRoot, + maybeTargetBlobsPerBlock) .buildProcessableBlockHeader(); final Address miningBeneficiary = diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlobSizeTransactionSelector.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlobSizeTransactionSelector.java index 9a4c83e9625..51651af7bdd 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlobSizeTransactionSelector.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlobSizeTransactionSelector.java @@ -56,7 +56,9 @@ public TransactionSelectionResult evaluateTransactionPreProcessing( if (tx.getType().supportsBlob()) { final var remainingBlobGas = - context.gasLimitCalculator().currentBlobGasLimit() + context + .gasLimitCalculator() + .currentBlobGasLimit() // TODO SLD EIP-7742 max blobs may change - transactionSelectionResults.getCumulativeBlobGasUsed(); if (remainingBlobGas == 0) { diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java index b70c48ad026..a26b3cce58d 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java @@ -157,6 +157,7 @@ void withProcessorAndEmptyWithdrawals_NoWithdrawalsAreProcessed() { Optional.empty(), Optional.empty(), Optional.empty(), + Optional.empty(), 1L, false, miningOn.parentHeader); @@ -176,6 +177,7 @@ void withNoProcessorAndEmptyWithdrawals_NoWithdrawalsAreNotProcessed() { Optional.empty(), Optional.empty(), Optional.empty(), + Optional.empty(), 1L, false, miningOn.parentHeader); @@ -197,6 +199,7 @@ void withProcessorAndWithdrawals_WithdrawalsAreProcessed() { Optional.of(withdrawals), Optional.empty(), Optional.empty(), + Optional.empty(), 1L, false, miningOn.parentHeader); @@ -221,6 +224,7 @@ void withNoProcessorAndWithdrawals_WithdrawalsAreNotProcessed() { Optional.of(withdrawals), Optional.empty(), Optional.empty(), + Optional.empty(), 1L, false, miningOn.parentHeader); @@ -255,6 +259,7 @@ public void computesGasUsageFromIncludedTransactions() { Optional.empty(), Optional.empty(), Optional.empty(), + Optional.empty(), 1L, false, miningOn.parentHeader); 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 0dcc3450121..8b0c7f065d2 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 @@ -221,8 +221,7 @@ private static BlockHeader buildHeader( .requestsHash(isPragueAtGenesis(genesis) ? Hash.EMPTY_REQUESTS_HASH : null) .targetBlobsPerBlock( isPragueAtGenesis(genesis) - // TODO SLD EIP-7742 Currently defaulting to null due to dependency on web3j - // BlockHeader in CodeDelegationTransactionAcceptanceTest + // TODO SLD EIP-7742 should we enforce a value instead of allowing null? ? genesis.getTargetBlobsPerBlock().map(UInt64::fromHexString).orElse(null) : null) .buildBlockHeader(); 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 381785995ac..aba13867273 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 @@ -168,7 +168,8 @@ public static BlockHeaderBuilder createPending( final MiningConfiguration miningConfiguration, final long timestamp, final Optional maybePrevRandao, - final Optional maybeParentBeaconBlockRoot) { + final Optional maybeParentBeaconBlockRoot, + final Optional maybeTargetBlobsPerBlock) { final long newBlockNumber = parentHeader.getNumber() + 1; final long gasLimit = @@ -208,7 +209,8 @@ public static BlockHeaderBuilder createPending( .timestamp(timestamp) .baseFee(baseFee) .prevRandao(prevRandao) - .parentBeaconBlockRoot(parentBeaconBlockRoot); + .parentBeaconBlockRoot(parentBeaconBlockRoot) + .targetBlobsPerBlock(maybeTargetBlobsPerBlock.orElse(null)); } public BlockHeader buildBlockHeader() { 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 20650bc74aa..2655a315632 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 @@ -47,7 +47,7 @@ public class ProcessableBlockHeader protected final Bytes32 mixHashOrPrevRandao; // parentBeaconBlockRoot is included for Cancun protected final Bytes32 parentBeaconBlockRoot; - // TODO SLD Quantity or UInt64Value instead? + // targetBlobsPerBlock is included for Prague EIP-7742 protected final UInt64 targetBlobsPerBlock; protected ProcessableBlockHeader( diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java index c4558ab14dc..1ea8747d66d 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java @@ -188,6 +188,7 @@ public ProcessableBlockHeader simulatePendingBlockHeader() { miningConfiguration, timestamp, Optional.empty(), + Optional.empty(), Optional.empty()) .buildProcessableBlockHeader(); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/BlobCache.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/BlobCache.java index 1cca3f5ee25..f30e32b76f9 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/BlobCache.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/BlobCache.java @@ -34,6 +34,7 @@ public class BlobCache { public BlobCache() { this.cache = Caffeine.newBuilder() + // TODO SLD EIP-7742 max blobs may change .maximumSize(6 * 32 * 3L) // 6 blobs max per 32 slots per 3 epochs .expireAfterWrite( 3 * 32 * 12L, TimeUnit.SECONDS) // 3 epochs of 32 slots which take 12 seconds each. diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolConfiguration.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolConfiguration.java index 2f823830fcc..80ea1610c09 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolConfiguration.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolConfiguration.java @@ -75,7 +75,7 @@ enum Implementation { long DEFAULT_PENDING_TRANSACTIONS_LAYER_MAX_CAPACITY_BYTES = 12_500_000L; int DEFAULT_MAX_PRIORITIZED_TRANSACTIONS = 2000; EnumMap DEFAULT_MAX_PRIORITIZED_TRANSACTIONS_BY_TYPE = - new EnumMap<>(Map.of(TransactionType.BLOB, 6)); + new EnumMap<>(Map.of(TransactionType.BLOB, 6)); // TODO SLD EIP-7742? max blobs may change int DEFAULT_MAX_FUTURE_BY_SENDER = 200; Implementation DEFAULT_TX_POOL_IMPLEMENTATION = Implementation.LAYERED; Set
DEFAULT_PRIORITY_SENDERS = Set.of(); diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index f8608f89325..11decc5f95d 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 = 'TPCo4SZ61OrJxRAa2SIcAIOAOjVTdRw+UOeHMuiJP84=' + knownHash = 'lgfTaInANOY3ueze2+tqEyyRi2foHhZDnFVfiO/Dhgk=' } 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 adc6af8c605..52d3e96f917 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 @@ -113,7 +113,6 @@ default Optional getBaseFee() { * @return The target blobs per block of this header. */ @Unstable - // TODO SLD should be Quantity or new subclass of Quantity? default Optional getTargetBlobsPerBlock() { return Optional.empty(); }