protected override async Task ProcessItemAsync(RpcMessage <BeaconBlocksByRange> rpcMessage) { try { if (rpcMessage.Direction == RpcDirection.Request) { if (_logger.IsDebug()) { LogDebug.ProcessBeaconBlocksByRange(_logger, rpcMessage.Content, null); } // TODO: Add some sanity checks on request to prevent DoS // TODO: Maybe add limit on number of blocks (as allowed by spec) Slot slot = new Slot(rpcMessage.Content.StartSlot + rpcMessage.Content.Step * (rpcMessage.Content.Count - 1)); Stack <(Root root, SignedBeaconBlock signedBlock)> signedBlocks = new Stack <(Root, SignedBeaconBlock)>(); // Search backwards from head for the requested slots Root root = rpcMessage.Content.HeadBlockRoot; while (slot >= rpcMessage.Content.StartSlot) { root = await _forkChoice.GetAncestorAsync(_store, root, slot); SignedBeaconBlock signedBlock = await _store.GetSignedBlockAsync(root); if (signedBlock.Message.Slot == slot) { signedBlocks.Push((root, signedBlock)); } else { // block is skipped if (_logger.IsWarn()) { Log.RequestedBlockSkippedSlot(_logger, slot, rpcMessage.Content.HeadBlockRoot, null); } } // If they requested for slot 0, then include it (anchor block is usually null), but don't underflow if (slot == Slot.Zero) { break; } slot = slot - Slot.One; } // Send each block in a response chunk, in slot order foreach (var data in signedBlocks) { if (_logger.IsDebug()) { LogDebug.SendingRequestBlocksByRangeResponse(_logger, data.signedBlock.Message, data.root, null); } await _networkPeering.SendBlockAsync(rpcMessage.PeerId, data.signedBlock); } } else { throw new Exception($"Unexpected direction {rpcMessage.Direction}"); } } catch (Exception ex) { if (_logger.IsError()) { Log.HandleRpcStatusError(_logger, rpcMessage.PeerId, ex.Message, ex); } } }
private void OnRpcReceived(ReadOnlySpan <byte> methodUtf8, int requestResponseFlag, ReadOnlySpan <byte> peerUtf8, ReadOnlySpan <byte> data) { Activity activity = new Activity("rpc-received"); activity.Start(); try { string peerId = Encoding.UTF8.GetString(peerUtf8); RpcDirection rpcDirection = requestResponseFlag == 0 ? RpcDirection.Request : RpcDirection.Response; // Even though the value '/eth2/beacon_chain/req/status/1/' is sent, when Mothra calls the received event it is 'HELLO' // if (methodUtf8.SequenceEqual(MethodUtf8.Status) // || methodUtf8.SequenceEqual(MethodUtf8.StatusMothraAlternative)) if (data.Length == Ssz.Ssz.PeeringStatusLength) { if (_logger.IsDebug()) { LogDebug.RpcReceived(_logger, rpcDirection, requestResponseFlag, Encoding.UTF8.GetString(methodUtf8), peerId, data.Length, nameof(MethodUtf8.Status), null); } PeeringStatus peeringStatus = Ssz.Ssz.DecodePeeringStatus(data); RpcMessage <PeeringStatus> statusRpcMessage = new RpcMessage <PeeringStatus>(peerId, rpcDirection, peeringStatus); _rpcPeeringStatusProcessor.Enqueue(statusRpcMessage); } //else if (methodUtf8.SequenceEqual(MethodUtf8.BeaconBlocksByRange)) else if (data.Length == Ssz.Ssz.BeaconBlocksByRangeLength || data.Length >= _minimumSignedBeaconBlockLength) { if (_logger.IsDebug()) { LogDebug.RpcReceived(_logger, rpcDirection, requestResponseFlag, Encoding.UTF8.GetString(methodUtf8), peerId, data.Length, nameof(MethodUtf8.BeaconBlocksByRange), null); } //if (rpcDirection == RpcDirection.Request) if (data.Length == Ssz.Ssz.BeaconBlocksByRangeLength) { BeaconBlocksByRange beaconBlocksByRange = Ssz.Ssz.DecodeBeaconBlocksByRange(data); RpcMessage <BeaconBlocksByRange> rpcMessage = new RpcMessage <BeaconBlocksByRange>(peerId, rpcDirection, beaconBlocksByRange); _rpcBeaconBlocksByRangeProcessor.Enqueue(rpcMessage); } else { SignedBeaconBlock signedBeaconBlock = Ssz.Ssz.DecodeSignedBeaconBlock(data); _signedBeaconBlockProcessor.Enqueue(signedBeaconBlock, peerId); } } else { // TODO: handle other RPC if (_logger.IsWarn()) { Log.UnknownRpcReceived(_logger, rpcDirection, requestResponseFlag, Encoding.UTF8.GetString(methodUtf8), peerId, data.Length, null); } } } catch (Exception ex) { if (_logger.IsError()) { Log.RpcReceivedError(_logger, Encoding.UTF8.GetString(methodUtf8), ex.Message, ex); } } finally { activity.Stop(); } }
public void Enqueue(RpcMessage <BeaconBlocksByRange> rpcMessage) { EnqueueItem(rpcMessage); }
public void Enqueue(RpcMessage <PeeringStatus> statusRpcMessage) { EnqueueItem(statusRpcMessage); }