void InvalidSendToInfluxShouldNotPass()
        {
            string nodeId = "4816d758dd37833a3a5551001dac8a5fa737a342";

            PayloadSigner signer = new PayloadSigner(nodeId, new FileKeyStore("./"));

            signer.Init();

            RealTimeTelemetryManager mgr = new RealTimeTelemetryManager(
                nodeId,
                "http://127.0.0.1",
                "ws://127.0.0.1",
                "https://localhost:5010/api/ingress/realtime",
                "ED:40:5C:C9:E2:71:44:11:78:47:1C:09:6F:28:2E:B5:F9:4D:6E:CE:90:BC:64:5B:ED:9A:46:1F:20:E2:EE:4E",
                signer,
                _ftpMgr,
                true);

            RealTimeTelemetryPayload rttp = new RealTimeTelemetryPayload
            {
                Client        = "Parity",
                BlockNum      = 0,
                BlockHash     = "",
                BlockTS       = 0,
                BlockReceived = 0,
                NumPeers      = 0,
                NumTxInBlock  = 0
            };

            RealTimeTelemetry rtt = new RealTimeTelemetry
            {
                NodeId    = "",
                Payload   = rttp,
                Signature = signer.SignPayload(JsonConvert.SerializeObject(rttp))
            };

            var currentConsoleOut = Console.Out;

            using (var cop = new ConsoleOutputCapturer())
            {
                MethodInfo methodInfo = typeof(RealTimeTelemetryManager).GetMethod("SendDataToIngress", BindingFlags.NonPublic | BindingFlags.Instance);
                object[]   parameters = { rtt };
                methodInfo.Invoke(mgr, parameters);

                string ret = cop.GetOuput();
                Assert.Contains("Connection refused", ret);
                //Assert.True(ret.Contains("ERROR Occurred While sending data to Ingress"));
            }
        }
        /// <summary>
        /// Function for sending data to ingress restful end point
        /// </summary>
        /// <param name="rtt">Reference of RealTimeTelemetry instance</param>
        private void SendDataToIngress(RealTimeTelemetry rtt)
        {
            try
            {
                //random pause of 55ms so we dnt have spike on ingress
                Thread.Sleep(new Random().Next(1, 500));

                //push data to ingress real time telemetry endpoint
                string jsonPayload = JsonConvert.SerializeObject(rtt);

                bool sendSuccess = _tti.SendRequest(jsonPayload).Result;

                if (!sendSuccess)
                {
                    // unable to send real time telemetry to ingress - send by second channel
                    Console.WriteLine("ERROR: Unable to send to real time telemetry ingress. Sending data on second channel.");

                    string fileName = $"{_nodeId}-{DateTime.UtcNow:yyyy-MM-dd_HH-mm-ss}.json";
                    try
                    {
                        if (!_ftpMgr.TransferData(jsonPayload, fileName))
                        {
                            Console.WriteLine("ERROR: Unable to send real time telemetry on second channel. Data File {0}", fileName);
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("ERROR: Unable to send real time telemetry on second channel. Error Details {0}", ex);
                    }
                }
                else
                {
                    Console.WriteLine("Real Time Telemetry Block data sent to Ingress Block # {0}", rtt.Payload.BlockNum);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR Occurred While sending data to Ingress. {0}", ex);
            }
        }
        /// <summary>
        /// Receive method for web socket connection, It receivesreal time block data from parity and sends that to Ingress restful end point
        /// </summary>
        /// <param name="webSocket">ClientWebSocket instance reference</param>
        private async Task Receive(ClientWebSocket webSocket)
        {
            int bufferSize = 4096;

            byte[] temporaryBuffer = new byte[bufferSize];
            byte[] buffer          = new byte[bufferSize * 20];
            int    offset          = 0;

            while (true)
            {
                WebSocketReceiveResult response = await webSocket.ReceiveAsync(
                    new ArraySegment <byte>(temporaryBuffer),
                    CancellationToken.None);

                temporaryBuffer.CopyTo(buffer, offset);
                offset         += response.Count;
                temporaryBuffer = new byte[bufferSize];

                if (response.EndOfMessage)
                {
                    RealTimeTelemetry rtt = ParseAndSignData(buffer);
                    if (rtt != null)
                    {
                        SendDataToIngress(rtt);
                    }

                    Array.Clear(temporaryBuffer, 0, temporaryBuffer.Length);
                    Array.Clear(buffer, 0, buffer.Length);
                    offset = 0;
                }
                if (response.MessageType == WebSocketMessageType.Close)
                {
                    await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);

                    break;
                }
            }
        }
Ejemplo n.º 4
0
        public ActionResult PostRealTimeTelemetry([FromBody] RealTimeTelemetry realTimePackage)
        {
            // verify incoming data
            if (realTimePackage?.NodeId == null ||
                string.IsNullOrWhiteSpace(realTimePackage.Signature) ||
                realTimePackage.Payload == null ||
                string.IsNullOrWhiteSpace(realTimePackage.Payload.Client) ||
                string.IsNullOrWhiteSpace(realTimePackage.Payload.BlockHash)
                )
            {
                Console.WriteLine("Bad Request: " + JsonConvert.SerializeObject(realTimePackage, Formatting.Indented));
                return(BadRequest());
            }

            // Get Node key from keystore
            string nodeKey;

            try
            {
                nodeKey = _keyStore.GetKeyForNode(realTimePackage.NodeId);
            }
            catch (KeyNotFoundException)
            {
                Console.WriteLine($"Node Unknown: {realTimePackage.NodeId}");
                return(StatusCode(403));
            }

            // Verify Signature
            string payload        = JsonConvert.SerializeObject(realTimePackage.Payload);
            bool   signatureValid = SignatureVerifier.IsSignatureValid(payload, realTimePackage.Signature, nodeKey);

            if (!signatureValid)
            {
                Console.WriteLine($"Bad signature from node: {realTimePackage.NodeId}");
                return(StatusCode(403));
            }


            //Point format |measurement|,tag_set| |field_set| |timestamp|

            //create a point from incoming JSON
            Console.WriteLine($"Accepted RT telemetry from {realTimePackage.NodeId} ");
            long   nanotimestamp = (long)(realTimePackage.Payload.BlockReceived * 1e9);
            string influxPoint   = string.Format("parity,nodeid={0},client={1} blocknum={2},numpeers={3},blockts={4},numtxinblock={5},propagationtime={6},gaslimit={8},gasused={9} {7}",
                                                 realTimePackage.NodeId,
                                                 realTimePackage.Payload.Client,
                                                 realTimePackage.Payload.BlockNum,
                                                 realTimePackage.Payload.NumPeers,
                                                 realTimePackage.Payload.BlockTS,
                                                 realTimePackage.Payload.NumTxInBlock,
                                                 (realTimePackage.Payload.BlockReceived - realTimePackage.Payload.BlockTS),
                                                 nanotimestamp,
                                                 realTimePackage.Payload.GasLimit,
                                                 realTimePackage.Payload.GasUsed);

            // Signature valid - record to db
            if (_influx.Enqueue(influxPoint, true))
            {
                return(Accepted());
            }
            else
            {
                return(StatusCode(400));
            }
        }
        /// <summary>
        /// Function for parsing and signing block data
        /// </summary>
        /// <param name="buffer">block data in byte array</param>
        /// <returns>returns instance of RealTimeTelemetry if valid data is provided else null</returns>
        private RealTimeTelemetry ParseAndSignData(byte[] buffer)
        {
            try
            {
                string numPeers      = GetCurrentNumPeers();
                string clientVersion = GetCurrentClientVersion();

                dynamic jsonObj   = JsonConvert.DeserializeObject(_encoder.GetString(buffer).Trim());
                dynamic paramsObj = jsonObj["params"];
                if (paramsObj != null && paramsObj["result"] != null)
                {
                    dynamic resultObj = paramsObj["result"];

                    string gasLimit = resultObj["gasLimit"];
                    string gasUsed  = resultObj["gasUsed"];

                    long currentEPoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;

                    RealTimeTelemetryPayload rttp = new RealTimeTelemetryPayload
                    {
                        Client        = clientVersion,
                        BlockNum      = Convert.ToUInt64(resultObj["number"].ToString(), 16),
                        BlockHash     = resultObj["hash"].ToString(),
                        BlockTS       = Convert.ToInt64(resultObj["timestamp"].ToString(), 16),
                        BlockReceived = currentEPoch,
                        NumPeers      = Convert.ToUInt16(numPeers, 16),
                        NumTxInBlock  = (ushort)resultObj["transactions"].Count,
                        GasLimit      = Convert.ToInt64(gasLimit, 16),
                        GasUsed       = Convert.ToInt64(gasUsed, 16)
                    };

                    RealTimeTelemetry rtt = new RealTimeTelemetry
                    {
                        NodeId    = _nodeId,
                        Payload   = rttp,
                        Signature = _signer.SignPayload(JsonConvert.SerializeObject(rttp))
                    };

                    if (_verbose)
                    {
                        Console.WriteLine("New Block received");
                        Console.WriteLine("block num: {0}", rttp.BlockNum);
                        Console.WriteLine("block hash: {0}", rttp.BlockHash);
                        Console.WriteLine("block time stamp: {0}", rttp.BlockTS);
                        Console.WriteLine("Tx Count: {0}", rttp.NumTxInBlock);
                        Console.WriteLine("Gas Limit: {0}", Convert.ToInt64(gasLimit, 16));
                        Console.WriteLine("Gas Used: {0}", Convert.ToInt64(gasUsed, 16));
                        Console.WriteLine("Peers: {0} ", rttp.NumPeers);
                    }

                    return(rtt);
                }

                Console.WriteLine("Unable to Parse\\Sign real Time data. Invalid Data");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Unable to Parse\\Sign real Time data. Error Occurred {0}", ex);
            }
            return(null);
        }