Fcu verify payload attributes (#3837)

* check that the timestamp in fcu payload attributes is greater than the one of the head block

Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net>
pull/3965/head
Daniel Lehrner 2 years ago committed by GitHub
parent c3a222a725
commit 81f25e15f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 28
      acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/06_update_forkchoice_invalid_payload_attributes.json
  3. 0
      acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/07_update_forkchoice.json
  4. 0
      acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/08_unknown_payload.json
  5. 0
      acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/09_invalid_head.json
  6. 22
      consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java
  7. 42
      consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeMiningCoordinator.java
  8. 44
      consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/PayloadAttributes.java
  9. 8
      consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/TransitionCoordinator.java
  10. 77
      consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java
  11. 72
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineForkchoiceUpdated.java
  12. 1
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/JsonRpcError.java
  13. 9
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineForkchoiceUpdatedTest.java

@ -5,6 +5,7 @@
### Additions and Improvements
- \[EXPERIMENTAL\] Add checkpoint sync `--sync-mode="X_CHECKPOINT"` [#3849](https://github.com/hyperledger/besu/pull/3849)
- Support `finalized` and `safe` as tags for the block parameter in RPC APIs [#3950](https://github.com/hyperledger/besu/pull/3950)
- Added verification of payload attributes in ForkchoiceUpdated [#3837](https://github.com/hyperledger/besu/pull/3837)
### Bug Fixes
- alias engine-rpc-port parameter with the former rpc param name [#3958](https://github.com/hyperledger/besu/pull/3958)

@ -0,0 +1,28 @@
{
"request": {
"jsonrpc": "2.0",
"method": "engine_forkchoiceUpdatedV1",
"params": [
{
"headBlockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858",
"safeBlockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858",
"finalizedBlockHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a"
},
{
"timestamp": "0x0",
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
"suggestedFeeRecipient": "0x0000000000000000000000000000000000000000"
}
],
"id": 67
},
"response": {
"jsonrpc": "2.0",
"id": 67,
"error": {
"code": -38003,
"message": "Invalid payload attributes"
}
},
"statusCode": 200
}

@ -15,6 +15,8 @@
package org.hyperledger.besu.consensus.merge.blockcreation;
import static org.hyperledger.besu.consensus.merge.TransitionUtils.isTerminalProofOfWorkBlock;
import static org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator.ForkchoiceResult.Status.INVALID;
import static org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator.ForkchoiceResult.Status.INVALID_PAYLOAD_ATTRIBUTES;
import static org.hyperledger.besu.util.Slf4jLambdaHelper.debugLambda;
import org.hyperledger.besu.consensus.merge.MergeContext;
@ -251,7 +253,10 @@ public class MergeCoordinator implements MergeMiningCoordinator {
@Override
public ForkchoiceResult updateForkChoice(
final BlockHeader newHead, final Hash finalizedBlockHash, final Hash safeBlockHash) {
final BlockHeader newHead,
final Hash finalizedBlockHash,
final Hash safeBlockHash,
final Optional<PayloadAttributes> maybePayloadAttributes) {
MutableBlockchain blockchain = protocolContext.getBlockchain();
Optional<BlockHeader> currentFinalized = mergeContext.getFinalized();
final Optional<BlockHeader> newFinalized = blockchain.getBlockHeader(finalizedBlockHash);
@ -262,6 +267,7 @@ public class MergeCoordinator implements MergeMiningCoordinator {
&& newFinalized.isPresent()
&& !isDescendantOf(currentFinalized.get(), newFinalized.get())) {
return ForkchoiceResult.withFailure(
INVALID,
String.format(
"new finalized block %s is not a descendant of current finalized block %s",
finalizedBlockHash, currentFinalized.get().getBlockHash()),
@ -281,14 +287,14 @@ public class MergeCoordinator implements MergeMiningCoordinator {
newHead.getBlockHash(), finalized.getBlockHash()));
if (descendantError.isPresent()) {
return ForkchoiceResult.withFailure(descendantError.get(), latestValid);
return ForkchoiceResult.withFailure(INVALID, descendantError.get(), latestValid);
}
Optional<BlockHeader> parentOfNewHead = blockchain.getBlockHeader(newHead.getParentHash());
if (parentOfNewHead.isPresent()
&& parentOfNewHead.get().getTimestamp() >= newHead.getTimestamp()) {
return ForkchoiceResult.withFailure(
"new head timestamp not greater than parent", latestValid);
INVALID, "new head timestamp not greater than parent", latestValid);
}
// set the new head
blockchain.rewindToBlock(newHead.getHash());
@ -308,6 +314,11 @@ public class MergeCoordinator implements MergeMiningCoordinator {
mergeContext.setSafeBlock(newSafeBlock);
});
if (maybePayloadAttributes.isPresent()
&& !isPayloadAttributesValid(maybePayloadAttributes.get(), newHead)) {
return ForkchoiceResult.withFailure(INVALID_PAYLOAD_ATTRIBUTES, null, Optional.empty());
}
return ForkchoiceResult.withResult(newFinalized, Optional.of(newHead));
}
@ -472,6 +483,11 @@ public class MergeCoordinator implements MergeMiningCoordinator {
return false;
}
private boolean isPayloadAttributesValid(
final PayloadAttributes payloadAttributes, final BlockHeader headBlockHeader) {
return payloadAttributes.getTimestamp() > headBlockHeader.getTimestamp();
}
@FunctionalInterface
interface MergeBlockCreatorFactory {
MergeBlockCreator forParams(BlockHeader header, Optional<Address> feeRecipient);

@ -14,6 +14,8 @@
*/
package org.hyperledger.besu.consensus.merge.blockcreation;
import static org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator.ForkchoiceResult.Status.VALID;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.BlockValidator.Result;
@ -36,7 +38,10 @@ public interface MergeMiningCoordinator extends MiningCoordinator {
Result executeBlock(final Block block);
ForkchoiceResult updateForkChoice(
final BlockHeader newHead, final Hash finalizedBlockHash, final Hash safeBlockHash);
final BlockHeader newHead,
final Hash finalizedBlockHash,
final Hash safeBlockHash,
final Optional<PayloadAttributes> maybePayloadAttributes);
Optional<Hash> getLatestValidAncestor(Hash blockHash);
@ -55,16 +60,25 @@ public interface MergeMiningCoordinator extends MiningCoordinator {
boolean isMiningBeforeMerge();
class ForkchoiceResult {
public enum Status {
VALID,
INVALID,
INVALID_PAYLOAD_ATTRIBUTES
}
private final Status status;
private final Optional<String> errorMessage;
private final Optional<BlockHeader> newFinalized;
private final Optional<BlockHeader> newHead;
private final Optional<Hash> latestValid;
private ForkchoiceResult(
final Status status,
final Optional<String> errorMessage,
final Optional<BlockHeader> newFinalized,
final Optional<BlockHeader> newHead,
final Optional<Hash> latestValid) {
this.status = status;
this.errorMessage = errorMessage;
this.newFinalized = newFinalized;
this.newHead = newHead;
@ -72,14 +86,22 @@ public interface MergeMiningCoordinator extends MiningCoordinator {
}
public static ForkchoiceResult withFailure(
final String errorMessage, final Optional<Hash> latestValid) {
final Status status, final String errorMessage, final Optional<Hash> latestValid) {
return new ForkchoiceResult(
Optional.of(errorMessage), Optional.empty(), Optional.empty(), latestValid);
status,
Optional.ofNullable(errorMessage),
Optional.empty(),
Optional.empty(),
latestValid);
}
public static ForkchoiceResult withResult(
final Optional<BlockHeader> newFinalized, final Optional<BlockHeader> newHead) {
return new ForkchoiceResult(Optional.empty(), newFinalized, newHead, Optional.empty());
return new ForkchoiceResult(VALID, Optional.empty(), newFinalized, newHead, Optional.empty());
}
public Status getStatus() {
return status;
}
public Optional<String> getErrorMessage() {
@ -98,16 +120,8 @@ public interface MergeMiningCoordinator extends MiningCoordinator {
return latestValid;
}
public boolean isFailed() {
return errorMessage.isPresent();
}
public boolean isSuccessful() {
return newHead.isPresent() || newFinalized.isPresent();
}
public boolean isUnknown() {
return errorMessage.isEmpty() && newFinalized.isEmpty();
public boolean isValid() {
return status == VALID;
}
}
}

@ -0,0 +1,44 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.consensus.merge.blockcreation;
import org.hyperledger.besu.datatypes.Address;
import org.apache.tuweni.bytes.Bytes32;
public class PayloadAttributes {
private final Long timestamp;
private final Bytes32 prevRandao;
private final Address suggestedFeeRecipient;
public PayloadAttributes(
final Long timestamp, final Bytes32 prevRandao, final Address suggestedFeeRecipient) {
this.timestamp = timestamp;
this.prevRandao = prevRandao;
this.suggestedFeeRecipient = suggestedFeeRecipient;
}
public Long getTimestamp() {
return timestamp;
}
public Bytes32 getPrevRandao() {
return prevRandao;
}
public Address getSuggestedFeeRecipient() {
return suggestedFeeRecipient;
}
}

@ -139,8 +139,12 @@ public class TransitionCoordinator extends TransitionUtils<MiningCoordinator>
@Override
public ForkchoiceResult updateForkChoice(
final BlockHeader newHead, final Hash finalizedBlockHash, final Hash safeBlockHash) {
return mergeCoordinator.updateForkChoice(newHead, finalizedBlockHash, safeBlockHash);
final BlockHeader newHead,
final Hash finalizedBlockHash,
final Hash safeBlockHash,
final Optional<PayloadAttributes> maybePayloadAttributes) {
return mergeCoordinator.updateForkChoice(
newHead, finalizedBlockHash, safeBlockHash, maybePayloadAttributes);
}
@Override

@ -143,9 +143,9 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
ForkchoiceResult result =
coordinator.updateForkChoice(
childHeader, terminalHeader.getHash(), terminalHeader.getHash());
childHeader, terminalHeader.getHash(), terminalHeader.getHash(), Optional.empty());
assertThat(result.isSuccessful()).isFalse();
assertThat(result.isValid()).isFalse();
assertThat(result.getErrorMessage()).isPresent();
assertThat(result.getErrorMessage().get())
.isEqualTo("new head timestamp not greater than parent");
@ -220,7 +220,10 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
coordinator.executeBlock(headBlock);
coordinator.updateForkChoice(
headBlockHeader, firstFinalizedBlock.getHash(), firstFinalizedBlock.getHash());
headBlockHeader,
firstFinalizedBlock.getHash(),
firstFinalizedBlock.getHash(),
Optional.empty());
verify(blockchain).setFinalized(firstFinalizedBlock.getHash());
verify(mergeContext).setFinalized(firstFinalizedHeader);
@ -248,7 +251,10 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
coordinator.executeBlock(headBlock);
coordinator.updateForkChoice(
headBlockHeader, lastFinalizedBlock.getHash(), lastFinalizedBlock.getHash());
headBlockHeader,
lastFinalizedBlock.getHash(),
lastFinalizedBlock.getHash(),
Optional.empty());
verify(blockchain).setFinalized(lastFinalizedBlock.getHash());
verify(mergeContext).setFinalized(lastFinalizedHeader);
@ -281,8 +287,12 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
.thenReturn(Optional.of(headBlockHeader));
var res =
coordinator.updateForkChoice(
headBlockHeader, lastFinalizedBlock.getHash(), lastFinalizedBlock.getHash());
assertThat(res.isFailed()).isTrue();
headBlockHeader,
lastFinalizedBlock.getHash(),
lastFinalizedBlock.getHash(),
Optional.empty());
assertThat(res.isValid()).isFalse();
assertThat(res.getStatus()).isEqualTo(ForkchoiceResult.Status.INVALID);
verify(blockchain, never()).setFinalized(lastFinalizedBlock.getHash());
verify(mergeContext, never()).setFinalized(lastFinalizedHeader);
@ -315,9 +325,12 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
.thenReturn(Optional.of(headBlockHeader));
var res =
coordinator.updateForkChoice(
headBlockHeader, lastFinalizedBlock.getHash(), lastFinalizedBlock.getHash());
assertThat(res.isSuccessful()).isFalse();
assertThat(res.isFailed()).isTrue();
headBlockHeader,
lastFinalizedBlock.getHash(),
lastFinalizedBlock.getHash(),
Optional.empty());
assertThat(res.isValid()).isFalse();
assertThat(res.getStatus()).isEqualTo(ForkchoiceResult.Status.INVALID);
verify(blockchain, never()).setFinalized(lastFinalizedBlock.getHash());
verify(mergeContext, never()).setFinalized(lastFinalizedHeader);
@ -349,9 +362,12 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
.thenReturn(Optional.of(headBlockHeader));
var res =
coordinator.updateForkChoice(
headBlockHeader, lastFinalizedBlock.getHash(), lastFinalizedBlock.getHash());
assertThat(res.isSuccessful()).isFalse();
assertThat(res.isFailed()).isTrue();
headBlockHeader,
lastFinalizedBlock.getHash(),
lastFinalizedBlock.getHash(),
Optional.empty());
assertThat(res.isValid()).isFalse();
assertThat(res.getStatus()).isEqualTo(ForkchoiceResult.Status.INVALID);
verify(blockchain, never()).setFinalized(lastFinalizedBlock.getHash());
verify(mergeContext, never()).setFinalized(lastFinalizedHeader);
@ -521,6 +537,43 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
assertThat(mockCoordinator.latestValidAncestorDescendsFromTerminal(blockZero)).isFalse();
}
@Test
public void invalidPayloadShouldReturnErrorAndUpdateForkchoiceState() {
BlockHeader terminalHeader = terminalPowBlock();
coordinator.executeBlock(new Block(terminalHeader, BlockBody.empty()));
BlockHeader prevFinalizedHeader = nextBlockHeader(terminalHeader);
Block prevFinalizedBlock = new Block(prevFinalizedHeader, BlockBody.empty());
coordinator.executeBlock(prevFinalizedBlock);
when(mergeContext.getFinalized()).thenReturn(Optional.of(prevFinalizedHeader));
BlockHeader lastFinalizedHeader = nextBlockHeader(prevFinalizedHeader);
Block lastFinalizedBlock = new Block(lastFinalizedHeader, BlockBody.empty());
coordinator.executeBlock(lastFinalizedBlock);
BlockHeader headBlockHeader = nextBlockHeader(lastFinalizedHeader);
Block headBlock = new Block(headBlockHeader, BlockBody.empty());
coordinator.executeBlock(headBlock);
var res =
coordinator.updateForkChoice(
headBlockHeader,
lastFinalizedBlock.getHash(),
lastFinalizedBlock.getHash(),
Optional.of(
new PayloadAttributes(
headBlockHeader.getTimestamp() - 1, Hash.ZERO, Address.ZERO)));
assertThat(res.isValid()).isFalse();
assertThat(res.getStatus()).isEqualTo(ForkchoiceResult.Status.INVALID_PAYLOAD_ATTRIBUTES);
verify(blockchain).setFinalized(lastFinalizedBlock.getHash());
verify(mergeContext).setFinalized(lastFinalizedHeader);
verify(blockchain).setSafeBlock(lastFinalizedBlock.getHash());
verify(mergeContext).setSafeBlock(lastFinalizedHeader);
}
private BlockHeader terminalPowBlock() {
return headerGenerator
.difficulty(Difficulty.MAX_VALUE)

@ -21,6 +21,7 @@ import static org.hyperledger.besu.util.Slf4jLambdaHelper.debugLambda;
import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator;
import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator.ForkchoiceResult;
import org.hyperledger.besu.consensus.merge.blockcreation.PayloadAttributes;
import org.hyperledger.besu.consensus.merge.blockcreation.PayloadIdentifier;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.ProtocolContext;
@ -65,7 +66,7 @@ public class EngineForkchoiceUpdated extends ExecutionEngineJsonRpcMethod {
final EngineForkchoiceUpdatedParameter forkChoice =
requestContext.getRequiredParameter(0, EngineForkchoiceUpdatedParameter.class);
final Optional<EnginePayloadAttributesParameter> optionalPayloadAttributes =
final Optional<EnginePayloadAttributesParameter> maybePayloadAttributes =
requestContext.getOptionalParameter(1, EnginePayloadAttributesParameter.class);
Optional<Hash> maybeFinalizedHash =
@ -96,6 +97,9 @@ public class EngineForkchoiceUpdated extends ExecutionEngineJsonRpcMethod {
forkChoice.getFinalizedBlockHash(),
forkChoice.getSafeBlockHash());
maybePayloadAttributes.ifPresentOrElse(
this::logPayload, () -> LOG.debug("Payload attributes are null"));
if (!isValidForkchoiceState(
forkChoice.getSafeBlockHash(), forkChoice.getFinalizedBlockHash(), newHead.get())) {
return new JsonRpcErrorResponse(requestId, JsonRpcError.INVALID_FORKCHOICE_STATE);
@ -114,22 +118,23 @@ public class EngineForkchoiceUpdated extends ExecutionEngineJsonRpcMethod {
ForkchoiceResult result =
mergeCoordinator.updateForkChoice(
newHead.get(), forkChoice.getFinalizedBlockHash(), forkChoice.getSafeBlockHash());
if (result.isFailed()) {
final Optional<Hash> latestValid = result.getLatestValid();
return new JsonRpcSuccessResponse(
requestId,
new EngineUpdateForkchoiceResult(
INVALID,
latestValid.isPresent() ? latestValid.get() : null,
null,
result.getErrorMessage()));
newHead.get(),
forkChoice.getFinalizedBlockHash(),
forkChoice.getSafeBlockHash(),
maybePayloadAttributes.map(
payloadAttributes ->
new PayloadAttributes(
payloadAttributes.getTimestamp(),
payloadAttributes.getPrevRandao(),
payloadAttributes.getSuggestedFeeRecipient())));
if (!result.isValid()) {
return handleForkchoiceError(requestId, result);
}
// begin preparing a block if we have a non-empty payload attributes param
Optional<PayloadIdentifier> payloadId =
optionalPayloadAttributes.map(
maybePayloadAttributes.map(
payloadAttributes ->
mergeCoordinator.preparePayload(
newHead.get(),
@ -143,7 +148,7 @@ public class EngineForkchoiceUpdated extends ExecutionEngineJsonRpcMethod {
LOG,
"returning identifier {} for requested payload {}",
pid::toHexString,
() -> optionalPayloadAttributes.map(EnginePayloadAttributesParameter::serialize)));
() -> maybePayloadAttributes.map(EnginePayloadAttributesParameter::serialize)));
return new JsonRpcSuccessResponse(
requestId,
@ -154,6 +159,45 @@ public class EngineForkchoiceUpdated extends ExecutionEngineJsonRpcMethod {
Optional.empty()));
}
private JsonRpcResponse handleForkchoiceError(
final Object requestId, final ForkchoiceResult result) {
JsonRpcResponse response;
final Optional<Hash> latestValid = result.getLatestValid();
switch (result.getStatus()) {
case INVALID:
response =
new JsonRpcSuccessResponse(
requestId,
new EngineUpdateForkchoiceResult(
INVALID,
latestValid.isPresent() ? latestValid.get() : null,
null,
result.getErrorMessage()));
break;
case INVALID_PAYLOAD_ATTRIBUTES:
response = new JsonRpcErrorResponse(requestId, JsonRpcError.INVALID_PAYLOAD_ATTRIBUTES);
break;
default:
throw new AssertionError(
"ForkchoiceResult.Status "
+ result.getStatus()
+ " not handled in EngineForkchoiceUpdated.handleForkchoiceError");
}
return response;
}
private void logPayload(final EnginePayloadAttributesParameter payloadAttributes) {
debugLambda(
LOG,
"timestamp: {}, prevRandao: {}, suggestedFeeRecipient: {}",
payloadAttributes::getTimestamp,
() -> payloadAttributes.getPrevRandao().toHexString(),
() -> payloadAttributes.getSuggestedFeeRecipient().toHexString());
}
private boolean isValidForkchoiceState(
final Hash safeBlockHash, final Hash finalizedBlockHash, final BlockHeader newBlock) {
Optional<BlockHeader> maybeFinalizedBlock = Optional.empty();

@ -76,6 +76,7 @@ public enum JsonRpcError {
UNKNOWN_PAYLOAD(-32001, "Payload does not exist / is not available"),
INVALID_TERMINAL_BLOCK(-32002, "Terminal block doesn't satisfy terminal block conditions"),
INVALID_FORKCHOICE_STATE(-38002, "Invalid forkchoice state"),
INVALID_PAYLOAD_ATTRIBUTES(-38003, "Invalid payload attributes"),
// Miner failures
COINBASE_NOT_SET(-32010, "Coinbase not set. Unable to start mining without a coinbase"),

@ -144,10 +144,13 @@ public class EngineForkchoiceUpdatedTest {
when(mergeCoordinator.latestValidAncestorDescendsFromTerminal(mockHeader)).thenReturn(true);
when(mergeCoordinator.isDescendantOf(any(), any())).thenReturn(true);
when(mergeContext.isSyncing()).thenReturn(false);
when(mergeCoordinator.updateForkChoice(mockHeader, parent.getHash(), parent.getHash()))
when(mergeCoordinator.updateForkChoice(
mockHeader, parent.getHash(), parent.getHash(), Optional.empty()))
.thenReturn(
ForkchoiceResult.withFailure(
"new head timestamp not greater than parent", Optional.of(parent.getHash())));
ForkchoiceResult.Status.INVALID,
"new head timestamp not greater than parent",
Optional.of(parent.getHash())));
EngineForkchoiceUpdatedParameter param =
new EngineForkchoiceUpdatedParameter(
@ -352,7 +355,7 @@ public class EngineForkchoiceUpdatedTest {
// result from mergeCoordinator has no new finalized, new head:
when(mergeCoordinator.updateForkChoice(
any(BlockHeader.class), any(Hash.class), any(Hash.class)))
any(BlockHeader.class), any(Hash.class), any(Hash.class), any()))
.thenReturn(forkchoiceResult);
var resp =
resp(new EngineForkchoiceUpdatedParameter(mockHash, mockHash, mockHash), payloadParam);

Loading…
Cancel
Save