private async Task HandleMissedBlocksAsync(Block arrivedBlock) { List <Block> missedBlocks = new List <Block> { arrivedBlock }; var currentHeader = arrivedBlock.Header; while (true) { Block missedBlock = await RpcClient.GetBlockAsync(currentHeader.HashPrevBlock).ConfigureAwait(false); if (missedBlocks.Count > 144) { missedBlocks.RemoveFirst(); } currentHeader = missedBlock.Header; currentHeader.PrecomputeHash(false, true); missedBlocks.Add(missedBlock); if (currentHeader.GetHash() == Network.GenesisHash) { var processedBlocksClone = ProcessedBlocks.ToArray(); var processedReversedBlocks = processedBlocksClone.Reverse(); ProcessedBlocks.Clear(); foreach (var processedBlock in processedReversedBlocks) { OnReorg?.Invoke(this, processedBlock); } break; } // If we found the proper chain. var foundPrevBlock = ProcessedBlocks.FirstOrDefault(x => x.GetHash() == currentHeader.HashPrevBlock); if (foundPrevBlock != null) { // If the last block hash is not what we found, then we missed a reorg also. if (foundPrevBlock.GetHash() != ProcessedBlocks.Last().GetHash()) { ReorgToBlock(foundPrevBlock); } break; } } missedBlocks.Reverse(); foreach (var b in missedBlocks) { AddBlock(b); } }
private void ReorgToBlock(BlockHeader correctBlock) { var index = ProcessedBlocks.IndexOf(correctBlock); int countToRemove = ProcessedBlocks.Count - (index + 1); var toRemoves = ProcessedBlocks.TakeLast(countToRemove).ToList(); ProcessedBlocks.RemoveRange(index + 1, countToRemove); toRemoves.Reverse(); foreach (var toRemove in toRemoves) { OnReorg?.Invoke(this, toRemove); } }