Add getForNextBlockHeader to protocol schedule (#5224)

Signed-off-by: Jason Frame <jason.frame@consensys.net>
pull/5257/head
Jason Frame 2 years ago committed by GitHub
parent 4dff9d3974
commit 764a9b6f2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthFeeHistory.java
  2. 6
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/UnsignedIntParameter.java
  3. 23
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthFeeHistoryTest.java
  4. 9
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java
  5. 7
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutor.java
  6. 13
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/HeaderBasedProtocolSchedule.java
  7. 19
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/DefaultTimestampScheduleTest.java
  8. 17
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MutableProtocolScheduleTest.java
  9. 2
      ethereum/referencetests/src/reference-test/external-resources

@ -75,7 +75,8 @@ public class EthFeeHistory implements JsonRpcMethod {
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()
@ -106,7 +107,14 @@ public class EthFeeHistory implements JsonRpcMethod {
.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(

@ -28,6 +28,12 @@ public class UnsignedIntParameter {
checkArgument(this.value >= 0);
}
@JsonCreator
public UnsignedIntParameter(final int value) {
this.value = value;
checkArgument(this.value >= 0);
}
public int getValue() {
return value;
}

@ -17,6 +17,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
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;
@ -65,7 +66,7 @@ public class EthFeeHistoryTest {
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
@ -85,10 +86,14 @@ public class EthFeeHistoryTest {
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()
@ -103,7 +108,7 @@ public class EthFeeHistoryTest {
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())
@ -129,7 +134,7 @@ public class EthFeeHistoryTest {
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();
@ -143,7 +148,7 @@ public class EthFeeHistoryTest {
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();
@ -155,7 +160,7 @@ public class EthFeeHistoryTest {
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());

@ -34,7 +34,6 @@ import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
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;
@ -156,13 +155,7 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
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);

@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
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;
@ -72,10 +73,14 @@ public class PoWMinerExecutor extends AbstractMinerExecutor<PoWBlockMiner> {
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,

@ -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;
@ -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);

@ -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;
@ -101,6 +104,22 @@ public class DefaultTimestampScheduleTest {
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();
}

@ -20,6 +20,7 @@ import static org.mockito.Mockito.when;
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;
@ -119,6 +120,22 @@ public class MutableProtocolScheduleTest {
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);

@ -1 +1 @@
Subproject commit 291118cf69f33a4a89f2f61c7bf5fe0e62c9c2f8
Subproject commit bac70c50a579197af68af5fc6d8c7b6163b92c52
Loading…
Cancel
Save