Skip to content

Commit

Permalink
Add getForNextBlockHeader to protocol schedule (hyperledger#5224)
Browse files Browse the repository at this point in the history
Signed-off-by: Jason Frame <jason.frame@consensys.net>
  • Loading branch information
jframe authored Mar 22, 2023
1 parent 4dff9d3 commit 764a9b6
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ public JsonRpcResponse response(final JsonRpcRequestContext request) {
final Optional<List<Double>> maybeRewardPercentiles =
request.getOptionalParameter(2, Double[].class).map(Arrays::asList);

final long chainHeadBlockNumber = blockchain.getChainHeadBlockNumber();
final BlockHeader chainHeadHeader = blockchain.getChainHeadHeader();
final long chainHeadBlockNumber = chainHeadHeader.getNumber();
final long resolvedHighestBlockNumber =
highestBlock
.getNumber()
Expand Down Expand Up @@ -106,7 +107,14 @@ public JsonRpcResponse response(final JsonRpcRequestContext request) {
.map(blockHeader -> blockHeader.getBaseFee().orElse(Wei.ZERO))
.orElseGet(
() ->
Optional.of(protocolSchedule.getByBlockNumber(nextBlockNumber).getFeeMarket())
Optional.of(
// We are able to use the chain head timestamp for next block header as
// the base fee market can only be pre or post London. If another fee
// market is added will need to reconsider this.
protocolSchedule
.getForNextBlockHeader(
chainHeadHeader, chainHeadHeader.getTimestamp())
.getFeeMarket())
.filter(FeeMarket::implementsBaseFee)
.map(BaseFeeMarket.class::cast)
.map(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ public UnsignedIntParameter(final String value) {
checkArgument(this.value >= 0);
}

@JsonCreator
public UnsignedIntParameter(final int value) {
this.value = value;
checkArgument(this.value >= 0);
}

public int getValue() {
return value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryBlockchain;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -65,7 +66,7 @@ public void setUp() {
public void params() {
final ProtocolSpec londonSpec = mock(ProtocolSpec.class);
when(londonSpec.getFeeMarket()).thenReturn(FeeMarket.london(5));
when(protocolSchedule.getByBlockNumber(anyLong())).thenReturn(londonSpec);
when(protocolSchedule.getForNextBlockHeader(any(), anyLong())).thenReturn(londonSpec);
// should fail because no required params given
assertThatThrownBy(this::feeHistoryRequest).isInstanceOf(InvalidJsonRpcParameters.class);
// should fail because newestBlock not given
Expand All @@ -85,10 +86,14 @@ public void params() {
public void allFieldsPresentForLatestBlock() {
final ProtocolSpec londonSpec = mock(ProtocolSpec.class);
when(londonSpec.getFeeMarket()).thenReturn(FeeMarket.london(5));
when(protocolSchedule.getByBlockNumber(eq(11L))).thenReturn(londonSpec);
assertThat(
((JsonRpcSuccessResponse) feeHistoryRequest("0x1", "latest", new double[] {100.0}))
.getResult())
when(protocolSchedule.getForNextBlockHeader(
eq(blockchain.getChainHeadHeader()),
eq(blockchain.getChainHeadHeader().getTimestamp())))
.thenReturn(londonSpec);
final Object latest =
((JsonRpcSuccessResponse) feeHistoryRequest("0x1", "latest", new double[] {100.0}))
.getResult();
assertThat(latest)
.isEqualTo(
FeeHistory.FeeHistoryResult.from(
ImmutableFeeHistory.builder()
Expand All @@ -103,7 +108,7 @@ public void allFieldsPresentForLatestBlock() {
public void cantGetBlockHigherThanChainHead() {
final ProtocolSpec londonSpec = mock(ProtocolSpec.class);
when(londonSpec.getFeeMarket()).thenReturn(FeeMarket.london(5));
when(protocolSchedule.getByBlockNumber(anyLong())).thenReturn(londonSpec);
when(protocolSchedule.getForNextBlockHeader(any(), anyLong())).thenReturn(londonSpec);
assertThat(
((JsonRpcErrorResponse) feeHistoryRequest("0x2", "11", new double[] {100.0}))
.getError())
Expand All @@ -129,7 +134,7 @@ public void blockCountBounds() {
public void doesntGoPastChainHeadWithHighBlockCount() {
final ProtocolSpec londonSpec = mock(ProtocolSpec.class);
when(londonSpec.getFeeMarket()).thenReturn(FeeMarket.london(5));
when(protocolSchedule.getByBlockNumber(anyLong())).thenReturn(londonSpec);
when(protocolSchedule.getForNextBlockHeader(any(), anyLong())).thenReturn(londonSpec);
final FeeHistory.FeeHistoryResult result =
(ImmutableFeeHistoryResult)
((JsonRpcSuccessResponse) feeHistoryRequest("0x14", "latest")).getResult();
Expand All @@ -143,7 +148,7 @@ public void doesntGoPastChainHeadWithHighBlockCount() {
public void correctlyHandlesForkBlock() {
final ProtocolSpec londonSpec = mock(ProtocolSpec.class);
when(londonSpec.getFeeMarket()).thenReturn(FeeMarket.london(11));
when(protocolSchedule.getByBlockNumber(anyLong())).thenReturn(londonSpec);
when(protocolSchedule.getForNextBlockHeader(any(), anyLong())).thenReturn(londonSpec);
final FeeHistory.FeeHistoryResult result =
(FeeHistory.FeeHistoryResult)
((JsonRpcSuccessResponse) feeHistoryRequest("0x1", "latest")).getResult();
Expand All @@ -155,7 +160,7 @@ public void correctlyHandlesForkBlock() {
public void allZeroPercentilesForZeroBlock() {
final ProtocolSpec londonSpec = mock(ProtocolSpec.class);
when(londonSpec.getFeeMarket()).thenReturn(FeeMarket.london(5));
when(protocolSchedule.getByBlockNumber(anyLong())).thenReturn(londonSpec);
when(protocolSchedule.getForNextBlockHeader(any(), anyLong())).thenReturn(londonSpec);
final BlockDataGenerator.BlockOptions blockOptions = BlockDataGenerator.BlockOptions.create();
blockOptions.hasTransactions(false);
blockOptions.setParentHash(blockchain.getChainHeadHash());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import org.hyperledger.besu.ethereum.mainnet.AbstractBlockProcessor;
import org.hyperledger.besu.ethereum.mainnet.BodyValidation;
import org.hyperledger.besu.ethereum.mainnet.DifficultyCalculator;
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
Expand Down Expand Up @@ -156,13 +155,7 @@ protected BlockCreationResult createBlock(

try (final MutableWorldState disposableWorldState = duplicateWorldStateAtParent()) {
final ProtocolSpec newProtocolSpec =
protocolSchedule.getByBlockHeader(
BlockHeaderBuilder.fromHeader(parentHeader)
.number(parentHeader.getNumber() + 1)
.timestamp(timestamp)
.parentHash(parentHeader.getHash())
.blockHeaderFunctions(new MainnetBlockHeaderFunctions())
.buildBlockHeader());
protocolSchedule.getForNextBlockHeader(parentHeader, timestamp);

final ProcessableBlockHeader processableBlockHeader =
createPendingBlockHeader(timestamp, maybePrevRandao, newProtocolSpec);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.hyperledger.besu.ethereum.mainnet.EpochCalculator;
import org.hyperledger.besu.ethereum.mainnet.PoWSolver;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.util.Subscribers;

import java.util.Optional;
Expand Down Expand Up @@ -72,10 +73,14 @@ public PoWBlockMiner createMiner(
final Subscribers<MinedBlockObserver> observers,
final Subscribers<PoWObserver> ethHashObservers,
final BlockHeader parentHeader) {
// We don't need to consider the timestamp when getting the protocol schedule for the next block
// as timestamps are not used for defining forks when using POW
final ProtocolSpec nextBlockProtocolSpec =
protocolSchedule.getForNextBlockHeader(parentHeader, 0);
final PoWSolver solver =
new PoWSolver(
nonceGenerator,
protocolSchedule.getByBlockNumber(parentHeader.getNumber() + 1).getPoWHasher().get(),
nextBlockProtocolSpec.getPoWHasher().get(),
stratumMiningEnabled,
ethHashObservers,
epochCalculator,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package org.hyperledger.besu.ethereum.mainnet;

import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder;
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;

import java.math.BigInteger;
Expand All @@ -28,6 +29,18 @@ public interface HeaderBasedProtocolSchedule {

ProtocolSpec getByBlockHeader(final ProcessableBlockHeader blockHeader);

default ProtocolSpec getForNextBlockHeader(
final BlockHeader parentBlockHeader, final long timestampForNextBlock) {
final BlockHeader nextBlockHeader =
BlockHeaderBuilder.fromHeader(parentBlockHeader)
.number(parentBlockHeader.getNumber() + 1)
.timestamp(timestampForNextBlock)
.parentHash(parentBlockHeader.getHash())
.blockHeaderFunctions(new MainnetBlockHeaderFunctions())
.buildBlockHeader();
return getByBlockHeader(nextBlockHeader);
}

Optional<BigInteger> getChainId();

void putMilestone(final long blockOrTimestamp, final ProtocolSpec protocolSpec);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@
package org.hyperledger.besu.ethereum.mainnet;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;

import org.hyperledger.besu.config.StubGenesisConfigOptions;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.evm.internal.EvmConfiguration;

import java.math.BigInteger;
import java.util.Optional;
import java.util.function.Function;

import org.junit.Before;
Expand Down Expand Up @@ -101,6 +104,22 @@ public void isOnMilestoneBoundary() {
assertThat(protocolSchedule.isOnMilestoneBoundary(header(4))).isEqualTo(true);
}

@Test
public void getForNextBlockHeader_shouldGetHeaderForNextTimestamp() {
final ProtocolSpec spec1 = mock(ProtocolSpec.class);
final ProtocolSpec spec2 = mock(ProtocolSpec.class);

final TimestampSchedule protocolSchedule = new DefaultTimestampSchedule(Optional.of(chainId));
protocolSchedule.putMilestone(0, spec1);
protocolSchedule.putMilestone(1000, spec2);

final BlockHeader blockHeader =
BlockHeaderBuilder.createDefault().number(0L).buildBlockHeader();
final ProtocolSpec spec = protocolSchedule.getForNextBlockHeader(blockHeader, 1000);

assertThat(spec).isEqualTo(spec2);
}

private BlockHeader header(final long timestamp) {
return new BlockHeaderTestFixture().timestamp(timestamp).buildHeader();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import org.hyperledger.besu.config.StubGenesisConfigOptions;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
Expand Down Expand Up @@ -119,6 +120,22 @@ public void getByBlockHeader_defaultMethodShouldUseGetByBlockNumber() {
assertThat(spec).isEqualTo(spec2);
}

@Test
public void getForNextBlockHeader_shouldGetHeaderForNextBlockNumber() {
final ProtocolSpec spec1 = mock(ProtocolSpec.class);
final ProtocolSpec spec2 = mock(ProtocolSpec.class);

final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule(CHAIN_ID);
protocolSchedule.putMilestone(0, spec1);
protocolSchedule.putMilestone(1, spec2);

final BlockHeader blockHeader =
BlockHeaderBuilder.createDefault().number(0L).buildBlockHeader();
final ProtocolSpec spec = protocolSchedule.getForNextBlockHeader(blockHeader, 0);

assertThat(spec).isEqualTo(spec2);
}

@Test
public void isOnMilestoneBoundary() {
config.berlinBlock(1L);
Expand Down

0 comments on commit 764a9b6

Please sign in to comment.