1- // SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited
1+ // SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
22// SPDX-License-Identifier: LGPL-3.0-only
33
4- using System ;
5- using System . Collections ;
6- using System . Collections . Generic ;
7- using System . IO ;
8- using System . Linq ;
9- using System . Reflection ;
104using FluentAssertions ;
115using Nethermind . Config ;
126using Nethermind . Consensus . AuRa . Config ;
1913using Nethermind . Logging ;
2014using Nethermind . Serialization . Json ;
2115using Nethermind . Specs . ChainSpecStyle ;
16+ using Nethermind . Specs . ChainSpecStyle . Json ;
2217using NSubstitute ;
2318using NUnit . Framework ;
19+ using System ;
20+ using System . Collections ;
21+ using System . Collections . Generic ;
22+ using System . IO ;
23+ using System . Linq ;
24+ using System . Reflection ;
2425
2526namespace Nethermind . Specs . Test . ChainSpecStyle ;
2627
@@ -45,11 +46,11 @@ public void Setup()
4546 [ TestCase ( 4 , 4673ul , true ) ]
4647 [ TestCase ( 5 , 4680ul , true ) ]
4748 [ NonParallelizable ]
48- public void Timstamp_activation_equal_to_genesis_timestamp_loads_correctly ( long blockNumber , ulong ? timestamp , bool isEip3855Enabled )
49+ public void Timestamp_activation_equal_to_genesis_timestamp_loads_correctly ( long blockNumber , ulong ? timestamp , bool isEip3855Enabled )
4950 {
5051 var loader = new ChainSpecFileLoader ( new EthereumJsonSerializer ( ) , LimboTraceLogger . Instance ) ;
5152 string path = Path . Combine ( TestContext . CurrentContext . WorkDirectory ,
52- $ "../../../../{ Assembly . GetExecutingAssembly ( ) . GetName ( ) . Name } /Specs/Timstamp_activation_equal_to_genesis_timestamp_test .json") ;
53+ $ "../../../../{ Assembly . GetExecutingAssembly ( ) . GetName ( ) . Name } /Specs/Timestamp_activation_equal_to_genesis_timestamp_test .json") ;
5354 ChainSpec chainSpec = loader . LoadEmbeddedOrFromFile ( path ) ;
5455 chainSpec . Parameters . Eip2537Transition . Should ( ) . BeNull ( ) ;
5556 ILogger logger = new ( Substitute . ForPartsOf < LimboTraceLogger > ( ) ) ;
@@ -821,6 +822,80 @@ public static IEnumerable BlockNumbersAndTimestampsNearForkActivations
821822 }
822823 }
823824
825+ [ TestCaseSource ( nameof ( BlobScheduleActivationsTestCaseSource ) ) ]
826+ public void Test_BlobSchedule_IsApplied_AlongWithForkSchedule (
827+ ulong eip4844Timestamp ,
828+ ulong eip7002Timestamp ,
829+ BlobScheduleSettings [ ] blobScheduleSettings ,
830+ ulong [ ] expectedActivationSettings )
831+ {
832+ ChainSpecBasedSpecProvider provider = new ( new ChainSpec
833+ {
834+ Parameters = new ChainParameters
835+ {
836+ Eip4844TransitionTimestamp = eip4844Timestamp ,
837+ Eip7002TransitionTimestamp = eip7002Timestamp ,
838+ BlobSchedule = [ .. blobScheduleSettings ]
839+ } ,
840+ EngineChainSpecParametersProvider = Substitute . For < IChainSpecParametersProvider > ( )
841+ } ) ;
842+
843+ IReleaseSpec spec = provider . GenesisSpec ;
844+ Assert . That ( spec . MaxBlobCount , Is . EqualTo ( expectedActivationSettings [ 0 ] ) ) ;
845+
846+ expectedActivationSettings = expectedActivationSettings [ 1 ..] ;
847+ Assert . That ( expectedActivationSettings , Has . Length . EqualTo ( provider . TransitionActivations . Length ) ) ;
848+
849+ for ( int i = 0 ; i < expectedActivationSettings . Length ; i ++ )
850+ {
851+ spec = provider . GetSpec ( ForkActivation . TimestampOnly ( provider . TransitionActivations [ i ] . Timestamp ! . Value ) ) ;
852+ Assert . That ( spec . MaxBlobCount , Is . EqualTo ( expectedActivationSettings [ i ] ) ) ;
853+ }
854+ }
855+
856+ public static IEnumerable BlobScheduleActivationsTestCaseSource
857+ {
858+ get
859+ {
860+ const int NoneAllowed = 0 ;
861+ const int Default = 6 ;
862+ static TestCaseData MakeTestCase ( string testName , int eip4844Timestamp , int eip7002Timestamp , ( int timestamp , int max ) [ ] settings , ulong [ ] expectedActivationSettings )
863+ => new ( [
864+ ( ulong ) eip4844Timestamp ,
865+ ( ulong ) eip7002Timestamp ,
866+ settings . Select ( s => new BlobScheduleSettings { Timestamp = ( ulong ) s . timestamp , Max = ( ulong ) s . max , Target = ( ulong ) s . max , BaseFeeUpdateFraction = ( ulong ) s . max } ) . ToArray ( ) ,
867+ expectedActivationSettings ] )
868+ { TestName = $ "BlobScheduleActivations: { testName } " } ;
869+
870+ yield return MakeTestCase ( "Default" , 1 , 2 , [ ] , [ NoneAllowed , Default , Default ] ) ;
871+
872+ yield return MakeTestCase ( "Both activate not at genesis" , 1 , 1 , [ ] , [ NoneAllowed , Default ] ) ;
873+
874+ yield return MakeTestCase ( "Named only from genesis" , 0 , 0 , [ ] , [ Default ] ) ;
875+
876+ yield return MakeTestCase ( "Default from genesis + BPO" , 0 , 0 , [ ( 1 , 7 ) ] , [ Default , 7 ] ) ;
877+
878+ yield return MakeTestCase ( "BPO from genesis" , 0 , 0 , [ ( 0 , 7 ) ] , [ 7 ] ) ;
879+
880+ yield return MakeTestCase ( "A named fork has no change in settings" , 1 , 2 , [ ( 3 , 10 ) ] , [ NoneAllowed , Default , Default , 10 ] ) ;
881+
882+ yield return MakeTestCase ( "Cancun and Prague have default settings, but a between bpo changes it" , 0 , 2 , [ ( 1 , 10 ) ] , [ Default , 10 , 10 ] ) ;
883+
884+ yield return MakeTestCase ( "Multiple BPOs" , 0 , 0 , [
885+ ( 1 , 5 ) ,
886+ ( 2 , 6 ) ,
887+ ( 3 , 10 ) ,
888+ ( 4 , 12 ) ,
889+ ( 5 , 10 ) ,
890+ ( 6 , 10 ) ] ,
891+ [ Default , 5 , 6 , 10 , 12 , 10 , 10 ] ) ;
892+
893+ yield return MakeTestCase ( "BPOs match named forks" , 1 , 2 , [ ( 1 , 10 ) , ( 2 , 3 ) ] , [ NoneAllowed , 10 , 3 ] ) ;
894+
895+ yield return MakeTestCase ( "BPO timestamp matches genesis, but not any other fork" , 0 , 2 , [ ( 0 , 10 ) , ( 1 , 11 ) ] , [ 10 , 11 , 11 ] ) ;
896+ }
897+ }
898+
824899 private static IEnumerable < ulong > GetTransitionTimestamps ( ChainParameters parameters ) => parameters . GetType ( )
825900 . Properties ( )
826901 . Where ( p => p . Name . EndsWith ( "TransitionTimestamp" , StringComparison . Ordinal ) )
0 commit comments