private void Handle(GetBlockHeadersMessage getBlockHeadersMessage) { if (Logger.IsTrace) { Logger.Trace($"GetBlockHeaders.MaxHeaders: {getBlockHeadersMessage.MaxHeaders}"); Logger.Trace($"GetBlockHeaders.Reverse: {getBlockHeadersMessage.Reverse}"); Logger.Trace($"GetBlockHeaders.Skip: {getBlockHeadersMessage.Skip}"); Logger.Trace($"GetBlockHeaders.StartingBlockhash: {getBlockHeadersMessage.StartingBlockHash}"); Logger.Trace($"GetBlockHeaders.StartingBlockNumber: {getBlockHeadersMessage.StartingBlockNumber}"); } Keccak startingHash = getBlockHeadersMessage.StartingBlockHash; if (startingHash == null) { startingHash = SyncManager.Find(getBlockHeadersMessage.StartingBlockNumber)?.Hash; } Block[] blocks = startingHash == null ? new Block[0] : SyncManager.Find(startingHash, (int)getBlockHeadersMessage.MaxHeaders, (int)getBlockHeadersMessage.Skip, getBlockHeadersMessage.Reverse == 1); BlockHeader[] headers = new BlockHeader[blocks.Length]; for (int i = 0; i < blocks.Length; i++) { headers[i] = blocks[i]?.Header; } Send(new BlockHeadersMessage(headers)); }
async Task <BlockHeader[]> ISyncPeer.GetBlockHeaders(long number, int maxBlocks, int skip, CancellationToken token) { if (maxBlocks == 0) { return(new BlockHeader[0]); } var msg = new GetBlockHeadersMessage(); msg.MaxHeaders = maxBlocks; msg.Reverse = 0; msg.Skip = skip; msg.StartingBlockNumber = number; // Logger.Info($"Sending headers request ({number}, {maxBlocks}, {skip}) to {this}"); BlockHeader[] headers = await SendRequest(msg, token); // int nonNullCount = 0; // for (int i = 0; i < headers.Length; i++) // { // if (headers[i] != null) // { // nonNullCount++; // } // } // Logger.Info($"Sent headers request ({number}, {maxBlocks}, {skip}) to {this} - received {headers.Length}, out of which {nonNullCount} non null"); return(headers); }
private void Handle(GetBlockHeadersMessage getBlockHeadersMessage) { if (Logger.IsTrace) { Logger.Trace($"GetBlockHeaders.MaxHeaders: {getBlockHeadersMessage.MaxHeaders}"); Logger.Trace($"GetBlockHeaders.Reverse: {getBlockHeadersMessage.Reverse}"); Logger.Trace($"GetBlockHeaders.Skip: {getBlockHeadersMessage.Skip}"); Logger.Trace($"GetBlockHeaders.StartingBlockhash: {getBlockHeadersMessage.StartingBlockHash}"); Logger.Trace($"GetBlockHeaders.StartingBlockNumber: {getBlockHeadersMessage.StartingBlockNumber}"); } Keccak startingHash = getBlockHeadersMessage.StartingBlockHash; if (startingHash == null) { startingHash = SyncServer.Find(getBlockHeadersMessage.StartingBlockNumber)?.Hash; } BlockHeader[] headers = startingHash == null ? new BlockHeader[0] : SyncServer.FindHeaders(startingHash, (int)getBlockHeadersMessage.MaxHeaders, (int)getBlockHeadersMessage.Skip, getBlockHeadersMessage.Reverse == 1); Send(new BlockHeadersMessage(headers)); }
async Task <BlockHeader> ISynchronizationPeer.GetHeadBlockHeader(CancellationToken token) { var msg = new GetBlockHeadersMessage(); msg.StartingBlockHash = _remoteHeadBlockHash; msg.MaxHeaders = 1; msg.Reverse = 0; msg.Skip = 0; BlockHeader[] headers = await SendRequest(msg, token); return(headers.Length > 0 ? headers[0] : null); }
async Task <BlockHeader[]> ISynchronizationPeer.GetBlockHeaders(UInt256 number, int maxBlocks, int skip, CancellationToken token) { var msg = new GetBlockHeadersMessage(); msg.MaxHeaders = maxBlocks; msg.Reverse = 0; msg.Skip = skip; msg.StartingBlockNumber = number; BlockHeader[] headers = await SendRequest(msg, token); return(headers); }
async Task <BlockHeader[]> ISyncPeer.GetBlockHeaders(Keccak blockHash, int maxBlocks, int skip, CancellationToken token) { var msg = new GetBlockHeadersMessage(); msg.MaxHeaders = maxBlocks; msg.Reverse = 0; msg.Skip = skip; msg.StartingBlockHash = blockHash; BlockHeader[] headers = await SendRequest(msg, token); return(headers); }
async Task <UInt256> ISynchronizationPeer.GetHeadDifficulty(CancellationToken token) { var msg = new GetBlockHeadersMessage(); msg.StartingBlockHash = _remoteHeadBlockHash; msg.MaxHeaders = 1; msg.Reverse = 0; msg.Skip = 0; BlockHeader[] headers = await SendRequest(msg, token); return(headers[0]?.Difficulty ?? 0); }
private async Task <BlockHeader[]> SendRequest(GetBlockHeadersMessage message, CancellationToken token) { if (_headersRequests.IsAddingCompleted || _isDisposed) { throw new TimeoutException("Session disposed"); } if (Logger.IsTrace) { Logger.Trace($"Sending headers request to {Session.Node:c}:"); Logger.Trace($" Starting blockhash: {message.StartingBlockHash}"); Logger.Trace($" Starting number: {message.StartingBlockNumber}"); Logger.Trace($" Skip: {message.Skip}"); Logger.Trace($" Reverse: {message.Reverse}"); Logger.Trace($" Max headers: {message.MaxHeaders}"); } var request = new Request <GetBlockHeadersMessage, BlockHeader[]>(message); _headersRequests.Add(request, token); request.StartMeasuringTime(); Send(request.Message); Task <BlockHeader[]> task = request.CompletionSource.Task; using CancellationTokenSource delayCancellation = new CancellationTokenSource(); using CancellationTokenSource compositeCancellation = CancellationTokenSource.CreateLinkedTokenSource(token, delayCancellation.Token); var firstTask = await Task.WhenAny(task, Task.Delay(Timeouts.Eth, compositeCancellation.Token)); if (firstTask.IsCanceled) { token.ThrowIfCancellationRequested(); } if (firstTask == task) { delayCancellation.Cancel(); long elapsed = request.FinishMeasuringTime(); long bytesPerMillisecond = (long)((decimal)request.ResponseSize / Math.Max(1, elapsed)); if (Logger.IsTrace) { Logger.Trace($"{this} speed is {request.ResponseSize}/{elapsed} = {bytesPerMillisecond}"); } StatsManager.ReportTransferSpeedEvent(Session.Node, bytesPerMillisecond); return(task.Result); } StatsManager.ReportTransferSpeedEvent(Session.Node, 0); throw new TimeoutException($"{Session} Request timeout in {nameof(GetBlockHeadersMessage)} with {message.MaxHeaders} max headers"); }
private async Task <BlockHeader[]> SendRequest(GetBlockHeadersMessage message, CancellationToken token) { if (_headersRequests.IsAddingCompleted || _isDisposed) { throw new TimeoutException("Session disposed"); } if (Logger.IsTrace) { Logger.Trace($"Sending headers request to {Session.Node:c}:"); Logger.Trace($" Starting blockhash: {message.StartingBlockHash}"); Logger.Trace($" Starting number: {message.StartingBlockNumber}"); Logger.Trace($" Skip: {message.Skip}"); Logger.Trace($" Reverse: {message.Reverse}"); Logger.Trace($" Max headers: {message.MaxHeaders}"); } var request = new Request <GetBlockHeadersMessage, BlockHeader[]>(message); _headersRequests.Add(request, token); var perfCalcId = _perfService.StartPerfCalc(); Send(request.Message); Task <BlockHeader[]> task = request.CompletionSource.Task; CancellationTokenSource delayCancellation = new CancellationTokenSource(); CancellationTokenSource compositeCancellation = CancellationTokenSource.CreateLinkedTokenSource(token, delayCancellation.Token); var firstTask = await Task.WhenAny(task, Task.Delay(Timeouts.Eth, compositeCancellation.Token)); if (firstTask.IsCanceled) { token.ThrowIfCancellationRequested(); } if (firstTask == task) { delayCancellation.Cancel(); var latency = _perfService.EndPerfCalc(perfCalcId); if (latency.HasValue) { StatsManager.ReportLatencyCaptureEvent(Session.Node, NodeLatencyStatType.BlockHeaders, latency.Value); } return(task.Result); } _perfService.EndPerfCalc(perfCalcId); throw new TimeoutException($"{Session} Request timeout in {nameof(GetBlockHeadersMessage)} with {message.MaxHeaders} max headers"); }
private void Handle(GetBlockHeadersMessage getBlockHeadersMessage) { Stopwatch stopwatch = Stopwatch.StartNew(); if (Logger.IsTrace) { Logger.Trace($"Received headers request from {Session.Node:c}:"); Logger.Trace($" MaxHeaders: {getBlockHeadersMessage.MaxHeaders}"); Logger.Trace($" Reverse: {getBlockHeadersMessage.Reverse}"); Logger.Trace($" Skip: {getBlockHeadersMessage.Skip}"); Logger.Trace($" StartingBlockhash: {getBlockHeadersMessage.StartingBlockHash}"); Logger.Trace($" StartingBlockNumber: {getBlockHeadersMessage.StartingBlockNumber}"); } Interlocked.Increment(ref Counter); // to clearly state that this client is an ETH client and not ETC (and avoid disconnections on reversed sync) // also to improve performance as this is the most common request // if (getBlockHeadersMessage.StartingBlockNumber == 1920000 && getBlockHeadersMessage.MaxHeaders == 1) // { // // hardcoded response // Packet packet = new Packet(ProtocolCode, Eth62MessageCode.BlockHeaders, Bytes.FromHexString("f90210f9020da0a218e2c611f21232d857e3c8cecdcdf1f65f25a4477f98f6f47e4063807f2308a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794bcdfc35b86bedf72f0cda046a3c16829a2ef41d1a0c5e389416116e3696cce82ec4533cce33efccb24ce245ae9546a4b8f0d5e9a75a07701df8e07169452554d14aadd7bfa256d4a1d0355c1d174ab373e3e2d0a3743a026cf9d9422e9dd95aedc7914db690b92bab6902f5221d62694a2fa5d065f534bb90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008638c3bf2616aa831d4c008347e7c08301482084578f7aa88d64616f2d686172642d666f726ba05b5acbf4bf305f948bd7be176047b20623e1417f75597341a059729165b9239788bede87201de42426")); // Session.DeliverMessage(packet); // if (Logger.IsTrace) Logger.Trace($"OUT {_counter:D5} hardcoded 1920000 BlockHeaders to {Node:c}"); // return; // } Keccak startingHash = getBlockHeadersMessage.StartingBlockHash; if (startingHash == null) { startingHash = SyncServer.FindHash(getBlockHeadersMessage.StartingBlockNumber); } BlockHeader[] headers = startingHash == null ? Array.Empty <BlockHeader>() : SyncServer.FindHeaders(startingHash, (int)getBlockHeadersMessage.MaxHeaders, (int)getBlockHeadersMessage.Skip, getBlockHeadersMessage.Reverse == 1); headers = FixHeadersForGeth(headers); Send(new BlockHeadersMessage(headers)); stopwatch.Stop(); if (Logger.IsTrace) { Logger.Trace($"OUT {Counter:D5} BlockHeaders to {Node:c} in {stopwatch.Elapsed.TotalMilliseconds}ms"); } }
async Task <BlockHeader[]> ISyncPeer.GetBlockHeaders(long number, int maxBlocks, int skip, CancellationToken token) { if (maxBlocks == 0) { return(new BlockHeader[0]); } var msg = new GetBlockHeadersMessage(); msg.MaxHeaders = maxBlocks; msg.Reverse = 0; msg.Skip = skip; msg.StartingBlockNumber = number; BlockHeader[] headers = await SendRequest(msg, token); return(headers); }
private async Task <BlockHeader[]> SendRequest(GetBlockHeadersMessage message, CancellationToken token) { if (Logger.IsTrace) { Logger.Trace("Sending headers request:"); Logger.Trace($"Starting blockhash: {message.StartingBlockHash}"); Logger.Trace($"Starting number: {message.StartingBlockNumber}"); Logger.Trace($"Skip: {message.Skip}"); Logger.Trace($"Reverse: {message.Reverse}"); Logger.Trace($"Max headers: {message.MaxHeaders}"); } var request = new Request <GetBlockHeadersMessage, BlockHeader[]>(message); _headersRequests.Add(request, token); var perfCalcId = _perfService.StartPerfCalc(); Send(request.Message); Task <BlockHeader[]> task = request.CompletionSource.Task; var firstTask = await Task.WhenAny(task, Task.Delay(Timeouts.Eth, token)); if (firstTask.IsCanceled) { token.ThrowIfCancellationRequested(); } if (firstTask == task) { var latency = _perfService.EndPerfCalc(perfCalcId); if (latency.HasValue) { P2PSession?.NodeStats.AddLatencyCaptureEvent(NodeLatencyStatType.BlockHeaders, latency.Value); } return(task.Result); } throw new TimeoutException($"{P2PSession.RemoteNodeId} Request timeout in {nameof(GetBlockHeadersMessage)}"); }
public virtual void HandleMessage(ZeroPacket message) { if (Logger.IsTrace) { Logger.Trace($"Handling {message} message from {Session.Node:c}."); } if (message.PacketType != Eth62MessageCode.Status && !_statusReceived) { throw new SubprotocolException($"No {nameof(StatusMessage)} received prior to communication with {Session.Node:c}."); } int size = message.Content.ReadableBytes; // Logger.Warn($"Received a message {message.Protocol}.{Enum.GetName(typeof(Eth62MessageCode), message.PacketType)} of size {size/1024}kb"); switch (message.PacketType) { case Eth62MessageCode.Status: StatusMessage statusMessage = Deserialize <StatusMessage>(message.Content); if (NetworkDiagTracer.IsEnabled) { NetworkDiagTracer.ReportIncomingMessage(Session.Node.Host, Name, statusMessage.ToString()); } Handle(statusMessage); break; case Eth62MessageCode.NewBlockHashes: if (NetworkDiagTracer.IsEnabled) { NetworkDiagTracer.ReportIncomingMessage(Session.Node.Host, Name, nameof(NewBlockHashesMessage)); } Interlocked.Increment(ref Counter); if (Logger.IsTrace) { Logger.Trace($"{Counter:D5} NewBlockHashes from {Node:c}"); } Metrics.Eth62NewBlockHashesReceived++; Handle(Deserialize <NewBlockHashesMessage>(message.Content)); break; case Eth62MessageCode.Transactions: Interlocked.Increment(ref Counter); Metrics.Eth62TransactionsReceived++; TransactionsMessage transactionsMessage = Deserialize <TransactionsMessage>(message.Content); if (NetworkDiagTracer.IsEnabled) { NetworkDiagTracer.ReportIncomingMessage(Session.Node.Host, Name, $"{nameof(TransactionsMessage)}({transactionsMessage.Transactions.Length})"); } if (!_isDowngradedDueToTxFlooding || 10 > _random.Next(0, 99)) // TODO: disable that when IsMining is set to true { Handle(transactionsMessage); } break; case Eth62MessageCode.GetBlockHeaders: Interlocked.Increment(ref Counter); if (Logger.IsTrace) { Logger.Trace($"{Counter:D5} GetBlockHeaders from {Node:c}"); } Metrics.Eth62GetBlockHeadersReceived++; GetBlockHeadersMessage getBlockHeadersMessage = Deserialize <GetBlockHeadersMessage>(message.Content); if (NetworkDiagTracer.IsEnabled) { NetworkDiagTracer.ReportIncomingMessage(Session.Node.Host, Name, $"{nameof(GetBlockHeadersMessage)}({getBlockHeadersMessage.StartingBlockNumber}|{getBlockHeadersMessage.StartingBlockHash}, {getBlockHeadersMessage.MaxHeaders})"); } Handle(getBlockHeadersMessage); break; case Eth62MessageCode.BlockHeaders: Interlocked.Increment(ref Counter); if (Logger.IsTrace) { Logger.Trace($"{Counter:D5} BlockHeaders from {Node:c}"); } Metrics.Eth62BlockHeadersReceived++; BlockHeadersMessage blockHeadersMessage = Deserialize <BlockHeadersMessage>(message.Content); if (NetworkDiagTracer.IsEnabled) { NetworkDiagTracer.ReportIncomingMessage(Session.Node.Host, Name, $"{nameof(BlockHeadersMessage)}({blockHeadersMessage.BlockHeaders.Length})"); } Handle(blockHeadersMessage, size); break; case Eth62MessageCode.GetBlockBodies: Interlocked.Increment(ref Counter); if (Logger.IsTrace) { Logger.Trace($"{Counter:D5} GetBlockBodies from {Node:c}"); } Metrics.Eth62GetBlockBodiesReceived++; GetBlockBodiesMessage getBlockBodiesMessage = Deserialize <GetBlockBodiesMessage>(message.Content); if (NetworkDiagTracer.IsEnabled) { NetworkDiagTracer.ReportIncomingMessage(Session.Node.Host, Name, $"{nameof(GetBlockBodiesMessage)}({getBlockBodiesMessage.BlockHashes.Count})"); } Handle(getBlockBodiesMessage); break; case Eth62MessageCode.BlockBodies: Interlocked.Increment(ref Counter); if (Logger.IsTrace) { Logger.Trace($"{Counter:D5} BlockBodies from {Node:c}"); } Metrics.Eth62BlockBodiesReceived++; BlockBodiesMessage blockBodiesMessage = Deserialize <BlockBodiesMessage>(message.Content); if (NetworkDiagTracer.IsEnabled) { NetworkDiagTracer.ReportIncomingMessage(Session.Node.Host, Name, $"{nameof(BlockBodiesMessage)}({blockBodiesMessage.Bodies.Length})"); } Handle(blockBodiesMessage, size); break; case Eth62MessageCode.NewBlock: Interlocked.Increment(ref Counter); if (Logger.IsTrace) { Logger.Trace($"{Counter:D5} NewBlock from {Node:c}"); } Metrics.Eth62NewBlockReceived++; NewBlockMessage newBlockMessage = Deserialize <NewBlockMessage>(message.Content); if (NetworkDiagTracer.IsEnabled) { NetworkDiagTracer.ReportIncomingMessage(Session.Node.Host, Name, $"{nameof(NewBlockMessage)}({newBlockMessage.Block.Number})"); } Handle(newBlockMessage); break; } }