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 7b394b5b952..cac3edf952c 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 @@ -254,7 +254,12 @@ public PayloadIdentifier preparePayload( final PayloadIdentifier payloadIdentifier = PayloadIdentifier.forPayloadParams( - parentHeader.getBlockHash(), timestamp, prevRandao, feeRecipient, withdrawals); + parentHeader.getBlockHash(), + timestamp, + prevRandao, + feeRecipient, + withdrawals, + parentBeaconBlockRoot); if (blockCreationTasks.containsKey(payloadIdentifier)) { LOG.debug( 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 6c946ba2ee2..ddd3c1b3e4e 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 @@ -62,6 +62,7 @@ public PayloadIdentifier(final Long payloadId) { * @param prevRandao the prev randao * @param feeRecipient the fee recipient * @param withdrawals the withdrawals + * @param parentBeaconBlockRoot the parent beacon block root * @return the payload identifier */ public static PayloadIdentifier forPayloadParams( @@ -69,7 +70,8 @@ public static PayloadIdentifier forPayloadParams( final Long timestamp, final Bytes32 prevRandao, final Address feeRecipient, - final Optional> withdrawals) { + final Optional> withdrawals, + final Optional parentBeaconBlockRoot) { return new PayloadIdentifier( timestamp @@ -84,7 +86,8 @@ public static PayloadIdentifier forPayloadParams( .sorted(Comparator.comparing(Withdrawal::getIndex)) .map(Withdrawal::hashCode) .reduce(1, (a, b) -> a ^ (b * 31))) - .orElse(0)); + .orElse(0) + ^ ((long) parentBeaconBlockRoot.hashCode()) << 40); } @Override 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 39597f9aabe..314224cf55d 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 @@ -48,7 +48,12 @@ public void serializesToEvenHexRepresentation() { public void conversionCoverage() { var idTest = PayloadIdentifier.forPayloadParams( - Hash.ZERO, 1337L, Bytes32.random(), Address.fromHexString("0x42"), Optional.empty()); + Hash.ZERO, + 1337L, + Bytes32.random(), + Address.fromHexString("0x42"), + Optional.empty(), + Optional.empty()); assertThat(new PayloadIdentifier(idTest.getAsBigInteger().longValue())).isEqualTo(idTest); assertThat(new PayloadIdentifier(idTest.getAsBigInteger().longValue())).isEqualTo(idTest); } @@ -82,10 +87,20 @@ public void differentWithdrawalAmountsYieldDifferentHash() { final Bytes32 prevRandao = Bytes32.random(); var idForWithdrawals1 = PayloadIdentifier.forPayloadParams( - Hash.ZERO, 1337L, prevRandao, Address.fromHexString("0x42"), Optional.of(withdrawals1)); + Hash.ZERO, + 1337L, + prevRandao, + Address.fromHexString("0x42"), + Optional.of(withdrawals1), + Optional.empty()); var idForWithdrawals2 = PayloadIdentifier.forPayloadParams( - Hash.ZERO, 1337L, prevRandao, Address.fromHexString("0x42"), Optional.of(withdrawals2)); + Hash.ZERO, + 1337L, + prevRandao, + Address.fromHexString("0x42"), + Optional.of(withdrawals2), + Optional.empty()); assertThat(idForWithdrawals1).isNotEqualTo(idForWithdrawals2); } @@ -118,10 +133,20 @@ public void differentOrderedWithdrawalsYieldSameHash() { final Bytes32 prevRandao = Bytes32.random(); var idForWithdrawals1 = PayloadIdentifier.forPayloadParams( - Hash.ZERO, 1337L, prevRandao, Address.fromHexString("0x42"), Optional.of(withdrawals1)); + Hash.ZERO, + 1337L, + prevRandao, + Address.fromHexString("0x42"), + Optional.of(withdrawals1), + Optional.empty()); var idForWithdrawals2 = PayloadIdentifier.forPayloadParams( - Hash.ZERO, 1337L, prevRandao, Address.fromHexString("0x42"), Optional.of(withdrawals2)); + Hash.ZERO, + 1337L, + prevRandao, + Address.fromHexString("0x42"), + Optional.of(withdrawals2), + Optional.empty()); assertThat(idForWithdrawals1).isEqualTo(idForWithdrawals2); } @@ -130,10 +155,64 @@ public void emptyOptionalAndEmptyListWithdrawalsYieldDifferentHash() { final Bytes32 prevRandao = Bytes32.random(); var idForWithdrawals1 = PayloadIdentifier.forPayloadParams( - Hash.ZERO, 1337L, prevRandao, Address.fromHexString("0x42"), Optional.empty()); + Hash.ZERO, + 1337L, + prevRandao, + Address.fromHexString("0x42"), + Optional.empty(), + Optional.empty()); var idForWithdrawals2 = PayloadIdentifier.forPayloadParams( - Hash.ZERO, 1337L, prevRandao, Address.fromHexString("0x42"), Optional.of(emptyList())); + Hash.ZERO, + 1337L, + prevRandao, + Address.fromHexString("0x42"), + Optional.of(emptyList()), + Optional.empty()); + assertThat(idForWithdrawals1).isNotEqualTo(idForWithdrawals2); + } + + @Test + public void emptyOptionalAndNonEmptyParentBeaconBlockRootYieldDifferentHash() { + final Bytes32 prevRandao = Bytes32.random(); + var idForWithdrawals1 = + PayloadIdentifier.forPayloadParams( + Hash.ZERO, + 1337L, + prevRandao, + Address.fromHexString("0x42"), + Optional.empty(), + Optional.empty()); + var idForWithdrawals2 = + PayloadIdentifier.forPayloadParams( + Hash.ZERO, + 1337L, + prevRandao, + Address.fromHexString("0x42"), + Optional.empty(), + Optional.of(Bytes32.ZERO)); + assertThat(idForWithdrawals1).isNotEqualTo(idForWithdrawals2); + } + + @Test + public void differentParentBeaconBlockRootYieldDifferentHash() { + final Bytes32 prevRandao = Bytes32.random(); + var idForWithdrawals1 = + PayloadIdentifier.forPayloadParams( + Hash.ZERO, + 1337L, + prevRandao, + Address.fromHexString("0x42"), + Optional.empty(), + Optional.of(Bytes32.fromHexStringLenient("0x1"))); + var idForWithdrawals2 = + PayloadIdentifier.forPayloadParams( + Hash.ZERO, + 1337L, + prevRandao, + Address.fromHexString("0x42"), + Optional.empty(), + Optional.of(Bytes32.ZERO)); assertThat(idForWithdrawals1).isNotEqualTo(idForWithdrawals2); } } 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 32dc15ffc57..63713c4bd0f 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 @@ -242,6 +242,7 @@ public void shouldReturnValidWithoutFinalizedWithPayload() { payloadParams.getTimestamp(), payloadParams.getPrevRandao(), payloadParams.getSuggestedFeeRecipient(), + Optional.empty(), Optional.empty()); when(mergeCoordinator.preparePayload( @@ -518,6 +519,7 @@ public void shouldReturnValidIfWithdrawalsIsNull_WhenWithdrawalsProhibited() { payloadParams.getTimestamp(), payloadParams.getPrevRandao(), payloadParams.getSuggestedFeeRecipient(), + Optional.empty(), Optional.empty()); when(mergeCoordinator.preparePayload( @@ -603,7 +605,8 @@ public void shouldReturnValidIfWithdrawalsIsNotNull_WhenWithdrawalsAllowed() { payloadParams.getTimestamp(), payloadParams.getPrevRandao(), payloadParams.getSuggestedFeeRecipient(), - withdrawals); + withdrawals, + Optional.empty()); when(mergeCoordinator.preparePayload( mockHeader, @@ -645,6 +648,7 @@ public void shouldReturnValidIfProtocolScheduleIsEmpty() { payloadParams.getTimestamp(), payloadParams.getPrevRandao(), payloadParams.getSuggestedFeeRecipient(), + Optional.empty(), Optional.empty()); when(mergeCoordinator.preparePayload( 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 823cd6712ab..fd2f02ba024 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 @@ -85,7 +85,12 @@ public AbstractEngineGetPayloadTest() { protected static final BlockResultFactory factory = new BlockResultFactory(); protected static final PayloadIdentifier mockPid = PayloadIdentifier.forPayloadParams( - Hash.ZERO, 1337L, Bytes32.random(), Address.fromHexString("0x42"), Optional.empty()); + Hash.ZERO, + 1337L, + Bytes32.random(), + Address.fromHexString("0x42"), + Optional.empty(), + Optional.empty()); protected static final BlockHeader mockHeader = new BlockHeaderTestFixture().prevRandao(Bytes32.random()).buildHeader(); private static final Block mockBlock = @@ -147,7 +152,12 @@ public void shouldFailForUnknownPayloadId() { resp( getMethodName(), PayloadIdentifier.forPayloadParams( - Hash.ZERO, 0L, Bytes32.random(), Address.fromHexString("0x42"), Optional.empty())); + Hash.ZERO, + 0L, + Bytes32.random(), + Address.fromHexString("0x42"), + 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/EngineGetPayloadV3Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV3Test.java index 3fc8a6bfd83..1e19bc3fd5d 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,7 @@ public void shouldReturnBlockForKnownPayloadId() { cancunHardfork.milestone(), Bytes32.random(), Address.fromHexString("0x42"), + Optional.empty(), Optional.empty()); BlobTestFixture blobTestFixture = new BlobTestFixture();