diff --git a/.agents/rules/di-patterns.md b/.agents/rules/di-patterns.md index b972db7929c3..017927b26467 100644 --- a/.agents/rules/di-patterns.md +++ b/.agents/rules/di-patterns.md @@ -102,3 +102,8 @@ IContainer container = new ContainerBuilder() ``` Never add test-specific code to production modules. Overrides belong in `TestEnvironmentModule`, `TestBlockProcessingModule`, or a new test module passed to `Build`. + +## Anti-pattern +- Using the form `.Add(ctx => new Foo(ctx.Resolve(), ctx.Resolve()))` is an anti-pattern. It will cause changes to the wiring when `Foo` adds new dependencies, which increases review load. + - Rather, do `.Add()` unless unavoidable. +- Similar case with using `IComponentContext` within a class that is not related to component wiring. Rather, pass in the dependency to the construct either directly as a type, or as a `Func` if multiple instantiation is needed or `Lazy` if lazy initialization is needed. diff --git a/src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs b/src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs index a953a91278c2..693a84f6b9fa 100644 --- a/src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs +++ b/src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs @@ -39,7 +39,7 @@ public interface IApiWithBlockchain : IApiWithStores ITxSender? TxSender { get; set; } INonceManager? NonceManager { get; set; } ITxPool? TxPool { get; set; } - CompositeTxGossipPolicy TxGossipPolicy { get; } + ITransactionComparerProvider? TransactionComparerProvider { get; set; } [SkipServiceCollection] diff --git a/src/Nethermind/Nethermind.Api/NethermindApi.cs b/src/Nethermind/Nethermind.Api/NethermindApi.cs index 8f16bef045e1..06b034586258 100644 --- a/src/Nethermind/Nethermind.Api/NethermindApi.cs +++ b/src/Nethermind/Nethermind.Api/NethermindApi.cs @@ -133,7 +133,7 @@ ILifetimeScope Context public IDisposableStack DisposeStack => Context.Resolve(); public IReadOnlyList Plugins => _dependencies.Plugins; public IProcessExitSource ProcessExit => _dependencies.ProcessExitSource; - public CompositeTxGossipPolicy TxGossipPolicy { get; } = new(); + public ILifetimeScope Context => _dependencies.Context; } } diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/InitializeBlockchainAuRa.cs b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/InitializeBlockchainAuRa.cs index a4c285bd14a6..f16ee0092b2c 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/InitializeBlockchainAuRa.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/InitializeBlockchainAuRa.cs @@ -20,8 +20,8 @@ namespace Nethermind.Consensus.AuRa.InitializationSteps; -public class InitializeBlockchainAuRa(AuRaNethermindApi api, IChainHeadInfoProvider chainHeadInfoProvider) - : InitializeBlockchain(api, chainHeadInfoProvider) +public class InitializeBlockchainAuRa(AuRaNethermindApi api, IChainHeadInfoProvider chainHeadInfoProvider, ITxGossipPolicy txGossipPolicy) + : InitializeBlockchain(api, chainHeadInfoProvider, txGossipPolicy) { private INethermindApi NethermindApi => api; @@ -98,7 +98,7 @@ protected override TxPool.TxPool CreateTxPool(IChainHeadInfoProvider chainHeadIn api.TxValidator!, api.LogManager, CreateTxPoolTxComparer(txPriorityContract, localDataSource), - api.TxGossipPolicy, + _txGossipPolicy, new TxFilterAdapter(api.BlockTree, txPoolFilter, api.LogManager, api.SpecProvider), api.HeadTxValidator, txPriorityContract is not null || localDataSource is not null); diff --git a/src/Nethermind/Nethermind.Core.Test/Container/OrderedComponentsTests.cs b/src/Nethermind/Nethermind.Core.Test/Container/OrderedComponentsTests.cs index 5aa6cfa3dbd8..7a4fafbfe5d5 100644 --- a/src/Nethermind/Nethermind.Core.Test/Container/OrderedComponentsTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Container/OrderedComponentsTests.cs @@ -49,6 +49,36 @@ public void TestDisallowIndividualRegistration() act.Should().Throw(); } + [Test] + public void TestCompositeResolved_EvenWhenNotLastRegistration() + { + // AddComposite is called before the last AddLast — composite should still be resolved as IItem + using IContainer ctx = new ContainerBuilder() + .AddLast(_ => new Item("1")) + .AddCompositeOrderedComponents() + .AddLast(_ => new Item("2")) + .Build(); + + IItem resolved = ctx.Resolve(); + resolved.Should().BeOfType(); + ((CompositeItem)resolved).Items.Select(i => i.Name).Should().BeEquivalentTo(["1", "2"]); + } + + [Test] + public void TestCompositeResolved_WhenCalledBeforeAnyAddLast() + { + // AddComposite is called before any AddLast — should still work + using IContainer ctx = new ContainerBuilder() + .AddCompositeOrderedComponents() + .AddLast(_ => new Item("1")) + .AddLast(_ => new Item("2")) + .Build(); + + IItem resolved = ctx.Resolve(); + resolved.Should().BeOfType(); + ((CompositeItem)resolved).Items.Select(i => i.Name).Should().BeEquivalentTo(["1", "2"]); + } + private class ModuleA : Module { protected override void Load(ContainerBuilder builder) => @@ -72,5 +102,11 @@ protected override void Load(ContainerBuilder builder) => builder .AddLast(_ => new Item("1")); } - private record Item(string Name); + private interface IItem { string Name { get; } } + private record Item(string Name) : IItem; + private class CompositeItem(IItem[] items) : IItem + { + public IItem[] Items { get; } = items; + public string Name => string.Join(",", Items.Select(i => i.Name)); + } } diff --git a/src/Nethermind/Nethermind.Core.Test/Modules/PseudoNetworkModule.cs b/src/Nethermind/Nethermind.Core.Test/Modules/PseudoNetworkModule.cs index a32fb6548490..19441183d8e1 100644 --- a/src/Nethermind/Nethermind.Core.Test/Modules/PseudoNetworkModule.cs +++ b/src/Nethermind/Nethermind.Core.Test/Modules/PseudoNetworkModule.cs @@ -30,7 +30,6 @@ protected override void Load(ContainerBuilder builder) .AddSingleton() .AddSingleton(Policy.FullGossip) - .AddComposite() // TODO: LastNStateRootTracker .AddSingleton(stateProvider => stateProvider.SnapServer!) diff --git a/src/Nethermind/Nethermind.Core.Test/Modules/TestBlockProcessingModule.cs b/src/Nethermind/Nethermind.Core.Test/Modules/TestBlockProcessingModule.cs index ada4a68da995..9328240ce33b 100644 --- a/src/Nethermind/Nethermind.Core.Test/Modules/TestBlockProcessingModule.cs +++ b/src/Nethermind/Nethermind.Core.Test/Modules/TestBlockProcessingModule.cs @@ -26,7 +26,6 @@ protected override void Load(ContainerBuilder builder) .AddSingleton() .AddSingleton() - .AddSingleton() .AddSingleton((chainHeadInfoProvider) => new NonceManager(chainHeadInfoProvider.ReadOnlyStateProvider)) // Seems to be only used by block producer. diff --git a/src/Nethermind/Nethermind.Core/Container/OrderedComponents.cs b/src/Nethermind/Nethermind.Core/Container/OrderedComponents.cs index 4315b5c6f8a6..1b7672d74fc2 100644 --- a/src/Nethermind/Nethermind.Core/Container/OrderedComponents.cs +++ b/src/Nethermind/Nethermind.Core/Container/OrderedComponents.cs @@ -19,4 +19,9 @@ public void AddFirst(T item) { _components.Insert(0, item); } + + public void Clear() + { + _components.Clear(); + } } diff --git a/src/Nethermind/Nethermind.Core/Container/OrderedComponentsContainerBuilderExtensions.cs b/src/Nethermind/Nethermind.Core/Container/OrderedComponentsContainerBuilderExtensions.cs index e4f64bfb89cf..807eed59d0c2 100644 --- a/src/Nethermind/Nethermind.Core/Container/OrderedComponentsContainerBuilderExtensions.cs +++ b/src/Nethermind/Nethermind.Core/Container/OrderedComponentsContainerBuilderExtensions.cs @@ -16,6 +16,9 @@ namespace Nethermind.Core.Container; /// public static class OrderedComponentsContainerBuilderExtensions { + private const string OrderedMarkerPrefix = "Registered OrderedComponents For "; + private const string CompositeMarkerPrefix = "Registered OrderedComponents Composite For "; + public static ContainerBuilder AddLast(this ContainerBuilder builder, Func factory) => builder .EnsureOrderedComponents() @@ -25,6 +28,11 @@ public static ContainerBuilder AddLast(this ContainerBuilder builder, Func(this ContainerBuilder builder) where TImpl : class, T => + builder + .AddLast(ctx => ctx.Resolve()) + .Add(); + public static ContainerBuilder AddFirst(this ContainerBuilder builder, Func factory) => builder .EnsureOrderedComponents() @@ -34,9 +42,48 @@ public static ContainerBuilder AddFirst(this ContainerBuilder builder, Func(this ContainerBuilder builder) where TImpl : class, T => + builder + .AddFirst(ctx => ctx.Resolve()) + .Add(); + + /// + /// Register a composite type that wraps the ordered components into a single service. + /// Unlike which uses Autofac's + /// RegisterComposite (collecting direct registrations), + /// this method registers via RegisterType so it receives + /// T[] from . It also relaxes the ordered components + /// safety check to allow this single registration. + /// + public static ContainerBuilder AddCompositeOrderedComponents(this ContainerBuilder builder) where T : class where TComposite : class, T + { + builder.EnsureOrderedComponents(); + + string compositeMarker = CompositeMarkerPrefix + typeof(T).Name; + if (!builder.Properties.TryAdd(compositeMarker, null)) + return builder; + + builder.RegisterType() + .As() + .AsSelf(); + + return builder; + } + + /// + /// Clear all previously registered ordered components for . + /// Useful when a plugin needs to disable all ordered policies (e.g., Hive). + /// + public static ContainerBuilder ClearOrderedComponents(this ContainerBuilder builder) => + builder.AddDecorator>((_, orderedComponents) => + { + orderedComponents.Clear(); + return orderedComponents; + }); + private static ContainerBuilder EnsureOrderedComponents(this ContainerBuilder builder) { - string registeredMarker = $"Registered OrderedComponents For {typeof(T).Name}"; + string registeredMarker = OrderedMarkerPrefix + typeof(T).Name; if (!builder.Properties.TryAdd(registeredMarker, null)) { return builder; @@ -45,7 +92,11 @@ private static ContainerBuilder EnsureOrderedComponents(this ContainerBuilder // Prevent registering separately which has no explicit ordering builder.RegisterBuildCallback(scope => { - if (scope.ComponentRegistry.ServiceRegistrationsFor(new TypedService(typeof(T))).Any()) + string decoratorMarker = CompositeMarkerPrefix + typeof(T).Name; + bool hasDecorator = builder.Properties.ContainsKey(decoratorMarker); + int registrationCount = scope.ComponentRegistry.ServiceRegistrationsFor(new TypedService(typeof(T))).Count(); + int expectedCount = hasDecorator ? 1 : 0; + if (registrationCount > expectedCount) { throw new InvalidOperationException( $"Service of type {typeof(T).Name} must only be registered with one of DSL in {nameof(OrderedComponentsContainerBuilderExtensions)}"); diff --git a/src/Nethermind/Nethermind.Hive/HivePlugin.cs b/src/Nethermind/Nethermind.Hive/HivePlugin.cs index 30821164e06e..5f319c96616d 100644 --- a/src/Nethermind/Nethermind.Hive/HivePlugin.cs +++ b/src/Nethermind/Nethermind.Hive/HivePlugin.cs @@ -6,6 +6,8 @@ using Nethermind.Api.Extensions; using Nethermind.Api.Steps; using Nethermind.Core; +using Nethermind.Core.Container; +using Nethermind.TxPool; namespace Nethermind.Hive; @@ -26,5 +28,6 @@ public class HiveModule : Module { protected override void Load(ContainerBuilder builder) => builder .AddSingleton() - .AddStep(typeof(HiveStep)); + .AddStep(typeof(HiveStep)) + .ClearOrderedComponents(); } diff --git a/src/Nethermind/Nethermind.Hive/HiveStep.cs b/src/Nethermind/Nethermind.Hive/HiveStep.cs index 5d9baa08e000..a74342b1064f 100644 --- a/src/Nethermind/Nethermind.Hive/HiveStep.cs +++ b/src/Nethermind/Nethermind.Hive/HiveStep.cs @@ -14,7 +14,6 @@ namespace Nethermind.Hive; [RunnerStepDependencies(typeof(InitializeNetwork), Optional = true)] public class HiveStep( ITxPool txPool, - CompositeTxGossipPolicy txGossipPolicy, HiveRunner hiveRunner, IProcessExitSource processExitSource, ILogManager logManager @@ -26,8 +25,6 @@ public async Task Execute(CancellationToken cancellationToken) { txPool!.AcceptTxWhenNotSynced = true; - txGossipPolicy.Policies.Clear(); - if (_logger.IsInfo) _logger.Info("Hive is starting"); await hiveRunner.Start(processExitSource.Token); diff --git a/src/Nethermind/Nethermind.Init/Modules/BlockProcessingModule.cs b/src/Nethermind/Nethermind.Init/Modules/BlockProcessingModule.cs index 0c712e4abcca..5f8917782eb2 100644 --- a/src/Nethermind/Nethermind.Init/Modules/BlockProcessingModule.cs +++ b/src/Nethermind/Nethermind.Init/Modules/BlockProcessingModule.cs @@ -46,6 +46,8 @@ protected override void Load(ContainerBuilder builder) .AddSingleton() .AddSingleton() + .AddLast() + // Block processing components common between rpc, validation and production .AddScoped() .AddScoped() diff --git a/src/Nethermind/Nethermind.Init/Modules/NetworkModule.cs b/src/Nethermind/Nethermind.Init/Modules/NetworkModule.cs index efb6fae4bc57..02c68f9789ec 100644 --- a/src/Nethermind/Nethermind.Init/Modules/NetworkModule.cs +++ b/src/Nethermind/Nethermind.Init/Modules/NetworkModule.cs @@ -17,6 +17,8 @@ using Nethermind.Network.P2P.ProtocolHandlers; using Nethermind.Network.Rlpx; using Nethermind.Stats; +using Nethermind.Synchronization.ParallelSync; +using Nethermind.TxPool; using Handshake = Nethermind.Network.Rlpx.Handshake; using P2P = Nethermind.Network.P2P.Messages; using V62 = Nethermind.Network.P2P.Subprotocols.Eth.V62.Messages; @@ -39,6 +41,8 @@ protected override void Load(ContainerBuilder builder) base.Load(builder); builder .AddModule(new SynchronizerModule(configProvider.GetConfig())) + .AddLast() + .AddCompositeOrderedComponents() .AddSingleton() .AddSingleton() diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs index 8e866c3ac38a..65001247fa68 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs @@ -29,9 +29,10 @@ namespace Nethermind.Init.Steps typeof(SetupKeyStore), typeof(InitializePrecompiles) )] - public class InitializeBlockchain(INethermindApi api, IChainHeadInfoProvider chainHeadInfoProvider) : IStep + public class InitializeBlockchain(INethermindApi api, IChainHeadInfoProvider chainHeadInfoProvider, ITxGossipPolicy txGossipPolicy) : IStep { private readonly INethermindApi _api = api; + protected readonly ITxGossipPolicy _txGossipPolicy = txGossipPolicy; public async Task Execute(CancellationToken _) { @@ -52,8 +53,6 @@ protected virtual Task InitBlockchain() blocksConfig.ExtraData : "- binary data -"); - _api.TxGossipPolicy.Policies.Add(new SpecDrivenTxGossipPolicy(chainHeadInfoProvider)); - ITxPool txPool = _api.TxPool = CreateTxPool(chainHeadInfoProvider); _api.BlockPreprocessor.AddFirst( @@ -109,7 +108,7 @@ protected virtual ITxPool CreateTxPool(IChainHeadInfoProvider chainHeadInfoProvi _api.TxValidator!, _api.LogManager, CreateTxPoolTxComparer(), - _api.TxGossipPolicy, + _txGossipPolicy, null, _api.HeadTxValidator ); diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeNetwork.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeNetwork.cs index 4028969e3f7c..bc4822e6723c 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeNetwork.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeNetwork.cs @@ -121,8 +121,6 @@ private async Task Initialize(CancellationToken cancellationToken) int maxPeersCount = _networkConfig.ActivePeersMaxCount; Network.Metrics.PeerLimit = maxPeersCount; - _api.TxGossipPolicy.Policies.Add(new SyncedTxGossipPolicy(_api.SyncModeSelector)); - if (cancellationToken.IsCancellationRequested) { return; diff --git a/src/Nethermind/Nethermind.Network.Stats/Model/DisconnectReason.cs b/src/Nethermind/Nethermind.Network.Stats/Model/DisconnectReason.cs index fbd862be8795..45d70e393cba 100644 --- a/src/Nethermind/Nethermind.Network.Stats/Model/DisconnectReason.cs +++ b/src/Nethermind/Nethermind.Network.Stats/Model/DisconnectReason.cs @@ -35,6 +35,7 @@ public enum DisconnectReason : byte InvalidForkId, ProtocolInitTimeout, TxFlooding, + InvalidTxReceived, NoCapabilityMatched, ClientFiltered, AppClosing, @@ -107,6 +108,7 @@ public static EthDisconnectReason ToEthDisconnectReason(this DisconnectReason di DisconnectReason.ReceiveMessageTimeout => EthDisconnectReason.ReceiveMessageTimeout, DisconnectReason.MultipleHeaderDependencies => EthDisconnectReason.MultipleHeaderDependencies, DisconnectReason.ConnectionReset => EthDisconnectReason.TcpSubSystemError, + DisconnectReason.InvalidTxReceived => EthDisconnectReason.Other, _ => EthDisconnectReason.Other, }; } diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/TxFloodControllerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/TxFloodControllerTests.cs index 06923774ec5d..2b1a88b6d349 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/TxFloodControllerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/TxFloodControllerTests.cs @@ -156,7 +156,7 @@ public void Will_disconnect_on_invalid_tx() _controller.Report(AcceptTxResult.Invalid); _session.Received(1) - .InitiateDisconnect(DisconnectReason.Other, "invalid tx"); + .InitiateDisconnect(DisconnectReason.InvalidTxReceived, "invalid tx"); } } } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/TxFloodController.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/TxFloodController.cs index be3dff9aa0e3..93d2fe0b2396 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/TxFloodController.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/TxFloodController.cs @@ -29,7 +29,7 @@ public void Report(AcceptTxResult accepted) if (accepted == AcceptTxResult.Invalid) { if (logger.IsDebug) logger.Debug($"Disconnecting {_protocolHandler} due to invalid tx received"); - _protocolHandler.Disconnect(DisconnectReason.Other, $"invalid tx"); + _protocolHandler.Disconnect(DisconnectReason.InvalidTxReceived, $"invalid tx"); return; } diff --git a/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs b/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs index 4044c0246810..f494cea96049 100644 --- a/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs +++ b/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs @@ -13,7 +13,7 @@ namespace Nethermind.Optimism; -public class InitializeBlockchainOptimism(OptimismNethermindApi api, IChainHeadInfoProvider chainHeadInfoProvider) : InitializeBlockchain(api, chainHeadInfoProvider) +public class InitializeBlockchainOptimism(OptimismNethermindApi api, IChainHeadInfoProvider chainHeadInfoProvider, ITxGossipPolicy txGossipPolicy) : InitializeBlockchain(api, chainHeadInfoProvider, txGossipPolicy) { protected override async Task InitBlockchain() { diff --git a/src/Nethermind/Nethermind.Taiko/InitializeBlockchainTaiko.cs b/src/Nethermind/Nethermind.Taiko/InitializeBlockchainTaiko.cs index 98ddc83ccae0..780ddf0221fa 100644 --- a/src/Nethermind/Nethermind.Taiko/InitializeBlockchainTaiko.cs +++ b/src/Nethermind/Nethermind.Taiko/InitializeBlockchainTaiko.cs @@ -7,7 +7,7 @@ namespace Nethermind.Taiko; -public class InitializeBlockchainTaiko(TaikoNethermindApi api, IChainHeadInfoProvider chainHeadInfoProvider) : InitializeBlockchain(api, chainHeadInfoProvider) +public class InitializeBlockchainTaiko(TaikoNethermindApi api, IChainHeadInfoProvider chainHeadInfoProvider, ITxGossipPolicy txGossipPolicy) : InitializeBlockchain(api, chainHeadInfoProvider, txGossipPolicy) { protected override IBlockProductionPolicy CreateBlockProductionPolicy() => NeverStartBlockProductionPolicy.Instance; } diff --git a/src/Nethermind/Nethermind.TxPool/ITxGossipPolicy.cs b/src/Nethermind/Nethermind.TxPool/ITxGossipPolicy.cs index 8947b68339ed..d3f925b7ea61 100644 --- a/src/Nethermind/Nethermind.TxPool/ITxGossipPolicy.cs +++ b/src/Nethermind/Nethermind.TxPool/ITxGossipPolicy.cs @@ -1,8 +1,7 @@ // SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Collections.Generic; -using System.Runtime.InteropServices; +using System; using Nethermind.Core; namespace Nethermind.TxPool; @@ -14,19 +13,20 @@ public interface ITxGossipPolicy bool ShouldGossipTransaction(Transaction tx) => true; } -public class CompositeTxGossipPolicy : ITxGossipPolicy +// Lazy: resolving ITxGossipPolicy[] eagerly pulls in the sync infrastructure +// (SyncedTxGossipPolicy → ISyncModeSelector → ...) which depends on services +// not yet available during init step construction. +public class CompositeTxGossipPolicy(Lazy policies) : ITxGossipPolicy { - public List Policies { get; } = new(); public bool ShouldListenToGossipedTransactions { get { - foreach (ITxGossipPolicy policy in CollectionsMarshal.AsSpan(Policies)) + ITxGossipPolicy[] p = policies.Value; + for (int i = 0; i < p.Length; i++) { - if (!policy.ShouldListenToGossipedTransactions) - { + if (!p[i].ShouldListenToGossipedTransactions) return false; - } } return true; } @@ -36,12 +36,11 @@ public bool CanGossipTransactions { get { - foreach (ITxGossipPolicy policy in CollectionsMarshal.AsSpan(Policies)) + ITxGossipPolicy[] p = policies.Value; + for (int i = 0; i < p.Length; i++) { - if (!policy.CanGossipTransactions) - { + if (!p[i].CanGossipTransactions) return false; - } } return true; } @@ -49,12 +48,11 @@ public bool CanGossipTransactions public bool ShouldGossipTransaction(Transaction tx) { - foreach (ITxGossipPolicy policy in CollectionsMarshal.AsSpan(Policies)) + ITxGossipPolicy[] p = policies.Value; + for (int i = 0; i < p.Length; i++) { - if (!policy.ShouldGossipTransaction(tx)) - { + if (!p[i].ShouldGossipTransaction(tx)) return false; - } } return true; } diff --git a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs index bd5ae3cdd845..a84da47aec86 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs @@ -180,16 +180,6 @@ protected override ContainerBuilder ConfigureContainer(ContainerBuilder builder, .AddSingleton((ctx) => { - var gossipPolicy = ctx.Resolve(); - - var compoundPolicy = new CompositeTxGossipPolicy(); - if (gossipPolicy != null) - { - compoundPolicy.Policies.Add(gossipPolicy); - } - - compoundPolicy.Policies.Add(new XdcTxGossipPolicy(SpecProvider, ctx.Resolve())); - Nethermind.TxPool.TxPool txPool = new(ctx.Resolve()!, ctx.Resolve() ?? NullBlobTxStorage.Instance, ctx.Resolve(), @@ -197,7 +187,7 @@ protected override ContainerBuilder ConfigureContainer(ContainerBuilder builder, ctx.Resolve(), ctx.Resolve(), new XdcTransactionComparerProvider(SpecProvider, BlockTree).GetDefaultComparer(), - compoundPolicy, + ctx.Resolve(), new SignTransactionFilter(SnapshotManager, BlockTree, SpecProvider), ctx.Resolve() ); diff --git a/src/Nethermind/Nethermind.Xdc/InitializeBlockchainXdc.cs b/src/Nethermind/Nethermind.Xdc/InitializeBlockchainXdc.cs index 326de6110fce..ff34f9edf1a1 100644 --- a/src/Nethermind/Nethermind.Xdc/InitializeBlockchainXdc.cs +++ b/src/Nethermind/Nethermind.Xdc/InitializeBlockchainXdc.cs @@ -11,13 +11,12 @@ namespace Nethermind.Xdc; -internal class InitializeBlockchainXdc(INethermindApi api, IChainHeadInfoProvider chainHeadInfoProvider) - : InitializeBlockchain(api, chainHeadInfoProvider) +internal class InitializeBlockchainXdc(INethermindApi api, IChainHeadInfoProvider chainHeadInfoProvider, ITxGossipPolicy txGossipPolicy) + : InitializeBlockchain(api, chainHeadInfoProvider, txGossipPolicy) { private readonly INethermindApi _api = api; protected override ITxPool CreateTxPool(IChainHeadInfoProvider chainHeadInfoProvider) { - _api.TxGossipPolicy.Policies.Add(new XdcTxGossipPolicy(_api.SpecProvider, chainHeadInfoProvider)); ISnapshotManager snapshotManager = _api.Context.Resolve(); Nethermind.TxPool.TxPool txPool = new(_api.EthereumEcdsa!, @@ -27,7 +26,7 @@ protected override ITxPool CreateTxPool(IChainHeadInfoProvider chainHeadInfoProv _api.TxValidator!, _api.LogManager, CreateTxPoolTxComparer(), - _api.TxGossipPolicy, + _txGossipPolicy, new SignTransactionFilter(snapshotManager, _api.BlockTree, _api.SpecProvider), _api.HeadTxValidator, true diff --git a/src/Nethermind/Nethermind.Xdc/XdcModule.cs b/src/Nethermind/Nethermind.Xdc/XdcModule.cs index b96a314e48f2..f33c736ea828 100644 --- a/src/Nethermind/Nethermind.Xdc/XdcModule.cs +++ b/src/Nethermind/Nethermind.Xdc/XdcModule.cs @@ -123,6 +123,7 @@ protected override void Load(ContainerBuilder builder) .AddMessageSerializer() .AddMessageSerializer() + .AddLast() .AddSingleton() // block processing