From 8f9172c33a0efd54e74b645c7eeaa15360ace292 Mon Sep 17 00:00:00 2001 From: Ruben Buniatyan Date: Wed, 14 Jun 2023 18:02:18 +0200 Subject: [PATCH] Add tests validating a slot by timestamp (#5792) --- .../ChainSpecBasedSpecProviderTests.cs | 34 +++- .../Nethermind.Specs/ChiadoSpecProvider.cs | 3 +- .../Nethermind.Specs/GnosisSpecProvider.cs | 15 +- .../Nethermind.Specs/GoerliSpecProvider.cs | 92 ++++++----- .../Nethermind.Specs/MainnetSpecProvider.cs | 147 +++++++++--------- .../Nethermind.Specs/SepoliaSpecProvider.cs | 46 +++--- 6 files changed, 183 insertions(+), 154 deletions(-) diff --git a/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs b/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs index 583ed6bdec5..f30ea51f403 100644 --- a/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs +++ b/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs @@ -22,6 +22,8 @@ namespace Nethermind.Specs.Test.ChainSpecStyle; [TestFixture] public class ChainSpecBasedSpecProviderTests { + private const ulong GnosisBlockTime = 5; + [TestCase(0, null, false)] [TestCase(0, 0ul, false)] [TestCase(0, 4660ul, false)] @@ -136,6 +138,9 @@ public void Sepolia_loads_properly() Assert.That(provider.GenesisSpec.DifficultyBombDelay, Is.EqualTo(long.MaxValue)); Assert.That(provider.ChainId, Is.EqualTo(BlockchainIds.Sepolia)); Assert.That(provider.NetworkId, Is.EqualTo(BlockchainIds.Sepolia)); + + GetTransitionTimestamps(chainSpec.Parameters).Should().AllSatisfy( + t => ValidateSlotByTimestamp(t, SepoliaSpecProvider.BeaconChainGenesisTimestamp).Should().BeTrue()); } [Test] @@ -193,6 +198,9 @@ public void Goerli_loads_properly() Assert.That(provider.TerminalTotalDifficulty, Is.EqualTo(GoerliSpecProvider.Instance.TerminalTotalDifficulty)); Assert.That(provider.ChainId, Is.EqualTo(BlockchainIds.Goerli)); Assert.That(provider.NetworkId, Is.EqualTo(BlockchainIds.Goerli)); + + GetTransitionTimestamps(chainSpec.Parameters).Should().AllSatisfy( + t => ValidateSlotByTimestamp(t, GoerliSpecProvider.BeaconChainGenesisTimestamp).Should().BeTrue()); } [Test] @@ -216,10 +224,10 @@ public void Chiado_loads_properly() Assert.That(provider.ChainId, Is.EqualTo(BlockchainIds.Chiado)); Assert.That(provider.NetworkId, Is.EqualTo(BlockchainIds.Chiado)); - IReleaseSpec? preShanghaiSpec = provider.GetSpec((1, ChiadoSpecProvider.ShanghaiTimestamp - 1)); - IReleaseSpec? postShanghaiSpec = provider.GetSpec((1, ChiadoSpecProvider.ShanghaiTimestamp)); + provider.GetSpec((1, ChiadoSpecProvider.ShanghaiTimestamp - 1)).MaxCodeSize.Should().Be(long.MaxValue); + provider.GetSpec((1, ChiadoSpecProvider.ShanghaiTimestamp)).MaxCodeSize.Should().Be(24576L); + provider.GetSpec((1, ChiadoSpecProvider.ShanghaiTimestamp)).MaxInitCodeSize.Should().Be(2 * 24576L); - VerifyGnosisShanghaiExceptions(preShanghaiSpec, postShanghaiSpec); GetTransitionTimestamps(chainSpec.Parameters).Should().AllSatisfy( t => ValidateSlotByTimestamp(t, ChiadoSpecProvider.BeaconChainGenesisTimestamp, GnosisBlockTime).Should().BeTrue()); } @@ -360,6 +368,9 @@ public void Mainnet_loads_properly() Assert.That(provider.TerminalTotalDifficulty, Is.EqualTo(MainnetSpecProvider.Instance.TerminalTotalDifficulty)); Assert.That(provider.ChainId, Is.EqualTo(BlockchainIds.Mainnet)); Assert.That(provider.NetworkId, Is.EqualTo(BlockchainIds.Mainnet)); + + GetTransitionTimestamps(chainSpec.Parameters).Should().AllSatisfy( + t => ValidateSlotByTimestamp(t, MainnetSpecProvider.BeaconChainGenesisTimestamp).Should().BeTrue()); } [Flags] @@ -804,4 +815,21 @@ void TestTransitions(ForkActivation activation, Action changes) }); TestTransitions((40001L, 1000000024), r => { r.IsEip1153Enabled = true; }); } + + private static IEnumerable GetTransitionTimestamps(ChainParameters parameters) => parameters.GetType() + .Properties() + .Where(p => p.Name.EndsWith("TransitionTimestamp", StringComparison.Ordinal)) + .Select(p => (ulong?)p.GetValue(parameters)) + .Where(t => t is not null) + .Select(t => t!.Value); + + /// + /// Validates the timestamp specified by making sure the resulting slot is a multiple of 8192. + /// + /// The timestamp to validate + /// The network's genesis timestamp + /// The network's block time in seconds + /// true if the timestamp is valid; otherwise, false. + private static bool ValidateSlotByTimestamp(ulong timestamp, ulong genesisTimestamp, ulong blockTime = 12) => + timestamp > genesisTimestamp && (timestamp - genesisTimestamp) / blockTime % 0x2000 == 0; } diff --git a/src/Nethermind/Nethermind.Specs/ChiadoSpecProvider.cs b/src/Nethermind/Nethermind.Specs/ChiadoSpecProvider.cs index f614cb8ddbf..dade428b89e 100644 --- a/src/Nethermind/Nethermind.Specs/ChiadoSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/ChiadoSpecProvider.cs @@ -10,7 +10,8 @@ namespace Nethermind.Specs; public class ChiadoSpecProvider : ISpecProvider { - public const ulong ShanghaiTimestamp = 0x646e0e4cUL; + public const ulong BeaconChainGenesisTimestamp = 0x6343ee4c; + public const ulong ShanghaiTimestamp = 0x646e0e4c; private ChiadoSpecProvider() { } diff --git a/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs b/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs index 935f8c77d28..39a549bbd32 100644 --- a/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs @@ -10,6 +10,14 @@ namespace Nethermind.Specs; public class GnosisSpecProvider : ISpecProvider { + public const long ConstantinopoleBlockNumber = 1_604_400; + public const long ConstantinopoleFixBlockNumber = 2_508_800; + public const long IstanbulBlockNumber = 7_298_030; + public const long BerlinBlockNumber = 16_101_500; + public const long LondonBlockNumber = 19_040_000; + public const ulong BeaconChainGenesisTimestamp = 0x61b10dbc; + public const ulong ShanghaiTimestamp = long.MaxValue; + private GnosisSpecProvider() { } public IReleaseSpec GetSpec(ForkActivation forkActivation) @@ -47,12 +55,5 @@ public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalD public ulong ChainId => BlockchainIds.Gnosis; public ForkActivation[] TransitionActivations { get; } - public const long ConstantinopoleBlockNumber = 1_604_400; - public const long ConstantinopoleFixBlockNumber = 2_508_800; - public const long IstanbulBlockNumber = 7_298_030; - public const long BerlinBlockNumber = 16_101_500; - public const long LondonBlockNumber = 19_040_000; - public const ulong ShanghaiTimestamp = long.MaxValue; - public static GnosisSpecProvider Instance { get; } = new(); } diff --git a/src/Nethermind/Nethermind.Specs/GoerliSpecProvider.cs b/src/Nethermind/Nethermind.Specs/GoerliSpecProvider.cs index 255cd982144..5defde805f0 100644 --- a/src/Nethermind/Nethermind.Specs/GoerliSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/GoerliSpecProvider.cs @@ -1,64 +1,60 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Linq; using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Int256; using Nethermind.Specs.Forks; -namespace Nethermind.Specs -{ - public class GoerliSpecProvider : ISpecProvider - { - public static readonly GoerliSpecProvider Instance = new(); - private GoerliSpecProvider() { } +namespace Nethermind.Specs; - private ForkActivation? _theMergeBlock = null; - private UInt256? _terminalTotalDifficulty = 10790000; - - public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalDifficulty = null) - { - if (blockNumber is not null) - _theMergeBlock = (ForkActivation)blockNumber; - if (terminalTotalDifficulty is not null) - _terminalTotalDifficulty = terminalTotalDifficulty; - } +public class GoerliSpecProvider : ISpecProvider +{ + public const long IstanbulBlockNumber = 1_561_651; + public const long BerlinBlockNumber = 4_460_644; + public const long LondonBlockNumber = 5_062_605; + public const ulong BeaconChainGenesisTimestamp = 0x6059f460; + public const ulong ShanghaiTimestamp = 0x6410f460; - public ForkActivation? MergeBlockNumber => _theMergeBlock; - public ulong TimestampFork => ShanghaiTimestamp; - public UInt256? TerminalTotalDifficulty => _terminalTotalDifficulty; - public IReleaseSpec GenesisSpec { get; } = ConstantinopleFix.Instance; + private GoerliSpecProvider() { } - public IReleaseSpec GetSpec(ForkActivation forkActivation) + public IReleaseSpec GetSpec(ForkActivation forkActivation) + { + return forkActivation.BlockNumber switch { - return forkActivation.BlockNumber switch + < IstanbulBlockNumber => GenesisSpec, + < BerlinBlockNumber => Istanbul.Instance, + < LondonBlockNumber => Berlin.Instance, + _ => forkActivation.Timestamp switch { - < IstanbulBlockNumber => GenesisSpec, - < BerlinBlockNumber => Istanbul.Instance, - < LondonBlockNumber => Berlin.Instance, - _ => forkActivation.Timestamp switch - { - null or < ShanghaiTimestamp => London.Instance, - _ => Shanghai.Instance - } - }; - } - - public long? DaoBlockNumber => null; - public const long IstanbulBlockNumber = 1_561_651; - public const long BerlinBlockNumber = 4_460_644; - public const long LondonBlockNumber = 5_062_605; - public const ulong ShanghaiTimestamp = 1678832736; - public ulong NetworkId => BlockchainIds.Goerli; - public ulong ChainId => NetworkId; - - public ForkActivation[] TransitionActivations { get; } = - { - (ForkActivation)IstanbulBlockNumber, - (ForkActivation)BerlinBlockNumber, - (ForkActivation)LondonBlockNumber, - (LondonBlockNumber, ShanghaiTimestamp) + null or < ShanghaiTimestamp => London.Instance, + _ => Shanghai.Instance + } }; } + + public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalDifficulty = null) + { + if (blockNumber is not null) + MergeBlockNumber = (ForkActivation)blockNumber; + if (terminalTotalDifficulty is not null) + TerminalTotalDifficulty = terminalTotalDifficulty; + } + + public ulong NetworkId => BlockchainIds.Goerli; + public ulong ChainId => NetworkId; + public long? DaoBlockNumber => null; + public ForkActivation? MergeBlockNumber { get; private set; } = null; + public ulong TimestampFork => ShanghaiTimestamp; + public UInt256? TerminalTotalDifficulty { get; private set; } = 10790000; + public IReleaseSpec GenesisSpec { get; } = ConstantinopleFix.Instance; + public ForkActivation[] TransitionActivations { get; } = + { + (ForkActivation)IstanbulBlockNumber, + (ForkActivation)BerlinBlockNumber, + (ForkActivation)LondonBlockNumber, + (LondonBlockNumber, ShanghaiTimestamp) + }; + + public static readonly GoerliSpecProvider Instance = new(); } diff --git a/src/Nethermind/Nethermind.Specs/MainnetSpecProvider.cs b/src/Nethermind/Nethermind.Specs/MainnetSpecProvider.cs index d810b27ce2e..1670bde6c46 100644 --- a/src/Nethermind/Nethermind.Specs/MainnetSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/MainnetSpecProvider.cs @@ -5,81 +5,88 @@ using Nethermind.Int256; using Nethermind.Specs.Forks; -namespace Nethermind.Specs +namespace Nethermind.Specs; + +public class MainnetSpecProvider : ISpecProvider { - public class MainnetSpecProvider : ISpecProvider - { - private ForkActivation? _theMergeBlock = null; - private UInt256? _terminalTotalDifficulty = UInt256.Parse("58750000000000000000000"); + public const long HomesteadBlockNumber = 1_150_000; + public const long DaoBlockNumberConst = 1_920_000; + public const long TangerineWhistleBlockNumber = 2_463_000; + public const long SpuriousDragonBlockNumber = 2_675_000; + public const long ByzantiumBlockNumber = 4_370_000; + public const long ConstantinopleFixBlockNumber = 7_280_000; + public const long IstanbulBlockNumber = 9_069_000; + public const long MuirGlacierBlockNumber = 9_200_000; + public const long BerlinBlockNumber = 12_244_000; + public const long LondonBlockNumber = 12_965_000; + public const long ArrowGlacierBlockNumber = 13_773_000; + public const long GrayGlacierBlockNumber = 15_050_000; + public const ulong GenesisBlockTimestamp = 0x55ba4215; + public const ulong BeaconChainGenesisTimestamp = 0x5fc63057; + public const ulong ShanghaiBlockTimestamp = 0x64373057; + public const ulong CancunBlockTimestamp = ulong.MaxValue - 3; + public const ulong PragueBlockTimestamp = ulong.MaxValue - 2; + public const ulong OsakaBlockTimestamp = ulong.MaxValue - 1; - public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalDifficulty = null) + public IReleaseSpec GetSpec(ForkActivation forkActivation) => + forkActivation switch { - if (blockNumber is not null) - _theMergeBlock = (ForkActivation)blockNumber; - if (terminalTotalDifficulty is not null) - _terminalTotalDifficulty = terminalTotalDifficulty; - } - - public ForkActivation? MergeBlockNumber => _theMergeBlock; - public ulong TimestampFork => ShanghaiBlockTimestamp; - public UInt256? TerminalTotalDifficulty => _terminalTotalDifficulty; - public IReleaseSpec GenesisSpec => Frontier.Instance; - - public IReleaseSpec GetSpec(ForkActivation forkActivation) => - forkActivation switch - { - { BlockNumber: < HomesteadBlockNumber } => Frontier.Instance, - { BlockNumber: < DaoBlockNumberConst } => Homestead.Instance, - { BlockNumber: < TangerineWhistleBlockNumber } => Dao.Instance, - { BlockNumber: < SpuriousDragonBlockNumber } => TangerineWhistle.Instance, - { BlockNumber: < ByzantiumBlockNumber } => SpuriousDragon.Instance, - { BlockNumber: < ConstantinopleFixBlockNumber } => Byzantium.Instance, - { BlockNumber: < IstanbulBlockNumber } => ConstantinopleFix.Instance, - { BlockNumber: < MuirGlacierBlockNumber } => Istanbul.Instance, - { BlockNumber: < BerlinBlockNumber } => MuirGlacier.Instance, - { BlockNumber: < LondonBlockNumber } => Berlin.Instance, - { BlockNumber: < ArrowGlacierBlockNumber } => London.Instance, - { BlockNumber: < GrayGlacierBlockNumber } => ArrowGlacier.Instance, - { Timestamp: null } or { Timestamp: < ShanghaiBlockTimestamp } => GrayGlacier.Instance, - { Timestamp: < CancunBlockTimestamp } => Shanghai.Instance, - _ => Cancun.Instance - }; + { BlockNumber: < HomesteadBlockNumber } => Frontier.Instance, + { BlockNumber: < DaoBlockNumberConst } => Homestead.Instance, + { BlockNumber: < TangerineWhistleBlockNumber } => Dao.Instance, + { BlockNumber: < SpuriousDragonBlockNumber } => TangerineWhistle.Instance, + { BlockNumber: < ByzantiumBlockNumber } => SpuriousDragon.Instance, + { BlockNumber: < ConstantinopleFixBlockNumber } => Byzantium.Instance, + { BlockNumber: < IstanbulBlockNumber } => ConstantinopleFix.Instance, + { BlockNumber: < MuirGlacierBlockNumber } => Istanbul.Instance, + { BlockNumber: < BerlinBlockNumber } => MuirGlacier.Instance, + { BlockNumber: < LondonBlockNumber } => Berlin.Instance, + { BlockNumber: < ArrowGlacierBlockNumber } => London.Instance, + { BlockNumber: < GrayGlacierBlockNumber } => ArrowGlacier.Instance, + { Timestamp: null } or { Timestamp: < ShanghaiBlockTimestamp } => GrayGlacier.Instance, + { Timestamp: < CancunBlockTimestamp } => Shanghai.Instance, + _ => Cancun.Instance + }; - public const long HomesteadBlockNumber = 1_150_000; - public long? DaoBlockNumber => DaoBlockNumberConst; - public const long DaoBlockNumberConst = 1_920_000; - public const long TangerineWhistleBlockNumber = 2_463_000; - public const long SpuriousDragonBlockNumber = 2_675_000; - public const long ByzantiumBlockNumber = 4_370_000; - public const long ConstantinopleFixBlockNumber = 7_280_000; - public const long IstanbulBlockNumber = 9_069_000; - public const long MuirGlacierBlockNumber = 9_200_000; - public const long BerlinBlockNumber = 12_244_000; - public const long LondonBlockNumber = 12_965_000; - public const long ArrowGlacierBlockNumber = 13_773_000; - public const long GrayGlacierBlockNumber = 15_050_000; - public const ulong GenesisBlockTimestamp = 1_438_269_973; - public const ulong ShanghaiBlockTimestamp = 1_681_338_455; - public const ulong CancunBlockTimestamp = ulong.MaxValue - 3; - public const ulong PragueBlockTimestamp = ulong.MaxValue - 2; - public const ulong OsakaBlockTimestamp = ulong.MaxValue - 1; - public static ForkActivation ShanghaiActivation = (15_050_001, ShanghaiBlockTimestamp); - public static ForkActivation CancunActivation = (15_050_002, CancunBlockTimestamp); - public static ForkActivation PragueActivation = (15_050_003, PragueBlockTimestamp); - public static ForkActivation OsakaActivation = (15_050_004, OsakaBlockTimestamp); + public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalDifficulty = null) + { + if (blockNumber is not null) + MergeBlockNumber = (ForkActivation)blockNumber; - public ulong NetworkId => Core.BlockchainIds.Mainnet; - public ulong ChainId => NetworkId; + if (terminalTotalDifficulty is not null) + TerminalTotalDifficulty = terminalTotalDifficulty; + } - public ForkActivation[] TransitionActivations { get; } = - { - (ForkActivation)HomesteadBlockNumber, (ForkActivation)DaoBlockNumberConst, (ForkActivation)TangerineWhistleBlockNumber, (ForkActivation)SpuriousDragonBlockNumber, - (ForkActivation)ByzantiumBlockNumber, (ForkActivation)ConstantinopleFixBlockNumber, (ForkActivation)IstanbulBlockNumber, (ForkActivation)MuirGlacierBlockNumber, - (ForkActivation)BerlinBlockNumber, (ForkActivation)LondonBlockNumber, (ForkActivation)ArrowGlacierBlockNumber, (ForkActivation)GrayGlacierBlockNumber, - ShanghaiActivation, CancunActivation, - //PragueActivation, OsakaActivation - }; + public ulong NetworkId { get; } = Core.BlockchainIds.Mainnet; + public ulong ChainId => NetworkId; + public long? DaoBlockNumber => DaoBlockNumberConst; + public ForkActivation? MergeBlockNumber { get; private set; } = null; + public ulong TimestampFork { get; } = ShanghaiBlockTimestamp; + public UInt256? TerminalTotalDifficulty { get; private set; } = UInt256.Parse("58750000000000000000000"); + public IReleaseSpec GenesisSpec => Frontier.Instance; + public static ForkActivation ShanghaiActivation { get; } = (15_050_001, ShanghaiBlockTimestamp); + public static ForkActivation CancunActivation { get; } = (15_050_002, CancunBlockTimestamp); + public static ForkActivation PragueActivation { get; } = (15_050_003, PragueBlockTimestamp); + public static ForkActivation OsakaActivation { get; } = (15_050_004, OsakaBlockTimestamp); + public ForkActivation[] TransitionActivations { get; } = + { + (ForkActivation)HomesteadBlockNumber, + (ForkActivation)DaoBlockNumberConst, + (ForkActivation)TangerineWhistleBlockNumber, + (ForkActivation)SpuriousDragonBlockNumber, + (ForkActivation)ByzantiumBlockNumber, + (ForkActivation)ConstantinopleFixBlockNumber, + (ForkActivation)IstanbulBlockNumber, + (ForkActivation)MuirGlacierBlockNumber, + (ForkActivation)BerlinBlockNumber, + (ForkActivation)LondonBlockNumber, + (ForkActivation)ArrowGlacierBlockNumber, + (ForkActivation)GrayGlacierBlockNumber, + ShanghaiActivation, + CancunActivation, + //PragueActivation, + //OsakaActivation + }; - public static readonly MainnetSpecProvider Instance = new(); - } + public static MainnetSpecProvider Instance { get; } = new(); } diff --git a/src/Nethermind/Nethermind.Specs/SepoliaSpecProvider.cs b/src/Nethermind/Nethermind.Specs/SepoliaSpecProvider.cs index 6049cdd8ac6..8a5976ca816 100644 --- a/src/Nethermind/Nethermind.Specs/SepoliaSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/SepoliaSpecProvider.cs @@ -1,8 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; -using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Int256; using Nethermind.Specs.Forks; @@ -11,23 +9,10 @@ namespace Nethermind.Specs; public class SepoliaSpecProvider : ISpecProvider { - private ForkActivation? _theMergeBlock = null; - private UInt256? _terminalTotalDifficulty = 17000000000000000; + public const ulong BeaconChainGenesisTimestamp = 0x62b07d60; + public const ulong ShanghaiBlockTimestamp = 0x63fd7d60; - public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalDifficulty = null) - { - if (blockNumber is not null) - _theMergeBlock = (ForkActivation)blockNumber; - if (terminalTotalDifficulty is not null) - _terminalTotalDifficulty = terminalTotalDifficulty; - } - - public ForkActivation? MergeBlockNumber => _theMergeBlock; - public ulong TimestampFork => ISpecProvider.TimestampForkNever; - public UInt256? TerminalTotalDifficulty => _terminalTotalDifficulty; - public IReleaseSpec GenesisSpec => London.Instance; - - public const ulong ShanghaiBlockTimestamp = 1677557088; + private SepoliaSpecProvider() { } public IReleaseSpec GetSpec(ForkActivation forkActivation) => forkActivation switch @@ -36,15 +21,26 @@ public IReleaseSpec GetSpec(ForkActivation forkActivation) => _ => Shanghai.Instance }; - public long? DaoBlockNumber => null; - + public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalDifficulty = null) + { + if (blockNumber is not null) + MergeBlockNumber = (ForkActivation)blockNumber; + if (terminalTotalDifficulty is not null) + TerminalTotalDifficulty = terminalTotalDifficulty; + } public ulong NetworkId => Core.BlockchainIds.Rinkeby; public ulong ChainId => NetworkId; + public long? DaoBlockNumber => null; + public ForkActivation? MergeBlockNumber { get; private set; } = null; + public ulong TimestampFork => ISpecProvider.TimestampForkNever; + public UInt256? TerminalTotalDifficulty { get; private set; } = 17000000000000000; + public IReleaseSpec GenesisSpec => London.Instance; + public ForkActivation[] TransitionActivations { get; } = + { + (ForkActivation)1735371, + (1735371, 1677557088) + }; - public ForkActivation[] TransitionActivations { get; } = { (ForkActivation)1735371, new ForkActivation(1735371, 1677557088) }; - - private SepoliaSpecProvider() { } - - public static readonly SepoliaSpecProvider Instance = new(); + public static SepoliaSpecProvider Instance { get; } = new(); }