Ejemplo n.º 1
0
        /// <summary>
        /// Creates a channel/client pair with the appropriate options and interceptors.
        /// </summary>
        /// <returns>A tuple of the channel and client</returns>
        private async Task <GrpcClient> CreateClientAsync(DnsEndPoint remoteEndpoint)
        {
            var certificate = await RetrieveServerCertificateAsync(remoteEndpoint);

            if (certificate == null)
            {
                return(null);
            }

            Logger.LogDebug($"Upgrading connection to TLS: {certificate}.");
            ChannelCredentials credentials = new SslCredentials(TlsHelper.ObjectToPem(certificate), _clientKeyCertificatePair);

            var channel = new Channel(remoteEndpoint.ToString(), credentials, new List <ChannelOption>
            {
                new ChannelOption(ChannelOptions.MaxSendMessageLength, GrpcConstants.DefaultMaxSendMessageLength),
                new ChannelOption(ChannelOptions.MaxReceiveMessageLength, GrpcConstants.DefaultMaxReceiveMessageLength),
                new ChannelOption(ChannelOptions.SslTargetNameOverride, GrpcConstants.DefaultTlsCommonName)
            });

            var nodePubkey = AsyncHelper.RunSync(() => _accountService.GetPublicKeyAsync()).ToHex();

            var interceptedChannel = channel.Intercept(metadata =>
            {
                metadata.Add(GrpcConstants.PubkeyMetadataKey, nodePubkey);
                return(metadata);
            }).Intercept(new RetryInterceptor());

            var client = new PeerService.PeerServiceClient(interceptedChannel);

            return(new GrpcClient(channel, client, certificate));
        }
Ejemplo n.º 2
0
        public GrpcPeer(GrpcClient client, DnsEndPoint remoteEndpoint, PeerConnectionInfo peerConnectionInfo)
        {
            _channel = client.Channel;
            _client  = client.Client;

            RemoteEndpoint = remoteEndpoint;
            Info           = peerConnectionInfo;

            _knownTransactionCache = new BoundedExpirationCache(TransactionCacheMaxItems, QueuedItemTimeout);
            _knownBlockCache       = new BoundedExpirationCache(BlockCacheMaxItems, QueuedItemTimeout);

            _recentRequestsRoundtripTimes = new ConcurrentDictionary <string, ConcurrentQueue <RequestMetric> >();
            RecentRequestsRoundtripTimes  =
                new ReadOnlyDictionary <string, ConcurrentQueue <RequestMetric> >(_recentRequestsRoundtripTimes);

            _recentRequestsRoundtripTimes.TryAdd(nameof(MetricNames.Announce), new ConcurrentQueue <RequestMetric>());
            _recentRequestsRoundtripTimes.TryAdd(nameof(MetricNames.GetBlock), new ConcurrentQueue <RequestMetric>());
            _recentRequestsRoundtripTimes.TryAdd(nameof(MetricNames.GetBlocks), new ConcurrentQueue <RequestMetric>());

            _sendAnnouncementJobs = new ActionBlock <StreamJob>(SendStreamJobAsync,
                                                                new ExecutionDataflowBlockOptions
            {
                BoundedCapacity = NetworkConstants.DefaultMaxBufferedAnnouncementCount
            });
            _sendBlockJobs = new ActionBlock <StreamJob>(SendStreamJobAsync,
                                                         new ExecutionDataflowBlockOptions
            {
                BoundedCapacity = NetworkConstants.DefaultMaxBufferedBlockCount
            });
            _sendTransactionJobs = new ActionBlock <StreamJob>(SendStreamJobAsync,
                                                               new ExecutionDataflowBlockOptions
            {
                BoundedCapacity = NetworkConstants.DefaultMaxBufferedTransactionCount
            });
        }
Ejemplo n.º 3
0
        public static GrpcPeer CreateNewPeer(string ipAddress = "127.0.0.1:2000", bool isValid = true, string publicKey = null)
        {
            var pubkey  = publicKey ?? NetworkTestConstants.FakePubkey;
            var channel = new Channel(ipAddress, ChannelCredentials.Insecure);

            PeerService.PeerServiceClient client;

            if (isValid)
            {
                client = new PeerService.PeerServiceClient(channel.Intercept(metadata =>
                {
                    metadata.Add(GrpcConstants.PubkeyMetadataKey, pubkey);
                    return(metadata);
                }));
            }
            else
            {
                client = new PeerService.PeerServiceClient(channel);
            }

            var connectionInfo = new PeerConnectionInfo
            {
                Pubkey          = pubkey,
                ProtocolVersion = KernelConstants.ProtocolVersion,
                ConnectionTime  = TimestampHelper.GetUtcNow(),
                SessionId       = new byte[] { 0, 1, 2 },
                IsInbound       = true
            };

            var peer = new GrpcPeer(new GrpcClient(channel, client), IpEndPointHelper.Parse(ipAddress), connectionInfo);

            peer.InboundSessionId = new byte[] { 0, 1, 2 };

            return(peer);
        }
Ejemplo n.º 4
0
        public static GrpcPeer CreatePeerWithClient(string ip, string pubkey, PeerService.PeerServiceClient client)
        {
            var peer = new GrpcPeer(new GrpcClient(CreateMockChannel(), client), IpEndPointHelper.Parse(ip), new PeerConnectionInfo {
                Pubkey = pubkey, SessionId = new byte[] { 0, 1, 2 }
            });

            peer.InboundSessionId = new byte[] { 0, 1, 2 };
            return(peer);
        }
Ejemplo n.º 5
0
        public async Task RemovePeerByAddress()
        {
            var channel = new Channel(TestIp, ChannelCredentials.Insecure);
            var client  = new PeerService.PeerServiceClient(channel);

            _pool.AddPeer(new GrpcPeer(channel, client, _testPubKey, TestIp));
            _pool.FindPeerByAddress(TestIp).ShouldNotBeNull();

            await _pool.RemovePeerByAddressAsync(TestIp);

            _pool.FindPeerByAddress(TestIp).ShouldBeNull();
        }
Ejemplo n.º 6
0
        public GrpcPeer(Channel channel, PeerService.PeerServiceClient client, string pubKey, string peerIpAddress)
        {
            _channel = channel;
            _client  = client;

            PeerIpAddress = peerIpAddress;

            PubKey = pubKey;

            _recentBlockHeightAndHashMappings = new ConcurrentDictionary <long, Hash>();
            RecentBlockHeightAndHashMappings  = new ReadOnlyDictionary <long, Hash>(_recentBlockHeightAndHashMappings);
        }
Ejemplo n.º 7
0
        private async Task <TResp> RequestAsync <TResp>(PeerService.PeerServiceClient client,
                                                        Func <PeerService.PeerServiceClient, AsyncUnaryCall <TResp> > func, string errorMessage)
        {
            try
            {
                return(await func(client));
            }
            catch (RpcException e)
            {
                HandleFailure(e, errorMessage);
            }

            return(default(TResp));
        }
Ejemplo n.º 8
0
        private GrpcPeer CreateNewPeer()
        {
            var pubkey         = "048f5ced21f8d687cb9ade1c22dc0e183b05f87124c82073f5d82a09b139cc466efbfb6f28494d0a9d7366fcb769fe5436cfb7b5d322a2b0f69c4bcb1c33ac24ad";
            var ipAddress      = "127.0.0.1:888";
            var remoteEndpoint = IpEndPointHelper.Parse(ipAddress);
            var channel        = new Channel(ipAddress, ChannelCredentials.Insecure);
            var client         = new PeerService.PeerServiceClient(channel);

            var connectionInfo = new PeerConnectionInfo
            {
                Pubkey          = pubkey,
                ProtocolVersion = KernelConstants.ProtocolVersion,
                ConnectionTime  = TimestampHelper.GetUtcNow(),
                IsInbound       = true
            };

            return(new GrpcPeer(new GrpcClient(channel, client), remoteEndpoint, connectionInfo));
        }
Ejemplo n.º 9
0
        public GrpcPeer(GrpcClient client, IPEndPoint remoteEndpoint, PeerInfo peerInfo)
        {
            _channel = client.Channel;
            _client  = client.Client;

            RemoteEndpoint = remoteEndpoint;
            Info           = peerInfo;

            _recentBlockHeightAndHashMappings = new ConcurrentDictionary <long, Hash>();
            RecentBlockHeightAndHashMappings  = new ReadOnlyDictionary <long, Hash>(_recentBlockHeightAndHashMappings);

            _recentRequestsRoundtripTimes = new ConcurrentDictionary <string, ConcurrentQueue <RequestMetric> >();
            RecentRequestsRoundtripTimes  =
                new ReadOnlyDictionary <string, ConcurrentQueue <RequestMetric> >(_recentRequestsRoundtripTimes);

            _recentRequestsRoundtripTimes.TryAdd(nameof(MetricNames.Announce), new ConcurrentQueue <RequestMetric>());
            _recentRequestsRoundtripTimes.TryAdd(nameof(MetricNames.GetBlock), new ConcurrentQueue <RequestMetric>());
            _recentRequestsRoundtripTimes.TryAdd(nameof(MetricNames.GetBlocks), new ConcurrentQueue <RequestMetric>());
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Creates a channel/client pair with the appropriate options and interceptors.
        /// </summary>
        /// <returns>A tuple of the channel and client</returns>
        public GrpcClient CreateClient(IPEndPoint endpoint)
        {
            var channel = new Channel(endpoint.ToString(), ChannelCredentials.Insecure, new List <ChannelOption>
            {
                new ChannelOption(ChannelOptions.MaxSendMessageLength, GrpcConstants.DefaultMaxSendMessageLength),
                new ChannelOption(ChannelOptions.MaxReceiveMessageLength, GrpcConstants.DefaultMaxReceiveMessageLength)
            });

            var nodePubkey = AsyncHelper.RunSync(() => _accountService.GetPublicKeyAsync()).ToHex();

            var interceptedChannel = channel.Intercept(metadata =>
            {
                metadata.Add(GrpcConstants.PubkeyMetadataKey, nodePubkey);
                return(metadata);
            }).Intercept(new RetryInterceptor());

            var client = new PeerService.PeerServiceClient(interceptedChannel);

            return(new GrpcClient(channel, client));
        }
Ejemplo n.º 11
0
        // todo consider removing client from the lambda as it is not used. It can be capture by the func.
        private async Task <TResp> RequestAsync <TResp>(PeerService.PeerServiceClient client,
                                                        Func <PeerService.PeerServiceClient, AsyncUnaryCall <TResp> > func, GrpcRequest requestParams)
        {
            var  metricsName      = requestParams.MetricName;
            bool timeRequest      = !string.IsNullOrEmpty(metricsName);
            var  requestStartTime = TimestampHelper.GetUtcNow();

            Stopwatch requestTimer = null;

            if (timeRequest)
            {
                requestTimer = Stopwatch.StartNew();
            }

            try
            {
                var response = await func(client);

                if (timeRequest)
                {
                    requestTimer.Stop();
                    RecordMetric(requestParams, requestStartTime, requestTimer.ElapsedMilliseconds);
                }

                return(response);
            }
            catch (AggregateException e)
            {
                HandleFailure(e.Flatten(), requestParams.ErrorMessage);
            }
            finally
            {
                if (timeRequest)
                {
                    requestTimer.Stop();
                    RecordMetric(requestParams, requestStartTime, requestTimer.ElapsedMilliseconds);
                }
            }

            return(default(TResp));
        }
Ejemplo n.º 12
0
        private GrpcPeer CreateNewPeer(string ipAddress = "127.0.0.1:2000", bool isValid = true)
        {
            var channel   = new Channel(ipAddress, ChannelCredentials.Insecure);
            var publicKey = AsyncHelper.RunSync(() => _acc.GetPublicKeyAsync()).ToHex();

            PeerService.PeerServiceClient client = null;
            if (isValid)
            {
                client = new PeerService.PeerServiceClient(channel.Intercept(metadata =>
                {
                    metadata.Add(GrpcConsts.PubkeyMetadataKey, publicKey);
                    return(metadata);
                }));
            }
            else
            {
                client = new PeerService.PeerServiceClient(channel);
            }

            return(new GrpcPeer(channel, client, publicKey, ipAddress));
        }
Ejemplo n.º 13
0
        public async Task Calling_DisposedPeer_ThrowsUnrecoverableNEtException()
        {
            await _networkServer.StartAsync();

            Channel channel = new Channel("localhost", 2001, ChannelCredentials.Insecure);

            PeerService.PeerServiceClient peerClient = new PeerService.PeerServiceClient(channel);

            GrpcClient grpcClient = new GrpcClient(channel, peerClient);

            AElfPeerEndpointHelper.TryParse("127.0.0.1:2001", out var endpoint);

            GrpcPeer peer = new GrpcPeer(grpcClient, endpoint, new PeerConnectionInfo
            {
                SessionId = new byte[] { 1, 2, 3 }
            });

            await peer.DisconnectAsync(false);

            var exHealthCheck = await Assert.ThrowsAsync <NetworkException>(async() => await peer.CheckHealthAsync());

            exHealthCheck.ExceptionType.ShouldBe(NetworkExceptionType.Unrecoverable);

            var exGetBlocks = await Assert.ThrowsAsync <NetworkException>(
                async() => await peer.GetBlocksAsync(Hash.FromString("blockHash"), 10));

            exGetBlocks.ExceptionType.ShouldBe(NetworkExceptionType.Unrecoverable);

            var exGetBlock = await Assert.ThrowsAsync <NetworkException>(
                async() => await peer.GetBlockByHashAsync(Hash.FromString("blockHash")));

            exGetBlock.ExceptionType.ShouldBe(NetworkExceptionType.Unrecoverable);

            var exGetNodes = await Assert.ThrowsAsync <NetworkException>(
                async() => await peer.GetNodesAsync());

            exGetNodes.ExceptionType.ShouldBe(NetworkExceptionType.Unrecoverable);

            await _networkServer.StopAsync();
        }
Ejemplo n.º 14
0
 public GrpcClient(Channel channel, PeerService.PeerServiceClient client)
 {
     Channel = channel;
     Client  = client;
 }
Ejemplo n.º 15
0
 public static GrpcPeer CreatePeerWithClient(string ip, string pubkey, PeerService.PeerServiceClient client)
 {
     return(new GrpcPeer(new GrpcClient(CreateMockChannel(), client), IpEndpointHelper.Parse(ip), new PeerInfo {
         Pubkey = pubkey
     }));
 }
Ejemplo n.º 16
0
 public GrpcClient(Channel channel, PeerService.PeerServiceClient client, X509Certificate certificate = null)
 {
     Channel     = channel;
     Client      = client;
     Certificate = certificate;
 }
Ejemplo n.º 17
0
        /// <summary>
        /// First step of the connect/auth process. Used to initiate a connection. The provided payload should be the
        /// clients authentication information. When receiving this call, protocol dictates you send the client your auth
        /// information. The response says whether or not you can connect.
        /// </summary>
        public override async Task <ConnectReply> Connect(Handshake handshake, ServerCallContext context)
        {
            Logger.LogTrace($"{context.Peer} has initiated a connection request.");

            if (handshake?.HskData == null)
            {
                return new ConnectReply {
                           Err = AuthError.InvalidHandshake
                }
            }
            ;

            // verify chain id
            if (handshake.HskData.ChainId != _blockChainService.GetChainId())
            {
                return new ConnectReply {
                           Err = AuthError.ChainMismatch
                }
            }
            ;

            // verify protocol
            if (handshake.HskData.Version != KernelConstants.ProtocolVersion)
            {
                return new ConnectReply {
                           Err = AuthError.ProtocolMismatch
                }
            }
            ;

            // verify signature
            var validData = await _accountService.VerifySignatureAsync(handshake.Sig.ToByteArray(),
                                                                       Hash.FromMessage(handshake.HskData).ToByteArray(), handshake.HskData.PublicKey.ToByteArray());

            if (!validData)
            {
                return new ConnectReply {
                           Err = AuthError.WrongSig
                }
            }
            ;

            var peer = GrpcUrl.Parse(context.Peer);

            if (peer == null)
            {
                return new ConnectReply {
                           Err = AuthError.InvalidPeer
                }
            }
            ;

            var peerAddress = peer.IpAddress + ":" + handshake.HskData.ListeningPort;

            Logger.LogDebug($"Attempting to create channel to {peerAddress}");

            Channel channel = new Channel(peerAddress, ChannelCredentials.Insecure);
            var     client  = new PeerService.PeerServiceClient(channel.Intercept(metadata =>
            {
                metadata.Add(GrpcConsts.PubkeyMetadataKey, AsyncHelper.RunSync(() => _accountService.GetPublicKeyAsync()).ToHex());
                return(metadata);
            }));

            if (channel.State != ChannelState.Ready)
            {
                var c = channel.WaitForStateChangedAsync(channel.State);
            }

            var pubKey   = handshake.HskData.PublicKey.ToHex();
            var grpcPeer = new GrpcPeer(channel, client, pubKey, peerAddress);

            // Verify auth
            bool valid = _peerPool.IsAuthenticatePeer(pubKey);

            if (!valid)
            {
                await channel.ShutdownAsync();

                Logger.LogDebug($"Failed to reach {grpcPeer}");
                return(new ConnectReply {
                    Err = AuthError.WrongAuth
                });
            }

            // send our credentials
            var hsk = await _peerPool.GetHandshakeAsync();

            // If auth ok -> add it to our peers
            _peerPool.AddPeer(grpcPeer);

            return(new ConnectReply {
                Handshake = hsk
            });
        }
Ejemplo n.º 18
0
        public RemotePeer(string host, int port)
        {
            var peerConnection = new grpc.Channel(host, port, grpc.ChannelCredentials.Insecure);

            client = new PeerService.PeerServiceClient(peerConnection);
        }
Ejemplo n.º 19
0
        private async Task <bool> DialAsync(string ipAddress)
        {
            Logger.LogTrace($"Attempting to reach {ipAddress}.");

            Channel channel = new Channel(ipAddress, ChannelCredentials.Insecure);

            var client = new PeerService.PeerServiceClient(channel.Intercept(metadata =>
            {
                metadata.Add(GrpcConsts.PubkeyMetadataKey, AsyncHelper.RunSync(() => _accountService.GetPublicKeyAsync()).ToHex());
                return(metadata);
            }));

            var hsk = await BuildHandshakeAsync();

            if (channel.State == ChannelState.TransientFailure)
            {
                // if failing give it some time to recover
                await channel.TryWaitForStateChangedAsync(channel.State,
                                                          DateTime.UtcNow.AddSeconds(_networkOptions.PeerDialTimeout));
            }

            ConnectReply connectReply;

            try
            {
                connectReply = await client.ConnectAsync(hsk,
                                                         new CallOptions().WithDeadline(DateTime.UtcNow.AddSeconds(_networkOptions.PeerDialTimeout)));
            }
            catch (RpcException e)
            {
                await channel.ShutdownAsync();

                Logger.LogError(e, $"Could not connect to {ipAddress}.");
                return(false);
            }

            // todo refactor so that connect returns the handshake and we'll check here
            // todo if not correct we kill the channel.
            if (connectReply?.Handshake?.HskData == null || connectReply.Err != AuthError.None)
            {
                Logger.LogWarning($"Incorrect handshake for {ipAddress}, {connectReply?.Err}.");
                await channel.ShutdownAsync();

                return(false);
            }

            var pubKey = connectReply.Handshake.HskData.PublicKey.ToHex();
            var peer   = new GrpcPeer(channel, client, pubKey, ipAddress);

            if (!_authenticatedPeers.TryAdd(pubKey, peer))
            {
                Logger.LogWarning($"Peer {pubKey} is already in list.");
                await channel.ShutdownAsync();

                return(false);
            }

            peer.DisconnectionEvent += PeerOnDisconnectionEvent;

            Logger.LogTrace($"Connected to {peer}.");

            return(true);
        }
Ejemplo n.º 20
0
 private GrpcPeer CreatePeer(PeerService.PeerServiceClient client)
 {
     return(GrpcTestPeerHelper.CreatePeerWithClient("127.0.0.1:2000", NetworkTestConstants.FakePubkey, client));
 }