public void Should_allocate_by_speed_post_merge() { ulong[] totalDifficulties = { 1, 3, 2 }; int[] averageSpeed = { 5, 8, 10 }; PublicKey[] publicKeys = { TestItem.PublicKeyA, TestItem.PublicKeyB, TestItem.PublicKeyC }; PeerInfo[] peers = new PeerInfo[3]; INodeStatsManager _nodeStatsManager = Substitute.For <INodeStatsManager>(); for (int i = 0; i < 3; i++) { ISyncPeer syncPeer = Substitute.For <ISyncPeer>(); syncPeer.IsInitialized.Returns(true); Node node = new Node(publicKeys[i], "192.168.1.18", i); syncPeer.Node.Returns(node); syncPeer.TotalDifficulty.Returns(new UInt256(totalDifficulties[i])); peers[i] = new PeerInfo(syncPeer); peers[i].HeadNumber.Returns(1); INodeStats nodeStats = Substitute.For <INodeStats>(); nodeStats.GetAverageTransferSpeed(Arg.Any <TransferSpeedType>()).Returns(averageSpeed[i]); _nodeStatsManager.GetOrAdd(peers[i].SyncPeer.Node).Returns(nodeStats); } IPoSSwitcher poSSwitcher = Substitute.For <IPoSSwitcher>(); poSSwitcher.TerminalTotalDifficulty.Returns(new UInt256(1)); poSSwitcher.HasEverReachedTerminalBlock().Returns(true); IBeaconPivot beaconPivot = Substitute.For <IBeaconPivot>(); IPeerAllocationStrategy mergePeerAllocationStrategy = (new MergeBlocksSyncPeerAllocationStrategyFactory(poSSwitcher, beaconPivot, Substitute.For <ILogManager>())).Create(new BlocksRequest()); IBlockTree _blockTree = Substitute.For <IBlockTree>(); PeerInfo? info = mergePeerAllocationStrategy.Allocate(null, peers, _nodeStatsManager, _blockTree); Assert.AreEqual(info, peers[2]); // peer with highest highest speed }
private async void BuildHeadersSyncBatches( Context ctx, BlockTree blockTree, BlockTree syncedBlockTree, IBeaconPivot pivot, long endLowestBeaconHeader) { ctx.Feed.InitializeFeed(); long lowestHeaderNumber = pivot.PivotNumber; while (lowestHeaderNumber > endLowestBeaconHeader) { HeadersSyncBatch batch = await ctx.Feed.PrepareRequest(); batch.Should().NotBeNull(); BuildHeadersSyncBatchResponse(batch, syncedBlockTree); ctx.Feed.HandleResponse(batch); lowestHeaderNumber = lowestHeaderNumber - batch.RequestSize < endLowestBeaconHeader ? endLowestBeaconHeader : lowestHeaderNumber - batch.RequestSize; BlockHeader?lowestHeader = syncedBlockTree.FindHeader(lowestHeaderNumber, BlockTreeLookupOptions.None); blockTree.LowestInsertedBeaconHeader?.Hash.Should().BeEquivalentTo(lowestHeader?.Hash); } }
public async Task Feed_able_to_sync_when_new_pivot_is_set() { BlockTree syncedBlockTree = Build.A.BlockTree().OfChainLength(1000).TestObject; Block genesisBlock = syncedBlockTree.FindBlock(syncedBlockTree.GenesisHash, BlockTreeLookupOptions.None) !; BlockTree blockTree = Build.A.BlockTree().TestObject; blockTree.SuggestBlock(genesisBlock); ISyncConfig syncConfig = new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "500", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000000" // default difficulty in block tree builder }; BlockHeader? pivotHeader = syncedBlockTree.FindHeader(700, BlockTreeLookupOptions.None); IBeaconPivot pivot = PreparePivot(700, syncConfig, blockTree, pivotHeader); Context ctx = new (blockTree, syncConfig, pivot); BuildAndProcessHeaderSyncBatches(ctx, blockTree, syncedBlockTree, pivot, 0, 501); // move best pointers forward as proxy for chain merge Block highestBlock = syncedBlockTree.FindBlock(700, BlockTreeLookupOptions.None) !; blockTree.Insert(highestBlock, BlockTreeInsertBlockOptions.SaveHeader); pivot.EnsurePivot(syncedBlockTree.FindHeader(900, BlockTreeLookupOptions.None)); BuildAndProcessHeaderSyncBatches(ctx, blockTree, syncedBlockTree, pivot, 700, 701); highestBlock = syncedBlockTree.FindBlock(900, BlockTreeLookupOptions.None) !; blockTree.Insert(highestBlock, BlockTreeInsertBlockOptions.SaveHeader); pivot.EnsurePivot(syncedBlockTree.FindHeader(999, BlockTreeLookupOptions.None)); BuildAndProcessHeaderSyncBatches(ctx, blockTree, syncedBlockTree, pivot, 900, 901); }
public MergeBlockDownloaderFactory(IPoSSwitcher poSSwitcher, IBeaconPivot beaconPivot, ISpecProvider specProvider, IBlockTree blockTree, IBlockCacheService blockCacheService, IReceiptStorage receiptStorage, IBlockValidator blockValidator, ISealValidator sealValidator, ISyncPeerPool peerPool, ISyncConfig syncConfig, IBetterPeerStrategy betterPeerStrategy, ISyncReport syncReport, ISyncProgressResolver syncProgressResolver, ILogManager logManager) { _poSSwitcher = poSSwitcher ?? throw new ArgumentNullException(nameof(poSSwitcher)); _beaconPivot = beaconPivot ?? throw new ArgumentNullException(nameof(beaconPivot)); _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); _receiptStorage = receiptStorage ?? throw new ArgumentNullException(nameof(receiptStorage)); _blockValidator = blockValidator ?? throw new ArgumentNullException(nameof(blockValidator)); _sealValidator = sealValidator ?? throw new ArgumentNullException(nameof(sealValidator)); _syncPeerPool = peerPool ?? throw new ArgumentNullException(nameof(peerPool)); _betterPeerStrategy = betterPeerStrategy ?? throw new ArgumentNullException(nameof(betterPeerStrategy)); _logManager = logManager ?? throw new ArgumentNullException(nameof(logManager)); _syncReport = syncReport ?? throw new ArgumentNullException(nameof(syncReport)); _chainLevelHelper = new ChainLevelHelper(_blockTree, _beaconPivot, syncConfig, _logManager); _syncProgressResolver = syncProgressResolver ?? throw new ArgumentNullException(nameof(syncProgressResolver));; }
public async Task Can_keep_returning_nulls_after_all_batches_were_prepared() { IDbProvider memDbProvider = await TestMemDbProvider.InitAsync(); BlockTree blockTree = new(memDbProvider, new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance); ISyncConfig syncConfig = new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "1000", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }; PoSSwitcher poSSwitcher = new(new MergeConfig(), syncConfig, memDbProvider.MetadataDb, blockTree !, MainnetSpecProvider.Instance, LimboLogs.Instance); IBeaconPivot pivot = PreparePivot(2000, syncConfig, blockTree); BeaconHeadersSyncFeed feed = new(poSSwitcher, Substitute.For <ISyncModeSelector>(), blockTree, Substitute.For <ISyncPeerPool>(), syncConfig, Substitute.For <ISyncReport>(), pivot, new MergeConfig() { Enabled = true }, new NoopInvalidChainTracker(), LimboLogs.Instance); feed.InitializeFeed(); for (int i = 0; i < 6; i++) { await feed.PrepareRequest(); } HeadersSyncBatch?result = await feed.PrepareRequest(); result.Should().BeNull(); }
public ForkchoiceUpdatedV1Handler( IBlockTree blockTree, IManualBlockFinalizationManager manualBlockFinalizationManager, IPoSSwitcher poSSwitcher, IPayloadPreparationService payloadPreparationService, IBlockProcessingQueue processingQueue, IBlockCacheService blockCacheService, IInvalidChainTracker invalidChainTracker, IMergeSyncController mergeSyncController, IBeaconPivot beaconPivot, IPeerRefresher peerRefresher, ILogManager logManager) { _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); _manualBlockFinalizationManager = manualBlockFinalizationManager ?? throw new ArgumentNullException(nameof(manualBlockFinalizationManager)); _poSSwitcher = poSSwitcher ?? throw new ArgumentNullException(nameof(poSSwitcher)); _payloadPreparationService = payloadPreparationService; _processingQueue = processingQueue; _blockCacheService = blockCacheService; _invalidChainTracker = invalidChainTracker; _mergeSyncController = mergeSyncController; _beaconPivot = beaconPivot; _peerRefresher = peerRefresher; _logger = logManager.GetClassLogger(); }
public MergeBlockDownloader( IPoSSwitcher posSwitcher, IBeaconPivot beaconPivot, ISyncFeed <BlocksRequest?>?feed, ISyncPeerPool?syncPeerPool, IBlockTree?blockTree, IBlockValidator?blockValidator, ISealValidator?sealValidator, ISyncReport?syncReport, IReceiptStorage?receiptStorage, ISpecProvider specProvider, IBetterPeerStrategy betterPeerStrategy, IChainLevelHelper chainLevelHelper, ISyncProgressResolver syncProgressResolver, ILogManager logManager) : base(feed, syncPeerPool, blockTree, blockValidator, sealValidator, syncReport, receiptStorage, specProvider, new MergeBlocksSyncPeerAllocationStrategyFactory(posSwitcher, beaconPivot, logManager), betterPeerStrategy, logManager) { _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); _chainLevelHelper = chainLevelHelper ?? throw new ArgumentNullException(nameof(chainLevelHelper)); _poSSwitcher = posSwitcher ?? throw new ArgumentNullException(nameof(posSwitcher)); _blockValidator = blockValidator ?? throw new ArgumentNullException(nameof(blockValidator)); _syncReport = syncReport ?? throw new ArgumentNullException(nameof(syncReport)); _receiptStorage = receiptStorage ?? throw new ArgumentNullException(nameof(receiptStorage)); _beaconPivot = beaconPivot; _receiptsRecovery = new ReceiptsRecovery(new EthereumEcdsa(specProvider.ChainId, logManager), specProvider); _syncProgressResolver = syncProgressResolver ?? throw new ArgumentNullException(nameof(syncProgressResolver)); _logger = logManager.GetClassLogger(); }
private async void BuildAndProcessHeaderSyncBatches( Context ctx, BlockTree blockTree, BlockTree syncedBlockTree, IBeaconPivot pivot, long bestPointer, long endLowestBeaconHeader) { ctx.BeaconSync.ShouldBeInBeaconHeaders().Should().BeTrue(); blockTree.BestKnownNumber.Should().Be(bestPointer); BlockHeader?startBestHeader = syncedBlockTree.FindHeader(bestPointer, BlockTreeLookupOptions.None); blockTree.BestSuggestedHeader.Should().BeEquivalentTo(startBestHeader); blockTree.LowestInsertedBeaconHeader.Should().BeEquivalentTo(syncedBlockTree.FindHeader(pivot.PivotNumber, BlockTreeLookupOptions.None)); BuildHeadersSyncBatches(ctx, blockTree, syncedBlockTree, pivot, endLowestBeaconHeader); HeadersSyncBatch result = await ctx.Feed.PrepareRequest(); result.Should().BeNull(); // check headers are inserted into block tree during sync blockTree.FindHeader(pivot.PivotNumber - 1, BlockTreeLookupOptions.TotalDifficultyNotNeeded).Should().NotBeNull(); blockTree.LowestInsertedBeaconHeader?.Hash.Should().BeEquivalentTo(syncedBlockTree.FindHeader(endLowestBeaconHeader, BlockTreeLookupOptions.None)?.Hash); blockTree.BestKnownNumber.Should().Be(bestPointer); blockTree.BestSuggestedHeader.Should().BeEquivalentTo(startBestHeader); ctx.Feed.CurrentState.Should().Be(SyncFeedState.Dormant); ctx.BeaconSync.ShouldBeInBeaconHeaders().Should().BeFalse(); }
public async Task Feed_able_to_connect_to_existing_chain_through_block_hash() { BlockTree syncedBlockTree = Build.A.BlockTree().OfChainLength(600).TestObject; Block genesisBlock = syncedBlockTree.FindBlock(syncedBlockTree.GenesisHash, BlockTreeLookupOptions.None) !; BlockTree blockTree = Build.A.BlockTree().TestObject; blockTree.SuggestBlock(genesisBlock); Block?firstBlock = syncedBlockTree.FindBlock(1, BlockTreeLookupOptions.None); blockTree.SuggestBlock(firstBlock); BlockHeader? pivotHeader = syncedBlockTree.FindHeader(500, BlockTreeLookupOptions.None); IBeaconPivot pivot = PreparePivot(500, new SyncConfig(), blockTree, pivotHeader); Context ctx = new (blockTree, new SyncConfig(), pivot); // fork in chain Block parent = firstBlock; for (int i = 0; i < 5; i++) { Block block = Build.A.Block.WithParent(parent).WithNonce(1).TestObject; blockTree.SuggestBlock(block); parent = block; } ctx.BeaconSync.ShouldBeInBeaconHeaders().Should().BeTrue(); blockTree.BestKnownNumber.Should().Be(6); BuildHeadersSyncBatches(ctx, blockTree, syncedBlockTree, pivot, 2); HeadersSyncBatch result = await ctx.Feed.PrepareRequest(); result.Should().BeNull(); blockTree.BestKnownNumber.Should().Be(6); ctx.Feed.CurrentState.Should().Be(SyncFeedState.Dormant); ctx.BeaconSync.ShouldBeInBeaconHeaders().Should().BeFalse(); }
public MergeBlocksSyncPeerAllocationStrategyFactory( IPoSSwitcher poSSwitcher, IBeaconPivot beaconPivot, ILogManager logManager) { _poSSwitcher = poSSwitcher; _beaconPivot = beaconPivot; _logManager = logManager; }
public MergeBetterPeerStrategy( IBetterPeerStrategy preMergeBetterPeerStrategy, IPoSSwitcher poSSwitcher, IBeaconPivot beaconPivot, ILogManager logManager) { _preMergeBetterPeerStrategy = preMergeBetterPeerStrategy; _poSSwitcher = poSSwitcher; _beaconPivot = beaconPivot; _logger = logManager.GetClassLogger(); }
public ChainLevelHelper( IBlockTree blockTree, IBeaconPivot beaconPivot, ISyncConfig syncConfig, ILogManager logManager) { _blockTree = blockTree; _beaconPivot = beaconPivot; _syncConfig = syncConfig; _logger = logManager.GetClassLogger(); }
public Context( IBlockTree?blockTree = null, ISyncConfig?syncConfig = null, IBeaconPivot?beaconPivot = null, IDb?metadataDb = null, IMergeConfig?mergeConfig = null) { if (blockTree == null) { IDb blockInfoDb = new MemDb(); Block genesis = Build.A.Block.Genesis.TestObject; BlockTree = new BlockTree(new MemDb(), new MemDb(), blockInfoDb, new ChainLevelInfoRepository(blockInfoDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance); BlockTree.SuggestBlock(genesis); } else { BlockTree = blockTree; } ISyncPeerPool peerPool = Substitute.For <ISyncPeerPool>(); ISyncReport report = Substitute.For <ISyncReport>(); MeasuredProgress measuredProgress = new MeasuredProgress(); report.BeaconHeaders.Returns(measuredProgress); report.HeadersInQueue.Returns(measuredProgress); MemDb stateDb = new(); _syncConfig = syncConfig ?? new SyncConfig(); _mergeConfig = mergeConfig ?? new MergeConfig(); _metadataDb = metadataDb ?? new MemDb(); PoSSwitcher poSSwitcher = new(_mergeConfig, _syncConfig, _metadataDb, blockTree !, MainnetSpecProvider.Instance, LimboLogs.Instance); ProgressTracker progressTracker = new(BlockTree, stateDb, LimboLogs.Instance); SyncProgressResolver syncProgressResolver = new( BlockTree, NullReceiptStorage.Instance, stateDb, new TrieStore(stateDb, LimboLogs.Instance), progressTracker, _syncConfig, LimboLogs.Instance); TotalDifficultyBetterPeerStrategy bestPeerStrategy = new (LimboLogs.Instance); BeaconPivot = beaconPivot ?? new BeaconPivot(_syncConfig, _metadataDb, BlockTree, LimboLogs.Instance); BeaconSync = new(BeaconPivot, BlockTree, _syncConfig, new BlockCacheService(), LimboLogs.Instance); ISyncModeSelector selector = new MultiSyncModeSelector(syncProgressResolver, peerPool, _syncConfig, BeaconSync, bestPeerStrategy, LimboLogs.Instance); Feed = new BeaconHeadersSyncFeed(poSSwitcher, selector, blockTree, peerPool, _syncConfig, report, BeaconPivot, _mergeConfig, new NoopInvalidChainTracker(), LimboLogs.Instance); }
public BeaconSync( IBeaconPivot beaconPivot, IBlockTree blockTree, ISyncConfig syncConfig, IBlockCacheService blockCacheService, ILogManager logManager) { _beaconPivot = beaconPivot; _blockTree = blockTree; _syncConfig = syncConfig; _blockCacheService = blockCacheService; _logger = logManager.GetClassLogger(); }
public ScenarioBuilder WithBlockTrees(int notSyncedTreeSize, int syncedTreeSize = -1, bool moveBlocksToMainChain = true, UInt256?ttd = null) { TestSpecProvider testSpecProvider = new TestSpecProvider(London.Instance); if (ttd != null) { testSpecProvider.TerminalTotalDifficulty = ttd; } NotSyncedTreeBuilder = Build.A.BlockTree().OfChainLength(notSyncedTreeSize); NotSyncedTree = new( NotSyncedTreeBuilder.BlocksDb, NotSyncedTreeBuilder.HeadersDb, NotSyncedTreeBuilder.BlockInfoDb, NotSyncedTreeBuilder.MetadataDb, NotSyncedTreeBuilder.ChainLevelInfoRepository, testSpecProvider, NullBloomStorage.Instance, new SyncConfig(), LimboLogs.Instance); if (syncedTreeSize > 0) { _syncedTreeBuilder = Build.A.BlockTree().OfChainLength(syncedTreeSize); SyncedTree = new( _syncedTreeBuilder.BlocksDb, _syncedTreeBuilder.HeadersDb, _syncedTreeBuilder.BlockInfoDb, _syncedTreeBuilder.MetadataDb, _syncedTreeBuilder.ChainLevelInfoRepository, testSpecProvider, NullBloomStorage.Instance, new SyncConfig(), LimboLogs.Instance); } _beaconPivot = new BeaconPivot(new SyncConfig(), new MemDb(), SyncedTree, LimboLogs.Instance); _chainLevelHelper = new ChainLevelHelper(NotSyncedTree, _beaconPivot, new SyncConfig(), LimboLogs.Instance); if (moveBlocksToMainChain) { NotSyncedTree.NewBestSuggestedBlock += OnNewBestSuggestedBlock; } return(this); }
private MergeBetterPeerStrategy CreateStrategy(long?beaconPivotNum = null) { const long ttd = 5; IPoSSwitcher poSSwitcher = Substitute.For <IPoSSwitcher>(); poSSwitcher.TerminalTotalDifficulty.Returns((UInt256)ttd); IBeaconPivot beaconPivot = Substitute.For <IBeaconPivot>(); if (beaconPivotNum != null) { beaconPivot.BeaconPivotExists().Returns(true); beaconPivot.PivotNumber.Returns((long)beaconPivotNum); } TotalDifficultyBetterPeerStrategy preMergeBetterPeerStrategy = new(LimboLogs.Instance); MergeBetterPeerStrategy betterPeerStrategy = new(preMergeBetterPeerStrategy, poSSwitcher, beaconPivot, LimboLogs.Instance); return(betterPeerStrategy); }
public async Task Finishes_when_all_downloaded() { IBlockTree blockTree = Substitute.For <IBlockTree>(); blockTree.LowestInsertedBeaconHeader.Returns(Build.A.BlockHeader.WithNumber(2000).TestObject); ISyncReport report = Substitute.For <ISyncReport>(); report.HeadersInQueue.Returns(new MeasuredProgress()); MeasuredProgress measuredProgress = new (); report.BeaconHeaders.Returns(measuredProgress); ISyncConfig syncConfig = new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "1000", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }; PoSSwitcher poSSwitcher = new(new MergeConfig(), syncConfig, new MemDb(), blockTree !, MainnetSpecProvider.Instance, LimboLogs.Instance); IBeaconPivot pivot = PreparePivot(2000, syncConfig, blockTree); BeaconHeadersSyncFeed feed = new (poSSwitcher, Substitute.For <ISyncModeSelector>(), blockTree, Substitute.For <ISyncPeerPool>(), syncConfig, report, pivot, new MergeConfig() { Enabled = true }, new NoopInvalidChainTracker(), LimboLogs.Instance); feed.InitializeFeed(); for (int i = 0; i < 6; i++) { await feed.PrepareRequest(); } blockTree.LowestInsertedBeaconHeader.Returns(Build.A.BlockHeader.WithNumber(1001).TestObject); HeadersSyncBatch?result = await feed.PrepareRequest(); result.Should().BeNull(); feed.CurrentState.Should().Be(SyncFeedState.Dormant); measuredProgress.CurrentValue.Should().Be(999); }
private IBetterPeerStrategy CreateMergePeerChoiceStrategy(IPoSSwitcher poSSwitcher, IBeaconPivot beaconPivot) { TotalDifficultyBetterPeerStrategy preMergePeerStrategy = new(LimboLogs.Instance); return(new MergeBetterPeerStrategy(preMergePeerStrategy, poSSwitcher, beaconPivot, LimboLogs.Instance)); }
public PostMergeBlocksSyncPeerAllocationStrategy(long?minBlocksAhead, IBeaconPivot beaconPivot) { _minBlocksAhead = minBlocksAhead; _beaconPivot = beaconPivot; }