Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/Nethermind/Nethermind.Consensus.AuRa/AuRaPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
using Nethermind.Logging;
using Nethermind.Serialization.Rlp;
using Nethermind.Specs.ChainSpecStyle;
using Nethermind.State.Repositories;
using Nethermind.Synchronization;

[assembly: InternalsVisibleTo("Nethermind.Merge.AuRa")]
Expand Down Expand Up @@ -90,6 +91,9 @@ protected override void Load(ContainerBuilder builder)
.AddSingleton<IMainProcessingModule, AuraMainProcessingModule>()
.AddScoped<IAuRaValidator, NullAuRaValidator>() // Note: for main block processor this is not the case
.AddScoped<IBlockProcessor, AuRaBlockProcessor>()
.AddSingleton<IAuRaBlockFinalizationManager, IBlockTree, IChainLevelInfoRepository, IValidatorStore, ILogManager, AuRaChainSpecEngineParameters>(
(blockTree, chainLevelInfoRepository, validatorStore, logManager, param) =>
new AuRaBlockFinalizationManager(blockTree, chainLevelInfoRepository, validatorStore, logManager, param.TwoThirdsMajorityTransition))

.AddSingleton<IRewardCalculatorSource, AuRaRewardCalculator.AuRaRewardCalculatorSource>()
.AddSingleton<IValidSealerStrategy, ValidSealerStrategy>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ namespace Nethermind.Consensus.AuRa.InitializationSteps
{
public class AuRaNethermindApi(NethermindApi.Dependencies dependencies) : NethermindApi(dependencies)
{
public IAuRaBlockFinalizationManager? AuRaFinalizationManager { get; set; }

public TxAuRaFilterBuilders TxAuRaFilterBuilders => Context.Resolve<TxAuRaFilterBuilders>();
public IValidatorStore ValidatorStore => Context.Resolve<IValidatorStore>();
public AuraStatefulComponents AuraStatefulComponents => Context.Resolve<AuraStatefulComponents>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ public class AuraMainProcessingModule(
AuRaChainSpecEngineParameters chainSpecAuRa
) : Module, IMainProcessingModule
{
protected override void Load(ContainerBuilder builder) => builder.AddSingleton<IAuRaValidator, AuRaNethermindApi, IWorldState, ITransactionProcessor>(CreateAuRaValidator);
protected override void Load(ContainerBuilder builder) => builder.AddSingleton<IAuRaValidator, AuRaNethermindApi, IWorldState, ITransactionProcessor, IAuRaBlockFinalizationManager>(CreateAuRaValidator);

private IAuRaValidator CreateAuRaValidator(AuRaNethermindApi api, IWorldState worldState, ITransactionProcessor transactionProcessor)
private IAuRaValidator CreateAuRaValidator(AuRaNethermindApi api, IWorldState worldState, ITransactionProcessor transactionProcessor, IAuRaBlockFinalizationManager finalizationManager)
{

IAuRaValidator validator = new AuRaValidatorFactory(
Expand All @@ -38,7 +38,7 @@ private IAuRaValidator CreateAuRaValidator(AuRaNethermindApi api, IWorldState wo
envFactory.Create(),
api.ReceiptStorage,
api.ValidatorStore,
api.AuRaFinalizationManager,
finalizationManager,
new TxPoolSender(api.TxPool, new TxSealer(api.EngineSigner, api.Timestamper), api.NonceManager, api.EthereumEcdsa),
api.TxPool,
api.Config<IBlocksConfig>(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

using System.Collections.Generic;
using System.Threading.Tasks;
using Autofac;
using Nethermind.Api;
using Nethermind.Blockchain.Data;
using Nethermind.Consensus.AuRa.Config;
using Nethermind.Consensus.AuRa.Contracts;
using Nethermind.Consensus.AuRa.Contracts.DataStore;
using Nethermind.Consensus.AuRa.Transactions;
Expand All @@ -27,14 +27,6 @@ public class InitializeBlockchainAuRa(AuRaNethermindApi api, IChainHeadInfoProvi

protected override async Task InitBlockchain()
{
AuRaChainSpecEngineParameters chainSpecAuRa = api.ChainSpec.EngineChainSpecParametersProvider.GetChainSpecParameters<AuRaChainSpecEngineParameters>();
api.AuRaFinalizationManager = new AuRaBlockFinalizationManager(
api.BlockTree!,
api.ChainLevelInfoRepository!,
api.ValidatorStore!,
api.LogManager,
chainSpecAuRa.TwoThirdsMajorityTransition);

await base.InitBlockchain();

WireFinalizationBranchProcessor();
Expand All @@ -49,7 +41,7 @@ protected override async Task InitBlockchain()
/// Got cyclic dependency. AuRaBlockFinalizationManager -> IAuraValidator -> AuraBlockProcessor -> AuraBlockFinalizationManager.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inderesting, loop is just due to event subscription seems like. We might try to solve it by some mediatr kind of stuff or so

/// </remarks>
protected virtual void WireFinalizationBranchProcessor() =>
api.AuRaFinalizationManager!.SetMainBlockBranchProcessor(api.MainProcessingContext!.BranchProcessor!);
api.Context.Resolve<IAuRaBlockFinalizationManager>().SetMainBlockBranchProcessor(api.MainProcessingContext!.BranchProcessor!);

private IComparer<Transaction> CreateTxPoolTxComparer(TxPriorityContract? txPriorityContract, TxPriorityContract.LocalDataSource? localDataSource)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,14 @@ protected override ContainerBuilder ConfigureContainer(ContainerBuilder builder,
.AddSingleton<IBlockImprovementContextFactory, IBlockProducer, IMergeConfig>((blockProducer,
mergeConfig) => new BlockImprovementContextFactory(blockProducer, TimeSpan.FromSeconds(mergeConfig.SecondsPerSlot)))

.AddSingleton<IAuRaBlockFinalizationManager>(Substitute.For<IAuRaBlockFinalizationManager>())

.AddDecorator<AuRaNethermindApi>((_, api) =>
{
// Yes getting from `TestBlockchain` itself, since steps are not run
// and some of these are not from DI. you know... chicken and egg, but don't forget about the rooster.
api.TxPool = TxPool;
api.TransactionComparerProvider = TransactionComparerProvider;
api.AuRaFinalizationManager = Substitute.For<IAuRaBlockFinalizationManager>();
return api;
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using Autofac;
using Nethermind.Blockchain;
using Nethermind.Consensus;
using Nethermind.Consensus.AuRa;
Expand Down Expand Up @@ -69,6 +70,28 @@ public void Terminal_block_handler_unsubscribes_itself()
_auRaFinalizationManager.DidNotReceive().Dispose();
}

[Test]
public void Registered_as_singleton_and_resolving_triggers_disposal_when_head_post_merge()
{
// The disposer is wired through DI (AuRaMergeModule + InitializeBlockchainAuRaMerge) rather than
// hand-constructed: registering it as a singleton and resolving it must trigger the same ctor
// side-effect (immediate disposal on a post-merge head) and yield a single instance.
SetHead(postMerge: true);

ContainerBuilder builder = new();
builder
.AddSingleton(_auRaFinalizationManager)
.AddSingleton(_poSSwitcher)
.AddSingleton(_blockTree)
.AddSingleton<AuRaTerminalBlockDisposer>();
using IContainer container = builder.Build();

AuRaTerminalBlockDisposer disposer = container.Resolve<AuRaTerminalBlockDisposer>();

Assert.That(container.Resolve<AuRaTerminalBlockDisposer>(), Is.SameAs(disposer));
_auRaFinalizationManager.Received(1).Dispose();
}

[Test]
public void Fresh_archive_with_FinalTotalDifficulty_in_config_does_not_dispose_pre_merge_aura()
{
Expand Down
16 changes: 4 additions & 12 deletions src/Nethermind/Nethermind.Merge.AuRa/AuRaMergePlugin.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Threading.Tasks;
using Autofac;
using Autofac.Core;
Expand Down Expand Up @@ -35,7 +34,6 @@ namespace Nethermind.Merge.AuRa
/// <remarks>IMPORTANT: this plugin should always come before MergePlugin</remarks>
public class AuRaMergePlugin(ChainSpec chainSpec, IMergeConfig mergeConfig) : MergePlugin(chainSpec, mergeConfig)
{
private AuRaNethermindApi? _auraApi;
private readonly IMergeConfig _mergeConfig = mergeConfig;
private readonly ChainSpec _chainSpec = chainSpec;

Expand All @@ -49,7 +47,6 @@ public override async Task Init(INethermindApi nethermindApi)
if (MergeEnabled)
{
await base.Init(nethermindApi);
_auraApi = (AuRaNethermindApi)nethermindApi;

// this runs before all init steps that use tx filters
TxAuRaFilterBuilders.CreateFilter = (originalFilter, fallbackFilter) =>
Expand All @@ -58,15 +55,6 @@ originalFilter is MinGasPriceContractTxFilter ? originalFilter
}
}

protected override void InitializeMergeFinalization()
{
IAuRaBlockFinalizationManager auRa = _auraApi!.AuRaFinalizationManager
?? throw new ArgumentNullException(nameof(_auraApi.AuRaFinalizationManager),
"Cannot construct AuRaTerminalBlockDisposer when AuRaFinalizationManager is null!");
AuRaTerminalBlockDisposer disposer = new(auRa, _poSSwitcher, _api.BlockTree!);
_api.DisposeStack.Push(disposer);
}

public override IModule Module => new AuRaMergeModule();
}

Expand Down Expand Up @@ -102,6 +90,10 @@ protected override void Load(ContainerBuilder builder) => builder
.AddDecorator<ISealValidator, MergeSealValidator>()
.AddDecorator<ISealer, MergeSealer>()

// Disposes the AuRa finalization manager at the merge transition. Resolved eagerly in
// InitializeBlockchainAuRaMerge for its constructor side-effect; Autofac owns disposal.
.AddSingleton<AuRaTerminalBlockDisposer>()

// Merge-aware override: skips wiring the branch processor on post-merge chains so
// the AuRa finalization manager's startup catch-up walk never runs.
.AddStep(typeof(InitializeBlockchainAuRaMerge))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2026 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System.Threading.Tasks;
using Autofac;
using Nethermind.Consensus;
using Nethermind.Consensus.AuRa.InitializationSteps;
Expand All @@ -16,6 +17,19 @@ namespace Nethermind.Merge.AuRa;
public class InitializeBlockchainAuRaMerge(AuRaNethermindApi api, IChainHeadInfoProvider chainHeadInfoProvider, ITxGossipPolicy txGossipPolicy)
: InitializeBlockchainAuRa(api, chainHeadInfoProvider, txGossipPolicy)
{
protected override async Task InitBlockchain()
{
await base.InitBlockchain();

// Construct the terminal-block disposer now (after WireFinalizationBranchProcessor ran in base):
// it either disposes the finalization manager immediately (head already post-merge) or subscribes
// to IPoSSwitcher.TerminalBlockReached. Resolving here triggers that constructor side-effect.
// Safe at this step — the head is loaded, IPoSSwitcher is initialized, and the block processor has
// not started, so the once-only TerminalBlockReached signal cannot be missed. Autofac owns its
// lifetime and disposal.
Api.Context.Resolve<AuRaTerminalBlockDisposer>();
}

protected override void WireFinalizationBranchProcessor()
{
if (!Api.Context.Resolve<IPoSSwitcher>().IsHeadPostMerge(Api.BlockTree!))
Expand Down
7 changes: 0 additions & 7 deletions src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,6 @@ public Task InitNetworkProtocol()

_mergeBlockProductionPolicy = new MergeBlockProductionPolicy(_api.BlockProductionPolicy);
_api.BlockProductionPolicy = _mergeBlockProductionPolicy;
InitializeMergeFinalization();

if (_poSSwitcher.TransitionFinished)
{
Expand All @@ -222,12 +221,6 @@ private void AddPostMergeNetworkProtocols()
_api.ProtocolsManager!.AddSupportedCapability(new(Protocol.Eth, 71));
}

/// <summary>
/// Hook for derived plugins (e.g. AuRaMergePlugin) to set up merge-transition lifecycle
/// (e.g. disposing AuRa's finalization manager at terminal block). Default: no-op.
/// </summary>
protected virtual void InitializeMergeFinalization() { }

public bool MustInitialize { get => true; }

public virtual IModule Module => new MergePluginModule();
Expand Down
7 changes: 0 additions & 7 deletions src/Nethermind/Nethermind.Runner.Test/EthereumRunnerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
using Nethermind.Blockchain.Synchronization;
using Nethermind.Config;
using Nethermind.Consensus;
using Nethermind.Consensus.AuRa;
using Nethermind.Consensus.AuRa.InitializationSteps;
using Nethermind.Consensus.AuRa.Validators;
using Nethermind.Consensus.Clique;
using Nethermind.Consensus.Processing;
Expand Down Expand Up @@ -215,11 +213,6 @@ public async Task Smoke_CanResolveAllSteps((string file, ConfigProvider configPr
api.BackgroundTaskScheduler = Substitute.For<IBackgroundTaskScheduler>();
api.NonceManager = Substitute.For<INonceManager>();

if (api is AuRaNethermindApi auRaNethermindApi)
{
auRaNethermindApi.AuRaFinalizationManager = Substitute.For<IAuRaBlockFinalizationManager>();
}

try
{
IEthereumStepsLoader stepsLoader = runner.LifetimeScope.Resolve<IEthereumStepsLoader>();
Expand Down
Loading