diff --git a/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java b/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java index 32518e2410c5..2938088a40de 100644 --- a/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java +++ b/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java @@ -24,14 +24,13 @@ import org.hyperledger.besu.cli.config.NetworkName; import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.config.GenesisConfigOptions; +import org.hyperledger.besu.consensus.merge.TransitionProtocolSchedule; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.GenesisState; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.forkid.ForkId; import org.hyperledger.besu.ethereum.forkid.ForkIdManager; -import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; -import org.hyperledger.besu.evm.internal.EvmConfiguration; import java.util.Collection; import java.util.List; @@ -73,8 +72,9 @@ public static Collection parameters() { NetworkName.SEPOLIA, List.of( new ForkId(Bytes.ofUnsignedInt(0xfe3366e7L), 1735371L), - new ForkId(Bytes.ofUnsignedInt(0xb96cbd13L), 0L), - new ForkId(Bytes.ofUnsignedInt(0xb96cbd13L), 0L)) + new ForkId(Bytes.ofUnsignedInt(0xb96cbd13L), 1677557088L), + new ForkId(Bytes.ofUnsignedInt(0xf7f9bc08L), 0L), + new ForkId(Bytes.ofUnsignedInt(0xf7f9bc08L), 0L)) }, new Object[] { NetworkName.RINKEBY, @@ -168,8 +168,7 @@ public void testForkId() { final GenesisConfigFile genesisConfigFile = GenesisConfigFile.fromConfig(EthNetworkConfig.jsonConfig(chainName)); final GenesisConfigOptions configOptions = genesisConfigFile.getConfigOptions(); - final ProtocolSchedule schedule = - MainnetProtocolSchedule.fromConfig(configOptions, EvmConfiguration.DEFAULT); + final ProtocolSchedule schedule = TransitionProtocolSchedule.fromConfig(configOptions); final GenesisState genesisState = GenesisState.fromConfig(genesisConfigFile, schedule); final Blockchain mockBlockchain = mock(Blockchain.class); final BlockHeader mockBlockHeader = mock(BlockHeader.class); @@ -179,6 +178,7 @@ public void testForkId() { final AtomicLong blockNumber = new AtomicLong(); when(mockBlockchain.getChainHeadHeader()).thenReturn(mockBlockHeader); when(mockBlockHeader.getNumber()).thenAnswer(o -> blockNumber.get()); + when(mockBlockHeader.getTimestamp()).thenAnswer(o -> blockNumber.get()); final ForkIdManager forkIdManager = new ForkIdManager( @@ -187,7 +187,7 @@ public void testForkId() { genesisConfigFile.getForkTimestamps(), false); - final var actualForkIds = + final List actualForkIds = Streams.concat(schedule.streamMilestoneBlocks(), Stream.of(Long.MAX_VALUE)) .map( block -> { diff --git a/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java index 94d5330ac190..2f66ab343bd9 100644 --- a/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java @@ -596,10 +596,6 @@ public List getForkBlockNumbers() { getArrowGlacierBlockNumber(), getGrayGlacierBlockNumber(), getMergeNetSplitBlockNumber(), - getShanghaiTime(), - getCancunTime(), - getFutureEipsTime(), - getExperimentalEipsTime(), getEcip1015BlockNumber(), getDieHardBlockNumber(), getGothamBlockNumber(), @@ -623,7 +619,9 @@ public List getForkBlockNumbers() { @Override public List getForkBlockTimestamps() { - Stream forkBlockTimestamps = Stream.of(getShanghaiTime(), getCancunTime()); + Stream forkBlockTimestamps = + Stream.of( + getShanghaiTime(), getCancunTime(), getFutureEipsTime(), getExperimentalEipsTime()); // when adding forks add an entry to ${REPO_ROOT}/config/src/test/resources/all_forks.json return forkBlockTimestamps diff --git a/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java index 468a78a83bbc..381602f901a1 100644 --- a/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java @@ -622,22 +622,22 @@ public StubGenesisConfigOptions cancunTime(final long timestamp) { /** * Future EIPs Time block. * - * @param blockNumber the block number + * @param timestamp the block timestamp * @return the stub genesis config options */ - public StubGenesisConfigOptions futureEipsTime(final long blockNumber) { - futureEipsTime = OptionalLong.of(blockNumber); + public StubGenesisConfigOptions futureEipsTime(final long timestamp) { + futureEipsTime = OptionalLong.of(timestamp); return this; } /** * Experimental EIPs Time block. * - * @param blockNumber the block number + * @param timestamp the block timestamp * @return the stub genesis config options */ - public StubGenesisConfigOptions experimentalEipsTime(final long blockNumber) { - experimentalEipsTime = OptionalLong.of(blockNumber); + public StubGenesisConfigOptions experimentalEipsTime(final long timestamp) { + experimentalEipsTime = OptionalLong.of(timestamp); return this; } diff --git a/config/src/main/resources/sepolia.json b/config/src/main/resources/sepolia.json index b1751b86e9dd..7bf96fb7f428 100644 --- a/config/src/main/resources/sepolia.json +++ b/config/src/main/resources/sepolia.json @@ -13,6 +13,7 @@ "londonBlock":0, "mergeNetSplitBlock": 1735371, "terminalTotalDifficulty": 17000000000000000, + "shanghaiTime": 1677557088, "ethash":{}, "discovery": { "dns": "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.sepolia.ethdisco.net", diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/TransitionProtocolSchedule.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/TransitionProtocolSchedule.java index 2859fc590e6a..5a2ab0a567ab 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/TransitionProtocolSchedule.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/TransitionProtocolSchedule.java @@ -16,11 +16,14 @@ import static org.hyperledger.besu.util.Slf4jLambdaHelper.debugLambda; +import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.core.Difficulty; +import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; import org.hyperledger.besu.ethereum.core.TransactionFilter; import org.hyperledger.besu.ethereum.mainnet.HeaderBasedProtocolSchedule; +import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.TimestampSchedule; @@ -60,6 +63,29 @@ public TransitionProtocolSchedule( new TransitionUtils<>(preMergeProtocolSchedule, postMergeProtocolSchedule, mergeContext); } + /** + * Create a Proof-of-Stake protocol schedule from a config object + * + * @param genesisConfigOptions {@link GenesisConfigOptions} containing the config options for the + * milestone starting points + * @return an initialised TransitionProtocolSchedule using post-merge defaults + */ + public static TransitionProtocolSchedule fromConfig( + final GenesisConfigOptions genesisConfigOptions) { + ProtocolSchedule preMergeProtocolSchedule = + MainnetProtocolSchedule.fromConfig(genesisConfigOptions); + ProtocolSchedule postMergeProtocolSchedule = + MergeProtocolSchedule.create(genesisConfigOptions, false); + TimestampSchedule timestampSchedule = + MergeProtocolSchedule.createTimestamp( + genesisConfigOptions, PrivacyParameters.DEFAULT, false); + return new TransitionProtocolSchedule( + preMergeProtocolSchedule, + postMergeProtocolSchedule, + PostMergeContext.get(), + timestampSchedule); + } + /** * Gets pre merge schedule. * @@ -162,8 +188,10 @@ public ProtocolSpec getByBlockNumber(final long number) { */ @Override public Stream streamMilestoneBlocks() { - return transitionUtils.dispatchFunctionAccordingToMergeState( - ProtocolSchedule::streamMilestoneBlocks); + Stream milestoneBlockNumbers = + transitionUtils.dispatchFunctionAccordingToMergeState( + ProtocolSchedule::streamMilestoneBlocks); + return Stream.concat(milestoneBlockNumbers, timestampSchedule.streamMilestoneBlocks()); } /** diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/DefaultTimestampSchedule.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/DefaultTimestampSchedule.java index 15677eb5537f..307339abd772 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/DefaultTimestampSchedule.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/DefaultTimestampSchedule.java @@ -26,6 +26,7 @@ import java.util.Optional; import java.util.TreeSet; import java.util.stream.Collectors; +import java.util.stream.Stream; public class DefaultTimestampSchedule implements TimestampSchedule { private final NavigableSet protocolSpecs = @@ -46,6 +47,11 @@ public Optional getByTimestamp(final long timestamp) { return Optional.empty(); } + @Override + public Stream streamMilestoneBlocks() { + return protocolSpecs.stream().map(TimedProtocolSpec::getTimestamp).sorted(); + } + @Override public Optional getChainId() { return chainId; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/HeaderBasedProtocolSchedule.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/HeaderBasedProtocolSchedule.java index 697abfc0b7cc..05f72726fe1a 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/HeaderBasedProtocolSchedule.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/HeaderBasedProtocolSchedule.java @@ -21,6 +21,7 @@ import java.math.BigInteger; import java.util.Optional; +import java.util.stream.Stream; public interface HeaderBasedProtocolSchedule { @@ -31,4 +32,6 @@ public interface HeaderBasedProtocolSchedule { void putMilestone(final long blockOrTimestamp, final ProtocolSpec protocolSpec); String listMilestones(); + + Stream streamMilestoneBlocks(); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolSchedule.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolSchedule.java index 7cef6b7696fa..30686f84eec0 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolSchedule.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolSchedule.java @@ -16,15 +16,11 @@ import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; -import java.util.stream.Stream; - public interface ProtocolSchedule extends HeaderBasedProtocolSchedule, PrivacySupportingProtocolSchedule { ProtocolSpec getByBlockNumber(long number); - Stream streamMilestoneBlocks(); - @Override default ProtocolSpec getByBlockHeader(final ProcessableBlockHeader blockHeader) { return getByBlockNumber(blockHeader.getNumber()); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/forkid/ForkIdTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/forkid/ForkIdTest.java index ac49d588053c..ba9837e01ddd 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/forkid/ForkIdTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/forkid/ForkIdTest.java @@ -313,11 +313,20 @@ public static Collection data() { empty() }, { - "Sepolia // Future", + "Sepolia // Shanghai", Network.SEPOLIA, 1735371L, 0L, - ForkIdTestUtil.wantForkId("0xb96cbd13", 0L), + ForkIdTestUtil.wantForkId("0xb96cbd13", 1677557088L), + Optional.of(ForkIds.SEPOLIA), + empty() + }, + { + "Sepolia // Future", + Network.SEPOLIA, + 1735372L, + 1677557088L, + ForkIdTestUtil.wantForkId("0xf7f9bc08", 0L), Optional.of(ForkIds.SEPOLIA), empty() }, diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/forkid/ForkIdTestUtil.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/forkid/ForkIdTestUtil.java index f0da68e5becf..62503177b08b 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/forkid/ForkIdTestUtil.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/forkid/ForkIdTestUtil.java @@ -73,8 +73,11 @@ public static class Forks { Arrays.asList( 1920000L, 1150000L, 2463000L, 2675000L, 2675000L, 4370000L, 7280000L, 7280000L, 9069000L, 9200000L, 12244000L, 12965000L, 13773000L, 15050000L); - public static final List SEPOLIA = + public static final List SEPOLIA_BLOCKNUMBERS = Arrays.asList(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1735371L); + + public static final List SEPOLIA_TIMESTAMPS = Arrays.asList(1677557088L); + public static final List RINKEBY = Arrays.asList(1L, 2L, 3L, 3L, 1035301L, 3660663L, 4321234L, 5435345L); public static final List GOERLI = Arrays.asList(0L, 0L, 0L, 0L, 0L, 0L, 0L, 1561651L); @@ -106,7 +109,8 @@ public static class ForkIds { public static final List SEPOLIA = Arrays.asList( new ForkId(Bytes.fromHexString("0xfe3366e7"), 1735371L), - new ForkId(Bytes.fromHexString("0xb96cbd13"), 0L)); + new ForkId(Bytes.fromHexString("0xb96cbd13"), 1677557088L), + new ForkId(Bytes.fromHexString("0xf7f9bc08"), 0L)); // First Shanghai block (timestamp) public static final List RINKEBY = Arrays.asList( new ForkId(Bytes.fromHexString("0x3b8e0691"), 1L), @@ -145,7 +149,8 @@ public static class ForkIds { public static class Network { public static final Network MAINNET = network(GenesisHash.MAINNET, Forks.MAINNET, emptyList()); - public static final Network SEPOLIA = network(GenesisHash.SEPOLIA, Forks.SEPOLIA, emptyList()); + public static final Network SEPOLIA = + network(GenesisHash.SEPOLIA, Forks.SEPOLIA_BLOCKNUMBERS, Forks.SEPOLIA_TIMESTAMPS); public static final Network RINKEBY = network(GenesisHash.RINKEBY, Forks.RINKEBY, emptyList()); public static final Network GOERLI = network(GenesisHash.GOERLI, Forks.GOERLI, emptyList()); public static final Network PRIVATE = network(GenesisHash.PRIVATE, Forks.PRIVATE, emptyList()); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/TimestampScheduleBuilderTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/TimestampScheduleBuilderTest.java index 035f3ae6fc4d..ab220f3ecbd4 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/TimestampScheduleBuilderTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/TimestampScheduleBuilderTest.java @@ -138,4 +138,15 @@ public void getByBlockHeader_whenSpecNotFoundReturnsNull() { assertThat(schedule.getByBlockHeader(BLOCK_HEADER)).isNull(); } + + @Test + public void streamMilestoneBlocksReturnTimestampsInOrder() { + config.shanghaiTime(FIRST_TIMESTAMP_FORK); + config.cancunTime(2L); + config.experimentalEipsTime(5L); + config.futureEipsTime(3L); + final TimestampSchedule schedule = builder.createTimestampSchedule(); + + assertThat(schedule.streamMilestoneBlocks()).containsExactly(FIRST_TIMESTAMP_FORK, 2L, 3L, 5L); + } }