Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/end to end synctest #8055

Merged
merged 37 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
ae9be3d
E2E sync test
asdacap Dec 28, 2024
813eb1c
Basic synchronizer
asdacap Jan 6, 2025
31d6bad
Blockprocessing
asdacap Jan 6, 2025
db7bbaa
Prewarmer
asdacap Jan 6, 2025
0628dd8
Cleanup
asdacap Jan 6, 2025
2fbfb95
Fix hanging test
asdacap Jan 7, 2025
d25ac70
Move txpool to upper level
asdacap Jan 7, 2025
5a4bcfe
Dont use block producer env factory.
asdacap Jan 7, 2025
c0fe888
Rlpx host
asdacap Jan 8, 2025
db367d1
Protocols manager
asdacap Jan 8, 2025
411b160
Can connect
asdacap Jan 11, 2025
b8eb5a8
With header encoding when excess gas is null
asdacap Jan 11, 2025
4c6262e
It seems to be able to full sync
asdacap Jan 11, 2025
8507304
Assert head and verify trie
asdacap Jan 11, 2025
e928945
Attempted fast sync
asdacap Jan 13, 2025
ec93b40
Fix fast sync
asdacap Jan 13, 2025
5be0ce1
Fix cannot state sync from another nethermind
asdacap Jan 13, 2025
9b29ad4
Multiple configuration
asdacap Jan 13, 2025
40417ab
Code cleanup
asdacap Jan 13, 2025
db345bc
Slight cleanup
asdacap Jan 13, 2025
d479460
Check for receipt and blocks also
asdacap Jan 13, 2025
6f24cf4
Merge configuration
asdacap Jan 14, 2025
4b4f926
Fix error on fix of not able to serve stae
asdacap Jan 14, 2025
aa54017
Slight cleanup
asdacap Jan 16, 2025
38e38c7
Slight cleanup
asdacap Jan 16, 2025
904e5ce
Auto resolve on activate.
asdacap Jan 16, 2025
e7f4b0f
Faster failure
asdacap Jan 16, 2025
5f0852f
Removed as it is a duplicate now.
asdacap Jan 16, 2025
cb1780d
Slight cleanup
asdacap Jan 16, 2025
ae09201
Rename
asdacap Jan 16, 2025
abf1d9e
Simplify test
asdacap Jan 16, 2025
6d57896
Simplify
asdacap Jan 16, 2025
57b705b
Whitespace
asdacap Jan 16, 2025
c50eb9b
Slight cleanup
asdacap Jan 16, 2025
9d6f3f7
Merge remote-tracking branch 'origin/master' into feature/end-to-end-…
asdacap Jan 16, 2025
f4b13ec
Addressing comments
asdacap Jan 20, 2025
ccbb5e8
Addressing comment
asdacap Jan 20, 2025
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
3 changes: 1 addition & 2 deletions src/Nethermind/Nethermind.Api/IBasicApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ public ContainerBuilder ConfigureContainerBuilderFromBasicApi(ContainerBuilder b
{
builder
.AddPropertiesFrom<IBasicApi>(this)
.AddSingleton(ConfigProvider.GetConfig<ISyncConfig>())
.AddSingleton(ConfigProvider.GetConfig<IReceiptConfig>())
.AddSource(new ConfigRegistrationSource())
.AddModule(new DbModule());

return builder;
Expand Down
5 changes: 3 additions & 2 deletions src/Nethermind/Nethermind.Blockchain/BlockTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Autofac.Features.AttributeFilters;
using Nethermind.Blockchain.Blocks;
using Nethermind.Blockchain.Find;
using Nethermind.Blockchain.Headers;
Expand Down Expand Up @@ -107,8 +108,8 @@ public BlockHeader? LowestInsertedBeaconHeader
public BlockTree(
IBlockStore? blockStore,
IHeaderStore? headerDb,
IDb? blockInfoDb,
IDb? metadataDb,
[KeyFilter(DbNames.BlockInfos)] IDb? blockInfoDb,
[KeyFilter(DbNames.Metadata)] IDb? metadataDb,
IBadBlockStore? badBlockStore,
IChainLevelInfoRepository? chainLevelInfoRepository,
ISpecProvider? specProvider,
Expand Down
3 changes: 2 additions & 1 deletion src/Nethermind/Nethermind.Blockchain/Blocks/BlockStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Buffers;
using Autofac.Features.AttributeFilters;
using Nethermind.Core;
using Nethermind.Core.Caching;
using Nethermind.Core.Crypto;
Expand All @@ -12,7 +13,7 @@

namespace Nethermind.Blockchain.Blocks;

public class BlockStore(IDb blockDb) : IBlockStore
public class BlockStore([KeyFilter(DbNames.Blocks)] IDb blockDb) : IBlockStore
{
private readonly BlockDecoder _blockDecoder = new();
public const int CacheSize = 128 + 32;
Expand Down
3 changes: 2 additions & 1 deletion src/Nethermind/Nethermind.Blockchain/Headers/HeaderStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Buffers.Binary;
using System.IO;
using Autofac.Features.AttributeFilters;
using Nethermind.Core;
using Nethermind.Core.Caching;
using Nethermind.Core.Crypto;
Expand All @@ -24,7 +25,7 @@ public class HeaderStore : IHeaderStore
private readonly ClockCache<ValueHash256, BlockHeader> _headerCache =
new(CacheSize);

public HeaderStore(IDb headerDb, IDb blockNumberDb)
public HeaderStore([KeyFilter(DbNames.Headers)] IDb headerDb, [KeyFilter(DbNames.BlockNumbers)] IDb blockNumberDb)
{
_headerDb = headerDb;
_blockNumberDb = blockNumberDb;
Expand Down
51 changes: 51 additions & 0 deletions src/Nethermind/Nethermind.Config/ConfigRegistrationSource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Collections.Generic;
using System.Linq;
using Autofac;
using Autofac.Core;
using Autofac.Core.Activators.Delegate;
using Autofac.Core.Lifetime;
using Autofac.Core.Registration;

namespace Nethermind.Config;

/// <summary>
/// Dynamically resolve IConfig<T>
/// </summary>
public class ConfigRegistrationSource : IRegistrationSource
asdacap marked this conversation as resolved.
Show resolved Hide resolved
{
public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<ServiceRegistration>> registrationAccessor)
{
IServiceWithType swt = service as IServiceWithType;
if (swt == null || !typeof(IConfig).IsAssignableFrom(swt.ServiceType))
{
// It's not a request for the base handler type, so skip it.
return Enumerable.Empty<IComponentRegistration>();
}

// Dynamically resolve IConfig
ComponentRegistration registration = new ComponentRegistration(
Guid.NewGuid(),
new DelegateActivator(swt.ServiceType, (c, p) =>
{
IConfigProvider configProvider = c.Resolve<IConfigProvider>();
object config = typeof(IConfigProvider)
.GetMethod("GetConfig")
.MakeGenericMethod(swt.ServiceType)
.Invoke(configProvider, new object[] { });
return config;
}),
new RootScopeLifetime(),
InstanceSharing.Shared,
InstanceOwnership.OwnedByLifetimeScope,
new[] { service },
new Dictionary<string, object>());

return new IComponentRegistration[] { registration };
}

public bool IsAdapterForIndividualComponents => false;
}
30 changes: 30 additions & 0 deletions src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using FluentAssertions;
using Nethermind.Core.Crypto;
using Nethermind.Core.Extensions;
using Nethermind.Core.Test.Builders;
using Nethermind.Crypto;
using Nethermind.Int256;
Expand Down Expand Up @@ -190,6 +191,35 @@ public void Can_encode_decode_with_ValidatorExitRoot_equals_to_null()
blockHeader.Should().BeEquivalentTo(header);
}

[Test]
public void Can_encode_decode_with_missing_excess_blob_gass()
{
BlockHeader header = Build.A.BlockHeader
.WithHash(new Hash256("0x3d8b9cc98eee58243461bd5a83663384b50293cd1e459a6841cb005296305590"))
.WithNumber(1000)
.WithParentHash(new Hash256("0x793b1ee71748f4b1b70cf70a53e083e6d5d356bffee9946e15a13fed8d70d7d6"))
.WithBeneficiary(new Address("0xb7705ae4c6f81b66cdb323c65f4e8133690fc099"))
.WithGasLimit(100000000)
.WithGasUsed(299331)
.WithTimestamp(1736575828)
.WithExtraData(Bytes.FromHexString("4e65746865726d696e64"))
.WithDifficulty(1)
.WithMixHash(new Hash256("0x0000000000000000000000000000000000000000000000000000000000000000"))
.WithNonce(0)
.WithUnclesHash(new Hash256("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"))
.WithTransactionsRoot(new Hash256("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"))
.WithReceiptsRoot(new Hash256("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"))
.WithStateRoot(new Hash256("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"))
.WithBaseFee(8)
.WithWithdrawalsRoot(new Hash256("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"))
.WithBlobGasUsed(0)
.TestObject;
;

Rlp rlp = Rlp.Encode(header);
_ = Rlp.Decode<BlockHeader>(rlp.Bytes.AsSpan());
}

public static IEnumerable<object?[]> CancunFieldsSource()
{
yield return new object?[] { null, null, null };
Expand Down
177 changes: 177 additions & 0 deletions src/Nethermind/Nethermind.Core.Test/Modules/BlockProcessingModule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System.Collections.Generic;
using Autofac;
using Nethermind.Api;
using Nethermind.Blockchain;
using Nethermind.Blockchain.BeaconBlockRoot;
using Nethermind.Blockchain.Blocks;
using Nethermind.Blockchain.Receipts;
using Nethermind.Config;
using Nethermind.Consensus;
using Nethermind.Consensus.Comparers;
using Nethermind.Consensus.Processing;
using Nethermind.Consensus.Producers;
using Nethermind.Consensus.Rewards;
using Nethermind.Consensus.Transactions;
using Nethermind.Consensus.Validators;
using Nethermind.Consensus.Withdrawals;
using Nethermind.Core.Specs;
using Nethermind.Core.Test.Blockchain;
using Nethermind.Evm;
using Nethermind.Evm.TransactionProcessing;
using Nethermind.Logging;
using Nethermind.State;
using Nethermind.TxPool;

namespace Nethermind.Core.Test.Modules;

public class BlockProcessingModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder
.AddSingleton<IBlockValidator, BlockValidator>()
.AddSingleton<ITxValidator, ISpecProvider>((spec) => new TxValidator(spec.ChainId))
.AddSingleton<IHeaderValidator, HeaderValidator>()
.AddSingleton<IUnclesValidator, UnclesValidator>()
.AddSingleton<IRewardCalculatorSource>(NoBlockRewards.Instance)
.AddSingleton<ISealValidator>(NullSealEngine.Instance)
.AddSingleton<ITransactionComparerProvider, TransactionComparerProvider>()
// NOTE: The ordering of block preprocessor is not guarenteed
.AddComposite<IBlockPreprocessorStep, CompositeBlockPreprocessorStep>()
.AddSingleton<IBlockPreprocessorStep, RecoverSignatures>()

// Yea, for some reason, the ICodeInfoRepository need to be the main one for ChainHeadInfoProvider to work.
// Like, is ICodeInfoRepository suppose to be global? Why not just IStateReader.
.AddKeyedSingleton<ICodeInfoRepository>(nameof(IWorldStateManager.GlobalWorldState), (ctx) =>
{
IWorldState worldState = ctx.Resolve<IWorldStateManager>().GlobalWorldState;
PreBlockCaches? preBlockCaches = (worldState as IPreBlockCaches)?.Caches;
return new CodeInfoRepository(preBlockCaches?.PrecompileCache);
})
.AddSingleton<IChainHeadInfoProvider, IComponentContext>((ctx) =>
{
ISpecProvider specProvider = ctx.Resolve<ISpecProvider>();
IBlockTree blockTree = ctx.Resolve<IBlockTree>();
IStateReader stateReader = ctx.Resolve<IStateReader>();
// need this to be the right one.
ICodeInfoRepository codeInfoRepository = ctx.ResolveNamed<ICodeInfoRepository>(nameof(IWorldStateManager.GlobalWorldState));
return new ChainHeadInfoProvider(specProvider, blockTree, stateReader, codeInfoRepository);
})

.AddSingleton<ITxPool, TxPool.TxPool>()

// These are common between processing and production and worldstate-ful, so they should be scoped instead
// of singleton.
.AddScoped<IBlockchainProcessor, BlockchainProcessor>()
.AddScoped<IBlockProcessor, BlockProcessor>()
.AddScoped<IRewardCalculator, IRewardCalculatorSource, ITransactionProcessor>((rewardCalculatorSource, txProcessor) => rewardCalculatorSource.Get(txProcessor))
.AddScoped<ITransactionProcessor, TransactionProcessor>()
.AddScoped<IBeaconBlockRootHandler, BeaconBlockRootHandler>()
.AddScoped<IBlockhashStore, BlockhashStore>()
.AddScoped<IVirtualMachine, VirtualMachine>()
.AddScoped<BlockchainProcessor>()
.AddScoped<IBlockhashProvider, BlockhashProvider>()

// The main block processing pipeline, anything that requires the use of the main IWorldState is wrapped
// in a `MainBlockProcessingContext`.
.AddSingleton<MainBlockProcessingContext, ILifetimeScope>(ConfigureMainBlockProcessingContext)
// Then component that has no ambiguity is extracted back out.
.Map<IBlockProcessingQueue, MainBlockProcessingContext>(ctx => ctx.BlockProcessingQueue)


// Seems to be only used by block producer.
.AddScoped<IGasLimitCalculator, TargetAdjustedGasLimitCalculator>()
.AddScoped<ITxSource, TxPoolTxSource>()
.AddScoped<ITxFilterPipeline, ILogManager, ISpecProvider, IBlocksConfig>(TxFilterPipelineBuilder.CreateStandardFilteringPipeline)
.AddScoped<ISealEngine, SealEngine>()
.AddScoped<IComparer<Transaction>, ITransactionComparerProvider>(txComparer => txComparer.GetDefaultComparer())
.AddScoped<BlockProducerEnvFactory>()

// Is this like a common thing or what?
.AddScoped<IWithdrawalProcessor, WithdrawalProcessor>()

// Much like block validation, anything that require the use of IWorldState in block producer, is wrapped in
// a `BlockProducerContext`.
.AddSingleton<BlockProducerContext, ILifetimeScope>(ConfigureBlockProducerContext)
// And then we extract it back out.
.Map<IBlockProducerRunner, BlockProducerContext>(ctx => ctx.BlockProducerRunner)
.Bind<IBlockProductionTrigger, IManualBlockProductionTrigger>()

// Something else entirely. Just some wrapper over things.
.AddSingleton<IManualBlockProductionTrigger, BuildBlocksWhenRequested>()
.AddSingleton<ProducedBlockSuggester>()
.ResolveOnServiceActivation<ProducedBlockSuggester, IBlockProducerRunner>()

;
}

private MainBlockProcessingContext ConfigureMainBlockProcessingContext(ILifetimeScope ctx)
{
IReceiptConfig receiptConfig = ctx.Resolve<IReceiptConfig>();
IInitConfig initConfig = ctx.Resolve<IInitConfig>();
IBlocksConfig blocksConfig = ctx.Resolve<IBlocksConfig>();
IWorldState mainWorldState = ctx.Resolve<IWorldStateManager>().GlobalWorldState;
ICodeInfoRepository mainCodeInfoRepository =
ctx.ResolveNamed<ICodeInfoRepository>(nameof(IWorldStateManager.GlobalWorldState));

ILifetimeScope innerScope = ctx.BeginLifetimeScope((processingCtxBuilder) =>
{
processingCtxBuilder
// These are main block processing specific
.AddScoped<ICodeInfoRepository>(mainCodeInfoRepository)
.AddScoped(mainWorldState)
.AddScoped<IBlockProcessor.IBlockTransactionsExecutor,
BlockProcessor.BlockValidationTransactionsExecutor>()
.AddScoped(new BlockchainProcessor.Options
{
StoreReceiptsByDefault = receiptConfig.StoreReceipts,
DumpOptions = initConfig.AutoDump
})
.AddScoped<GenesisLoader>()

// And finally, to wrap things up.
.AddScoped<MainBlockProcessingContext>()
;

if (blocksConfig.PreWarmStateOnBlockProcessing)
{
processingCtxBuilder
.AddScoped<PreBlockCaches>((mainWorldState as IPreBlockCaches)!.Caches)
.AddScoped<IBlockCachePreWarmer, BlockCachePreWarmer>()
.AddScoped<ReadOnlyTxProcessingEnvFactory>();
}
});

return innerScope.Resolve<MainBlockProcessingContext>();
}

private BlockProducerContext ConfigureBlockProducerContext(ILifetimeScope ctx)
{
// Note: This is modelled after TestBlockchain, not prod
IWorldState thisBlockProducerWorldState = ctx.Resolve<IWorldStateManager>().CreateResettableWorldState();
ILifetimeScope innerScope = ctx.BeginLifetimeScope((producerCtx) =>
{
producerCtx
.AddScoped<IWorldState>(thisBlockProducerWorldState)

// Block producer specific
.AddDecorator<IBlockchainProcessor, OneTimeChainProcessor>()
.AddScoped(BlockchainProcessor.Options.NoReceipts)
.AddScoped<IBlockProcessor.IBlockTransactionsExecutor, BlockProcessor.BlockProductionTransactionsExecutor>()
.AddDecorator<IWithdrawalProcessor, BlockProductionWithdrawalProcessor>()

.AddScoped<ICodeInfoRepository, CodeInfoRepository>()

// TODO: What is this suppose to be?
.AddScoped<IBlockProducer, TestBlockProducer>()

.AddScoped<IBlockProducerRunner, StandardBlockProducerRunner>()
.AddScoped<BlockProducerContext>();
});

return innerScope.Resolve<BlockProducerContext>();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Threading.Tasks;
using Autofac;
using Nethermind.Consensus;

namespace Nethermind.Core.Test.Modules;

public record BlockProducerContext(
ILifetimeScope LifetimeScope,
IBlockProducerRunner BlockProducerRunner
) : IAsyncDisposable
{
public async ValueTask DisposeAsync()
{
await LifetimeScope.DisposeAsync();
}
}
Loading
Loading