public async Task <PagedResult> GetBlocksAsync(BlocksRequest request) { var num = request.Num; if (!num.HasValue || num.Value == 0) { num = (await m_EosApi.GetInfo()).head_block_num; } var blocks = new List <Block>(); long start = (long)num - (long)request.Skip - (long)request.Limit; long end = start + (long)request.Limit; if (start < 0) { start = 0; } for (var i = end; i > start; i--) { var block = await m_EosApi.GetBlock(new GetBlockRequest() { block_num_or_id = i.ToString() }); blocks.Add(new Block { Id = block.id, Time = block.timestamp, Num = block.block_num, Producer = block.producer, Txns = block.transactions.Count }); } return(PagedResult.Create(blocks, (int)num.Value)); }
public override async Task <BlockList> RequestBlocks(BlocksRequest request, ServerCallContext context) { if (request == null || request.PreviousBlockHash == null || _syncStateService.SyncState != SyncState.Finished) { return(new BlockList()); } Logger.LogDebug($"Peer {context.GetPeerInfo()} requested {request.Count} blocks from {request.PreviousBlockHash}."); var blockList = new BlockList(); var blocks = await _blockchainService.GetBlocksWithTransactions(request.PreviousBlockHash, request.Count); if (blocks == null) { return(blockList); } blockList.Blocks.AddRange(blocks); if (blockList.Blocks.Count != request.Count) { Logger.LogTrace($"Replied with {blockList.Blocks.Count} blocks for request {request}"); } if (NetworkOptions.CompressBlocksOnRequest) { var headers = new Metadata { new Metadata.Entry(GrpcConstants.GrpcRequestCompressKey, GrpcConstants.GrpcGzipConst) }; await context.WriteResponseHeadersAsync(headers); } return(blockList); }
public async Task <List <BlockWithTransactions> > GetBlocksAsync(Hash firstHash, int count) { var blockRequest = new BlocksRequest { PreviousBlockHash = firstHash, Count = count }; var blockInfo = $"{{ first: {firstHash}, count: {count} }}"; GrpcRequest request = new GrpcRequest { ErrorMessage = $"Get blocks for {blockInfo} failed.", MetricName = nameof(MetricNames.GetBlocks), MetricInfo = $"Get blocks for {blockInfo}" }; Metadata data = new Metadata { { GrpcConstants.TimeoutMetadataKey, BlocksRequestTimeout.ToString() }, { GrpcConstants.SessionIdMetadataKey, OutboundSessionId } }; var list = await RequestAsync(() => _client.RequestBlocksAsync(blockRequest, data), request); if (list == null) { return(new List <BlockWithTransactions>()); } return(list.Blocks.ToList()); }
/// <summary> /// Gets list of blocks asynchronously /// </summary> /// <param name="req">BlocksRequest</param> /// <returns>BlocksResponse with blocks list</returns> public async Task <BlocksResponse> GetBlocksAsync(BlocksRequest req) { _url.Path = Constants.ApiGetBlocks; _url.Query = req.ToQuery(); var response = await _client.GetJsonAsync <BlocksResponse>(_url.ToString()); ResetPath(); return(response); }
public async Task <List <Block> > GetBlocksAsync(Hash firstHash, int count) { var blockRequest = new BlocksRequest { PreviousBlockHash = firstHash, Count = count }; var list = await RequestAsync(_client, c => c.RequestBlocksAsync(blockRequest), $"Get blocks for {{ first: {firstHash}, count: {count} }} failed."); if (list == null) { return(new List <Block>()); } return(list.Blocks.ToList()); }
public override async Task <BlockList> RequestBlocks(BlocksRequest request, ServerCallContext context) { if (request == null || request.PreviousBlockHash == null || _syncStateService.SyncState != SyncState.Finished || request.Count == 0 || request.Count > GrpcConstants.MaxSendBlockCountLimit) { return(new BlockList()); } Logger.LogDebug( $"Peer {context.GetPeerInfo()} requested {request.Count} blocks from {request.PreviousBlockHash}."); var blockList = new BlockList(); try { var blocks = await _blockchainService.GetBlocksWithTransactions(request.PreviousBlockHash, request.Count); blockList.Blocks.AddRange(blocks); if (NetworkOptions.CompressBlocksOnRequest) { var headers = new Metadata { new Metadata.Entry(GrpcConstants.GrpcRequestCompressKey, GrpcConstants.GrpcGzipConst) }; await context.WriteResponseHeadersAsync(headers); } Logger.LogTrace( $"Replied to {context.GetPeerInfo()} with {blockList.Blocks.Count}, request was {request}"); } catch (Exception e) { Logger.LogError(e, $"Request blocks error - {context.GetPeerInfo()} - request {request}: "); throw; } return(blockList); }
public Task <PagedResult> Blocks([FromQuery] BlocksRequest request) { var blocks = m_ChainManager.GetBlocksAsync(request); return(blocks); }
public override async Task <long> DownloadBlocks(PeerInfo?bestPeer, BlocksRequest blocksRequest, CancellationToken cancellation) { if (_beaconPivot.BeaconPivotExists() == false && _poSSwitcher.HasEverReachedTerminalBlock() == false) { return(await base.DownloadBlocks(bestPeer, blocksRequest, cancellation)); } if (bestPeer == null) { string message = $"Not expecting best peer to be null inside the {nameof(BlockDownloader)}"; if (_logger.IsError) { _logger.Error(message); } throw new ArgumentNullException(message); } DownloaderOptions options = blocksRequest.Options; bool downloadReceipts = (options & DownloaderOptions.WithReceipts) == DownloaderOptions.WithReceipts; bool shouldProcess = (options & DownloaderOptions.Process) == DownloaderOptions.Process; bool shouldMoveToMain = (options & DownloaderOptions.MoveToMain) == DownloaderOptions.MoveToMain; int blocksSynced = 0; long currentNumber = _blockTree.BestKnownNumber; if (_logger.IsTrace) { _logger.Trace( $"MergeBlockDownloader GetCurrentNumber: currentNumber {currentNumber}, beaconPivotExists: {_beaconPivot.BeaconPivotExists()}, BestSuggestedBody: {_blockTree.BestSuggestedBody?.Number}, BestKnownNumber: {_blockTree.BestKnownNumber}, BestPeer: {bestPeer}, BestKnownBeaconNumber {_blockTree.BestKnownBeaconNumber}"); } bool HasMoreToSync(out BlockHeader[]?headers, out int headersToRequest) { if (_logger.IsDebug) { _logger.Debug($"Continue full sync with {bestPeer} (our best {_blockTree.BestKnownNumber})"); } headersToRequest = Math.Min(_syncBatchSize.Current, bestPeer.MaxHeadersPerRequest()); if (_logger.IsTrace) { _logger.Trace( $"Full sync request {currentNumber}+{headersToRequest} to peer {bestPeer} with {bestPeer.HeadNumber} blocks. Got {currentNumber} and asking for {headersToRequest} more."); } // Note: blocksRequest.NumberOfLatestBlocksToBeIgnored not accounted for headers = _chainLevelHelper.GetNextHeaders(headersToRequest, bestPeer.HeadNumber); if (headers == null || headers.Length <= 1) { if (_logger.IsTrace) { _logger.Trace("Chain level helper got no headers suggestion"); } return(false); } return(true); } while (HasMoreToSync(out BlockHeader[]? headers, out int headersToRequest)) { if (cancellation.IsCancellationRequested) { return(blocksSynced); // check before every heavy operation } Block[]? blocks = null; TxReceipt[]?[]? receipts = null; if (_logger.IsTrace) { _logger.Trace( $"Downloading blocks from peer. CurrentNumber: {currentNumber}, BeaconPivot: {_beaconPivot.PivotNumber}, BestPeer: {bestPeer}, HeaderToRequest: {headersToRequest}"); } BlockDownloadContext context = new(_specProvider, bestPeer, headers !, downloadReceipts, _receiptsRecovery); if (cancellation.IsCancellationRequested) { return(blocksSynced); // check before every heavy operation } await RequestBodies(bestPeer, cancellation, context); if (downloadReceipts) { if (cancellation.IsCancellationRequested) { return(blocksSynced); // check before every heavy operation } await RequestReceipts(bestPeer, cancellation, context); } _sinceLastTimeout++; if (_sinceLastTimeout > 2) { _syncBatchSize.Expand(); } blocks = context.Blocks; receipts = context.ReceiptsForBlocks; if (!(blocks?.Length > 0)) { if (_logger.IsTrace) { _logger.Trace("Break early due to no blocks."); } break; } for (int blockIndex = 0; blockIndex < blocks.Length; blockIndex++) { if (cancellation.IsCancellationRequested) { if (_logger.IsTrace) { _logger.Trace("Peer sync cancelled"); } break; } Block currentBlock = blocks[blockIndex]; if (_logger.IsTrace) { _logger.Trace($"Received {currentBlock} from {bestPeer}"); } if (currentBlock.IsBodyMissing) { throw new EthSyncException($"{bestPeer} didn't send body for block {currentBlock.ToString(Block.Format.Short)}."); } // can move this to block tree now? if (!_blockValidator.ValidateSuggestedBlock(currentBlock)) { throw new EthSyncException($"{bestPeer} sent an invalid block {currentBlock.ToString(Block.Format.Short)}."); } if (shouldProcess) { // covering edge case during fastSyncTransition when we're trying to SuggestBlock without the state bool headIsGenesis = _blockTree.Head?.IsGenesis ?? false; bool toBeProcessedIsNotBlockOne = currentBlock.Number > 1; bool isFastSyncTransition = headIsGenesis && toBeProcessedIsNotBlockOne; if (isFastSyncTransition) { long bestFullState = _syncProgressResolver.FindBestFullState(); shouldProcess = currentBlock.Number > bestFullState && bestFullState != 0; if (!shouldProcess) { if (_logger.IsInfo) { _logger.Info($"Skipping processing during fastSyncTransition, currentBlock: {currentBlock}, bestFullState: {bestFullState}"); } downloadReceipts = true; } } } if (downloadReceipts) { TxReceipt[]? contextReceiptsForBlock = receipts ![blockIndex]; if (currentBlock.Header.HasBody && contextReceiptsForBlock == null) { throw new EthSyncException($"{bestPeer} didn't send receipts for block {currentBlock.ToString(Block.Format.Short)}."); } }
/// <summary> /// Gets list of block synchronously /// </summary> /// <param name="req">BlocksRequest</param> /// <returns>BlocksResponse with blocks list</returns> public BlocksResponse GetBlocks(BlocksRequest req) { return(GetBlocksAsync(req).GetAwaiter().GetResult()); }
/// <summary> /// Gets list of blocks asynchronously /// </summary> /// <param name="req">BlocksRequest</param> /// <returns>BlocksResponse with blocks list</returns> public async Task<BlocksResponse> GetBlocksAsync(BlocksRequest req) { _url.Path = Constants.ApiGetBlocks; _url.Query = req.ToQuery(); var response = await _client.GetJsonAsync<BlocksResponse>(_url.ToString()); ResetPath(); return response; }
/// <summary> /// Gets list of block synchronously /// </summary> /// <param name="req">BlocksRequest</param> /// <returns>BlocksResponse with blocks list</returns> public BlocksResponse GetBlocks(BlocksRequest req) { return GetBlocksAsync(req).GetAwaiter().GetResult(); }