diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs index 00c654b7853..13e1cc2d6f0 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs @@ -118,6 +118,25 @@ public async Task Finishes_when_all_downloaded() measuredProgress.HasEnded.Should().BeTrue(); } + [Test] + public async Task Can_resume_downloading_from_parent_of_lowest_inserted_header() + { + IBlockTree blockTree = Substitute.For(); + blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader + .WithNumber(500) + .WithTotalDifficulty(10_000_000) + .TestObject); + + ISyncReport report = Substitute.For(); + report.HeadersInQueue.Returns(new MeasuredProgress()); + report.FastBlocksHeaders.Returns(new MeasuredProgress()); + + HeadersSyncFeed feed = new(Substitute.For(), blockTree, Substitute.For(), new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "1000", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, report, LimboLogs.Instance); + feed.InitializeFeed(); + var result = await feed.PrepareRequest(); + result.EndNumber.Should().Be(499); + } + private class ResettableHeaderSyncFeed : HeadersSyncFeed { public ResettableHeaderSyncFeed(ISyncModeSelector syncModeSelector, IBlockTree? blockTree, ISyncPeerPool? syncPeerPool, ISyncConfig? syncConfig, ISyncReport? syncReport, ILogManager? logManager, bool alwaysStartHeaderSync = false) : base(syncModeSelector, blockTree, syncPeerPool, syncConfig, syncReport, logManager, alwaysStartHeaderSync) diff --git a/src/Nethermind/Nethermind.Synchronization/FastBlocks/FastHeadersSyncFeed.cs b/src/Nethermind/Nethermind.Synchronization/FastBlocks/FastHeadersSyncFeed.cs index ad771a76bdd..5db2a2e1851 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastBlocks/FastHeadersSyncFeed.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastBlocks/FastHeadersSyncFeed.cs @@ -183,18 +183,20 @@ public HeadersSyncFeed( public override void InitializeFeed() { + _logger.Info("Feed reinitialized"); _pivotNumber = _syncConfig.PivotNumberParsed; - bool useSyncPivot = _blockTree.LowestInsertedHeader is null || _blockTree.LowestInsertedHeader.Number > _pivotNumber; - BlockHeader? lowestInserted = _blockTree.LowestInsertedHeader; - long startNumber = useSyncPivot ? _pivotNumber : lowestInserted.Number; - Keccak startHeaderHash = useSyncPivot ? _syncConfig.PivotHashParsed : lowestInserted.Hash; - UInt256? startTotalDifficulty = useSyncPivot ? _syncConfig.PivotTotalDifficultyParsed : lowestInserted?.TotalDifficulty; - - _nextHeaderHash = startHeaderHash; - _nextHeaderDiff = startTotalDifficulty; + _lowestRequestedHeaderNumber = _pivotNumber + 1; // Because we want the pivot to be requested + _nextHeaderHash = _syncConfig.PivotHashParsed; + _nextHeaderDiff = _syncConfig.PivotTotalDifficultyParsed; - _lowestRequestedHeaderNumber = startNumber + 1; + // Resume logic + BlockHeader? lowestInserted = _blockTree.LowestInsertedHeader; + if (lowestInserted != null && lowestInserted!.Number < _pivotNumber) + { + SetExpectedNextHeaderToParent(lowestInserted); + _lowestRequestedHeaderNumber = lowestInserted.Number; + } base.InitializeFeed(); } @@ -652,19 +654,24 @@ protected virtual AddBlockResult InsertToBlockTree(BlockHeader header) AddBlockResult insertOutcome = _blockTree.Insert(header); if (insertOutcome == AddBlockResult.Added || insertOutcome == AddBlockResult.AlreadyKnown) { - ulong nextHeaderDiff = 0; - _nextHeaderHash = header.ParentHash!; - if (_expectedDifficultyOverride?.TryGetValue(header.Number, out nextHeaderDiff) == true) - { - _nextHeaderDiff = nextHeaderDiff; - } - else - { - _nextHeaderDiff = (header.TotalDifficulty ?? 0) - header.Difficulty; - } + SetExpectedNextHeaderToParent(header); } return insertOutcome; } + + private void SetExpectedNextHeaderToParent(BlockHeader header) + { + ulong nextHeaderDiff = 0; + _nextHeaderHash = header.ParentHash!; + if (_expectedDifficultyOverride?.TryGetValue(header.Number, out nextHeaderDiff) == true) + { + _nextHeaderDiff = nextHeaderDiff; + } + else + { + _nextHeaderDiff = (header.TotalDifficulty ?? 0) - header.Difficulty; + } + } } }