Skip to content

Commit

Permalink
Replace usage of getByTimestamp in WithdrawalsValidatorProvider (hype…
Browse files Browse the repository at this point in the history
…rledger#5261)

Use schedule.getByBlockHeader for newPayload, constructing a dummy header for the sole purpose of getting the correct WithdrawalsValidator for this block. See reviews comments below for context.

Use schedule.getForNextBlockHeader for forkchoiceUpdated.

Once we remove usages of schedule.getByTimestamp, we can unify the protocol schedules.

Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
  • Loading branch information
siladu authored and eum602 committed Nov 3, 2023
1 parent 5834d60 commit 640114b
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ private boolean isPayloadAttributesValid(
final boolean newTimestampGreaterThanHead =
payloadAttributes.getTimestamp() > headBlockHeader.getTimestamp();
return newTimestampGreaterThanHead
&& getWithdrawalsValidator(timestampSchedule, payloadAttributes.getTimestamp())
&& getWithdrawalsValidator(
timestampSchedule, headBlockHeader, payloadAttributes.getTimestamp())
.validateWithdrawals(maybeWithdrawals);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext)
final Optional<List<Withdrawal>> maybeWithdrawals =
Optional.ofNullable(blockParam.getWithdrawals())
.map(ws -> ws.stream().map(WithdrawalParameter::toWithdrawal).collect(toList()));
if (!getWithdrawalsValidator(timestampSchedule, blockParam.getTimestamp())

if (!getWithdrawalsValidator(
timestampSchedule, blockParam.getTimestamp(), blockParam.getBlockNumber())
.validateWithdrawals(maybeWithdrawals)) {
return new JsonRpcErrorResponse(reqId, INVALID_PARAMS);
}
Expand Down Expand Up @@ -188,10 +190,10 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext)
"Block already present in bad block manager.");
}

Optional<BlockHeader> parentHeader =
final Optional<BlockHeader> maybeParentHeader =
protocolContext.getBlockchain().getBlockHeader(blockParam.getParentHash());
if (parentHeader.isPresent()
&& (blockParam.getTimestamp() <= parentHeader.get().getTimestamp())) {
if (maybeParentHeader.isPresent()
&& (blockParam.getTimestamp() <= maybeParentHeader.get().getTimestamp())) {
return respondWithInvalid(
reqId,
blockParam,
Expand All @@ -206,7 +208,7 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext)
new BlockBody(
transactions, Collections.emptyList(), maybeWithdrawals, Optional.empty()));

if (parentHeader.isEmpty()) {
if (maybeParentHeader.isEmpty()) {
LOG.atDebug()
.setMessage("Parent of block {} is not present, append it to backward sync")
.addArgument(block::toLogString)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,42 @@

package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine;

import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.mainnet.TimestampSchedule;
import org.hyperledger.besu.ethereum.mainnet.WithdrawalsValidator;

import java.util.Optional;

public class WithdrawalsValidatorProvider {

static WithdrawalsValidator getWithdrawalsValidator(
final TimestampSchedule timestampSchedule, final long newPayloadTimestamp) {
final TimestampSchedule timestampSchedule,
final long blockTimestamp,
final long blockNumber) {

final BlockHeader blockHeader =
BlockHeaderBuilder.createDefault()
.timestamp(blockTimestamp)
.number(blockNumber)
.buildBlockHeader();
return Optional.ofNullable(timestampSchedule.getByBlockHeader(blockHeader))
.map(ProtocolSpec::getWithdrawalsValidator)
// TODO Withdrawals this is a quirk of the fact timestampSchedule doesn't fallback to the
// previous fork. This might be resolved when
// https://github.com/hyperledger/besu/issues/4789 is played
// and if we can combine protocolSchedule and timestampSchedule.
.orElseGet(WithdrawalsValidator.ProhibitedWithdrawals::new);
}

static WithdrawalsValidator getWithdrawalsValidator(
final TimestampSchedule timestampSchedule,
final BlockHeader parentBlockHeader,
final long timestampForNextBlock) {

return timestampSchedule
.getByTimestamp(newPayloadTimestamp)
return Optional.ofNullable(
timestampSchedule.getForNextBlockHeader(parentBlockHeader, timestampForNextBlock))
.map(ProtocolSpec::getWithdrawalsValidator)
// TODO Withdrawals this is a quirk of the fact timestampSchedule doesn't fallback to the
// previous fork. This might be resolved when
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public void before() {
when(protocolContext.getBlockchain()).thenReturn(blockchain);
when(protocolSpec.getWithdrawalsValidator())
.thenReturn(new WithdrawalsValidator.ProhibitedWithdrawals());
when(timestampSchedule.getByTimestamp(anyLong())).thenReturn(Optional.of(protocolSpec));
when(timestampSchedule.getForNextBlockHeader(any(), anyLong())).thenReturn(protocolSpec);
this.method =
methodFactory.create(
vertx, timestampSchedule, protocolContext, mergeCoordinator, engineCallListener);
Expand Down Expand Up @@ -619,7 +619,7 @@ public void shouldReturnValidIfWithdrawalsIsNotNull_WhenWithdrawalsAllowed() {

@Test
public void shouldReturnValidIfTimestampScheduleIsEmpty() {
when(timestampSchedule.getByTimestamp(anyLong())).thenReturn(Optional.empty());
when(timestampSchedule.getForNextBlockHeader(any(), anyLong())).thenReturn(null);

BlockHeader mockParent = blockHeaderBuilder.number(9L).buildHeader();
BlockHeader mockHeader =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalParameterTestFixture.WITHDRAWAL_PARAM_1;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.INVALID_PARAMS;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
Expand Down Expand Up @@ -124,7 +123,7 @@ public void before() {
when(protocolContext.getBlockchain()).thenReturn(blockchain);
when(protocolSpec.getWithdrawalsValidator())
.thenReturn(new WithdrawalsValidator.ProhibitedWithdrawals());
when(timestampSchedule.getByTimestamp(anyLong())).thenReturn(Optional.of(protocolSpec));
when(timestampSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
when(ethPeers.peerCount()).thenReturn(1);
this.method =
methodFactory.create(
Expand Down Expand Up @@ -462,7 +461,7 @@ public void shouldReturnValidIfWithdrawalsIsNotNull_WhenWithdrawalsAllowed() {

@Test
public void shouldReturnValidIfTimestampScheduleIsEmpty() {
when(timestampSchedule.getByTimestamp(anyLong())).thenReturn(Optional.empty());
when(timestampSchedule.getByBlockHeader(any())).thenReturn(null);
BlockHeader mockHeader =
setupValidPayload(
new BlockProcessingResult(Optional.of(new BlockProcessingOutputs(null, List.of()))),
Expand Down

0 comments on commit 640114b

Please sign in to comment.