Skip to content

Commit

Permalink
Properly activate timestamp fork (#6386)
Browse files Browse the repository at this point in the history
* Activate timestamp fork even if block matches block only fork

* Remove duplication
  • Loading branch information
flcl42 committed Dec 18, 2023
1 parent 97fb56c commit 18e37da
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -100,15 +101,16 @@ public void Logs_warning_when_timestampActivation_happens_before_blockActivation
expectedSpec.IsEip3855Enabled = isEip3855Enabled;
expectedSpec.Eip1559TransitionBlock = 0;
expectedSpec.DifficultyBombDelay = 0;
TestSpecProvider testProvider = TestSpecProvider.Instance;
testProvider.SpecToReturn = expectedSpec;
testProvider.TerminalTotalDifficulty = 0;
testProvider.GenesisSpec = expectedSpec;
List<ForkActivation> forkActivationsToTest = new()
{
(blockNumber, timestamp),
};
CompareSpecProviders(testProvider, provider, forkActivationsToTest);

foreach (ForkActivation activation in forkActivationsToTest)
{
provider.GetSpec(activation);
}

if (receivesWarning)
{
logger.Received(1).Warn(Arg.Is("Chainspec file is misconfigured! Timestamp transition is configured to happen before the last block transition."));
Expand Down Expand Up @@ -263,8 +265,8 @@ public void Gnosis_loads_properly()
(ForkActivation)(GnosisSpecProvider.BerlinBlockNumber),
(ForkActivation)(GnosisSpecProvider.LondonBlockNumber -1),
(ForkActivation)(GnosisSpecProvider.LondonBlockNumber),
(1, GnosisSpecProvider.ShanghaiTimestamp - 1),
(1, GnosisSpecProvider.ShanghaiTimestamp),
(GnosisSpecProvider.LondonBlockNumber, GnosisSpecProvider.ShanghaiTimestamp - 1),
(GnosisSpecProvider.LondonBlockNumber, GnosisSpecProvider.ShanghaiTimestamp),
(999_999_999, 999_999_999) // far in the future
};

Expand Down Expand Up @@ -804,6 +806,43 @@ void TestTransitions(ForkActivation activation, Action<ReleaseSpec> changes)
TestTransitions((40001L, 1000000024), r => { r.IsEip1153Enabled = r.IsEip2537Enabled = true; });
}

[TestCaseSource(nameof(BlockNumbersAndTimestampsNearForkActivations))]
public void Forks_should_be_selected_properly_for_exact_matches(ForkActivation forkActivation, bool isEip3651Enabled, bool isEip3198Enabled, bool isEip3855Enabled)
{
ISpecProvider provider = new CustomSpecProvider(
(new ForkActivation(0), new ReleaseSpec() { IsEip3651Enabled = true }),
(new ForkActivation(2, 10), new ReleaseSpec() { IsEip3651Enabled = true, IsEip3198Enabled = true, }),
(new ForkActivation(2, 20), new ReleaseSpec() { IsEip3651Enabled = true, IsEip3198Enabled = true, IsEip3855Enabled = true })
);

IReleaseSpec spec = provider.GetSpec(forkActivation);
Assert.Multiple(() =>
{
Assert.That(spec.IsEip3651Enabled, Is.EqualTo(isEip3651Enabled));
Assert.That(spec.IsEip3198Enabled, Is.EqualTo(isEip3198Enabled));
Assert.That(spec.IsEip3855Enabled, Is.EqualTo(isEip3855Enabled));
});
}

public static IEnumerable BlockNumbersAndTimestampsNearForkActivations
{
get
{
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);
yield return new TestCaseData(new ForkActivation(2, 11), true, true, false);
yield return new TestCaseData(new ForkActivation(2, 19), true, true, false);
yield return new TestCaseData(new ForkActivation(2, 20), true, true, true);
yield return new TestCaseData(new ForkActivation(2, 21), true, true, true);
yield return new TestCaseData(new ForkActivation(3, 10), true, true, false);
yield return new TestCaseData(new ForkActivation(3, 11), true, true, false);
yield return new TestCaseData(new ForkActivation(3, 19), true, true, false);
yield return new TestCaseData(new ForkActivation(3, 20), true, true, true);
yield return new TestCaseData(new ForkActivation(3, 21), true, true, true);
}
}

private static IEnumerable<ulong> GetTransitionTimestamps(ChainParameters parameters) => parameters.GetType()
.Properties()
.Where(p => p.Name.EndsWith("TransitionTimestamp", StringComparison.Ordinal))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace Nethermind.Specs.ChainSpecStyle
public class ChainSpecBasedSpecProvider : ISpecProvider
{
private (ForkActivation Activation, ReleaseSpec Spec)[] _transitions;
private (ForkActivation Activation, ReleaseSpec Spec)[] _timestampOnlyTransitions;
private ForkActivation? _firstTimestampActivation;

private readonly ChainSpec _chainSpec;
Expand Down Expand Up @@ -98,6 +99,7 @@ static void Add(SortedSet<T> transitions, T value, T? minValueExclusive)
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)
{
Expand Down Expand Up @@ -268,6 +270,8 @@ public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalD

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)
{
Expand All @@ -276,9 +280,14 @@ public IReleaseSpec GetSpec(ForkActivation activation)
{
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 _transitions.TryGetSearchedItem(activation,
return consideredTransitions.TryGetSearchedItem(activation,
CompareTransitionOnActivation,
out (ForkActivation Activation, ReleaseSpec Spec) transition)
? transition.Spec
Expand Down

0 comments on commit 18e37da

Please sign in to comment.