예제 #1
0
        public void Switch_correctly_from_full_sync_to_state_nodes_catch_up()
        {
            ISyncProgressResolver syncProgressResolver = Substitute.For <ISyncProgressResolver>();

            syncProgressResolver.FindBestHeader().Returns(Scenario.ChainHead.Number);
            syncProgressResolver.FindBestFullBlock().Returns(Scenario.ChainHead.Number);
            syncProgressResolver.FindBestFullState().Returns(Scenario.ChainHead.Number - MultiSyncModeSelector.FastSyncLag);
            syncProgressResolver.FindBestProcessedBlock().Returns(0);
            syncProgressResolver.IsFastBlocksFinished().Returns(FastBlocksState.FinishedReceipts);
            syncProgressResolver.ChainDifficulty.Returns(UInt256.Zero);

            List <ISyncPeer> syncPeers = new();

            BlockHeader header   = Scenario.ChainHead;
            ISyncPeer   syncPeer = Substitute.For <ISyncPeer>();

            syncPeer.HeadHash.Returns(header.Hash);
            syncPeer.HeadNumber.Returns(header.Number);
            syncPeer.TotalDifficulty.Returns(header.TotalDifficulty ?? 0);
            syncPeer.IsInitialized.Returns(true);
            syncPeer.ClientId.Returns("nethermind");

            syncPeers.Add(syncPeer);
            ISyncPeerPool          syncPeerPool = Substitute.For <ISyncPeerPool>();
            IEnumerable <PeerInfo> peerInfos    = syncPeers.Select(p => new PeerInfo(p));

            syncPeerPool.InitializedPeers.Returns(peerInfos);
            syncPeerPool.AllPeers.Returns(peerInfos);

            ISyncConfig syncConfig = new SyncConfig()
            {
                FastSyncCatchUpHeightDelta = 2
            };

            syncConfig.FastSync = true;

            TotalDifficultyBetterPeerStrategy bestPeerStrategy = new(LimboLogs.Instance);
            MultiSyncModeSelector             selector         = new(syncProgressResolver, syncPeerPool, syncConfig, No.BeaconSync, bestPeerStrategy, LimboLogs.Instance);

            selector.Stop();
            syncProgressResolver.FindBestProcessedBlock().Returns(Scenario.ChainHead.Number);
            selector.Update();
            selector.Current.Should().Be(SyncMode.Full);

            for (uint i = 0; i < syncConfig.FastSyncCatchUpHeightDelta + 1; i++)
            {
                long number = header.Number + i;
                syncPeer.HeadNumber.Returns(number);
                syncPeer.TotalDifficulty.Returns(header.TotalDifficulty.Value + i);
                syncProgressResolver.FindBestHeader().Returns(number);
                syncProgressResolver.FindBestFullBlock().Returns(number);
                selector.Update();
            }

            selector.Current.Should().Be(SyncMode.StateNodes);
        }
예제 #2
0
        public void Update()
        {
            if (_syncPeerPool.PeerCount == 0)
            {
                return;
            }

            if (!_syncConfig.FastSync)
            {
                if (Current == SyncMode.NotStarted)
                {
                    Current = SyncMode.Full;
                    Changed?.Invoke(this, EventArgs.Empty);
                }
            }
            else
            {
                long bestHeader               = _syncProgressResolver.FindBestHeader();
                long bestFullBlock            = _syncProgressResolver.FindBestFullBlock();
                long bestFullState            = _syncProgressResolver.FindBestFullState();
                long maxBlockNumberAmongPeers = 0;
                if (bestFullBlock < 0 ||
                    bestHeader < 0 ||
                    bestFullState < 0 ||
                    bestFullBlock > bestHeader)
                {
                    string errorMessage = $"Invalid best state calculation: {BuildStateString(bestHeader, bestFullBlock, bestFullBlock, maxBlockNumberAmongPeers)}";
                    if (_logger.IsError)
                    {
                        _logger.Error(errorMessage);
                    }
                    throw new InvalidOperationException(errorMessage);
                }

                foreach (PeerInfo peerInfo in _syncPeerPool.UsefulPeers)
                {
                    maxBlockNumberAmongPeers = Math.Max(maxBlockNumberAmongPeers, peerInfo.HeadNumber);
                }

                SyncMode newSyncMode;
                if (!_syncProgressResolver.IsFastBlocksFinished())
                {
                    newSyncMode = SyncMode.FastBlocks;
                }
                else if (maxBlockNumberAmongPeers - Math.Max(bestFullState, bestFullBlock) <= FullSyncThreshold)
                {
                    newSyncMode = Math.Max(bestFullState, bestFullBlock) >= bestHeader ? SyncMode.Full : SyncMode.StateNodes;
                }
                else if (maxBlockNumberAmongPeers - bestHeader <= FullSyncThreshold)
                {
                    // TODO: we need to check here if there are any blocks in processing queue... any other checks are wrong
                    newSyncMode = bestFullBlock > bestFullState ? SyncMode.WaitForProcessor : SyncMode.StateNodes;
                }
                else
                {
                    newSyncMode = bestFullBlock > bestFullState ? SyncMode.WaitForProcessor : SyncMode.Headers;
                }

                if (newSyncMode != Current)
                {
                    if (_logger.IsInfo)
                    {
                        _logger.Info($"Switching sync mode from {Current} to {newSyncMode} {BuildStateString(bestHeader, bestFullBlock, bestFullState, maxBlockNumberAmongPeers)}");
                    }
                    Current = newSyncMode;
                    Changed?.Invoke(this, EventArgs.Empty);
                }
                else
                {
                    if (_logger.IsInfo)
                    {
                        _logger.Info($"Staying on sync mode {Current} {BuildStateString(bestHeader, bestFullBlock, bestFullState, maxBlockNumberAmongPeers)}");
                    }
                }
            }
        }
예제 #3
0
        public void Update()
        {
            if (!_fastSyncEnabled)
            {
                return;
            }

            if (_syncPeerPool.PeerCount == 0)
            {
                return;
            }

            long bestFullBlock = _syncProgressResolver.FindBestFullBlock();
            long bestHeader    = _syncProgressResolver.FindBestHeader();
            long bestFullState = _syncProgressResolver.FindBestFullState();

            if (bestFullBlock < 0 || bestHeader < 0 || bestFullState < 0 ||
                bestFullBlock > bestHeader)
            {
                string errorMessage = $"Invalid best state calculation: F:{bestFullBlock}|H:{bestHeader}|S:{bestFullState}";
                if (_logger.IsError)
                {
                    _logger.Error(errorMessage);
                }
                throw new InvalidOperationException(errorMessage);
            }

            long maxBlockNumberAmongPeers = 0;

            foreach (PeerInfo peerInfo in _syncPeerPool.UsefulPeers)
            {
                maxBlockNumberAmongPeers = Math.Max(maxBlockNumberAmongPeers, peerInfo.HeadNumber);
            }

            SyncMode newSyncMode;

            if (maxBlockNumberAmongPeers - Math.Max(bestFullState, bestFullBlock) <= FullSyncThreshold)
            {
                newSyncMode = Math.Max(bestFullState, bestFullBlock) >= bestHeader ? SyncMode.Full : SyncMode.StateNodes;
            }
            else if (maxBlockNumberAmongPeers - bestHeader <= FullSyncThreshold)
            {
                // TODO: we need to check here if there are any blocks in processing queue... any other checks are wrong
                newSyncMode = bestFullBlock > bestFullState ? SyncMode.WaitForProcessor : SyncMode.StateNodes;
            }
            else
            {
                newSyncMode = bestFullBlock > bestFullState ? SyncMode.WaitForProcessor : SyncMode.Headers;
            }

            if (newSyncMode != Current)
            {
                if (_logger.IsInfo)
                {
                    _logger.Info($"Switching sync mode from {Current} to {newSyncMode} H:{bestHeader}|F:{bestFullBlock}|S:{bestFullState}|R:{maxBlockNumberAmongPeers}.");
                }
                Current = newSyncMode;
                Changed?.Invoke(this, EventArgs.Empty);
            }
            else
            {
                if (_logger.IsInfo)
                {
                    _logger.Info($"Staying on sync mode {Current} |best header:{bestHeader}|best full block:{bestFullBlock}|best state:{bestFullState}|best peer block:{maxBlockNumberAmongPeers}");
                }
            }
        }