private AddBlockResult InsertHeader(BlockHeader header) { if (header.IsGenesis) { return(AddBlockResult.AlreadyKnown); } 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; } } return(insertOutcome); }
private AddBlockResult InsertHeader(BlockHeader header) { if (header.IsGenesis) { return(AddBlockResult.AlreadyKnown); } AddBlockResult insertOutcome = _blockTree.Insert(header); if (insertOutcome == AddBlockResult.Added || insertOutcome == AddBlockResult.AlreadyKnown) { _nextHeaderHash = header.ParentHash; _nextHeaderDiff = (header.TotalDifficulty ?? 0) - header.Difficulty; } return(insertOutcome); }
private AddBlockResult InsertHeader(BlockHeader header) { if (header.IsGenesis) { return(AddBlockResult.AlreadyKnown); } AddBlockResult insertOutcome = _blockTree.Insert(header); if (insertOutcome == AddBlockResult.Added || insertOutcome == AddBlockResult.AlreadyKnown) { _nextHeaderHash = header.ParentHash; _nextHeaderDiff = (header.TotalDifficulty ?? 0) - header.Difficulty; long parentNumber = header.Number - 1; if (_dependencies.TryRemove(parentNumber, out HeadersSyncBatch batch)) { InsertHeaders(batch); } } return(insertOutcome); }
public async Task <long> DownloadHeaders(PeerInfo bestPeer, int newBlocksToSkip, CancellationToken cancellation) { if (bestPeer == null) { string message = $"Not expecting best peer to be null inside the {nameof(BlockDownloader)}"; _logger.Error(message); throw new ArgumentNullException(message); } int headersSynced = 0; int ancestorLookupLevel = 0; long currentNumber = Math.Max(0, Math.Min(_blockTree.BestKnownNumber, bestPeer.HeadNumber - 1)); while (bestPeer.TotalDifficulty > (_blockTree.BestSuggestedHeader?.TotalDifficulty ?? 0) && currentNumber <= bestPeer.HeadNumber) { if (_logger.IsTrace) { _logger.Trace($"Continue headers sync with {bestPeer} (our best {_blockTree.BestKnownNumber})"); } long blocksLeft = bestPeer.HeadNumber - currentNumber - newBlocksToSkip; int headersToRequest = (int)Math.Min(blocksLeft + 1, _syncBatchSize.Current); if (headersToRequest <= 1) { break; } if (_logger.IsTrace) { _logger.Trace($"Headers request {currentNumber}+{headersToRequest} to peer {bestPeer} with {bestPeer.HeadNumber} blocks. Got {currentNumber} and asking for {headersToRequest} more."); } BlockHeader[] headers = await RequestHeaders(bestPeer, cancellation, currentNumber, headersToRequest); BlockHeader startingPoint = headers[0] == null ? null : _blockTree.FindHeader(headers[0].Hash, BlockTreeLookupOptions.TotalDifficultyNotNeeded); if (startingPoint == null) { ancestorLookupLevel++; if (ancestorLookupLevel >= _ancestorJumps.Length) { if (_logger.IsWarn) { _logger.Warn($"Could not find common ancestor with {bestPeer}"); } throw new EthSynchronizationException("Peer with inconsistent chain in sync"); } int ancestorJump = _ancestorJumps[ancestorLookupLevel] - _ancestorJumps[ancestorLookupLevel - 1]; currentNumber = currentNumber >= ancestorJump ? (currentNumber - ancestorJump) : 0L; continue; } ancestorLookupLevel = 0; _sinceLastTimeout++; if (_sinceLastTimeout >= 2) { // if peers are not timing out then we can try to be slightly more eager _syncBatchSize.Expand(); } for (int i = 1; i < headers.Length; i++) { if (cancellation.IsCancellationRequested) { break; } BlockHeader currentHeader = headers[i]; if (currentHeader == null) { if (headersSynced > 0) { break; } return(0); } if (_logger.IsTrace) { _logger.Trace($"Received {currentHeader} from {bestPeer:s}"); } bool isValid = i > 1 ? _blockValidator.ValidateHeader(currentHeader, headers[i - 1], false) : _blockValidator.ValidateHeader(currentHeader, false); if (!isValid) { throw new EthSynchronizationException($"{bestPeer} sent a block {currentHeader.ToString(BlockHeader.Format.Short)} with an invalid header"); } if (HandleAddResult(bestPeer, currentHeader, i == 0, _blockTree.Insert(currentHeader))) { headersSynced++; } currentNumber = currentNumber + 1; } if (headersSynced > 0) { _syncReport.FullSyncBlocksDownloaded.Update(_blockTree.BestSuggestedHeader?.Number ?? 0); _syncReport.FullSyncBlocksKnown = bestPeer.HeadNumber; } else { break; } } return(headersSynced); }
public AddBlockResult Insert(Block block) { return(_blockTree.Insert(block)); }
private void InsertBlocks(List <Block> validResponses) { _blockTree.Insert(validResponses); }
public async Task <long> DownloadHeaders(PeerInfo bestPeer, BlocksRequest blocksRequest, CancellationToken cancellation) { if (bestPeer == null) { string message = $"Not expecting best peer to be null inside the {nameof(BlockDownloader)}"; _logger.Error(message); throw new ArgumentNullException(message); } int headersSynced = 0; int ancestorLookupLevel = 0; long currentNumber = Math.Max(0, Math.Min(_blockTree.BestKnownNumber, bestPeer.HeadNumber - 1)); while (bestPeer.TotalDifficulty > (_blockTree.BestSuggestedHeader?.TotalDifficulty ?? 0) && currentNumber <= bestPeer.HeadNumber) { int headersSyncedInPreviousRequests = headersSynced; if (_logger.IsTrace) { _logger.Trace($"Continue headers sync with {bestPeer} (our best {_blockTree.BestKnownNumber})"); } long blocksLeft = bestPeer.HeadNumber - currentNumber - (blocksRequest.NumberOfLatestBlocksToBeIgnored ?? 0); int headersToRequest = (int)Math.Min(blocksLeft + 1, _syncBatchSize.Current); if (headersToRequest <= 1) { break; } if (_logger.IsDebug) { _logger.Debug($"Headers request {currentNumber}+{headersToRequest} to peer {bestPeer} with {bestPeer.HeadNumber} blocks. Got {currentNumber} and asking for {headersToRequest} more."); } BlockHeader?[] headers = await RequestHeaders(bestPeer, cancellation, currentNumber, headersToRequest); Keccak? startHeaderHash = headers[0]?.Hash; BlockHeader?startHeader = (startHeaderHash is null) ? null : _blockTree.FindHeader(startHeaderHash, BlockTreeLookupOptions.TotalDifficultyNotNeeded); if (startHeader is null) { ancestorLookupLevel++; if (ancestorLookupLevel >= _ancestorJumps.Length) { if (_logger.IsWarn) { _logger.Warn($"Could not find common ancestor with {bestPeer}"); } throw new EthSyncException("Peer with inconsistent chain in sync"); } int ancestorJump = _ancestorJumps[ancestorLookupLevel] - _ancestorJumps[ancestorLookupLevel - 1]; currentNumber = currentNumber >= ancestorJump ? (currentNumber - ancestorJump) : 0L; continue; } ancestorLookupLevel = 0; _sinceLastTimeout++; if (_sinceLastTimeout >= 2) { // if peers are not timing out then we can try to be slightly more eager _syncBatchSize.Expand(); } for (int i = 1; i < headers.Length; i++) { if (cancellation.IsCancellationRequested) { break; } BlockHeader?currentHeader = headers[i]; if (currentHeader == null) { if (headersSynced - headersSyncedInPreviousRequests > 0) { break; } SyncPeerPool.ReportNoSyncProgress(bestPeer, AllocationContexts.Blocks); return(0); } if (_logger.IsTrace) { _logger.Trace($"Received {currentHeader} from {bestPeer:s}"); } bool isValid = i > 1 ? _blockValidator.Validate(currentHeader, headers[i - 1]) : _blockValidator.Validate(currentHeader); if (!isValid) { throw new EthSyncException($"{bestPeer} sent a block {currentHeader.ToString(BlockHeader.Format.Short)} with an invalid header"); } // i == 0 is always false but leave it this was as it will be possible that we will change the // loop iterator to start with o if (HandleAddResult(bestPeer, currentHeader, i == 0, _blockTree.Insert(currentHeader))) { headersSynced++; } currentNumber = currentNumber + 1; } if (headersSynced > 0) { _syncReport.FullSyncBlocksDownloaded.Update(_blockTree.BestSuggestedHeader?.Number ?? 0); _syncReport.FullSyncBlocksKnown = bestPeer.HeadNumber; } else { break; } } return(headersSynced); }