diff --git a/src/Nethermind/Chains/goerli.json b/src/Nethermind/Chains/goerli.json index 02490845d6d..d311313156f 100644 --- a/src/Nethermind/Chains/goerli.json +++ b/src/Nethermind/Chains/goerli.json @@ -43,6 +43,12 @@ "eip3855TransitionTimestamp": "0x6410F460", "eip3860TransitionTimestamp": "0x6410F460", "eip4895TransitionTimestamp": "0x6410F460", + "eip1153TransitionTimestamp": "0x65A77460", + "eip4788TransitionTimestamp": "0x65A77460", + "eip4844TransitionTimestamp": "0x65A77460", + "eip5656TransitionTimestamp": "0x65A77460", + "eip6780TransitionTimestamp": "0x65A77460", + "eip4788ContractAddress": "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02", "terminalTotalDifficulty": "A4A470", "gasLimitBoundDivisor": "0x400", "maxCodeSize": "0x6000", @@ -66,15 +72,15 @@ "timestamp": "0x5c51a607" }, "nodes": [ - "enode://011f758e6552d105183b1761c5e2dea0111bc20fd5f6422bc7f91e0fabbec9a6595caf6239b37feb773dddd3f87240d99d859431891e4a642cf2a0a9e6cbb98a@51.141.78.53:30303", - "enode://176b9417f511d05b6b2cf3e34b756cf0a7096b3094572a8f6ef4cdcb9d1f9d00683bf0f83347eebdf3b81c3521c2332086d9592802230bf528eaf606a1d9677b@13.93.54.137:30303", - "enode://46add44b9f13965f7b9875ac6b85f016f341012d84f975377573800a863526f4da19ae2c620ec73d11591fa9510e992ecc03ad0751f53cc02f7c7ed6d55c7291@94.237.54.114:30313", - "enode://c1f8b7c2ac4453271fa07d8e9ecf9a2e8285aa0bd0c07df0131f47153306b0736fd3db8924e7a9bf0bed6b1d8d4f87362a71b033dc7c64547728d953e43e59b2@52.64.155.147:30303", - "enode://f4a9c6ee28586009fb5a96c8af13a58ed6d8315a9eee4772212c1d4d9cebe5a8b8a78ea4434f318726317d04a3f531a1ef0420cf9752605a562cfe858c46e263@213.186.16.82:30303", - "enode://a61215641fb8714a373c80edbfa0ea8878243193f57c96eeb44d0bc019ef295abd4e044fd619bfc4c59731a73fb79afe84e9ab6da0c743ceb479cbb6d263fa91@3.11.147.67:30303", - "enode://b5948a2d3e9d486c4d75bf32713221c2bd6cf86463302339299bd227dc2e276cd5a1c7ca4f43a0e9122fe9af884efed563bd2a1fd28661f3b5f5ad7bf1de5949@18.218.250.66:30303", - "enode://d2b720352e8216c9efc470091aa91ddafc53e222b32780f505c817ceef69e01d5b0b0797b69db254c586f493872352f5a022b4d8479a00fc92ec55f9ad46a27e@88.99.70.182:30303", - "enode://d4f764a48ec2a8ecf883735776fdefe0a3949eb0ca476bd7bc8d0954a9defe8fea15ae5da7d40b5d2d59ce9524a99daedadf6da6283fca492cc80b53689fb3b3@46.4.99.122:32109" + "enode://011f758e6552d105183b1761c5e2dea0111bc20fd5f6422bc7f91e0fabbec9a6595caf6239b37feb773dddd3f87240d99d859431891e4a642cf2a0a9e6cbb98a@51.141.78.53:30303", + "enode://176b9417f511d05b6b2cf3e34b756cf0a7096b3094572a8f6ef4cdcb9d1f9d00683bf0f83347eebdf3b81c3521c2332086d9592802230bf528eaf606a1d9677b@13.93.54.137:30303", + "enode://46add44b9f13965f7b9875ac6b85f016f341012d84f975377573800a863526f4da19ae2c620ec73d11591fa9510e992ecc03ad0751f53cc02f7c7ed6d55c7291@94.237.54.114:30313", + "enode://c1f8b7c2ac4453271fa07d8e9ecf9a2e8285aa0bd0c07df0131f47153306b0736fd3db8924e7a9bf0bed6b1d8d4f87362a71b033dc7c64547728d953e43e59b2@52.64.155.147:30303", + "enode://f4a9c6ee28586009fb5a96c8af13a58ed6d8315a9eee4772212c1d4d9cebe5a8b8a78ea4434f318726317d04a3f531a1ef0420cf9752605a562cfe858c46e263@213.186.16.82:30303", + "enode://a61215641fb8714a373c80edbfa0ea8878243193f57c96eeb44d0bc019ef295abd4e044fd619bfc4c59731a73fb79afe84e9ab6da0c743ceb479cbb6d263fa91@3.11.147.67:30303", + "enode://b5948a2d3e9d486c4d75bf32713221c2bd6cf86463302339299bd227dc2e276cd5a1c7ca4f43a0e9122fe9af884efed563bd2a1fd28661f3b5f5ad7bf1de5949@18.218.250.66:30303", + "enode://d2b720352e8216c9efc470091aa91ddafc53e222b32780f505c817ceef69e01d5b0b0797b69db254c586f493872352f5a022b4d8479a00fc92ec55f9ad46a27e@88.99.70.182:30303", + "enode://d4f764a48ec2a8ecf883735776fdefe0a3949eb0ca476bd7bc8d0954a9defe8fea15ae5da7d40b5d2d59ce9524a99daedadf6da6283fca492cc80b53689fb3b3@46.4.99.122:32109" ], "accounts": { "0x0000000000000000000000000000000000000000": { diff --git a/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs b/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs index ab5b8daa3ee..ac26dcd4253 100644 --- a/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs @@ -107,8 +107,10 @@ public void Fork_id_and_hash_as_expected_with_merge_fork_id(long head, ulong hea [TestCase(4_600_000L, 0ul, "0x757a1c47", 5_062_605ul, "Future Berlin block")] [TestCase(5_062_605L, 0ul, "0xB8C6299D", 1678832736ul, "First London block")] [TestCase(6_000_000, 0ul, "0xB8C6299D", 1678832736ul, "Future London block")] - [TestCase(6_000_001, 1678832736ul, "0xf9843abf", 0ul, "First Shanghai timestamp")] - [TestCase(6_000_001, 2678832736ul, "0xf9843abf", 0ul, "Future Shanghai timestamp")] + [TestCase(6_000_001, 1678832736ul, "0xf9843abf", 1705473120ul, "First Shanghai timestamp")] + [TestCase(6_000_001, 1705473119ul, "0xf9843abf", 1705473120ul, "Future Shanghai timestamp")] + [TestCase(6_000_002, 1705473120ul, "0x70cc14e2", 0ul, "First Cancun timestamp")] + [TestCase(6_000_002, 1905473119ul, "0x70cc14e2", 0ul, "Future Cancun timestamp")] public void Fork_id_and_hash_as_expected_on_goerli(long head, ulong headTimestamp, string forkHashHex, ulong next, string description) { Test(head, headTimestamp, KnownHashes.GoerliGenesis, forkHashHex, next, description, GoerliSpecProvider.Instance, "goerli.json"); diff --git a/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs b/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs index 681839f3248..1dd79cb0a19 100644 --- a/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs +++ b/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs @@ -58,11 +58,8 @@ public void Timstamp_activation_equal_to_genesis_timestamp_loads_correctly(long testProvider.SpecToReturn = expectedSpec; testProvider.TerminalTotalDifficulty = 0; testProvider.GenesisSpec = expectedSpec; - List forkActivationsToTest = new() - { - (blockNumber, timestamp), - }; - CompareSpecProviders(testProvider, provider, forkActivationsToTest); + + CompareSpecs(testProvider, provider, (blockNumber, timestamp)); Assert.That(provider.GenesisSpec.Eip1559TransitionBlock, Is.EqualTo(testProvider.GenesisSpec.Eip1559TransitionBlock)); Assert.That(provider.GenesisSpec.DifficultyBombDelay, Is.EqualTo(testProvider.GenesisSpec.DifficultyBombDelay)); } @@ -121,23 +118,26 @@ public void Logs_warning_when_timestampActivation_happens_before_blockActivation } } - [Test] - public void Sepolia_loads_properly() + public static IEnumerable SepoliaActivations + { + get + { + yield return new TestCaseData((ForkActivation)(2, 0)) { TestName = "First" }; + yield return new TestCaseData((ForkActivation)(120_000_000, 0)) { TestName = "Block number" }; + yield return new TestCaseData((ForkActivation)(1735372, 3)) { TestName = "Low timestamp" }; + yield return new TestCaseData((ForkActivation)(1735372, 1677557088)) { TestName = "1677557088" }; + yield return new TestCaseData((ForkActivation)(1735372, 1677557087)) { TestName = "1677557087" }; + } + } + + [TestCaseSource(nameof(SepoliaActivations))] + public void Sepolia_loads_properly(ForkActivation forkActivation) { ChainSpec chainSpec = LoadChainSpecFromChainFolder("sepolia"); ChainSpecBasedSpecProvider provider = new(chainSpec); SepoliaSpecProvider sepolia = SepoliaSpecProvider.Instance; - List forkActivationsToTest = new() - { - new ForkActivation(2, 0), - new ForkActivation(120_000_000, 0), - new ForkActivation(1735372, 3), - new ForkActivation(1735372, 1677557088), - new ForkActivation(1735372, 1677557087) - }; - - CompareSpecProviders(sepolia, provider, forkActivationsToTest); + CompareSpecs(sepolia, provider, forkActivation); Assert.That(provider.TerminalTotalDifficulty, Is.EqualTo(SepoliaSpecProvider.Instance.TerminalTotalDifficulty)); Assert.That(provider.GenesisSpec.Eip1559TransitionBlock, Is.EqualTo(0)); Assert.That(provider.GenesisSpec.DifficultyBombDelay, Is.EqualTo(long.MaxValue)); @@ -148,23 +148,26 @@ public void Sepolia_loads_properly() t => ValidateSlotByTimestamp(t, SepoliaSpecProvider.BeaconChainGenesisTimestamp).Should().BeTrue()); } - [Test] - public void Holesky_loads_properly() + public static IEnumerable HoleskyActivations { - ChainSpec chainSpec = LoadChainSpecFromChainFolder("holesky"); - ChainSpecBasedSpecProvider provider = new(chainSpec); - ISpecProvider hardCodedSpec = HoleskySpecProvider.Instance; - - List forkActivationsToTest = new() + get { - new ForkActivation(0, HoleskySpecProvider.GenesisTimestamp), - new ForkActivation(1, HoleskySpecProvider.ShanghaiTimestamp), - new ForkActivation(3, HoleskySpecProvider.ShanghaiTimestamp + 24), + yield return new TestCaseData(new ForkActivation(0, HoleskySpecProvider.GenesisTimestamp)) { TestName = "Genesis" }; + yield return new TestCaseData(new ForkActivation(1, HoleskySpecProvider.ShanghaiTimestamp)) { TestName = "Shanghai" }; + yield return new TestCaseData(new ForkActivation(3, HoleskySpecProvider.ShanghaiTimestamp + 24)) { TestName = "Post Shanghai" }; //new ForkActivation(4, HoleskySpecProvider.CancunTimestamp), //new ForkActivation(5, HoleskySpecProvider.CancunTimestamp + 12), - }; + } + } - CompareSpecProviders(hardCodedSpec, provider, forkActivationsToTest); + [TestCaseSource(nameof(HoleskyActivations))] + public void Holesky_loads_properly(ForkActivation forkActivation) + { + ChainSpec chainSpec = LoadChainSpecFromChainFolder("holesky"); + ChainSpecBasedSpecProvider provider = new(chainSpec); + ISpecProvider hardCodedSpec = HoleskySpecProvider.Instance; + + CompareSpecs(hardCodedSpec, provider, forkActivation); Assert.That(provider.TerminalTotalDifficulty, Is.EqualTo(hardCodedSpec.TerminalTotalDifficulty)); Assert.That(provider.GenesisSpec.Eip1559TransitionBlock, Is.EqualTo(0)); Assert.That(provider.GenesisSpec.DifficultyBombDelay, Is.EqualTo(0)); @@ -176,28 +179,34 @@ public void Holesky_loads_properly() // t => ValidateSlotByTimestamp(t, HoleskySpecProvider.GenesisTimestamp).Should().BeTrue()); } - [Test] - public void Goerli_loads_properly() + public static IEnumerable GoerliActivations + { + get + { + yield return new TestCaseData((ForkActivation)0) { TestName = "Genesis" }; + yield return new TestCaseData((ForkActivation)1) { TestName = "1" }; + yield return new TestCaseData((ForkActivation)(GoerliSpecProvider.IstanbulBlockNumber - 1)) { TestName = "Before Istanbul" }; + yield return new TestCaseData((ForkActivation)GoerliSpecProvider.IstanbulBlockNumber) { TestName = "Istanbul" }; + yield return new TestCaseData((ForkActivation)(GoerliSpecProvider.BerlinBlockNumber - 1)) { TestName = "Before Berlin" }; + yield return new TestCaseData((ForkActivation)GoerliSpecProvider.BerlinBlockNumber) { TestName = "Berlin" }; + yield return new TestCaseData((ForkActivation)(GoerliSpecProvider.LondonBlockNumber - 1)) { TestName = "Before London" }; + yield return new TestCaseData((ForkActivation)GoerliSpecProvider.LondonBlockNumber) { TestName = "London" }; + yield return new TestCaseData(new ForkActivation(GoerliSpecProvider.LondonBlockNumber + 1, GoerliSpecProvider.ShanghaiTimestamp - 1)) { TestName = "Before Shanghai" }; + yield return new TestCaseData(new ForkActivation(GoerliSpecProvider.LondonBlockNumber + 1, GoerliSpecProvider.ShanghaiTimestamp)) { TestName = "Shanghai" }; + yield return new TestCaseData(new ForkActivation(GoerliSpecProvider.LondonBlockNumber + 2, GoerliSpecProvider.CancunTimestamp - 1)) { TestName = "Before Cancun" }; + yield return new TestCaseData(new ForkActivation(GoerliSpecProvider.LondonBlockNumber + 2, GoerliSpecProvider.CancunTimestamp)) { TestName = "Cancun" }; + yield return new TestCaseData(new ForkActivation(GoerliSpecProvider.LondonBlockNumber + 2, GoerliSpecProvider.CancunTimestamp + 100000000)) { TestName = "Future" }; + } + } + + [TestCaseSource(nameof(GoerliActivations))] + public void Goerli_loads_properly(ForkActivation forkActivation) { ChainSpec chainSpec = LoadChainSpecFromChainFolder("goerli"); ChainSpecBasedSpecProvider provider = new(chainSpec); GoerliSpecProvider goerli = GoerliSpecProvider.Instance; - List forkActivationsToTest = new() - { - (ForkActivation)0, - (ForkActivation)1, - (ForkActivation)(GoerliSpecProvider.IstanbulBlockNumber - 1), - (ForkActivation)GoerliSpecProvider.IstanbulBlockNumber, - (ForkActivation)(GoerliSpecProvider.BerlinBlockNumber - 1), - (ForkActivation)GoerliSpecProvider.BerlinBlockNumber, - (ForkActivation)(GoerliSpecProvider.LondonBlockNumber - 1), - (ForkActivation)GoerliSpecProvider.LondonBlockNumber, - new ForkActivation(GoerliSpecProvider.LondonBlockNumber + 1, GoerliSpecProvider.ShanghaiTimestamp), - new ForkActivation(GoerliSpecProvider.LondonBlockNumber + 1, GoerliSpecProvider.ShanghaiTimestamp + 100000000) // far in future - }; - - CompareSpecProviders(goerli, provider, forkActivationsToTest); + CompareSpecs(goerli, provider, forkActivation); Assert.That(provider.GenesisSpec.Eip1559TransitionBlock, Is.EqualTo(GoerliSpecProvider.LondonBlockNumber)); Assert.That(provider.TerminalTotalDifficulty, Is.EqualTo(GoerliSpecProvider.Instance.TerminalTotalDifficulty)); Assert.That(provider.ChainId, Is.EqualTo(BlockchainIds.Goerli)); @@ -207,23 +216,26 @@ public void Goerli_loads_properly() t => ValidateSlotByTimestamp(t, GoerliSpecProvider.BeaconChainGenesisTimestamp).Should().BeTrue()); } - [Test] - public void Chiado_loads_properly() + public static IEnumerable ChiadoActivations + { + get + { + yield return new TestCaseData((ForkActivation)0) { TestName = "Genesis" }; + yield return new TestCaseData((ForkActivation)(1, 20)) { TestName = "(1, 20)" }; + yield return new TestCaseData((ForkActivation)(1, ChiadoSpecProvider.ShanghaiTimestamp - 1)) { TestName = "Before Shanghai" }; + yield return new TestCaseData((ForkActivation)(1, ChiadoSpecProvider.ShanghaiTimestamp)) { TestName = "Shanghai" }; + yield return new TestCaseData(new ForkActivation(1, GoerliSpecProvider.ShanghaiTimestamp + 100000000)) { TestName = "Future" }; + } + } + + [TestCaseSource(nameof(ChiadoActivations))] + public void Chiado_loads_properly(ForkActivation forkActivation) { ChainSpec chainSpec = LoadChainSpecFromChainFolder("chiado"); ChainSpecBasedSpecProvider provider = new(chainSpec); ChiadoSpecProvider chiado = ChiadoSpecProvider.Instance; - List forkActivationsToTest = new() - { - (ForkActivation)0, - (ForkActivation)(1, 20), - (1, ChiadoSpecProvider.ShanghaiTimestamp - 1), - (1, ChiadoSpecProvider.ShanghaiTimestamp), - (999_999_999, 999_999_999) // far in the future - }; - - CompareSpecProviders(chiado, provider, forkActivationsToTest, CompareSpecsOptions.IsGnosis); + CompareSpecs(chiado, provider, forkActivation, CompareSpecsOptions.IsGnosis); Assert.That(provider.TerminalTotalDifficulty, Is.EqualTo(ChiadoSpecProvider.Instance.TerminalTotalDifficulty)); Assert.That(provider.ChainId, Is.EqualTo(BlockchainIds.Chiado)); Assert.That(provider.NetworkId, Is.EqualTo(BlockchainIds.Chiado)); @@ -244,33 +256,36 @@ public void Chiado_loads_properly() }); } - [Test] - public void Gnosis_loads_properly() + public static IEnumerable GnosisActivations + { + get + { + yield return new TestCaseData((ForkActivation)0) { TestName = "Genesis" }; + yield return new TestCaseData((ForkActivation)1) { TestName = "Genesis + 1" }; + yield return new TestCaseData((ForkActivation)(GnosisSpecProvider.ConstantinopoleBlockNumber - 1)) { TestName = "Before Constantinopole" }; + yield return new TestCaseData((ForkActivation)GnosisSpecProvider.ConstantinopoleBlockNumber) { TestName = "Constantinopole" }; + yield return new TestCaseData((ForkActivation)(GnosisSpecProvider.ConstantinopoleFixBlockNumber - 1)) { TestName = "Before ConstantinopoleFix" }; + yield return new TestCaseData((ForkActivation)GnosisSpecProvider.ConstantinopoleFixBlockNumber) { TestName = "ConstantinopoleFix" }; + yield return new TestCaseData((ForkActivation)(GnosisSpecProvider.IstanbulBlockNumber - 1)) { TestName = "Before Istanbul" }; + yield return new TestCaseData((ForkActivation)GnosisSpecProvider.IstanbulBlockNumber) { TestName = "Istanbul" }; + yield return new TestCaseData((ForkActivation)(GnosisSpecProvider.BerlinBlockNumber - 1)) { TestName = "Before Berlin" }; + yield return new TestCaseData((ForkActivation)GnosisSpecProvider.BerlinBlockNumber) { TestName = "Berlin" }; + yield return new TestCaseData((ForkActivation)(GnosisSpecProvider.LondonBlockNumber - 1)) { TestName = "Before London" }; + yield return new TestCaseData((ForkActivation)GnosisSpecProvider.LondonBlockNumber) { TestName = "London" }; + yield return new TestCaseData((ForkActivation)(GnosisSpecProvider.LondonBlockNumber, GnosisSpecProvider.ShanghaiTimestamp - 1)) { TestName = "Before Shanghai" }; + yield return new TestCaseData((ForkActivation)(GnosisSpecProvider.LondonBlockNumber, GnosisSpecProvider.ShanghaiTimestamp)) { TestName = "Shanghai" }; + yield return new TestCaseData((ForkActivation)(999_999_999, 999_999_999)) { TestName = "Future" }; + } + } + + [TestCaseSource(nameof(GnosisActivations))] + public void Gnosis_loads_properly(ForkActivation forkActivation) { ChainSpec chainSpec = LoadChainSpecFromChainFolder("gnosis"); ChainSpecBasedSpecProvider provider = new(chainSpec); GnosisSpecProvider gnosisSpecProvider = GnosisSpecProvider.Instance; - List forkActivationsToTest = new() - { - (ForkActivation)0, - (ForkActivation)1, - (ForkActivation)(GnosisSpecProvider.ConstantinopoleBlockNumber -1), - (ForkActivation)(GnosisSpecProvider.ConstantinopoleBlockNumber), - (ForkActivation)(GnosisSpecProvider.ConstantinopoleFixBlockNumber -1), - (ForkActivation)(GnosisSpecProvider.ConstantinopoleFixBlockNumber), - (ForkActivation)(GnosisSpecProvider.IstanbulBlockNumber -1), - (ForkActivation)(GnosisSpecProvider.IstanbulBlockNumber), - (ForkActivation)(GnosisSpecProvider.BerlinBlockNumber -1), - (ForkActivation)(GnosisSpecProvider.BerlinBlockNumber), - (ForkActivation)(GnosisSpecProvider.LondonBlockNumber -1), - (ForkActivation)(GnosisSpecProvider.LondonBlockNumber), - (GnosisSpecProvider.LondonBlockNumber, GnosisSpecProvider.ShanghaiTimestamp - 1), - (GnosisSpecProvider.LondonBlockNumber, GnosisSpecProvider.ShanghaiTimestamp), - (999_999_999, 999_999_999) // far in the future - }; - - CompareSpecProviders(gnosisSpecProvider, provider, forkActivationsToTest, CompareSpecsOptions.IsGnosis); + CompareSpecs(gnosisSpecProvider, provider, forkActivation, CompareSpecsOptions.IsGnosis); Assert.That(provider.TerminalTotalDifficulty, Is.EqualTo(GnosisSpecProvider.Instance.TerminalTotalDifficulty)); Assert.That(provider.ChainId, Is.EqualTo(BlockchainIds.Gnosis)); Assert.That(provider.NetworkId, Is.EqualTo(BlockchainIds.Gnosis)); @@ -323,47 +338,49 @@ private void VerifyGnosisPreShanghaiExceptions(ISpecProvider specProvider) .BeTrue(); } + public static IEnumerable MainnetActivations + { + get + { + yield return new TestCaseData((ForkActivation)0) { TestName = "Genesis" }; + yield return new TestCaseData((ForkActivation)(0, null)) { TestName = "Genesis null" }; + yield return new TestCaseData((ForkActivation)(0, 0)) { TestName = "Genesis timestamp" }; + yield return new TestCaseData((ForkActivation)1) { TestName = "Genesis + 1" }; + yield return new TestCaseData((ForkActivation)(MainnetSpecProvider.HomesteadBlockNumber - 1)) { TestName = "Before Homestead" }; + yield return new TestCaseData((ForkActivation)MainnetSpecProvider.HomesteadBlockNumber) { TestName = "Homestead" }; + yield return new TestCaseData((ForkActivation)(MainnetSpecProvider.TangerineWhistleBlockNumber - 1)) { TestName = "Before TangerineWhistle" }; + yield return new TestCaseData((ForkActivation)MainnetSpecProvider.TangerineWhistleBlockNumber) { TestName = "TangerineWhistle" }; + yield return new TestCaseData((ForkActivation)(MainnetSpecProvider.SpuriousDragonBlockNumber - 1)) { TestName = "Before SpuriousDragon" }; + yield return new TestCaseData((ForkActivation)MainnetSpecProvider.SpuriousDragonBlockNumber) { TestName = "SpuriousDragon" }; + yield return new TestCaseData((ForkActivation)(MainnetSpecProvider.ByzantiumBlockNumber - 1)) { TestName = "Before Byzantium" }; + yield return new TestCaseData((ForkActivation)MainnetSpecProvider.ByzantiumBlockNumber) { TestName = "Byzantium" }; + yield return new TestCaseData((ForkActivation)(MainnetSpecProvider.ConstantinopleFixBlockNumber - 1)) { TestName = "Before Constantinople" }; + yield return new TestCaseData((ForkActivation)MainnetSpecProvider.ConstantinopleFixBlockNumber) { TestName = "Constantinople" }; + yield return new TestCaseData((ForkActivation)(MainnetSpecProvider.IstanbulBlockNumber - 1)) { TestName = "Before Istanbul" }; + yield return new TestCaseData((ForkActivation)MainnetSpecProvider.IstanbulBlockNumber) { TestName = "Istanbul" }; + yield return new TestCaseData((ForkActivation)(MainnetSpecProvider.MuirGlacierBlockNumber - 1)) { TestName = "Before MuirGlacier" }; + yield return new TestCaseData((ForkActivation)MainnetSpecProvider.MuirGlacierBlockNumber) { TestName = "MuirGlacier" }; + yield return new TestCaseData((ForkActivation)(MainnetSpecProvider.BerlinBlockNumber - 1)) { TestName = "Before Berlin" }; + yield return new TestCaseData((ForkActivation)MainnetSpecProvider.BerlinBlockNumber) { TestName = "Berlin" }; + yield return new TestCaseData((ForkActivation)(MainnetSpecProvider.LondonBlockNumber - 1)) { TestName = "Before London" }; + yield return new TestCaseData((ForkActivation)MainnetSpecProvider.LondonBlockNumber) { TestName = "London" }; + yield return new TestCaseData((ForkActivation)(MainnetSpecProvider.ArrowGlacierBlockNumber - 1)) { TestName = "Before ArrowGlacier" }; + yield return new TestCaseData((ForkActivation)MainnetSpecProvider.ArrowGlacierBlockNumber) { TestName = "ArrowGlacier" }; + yield return new TestCaseData((ForkActivation)(MainnetSpecProvider.ArrowGlacierBlockNumber - 1)) { TestName = "Before GrayGlacier" }; + yield return new TestCaseData((ForkActivation)MainnetSpecProvider.ArrowGlacierBlockNumber) { TestName = "GrayGlacier" }; + yield return new TestCaseData(MainnetSpecProvider.ShanghaiActivation) { TestName = "Shanghai" }; + yield return new TestCaseData(new ForkActivation(99_000_000, 99_681_338_455)) { TestName = "Future" }; + } + } - [Test] - public void Mainnet_loads_properly() + [TestCaseSource(nameof(MainnetActivations))] + public void Mainnet_loads_properly(ForkActivation forkActivation) { ChainSpec chainSpec = LoadChainSpecFromChainFolder("foundation"); ChainSpecBasedSpecProvider provider = new(chainSpec); MainnetSpecProvider mainnet = MainnetSpecProvider.Instance; - List forkActivationsToTest = new() - { - (ForkActivation)0, - (0, 0), - (0, null), - (ForkActivation)1, - (ForkActivation)(MainnetSpecProvider.HomesteadBlockNumber - 1), - (ForkActivation)MainnetSpecProvider.HomesteadBlockNumber, - (ForkActivation)(MainnetSpecProvider.TangerineWhistleBlockNumber - 1), - (ForkActivation)MainnetSpecProvider.TangerineWhistleBlockNumber, - (ForkActivation)(MainnetSpecProvider.SpuriousDragonBlockNumber - 1), - (ForkActivation)MainnetSpecProvider.SpuriousDragonBlockNumber, - (ForkActivation)(MainnetSpecProvider.ByzantiumBlockNumber - 1), - (ForkActivation)MainnetSpecProvider.ByzantiumBlockNumber, - (ForkActivation)(MainnetSpecProvider.ConstantinopleFixBlockNumber - 1), - (ForkActivation)MainnetSpecProvider.ConstantinopleFixBlockNumber, - (ForkActivation)(MainnetSpecProvider.IstanbulBlockNumber - 1), - (ForkActivation)MainnetSpecProvider.IstanbulBlockNumber, - (ForkActivation)(MainnetSpecProvider.MuirGlacierBlockNumber - 1), - (ForkActivation)MainnetSpecProvider.MuirGlacierBlockNumber, - (ForkActivation)(MainnetSpecProvider.BerlinBlockNumber - 1), - (ForkActivation)MainnetSpecProvider.BerlinBlockNumber, - (ForkActivation)(MainnetSpecProvider.LondonBlockNumber - 1), - (ForkActivation)MainnetSpecProvider.LondonBlockNumber, - (ForkActivation)(MainnetSpecProvider.ArrowGlacierBlockNumber - 1), - (ForkActivation)MainnetSpecProvider.ArrowGlacierBlockNumber, - (ForkActivation)(MainnetSpecProvider.GrayGlacierBlockNumber - 1), - (ForkActivation)MainnetSpecProvider.GrayGlacierBlockNumber, - MainnetSpecProvider.ShanghaiActivation, - new ForkActivation(99_000_000, 99_681_338_455) // far in the future - }; - - CompareSpecProviders(mainnet, provider, forkActivationsToTest, CompareSpecsOptions.CheckDifficultyBomb); + CompareSpecs(mainnet, provider, forkActivation, CompareSpecsOptions.CheckDifficultyBomb); provider.GetSpec((MainnetSpecProvider.SpuriousDragonBlockNumber, null)).MaxCodeSize.Should().Be(24576L); provider.GetSpec((MainnetSpecProvider.SpuriousDragonBlockNumber, null)).MaxInitCodeSize.Should().Be(2 * 24576L); @@ -401,24 +418,21 @@ enum CompareSpecsOptions IsGnosis = 4 // for Gnosis and Chiado testnets } - private static void CompareSpecProviders( + private static void CompareSpecs( ISpecProvider oldSpecProvider, ISpecProvider newSpecProvider, - IEnumerable forkActivations, + ForkActivation activation, CompareSpecsOptions compareSpecsOptions = CompareSpecsOptions.None) { - foreach (ForkActivation activation in forkActivations) - { - IReleaseSpec oldSpec = oldSpecProvider.GetSpec(activation); - IReleaseSpec newSpec = newSpecProvider.GetSpec(activation); - long? daoBlockNumber = newSpecProvider.DaoBlockNumber; + IReleaseSpec oldSpec = oldSpecProvider.GetSpec(activation); + IReleaseSpec newSpec = newSpecProvider.GetSpec(activation); + long? daoBlockNumber = newSpecProvider.DaoBlockNumber; - bool isMainnet = daoBlockNumber is not null; - if (isMainnet) - compareSpecsOptions |= CompareSpecsOptions.IsMainnet; + bool isMainnet = daoBlockNumber is not null; + if (isMainnet) + compareSpecsOptions |= CompareSpecsOptions.IsMainnet; - CompareSpecs(oldSpec, newSpec, activation, compareSpecsOptions); - } + CompareSpecs(oldSpec, newSpec, activation, compareSpecsOptions); } private static void CompareSpecs(IReleaseSpec expectedSpec, IReleaseSpec actualSpec, ForkActivation activation, CompareSpecsOptions compareSpecsOptions) @@ -828,6 +842,9 @@ public static IEnumerable BlockNumbersAndTimestampsNearForkActivations { get { + yield return new TestCaseData(new ForkActivation(1), true, false, false); + yield return new TestCaseData(new ForkActivation(2), true, false, false); + yield return new TestCaseData(new ForkActivation(3), true, false, false); yield return new TestCaseData(new ForkActivation(1, 9), true, false, false); yield return new TestCaseData(new ForkActivation(2, 9), true, false, false); yield return new TestCaseData(new ForkActivation(2, 10), true, true, false); diff --git a/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecLoaderTests.cs b/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecLoaderTests.cs index 0e2413c5898..d44ac4d2a4a 100644 --- a/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecLoaderTests.cs +++ b/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecLoaderTests.cs @@ -147,6 +147,7 @@ public void Can_load_goerli() chainSpec.LondonBlockNumber.Should().Be(GoerliSpecProvider.LondonBlockNumber); chainSpec.ShanghaiTimestamp.Should().Be(GoerliSpecProvider.ShanghaiTimestamp); chainSpec.ShanghaiTimestamp.Should().Be(GoerliSpecProvider.Instance.TimestampFork); + chainSpec.CancunTimestamp.Should().Be(GoerliSpecProvider.CancunTimestamp); } [Test] diff --git a/src/Nethermind/Nethermind.Specs.Test/CustomSpecProvider.cs b/src/Nethermind/Nethermind.Specs.Test/CustomSpecProvider.cs index 2a00eb2019d..6b405e37354 100644 --- a/src/Nethermind/Nethermind.Specs.Test/CustomSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs.Test/CustomSpecProvider.cs @@ -1,86 +1,59 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; using System.Linq; using Nethermind.Core; -using Nethermind.Core.Collections; using Nethermind.Core.Specs; using Nethermind.Int256; +using Nethermind.Specs.ChainSpecStyle; using Nethermind.Specs.Forks; -namespace Nethermind.Specs.Test -{ - public class CustomSpecProvider : ISpecProvider - { - private ForkActivation? _theMergeBlock = null; - private readonly (ForkActivation Activation, IReleaseSpec Spec)[] _transitions; - - public ulong NetworkId { get; } - public ulong ChainId { get; } +namespace Nethermind.Specs.Test; - public ForkActivation[] TransitionActivations { get; } - - public CustomSpecProvider(params (ForkActivation Activation, IReleaseSpec Spec)[] transitions) : this(TestBlockchainIds.NetworkId, TestBlockchainIds.ChainId, transitions) - { - } - - public CustomSpecProvider(ulong networkId, ulong chainId, params (ForkActivation Activation, IReleaseSpec Spec)[] transitions) - { - NetworkId = networkId; - ChainId = chainId; +public class CustomSpecProvider : SpecProviderBase, ISpecProvider +{ + private ForkActivation? _theMergeBlock = null; - if (transitions.Length == 0) - { - throw new ArgumentException($"There must be at least one release specified when instantiating {nameof(CustomSpecProvider)}", $"{nameof(transitions)}"); - } + public ulong NetworkId { get; } + public ulong ChainId { get; } - _transitions = transitions.OrderBy(r => r.Activation).ToArray(); - TransitionActivations = _transitions.Select(t => t.Activation).ToArray(); + public CustomSpecProvider(params (ForkActivation Activation, IReleaseSpec Spec)[] transitions) : this(TestBlockchainIds.NetworkId, TestBlockchainIds.ChainId, transitions) + { + } - if (transitions[0].Activation.BlockNumber != 0L) - { - throw new ArgumentException($"First release specified when instantiating {nameof(CustomSpecProvider)} should be at genesis block (0)", $"{nameof(transitions)}"); - } - } + public CustomSpecProvider(ulong networkId, ulong chainId, params (ForkActivation Activation, IReleaseSpec Spec)[] transitions) + { + NetworkId = networkId; + ChainId = chainId; - public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalDifficulty = null) - { - if (blockNumber is not null) - _theMergeBlock = (ForkActivation)blockNumber; - if (terminalTotalDifficulty is not null) - TerminalTotalDifficulty = terminalTotalDifficulty; - } + (ForkActivation Activation, IReleaseSpec Spec)[] orderedTransitions = transitions.OrderBy(r => r.Activation).ToArray(); - public ForkActivation? MergeBlockNumber => _theMergeBlock; + LoadTransitions(orderedTransitions); - public ulong TimestampFork { get; set; } = ISpecProvider.TimestampForkNever; - public UInt256? TerminalTotalDifficulty { get; set; } + TransitionActivations = orderedTransitions.Select(t => t.Activation).ToArray(); + } -#pragma warning disable CS8602 -#pragma warning disable CS8603 - public IReleaseSpec GenesisSpec => _transitions.Length == 0 ? null : _transitions[0].Spec; -#pragma warning restore CS8603 -#pragma warning restore CS8602 + public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalDifficulty = null) + { + if (blockNumber is not null) + _theMergeBlock = (ForkActivation)blockNumber; + if (terminalTotalDifficulty is not null) + TerminalTotalDifficulty = terminalTotalDifficulty; + } - public IReleaseSpec GetSpec(ForkActivation forkActivation) => - _transitions.TryGetSearchedItem(forkActivation, - CompareTransitionOnBlock, - out (ForkActivation Activation, IReleaseSpec Spec) transition) - ? transition.Spec - : GenesisSpec; + public ForkActivation? MergeBlockNumber => _theMergeBlock; - private static int CompareTransitionOnBlock(ForkActivation forkActivation, (ForkActivation Activation, IReleaseSpec Spec) transition) => - forkActivation.CompareTo(transition.Activation); + public ulong TimestampFork { get; set; } = ISpecProvider.TimestampForkNever; + public UInt256? TerminalTotalDifficulty { get; set; } - public long? DaoBlockNumber + public long? DaoBlockNumber + { + get { - get - { - (ForkActivation forkActivation, IReleaseSpec daoRelease) = _transitions.SingleOrDefault(t => t.Spec == Dao.Instance); - return daoRelease is not null ? forkActivation.BlockNumber : null; - } + (ForkActivation forkActivation, IReleaseSpec? daoRelease) = _blockTransitions.SingleOrDefault(t => t.Spec == Dao.Instance); + return daoRelease is not null ? forkActivation.BlockNumber : null; } - } + } + diff --git a/src/Nethermind/Nethermind.Specs.Test/CustomSpecProviderTests.cs b/src/Nethermind/Nethermind.Specs.Test/CustomSpecProviderTests.cs index 76ecf40eb11..df91b86c5e5 100644 --- a/src/Nethermind/Nethermind.Specs.Test/CustomSpecProviderTests.cs +++ b/src/Nethermind/Nethermind.Specs.Test/CustomSpecProviderTests.cs @@ -21,10 +21,6 @@ public void When_no_transitions_specified_throws_argument_exception() public void When_first_release_is_not_at_block_zero_then_throws_argument_exception() { Assert.Throws(() => _ = new CustomSpecProvider(((ForkActivation)1, Byzantium.Instance)), "ordered"); - - Assert.Throws(() => _ = new CustomSpecProvider( - ((ForkActivation)1, Byzantium.Instance), - ((ForkActivation)0, Frontier.Instance)), "not ordered"); } [Test] diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecBasedSpecProvider.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecBasedSpecProvider.cs index 64d5257070b..4e94afb5f12 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecBasedSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecBasedSpecProvider.cs @@ -6,26 +6,20 @@ using System.Linq; using System.Numerics; using System.Reflection; -using Nethermind.Core.Collections; using Nethermind.Core.Specs; using Nethermind.Int256; using Nethermind.Logging; namespace Nethermind.Specs.ChainSpecStyle { - public class ChainSpecBasedSpecProvider : ISpecProvider + public class ChainSpecBasedSpecProvider : SpecProviderBase, ISpecProvider { - private (ForkActivation Activation, ReleaseSpec Spec)[] _transitions; - private (ForkActivation Activation, ReleaseSpec Spec)[] _timestampOnlyTransitions; - private ForkActivation? _firstTimestampActivation; - private readonly ChainSpec _chainSpec; - private readonly ILogger _logger; public ChainSpecBasedSpecProvider(ChainSpec chainSpec, ILogManager logManager = null) + : base(logManager?.GetClassLogger() ?? LimboTraceLogger.Instance) { _chainSpec = chainSpec ?? throw new ArgumentNullException(nameof(chainSpec)); - _logger = logManager?.GetClassLogger() ?? LimboTraceLogger.Instance; BuildTransitions(); } @@ -96,10 +90,12 @@ static void Add(SortedSet transitions, T value, T? minValueExclusive) transitionBlockNumbers.Add(bombDelay.Key); } + + (ForkActivation Activation, IReleaseSpec Spec)[] allTransitions = CreateTransitions(_chainSpec, transitionBlockNumbers, transitionTimestamps); + + LoadTransitions(allTransitions); + TransitionActivations = CreateTransitionActivations(transitionBlockNumbers, transitionTimestamps); - _transitions = CreateTransitions(_chainSpec, transitionBlockNumbers, transitionTimestamps); - _firstTimestampActivation = TransitionActivations.FirstOrDefault(t => t.Timestamp is not null); - _timestampOnlyTransitions = _transitions.SkipWhile(t => t.Activation.Timestamp is null).ToArray(); if (_chainSpec.Parameters.TerminalPoWBlockNumber is not null) { @@ -109,12 +105,12 @@ static void Add(SortedSet transitions, T value, T? minValueExclusive) TerminalTotalDifficulty = _chainSpec.Parameters.TerminalTotalDifficulty; } - private static (ForkActivation, ReleaseSpec Spec)[] CreateTransitions( + private static (ForkActivation, IReleaseSpec Spec)[] CreateTransitions( ChainSpec chainSpec, SortedSet transitionBlockNumbers, SortedSet transitionTimestamps) { - (ForkActivation Activation, ReleaseSpec Spec)[] transitions = new (ForkActivation, ReleaseSpec Spec)[transitionBlockNumbers.Count + transitionTimestamps.Count]; + (ForkActivation Activation, IReleaseSpec Spec)[] transitions = new (ForkActivation, IReleaseSpec Spec)[transitionBlockNumbers.Count + transitionTimestamps.Count]; long biggestBlockTransition = transitionBlockNumbers.Max; int index = 0; @@ -266,41 +262,9 @@ public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalD public UInt256? TerminalTotalDifficulty { get; private set; } - public IReleaseSpec GenesisSpec => _transitions.Length == 0 ? null : _transitions[0].Spec; - - public IReleaseSpec GetSpec(ForkActivation activation) - { - (ForkActivation Activation, ReleaseSpec Spec)[] consideredTransitions = _transitions; - - // TODO: Is this actually needed? Can this be tricked with invalid activation check if someone would fake timestamp from the future? - if (_firstTimestampActivation is not null && activation.Timestamp is not null) - { - if (_firstTimestampActivation.Value.Timestamp < activation.Timestamp - && _firstTimestampActivation.Value.BlockNumber > activation.BlockNumber) - { - if (_logger.IsWarn) _logger.Warn($"Chainspec file is misconfigured! Timestamp transition is configured to happen before the last block transition."); - } - - if (_firstTimestampActivation.Value.Timestamp <= activation.Timestamp) - { - consideredTransitions = _timestampOnlyTransitions; - } - } - - return consideredTransitions.TryGetSearchedItem(activation, - CompareTransitionOnActivation, - out (ForkActivation Activation, ReleaseSpec Spec) transition) - ? transition.Spec - : GenesisSpec; - } - - private static int CompareTransitionOnActivation(ForkActivation activation, (ForkActivation Activation, ReleaseSpec Spec) transition) => - activation.CompareTo(transition.Activation); - public long? DaoBlockNumber => _chainSpec.DaoForkBlockNumber; public ulong NetworkId => _chainSpec.NetworkId; public ulong ChainId => _chainSpec.ChainId; - public ForkActivation[] TransitionActivations { get; private set; } } } diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/SpecProviderBase.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/SpecProviderBase.cs new file mode 100644 index 00000000000..bc5410bb807 --- /dev/null +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/SpecProviderBase.cs @@ -0,0 +1,71 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Core.Collections; +using Nethermind.Core.Specs; +using Nethermind.Logging; +using System; +using System.Linq; + +namespace Nethermind.Specs.ChainSpecStyle; + +public abstract class SpecProviderBase +{ + protected (ForkActivation Activation, IReleaseSpec Spec)[] _blockTransitions; + private (ForkActivation Activation, IReleaseSpec Spec)[] _timestampTransitions; + private ForkActivation? _firstTimestampActivation; + protected readonly ILogger _logger; + + public SpecProviderBase(ILogger logger = null) + { + _logger = logger; + } + + protected void LoadTransitions((ForkActivation Activation, IReleaseSpec Spec)[] transitions) + { + if (transitions.Length == 0) + { + throw new ArgumentException($"There must be at least one release specified when instantiating {GetType()}", $"{nameof(transitions)}"); + } + + if (transitions.First().Activation.BlockNumber != 0L) + { + throw new ArgumentException($"First release specified when instantiating {GetType()} should be at genesis block (0)", $"{nameof(transitions)}"); + } + + _blockTransitions = transitions.TakeWhile(t => t.Activation.Timestamp is null).ToArray(); + _timestampTransitions = transitions.SkipWhile(t => t.Activation.Timestamp is null).ToArray(); + _firstTimestampActivation = _timestampTransitions.Length != 0 ? _timestampTransitions.First().Activation : null; + GenesisSpec = transitions.First().Spec; + } + + public ForkActivation[] TransitionActivations { get; protected set; } + + public IReleaseSpec GenesisSpec { get; private set; } + + public IReleaseSpec GetSpec(ForkActivation activation) + { + static int CompareTransitionOnActivation(ForkActivation activation, (ForkActivation Activation, IReleaseSpec Spec) transition) => + activation.CompareTo(transition.Activation); + + (ForkActivation Activation, IReleaseSpec Spec)[] consideredTransitions = _blockTransitions; + + if (_firstTimestampActivation is not null && activation.Timestamp is not null) + { + if (_firstTimestampActivation.Value.Timestamp < activation.Timestamp + && _firstTimestampActivation.Value.BlockNumber > activation.BlockNumber) + { + if (_logger is not null && _logger.IsWarn) _logger.Warn($"Chainspec file is misconfigured! Timestamp transition is configured to happen before the last block transition."); + } + + if (_firstTimestampActivation.Value.Timestamp <= activation.Timestamp) + consideredTransitions = _timestampTransitions; + } + + return consideredTransitions.TryGetSearchedItem(activation, + CompareTransitionOnActivation, + out (ForkActivation Activation, IReleaseSpec Spec) transition) + ? transition.Spec + : GenesisSpec; + } +} diff --git a/src/Nethermind/Nethermind.Specs/Forks/16_Cancun.cs b/src/Nethermind/Nethermind.Specs/Forks/16_Cancun.cs index b92ae9e61a4..a6d72720ba2 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/16_Cancun.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/16_Cancun.cs @@ -15,10 +15,10 @@ protected Cancun() { Name = "Cancun"; IsEip1153Enabled = true; - IsEip5656Enabled = true; + IsEip4788Enabled = true; IsEip4844Enabled = true; + IsEip5656Enabled = true; IsEip6780Enabled = true; - IsEip4788Enabled = true; Eip4788ContractAddress = new Address("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02"); } diff --git a/src/Nethermind/Nethermind.Specs/GoerliSpecProvider.cs b/src/Nethermind/Nethermind.Specs/GoerliSpecProvider.cs index 5defde805f0..13b68ffbe88 100644 --- a/src/Nethermind/Nethermind.Specs/GoerliSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/GoerliSpecProvider.cs @@ -15,6 +15,7 @@ public class GoerliSpecProvider : ISpecProvider public const long LondonBlockNumber = 5_062_605; public const ulong BeaconChainGenesisTimestamp = 0x6059f460; public const ulong ShanghaiTimestamp = 0x6410f460; + public const ulong CancunTimestamp = 0x65A77460; private GoerliSpecProvider() { } @@ -28,7 +29,8 @@ public IReleaseSpec GetSpec(ForkActivation forkActivation) _ => forkActivation.Timestamp switch { null or < ShanghaiTimestamp => London.Instance, - _ => Shanghai.Instance + < CancunTimestamp => Shanghai.Instance, + _ => Cancun.Instance } }; } @@ -53,7 +55,8 @@ public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalD (ForkActivation)IstanbulBlockNumber, (ForkActivation)BerlinBlockNumber, (ForkActivation)LondonBlockNumber, - (LondonBlockNumber, ShanghaiTimestamp) + (LondonBlockNumber + 1, ShanghaiTimestamp), + (LondonBlockNumber + 2, CancunTimestamp) }; public static readonly GoerliSpecProvider Instance = new();