Example #1
0
        public override Task <TResponse> UnaryServerHandler <TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod <TRequest, TResponse> continuation)
        {
            try
            {
                if (context.Method != GetFullMethodName(nameof(PeerService.PeerServiceBase.DoHandshake)))
                {
                    // a method other than DoHandshake is being called

                    var peer = _peerPool.FindPeerByPublicKey(context.GetPublicKey());

                    if (peer == null && context.Method != GetFullMethodName(nameof(PeerService.PeerServiceBase.Ping)))
                    {
                        Logger.LogWarning($"Could not find peer {context.GetPublicKey()}");
                        return(Task.FromResult <TResponse>(null));
                    }

                    // check that the peers session is equal to one announced in the headers
                    if (peer != null && !peer.InboundSessionId.BytesEqual(context.GetSessionId()))
                    {
                        Logger.LogWarning($"Wrong session id, ({peer.InboundSessionId.ToHex()} vs {context.GetSessionId().ToHex()}) {context.GetPublicKey()}");
                        return(Task.FromResult <TResponse>(null));
                    }

                    context.RequestHeaders.Add(new Metadata.Entry(GrpcConstants.PeerInfoMetadataKey, $"{peer}"));
                }
            }
            catch (Exception e)
            {
                Logger.LogError(e, "Auth interceptor error: ");
                throw;
            }

            return(continuation(request, context));
        }
Example #2
0
        public override Task <TResponse> ClientStreamingServerHandler <TRequest, TResponse>(IAsyncStreamReader <TRequest> requestStream, ServerCallContext context,
                                                                                            ClientStreamingServerMethod <TRequest, TResponse> continuation)
        {
            try
            {
                var peer = _peerPool.FindPeerByPublicKey(context.GetPublicKey());

                if (peer == null)
                {
                    Logger.LogWarning($"Could not find peer {context.GetPublicKey()}");
                    return(Task.FromResult <TResponse>(null));
                }

                if (!peer.InboundSessionId.BytesEqual(context.GetSessionId()))
                {
                    Logger.LogWarning($"Wrong session id, ({peer.InboundSessionId.ToHex()} vs {context.GetSessionId().ToHex()}) {context.GetPublicKey()}");
                    return(Task.FromResult <TResponse>(null));
                }

                context.RequestHeaders.Add(new Metadata.Entry(GrpcConstants.PeerInfoMetadataKey, $"{peer}"));
            }
            catch (Exception e)
            {
                Logger.LogError(e, "Auth stream interceptor error: ");
                return(null);
            }

            return(continuation(requestStream, context));
        }
Example #3
0
        public override Task <TResponse> ClientStreamingServerHandler <TRequest, TResponse>(IAsyncStreamReader <TRequest> requestStream, ServerCallContext context,
                                                                                            ClientStreamingServerMethod <TRequest, TResponse> continuation)
        {
            var peer = _peerPool.FindPeerByPublicKey(context.GetPublicKey());

            if (peer == null)
            {
                Logger.LogWarning($"Could not find peer {context.GetPublicKey()}");
                return(Task.FromResult <TResponse>(null));
            }

            context.RequestHeaders.Add(new Metadata.Entry(GrpcConstants.PeerInfoMetadataKey, $"{peer}"));

            return(continuation(requestStream, context));
        }
Example #4
0
        public override Task <TResponse> UnaryServerHandler <TRequest, TResponse>(TRequest request,
                                                                                  ServerCallContext context, UnaryServerMethod <TRequest, TResponse> continuation)
        {
            try
            {
                if (IsNeedAuth(context.Method))
                {
                    var peer = _peerPool.FindPeerByPublicKey(context.GetPublicKey());

                    if (peer == null)
                    {
                        Logger.LogWarning($"Could not find peer {context.GetPublicKey()}");
                        return(Task.FromResult <TResponse>(null));
                    }

                    // check that the peers session is equal to one announced in the headers
                    var sessionId = context.GetSessionId();

                    if (!peer.InboundSessionId.BytesEqual(sessionId))
                    {
                        if (peer.InboundSessionId == null)
                        {
                            Logger.LogWarning($"Wrong inbound session id {context.Peer}, {context.Method}");
                            return(Task.FromResult <TResponse>(null));
                        }

                        if (sessionId == null)
                        {
                            Logger.LogWarning($"Wrong context session id {context.Peer}, {context.Method}, {peer}");
                            return(Task.FromResult <TResponse>(null));
                        }

                        Logger.LogWarning(
                            $"Unequal session id, {context.Peer} ({peer.InboundSessionId.ToHex()} vs {sessionId.ToHex()}) {context.GetPublicKey()}");
                        return(Task.FromResult <TResponse>(null));
                    }

                    context.RequestHeaders.Add(new Metadata.Entry(GrpcConstants.PeerInfoMetadataKey, $"{peer}"));
                }
            }
            catch (Exception e)
            {
                Logger.LogError(e, $"Auth interceptor error {context.Peer}, {context.Method}: ");
                throw;
            }

            return(continuation(request, context));
        }
Example #5
0
 public override async Task <VoidReply> ConfirmHandshake(ConfirmHandshakeRequest request,
                                                         ServerCallContext context)
 {
     Logger.LogDebug($"Peer {context.GetPeerInfo()} has requested a confirm handshake.");
     _connectionService.ConfirmHandshake(context.GetPublicKey());
     return(new VoidReply());
 }
Example #6
0
        public Task ProcessLibAnnouncement(LibAnnouncement announcement, ServerCallContext context)
        {
            if (announcement?.LibHash == null)
            {
                Logger.LogWarning($"Received null or empty announcement from {context.GetPeerInfo()}.");
                return(Task.CompletedTask);
            }

            Logger.LogDebug(
                $"Received lib announce hash: {announcement.LibHash}, height {announcement.LibHeight} from {context.GetPeerInfo()}.");

            var peer = _connectionService.GetPeerByPubkey(context.GetPublicKey());

            if (peer == null)
            {
                // if peer already removed, drop.
                return(Task.CompletedTask);
            }

            peer.UpdateLastKnownLib(announcement);

            if (peer.SyncState != SyncState.Finished)
            {
                peer.SyncState = SyncState.Finished;
            }

            return(Task.CompletedTask);
        }
Example #7
0
        /// <summary>
        /// This method returns a block. The parameter is a <see cref="BlockRequest"/> object, if the value
        /// of <see cref="BlockRequest.Hash"/> is not null, the request is by ID, otherwise it will be
        /// by height.
        /// </summary>
        public override async Task <BlockReply> RequestBlock(BlockRequest request, ServerCallContext context)
        {
            if (request == null || request.Hash == null || _syncStateService.SyncState != SyncState.Finished)
            {
                return(new BlockReply());
            }

            Logger.LogDebug($"Peer {context.GetPeerInfo()} requested block {request.Hash}.");

            BlockWithTransactions block;

            try
            {
                block = await _blockchainService.GetBlockWithTransactionsByHash(request.Hash);

                if (block == null)
                {
                    Logger.LogDebug($"Could not find block {request.Hash} for {context.GetPeerInfo()}.");
                }
                else
                {
                    var peer = _connectionService.GetPeerByPubkey(context.GetPublicKey());
                    peer.TryAddKnownBlock(block.GetHash());
                }
            }
            catch (Exception e)
            {
                Logger.LogError(e, $"Request block error: {context.GetPeerInfo()}");
                throw;
            }

            return(new BlockReply {
                Block = block
            });
        }
Example #8
0
        public override async Task <VoidReply> BlockBroadcastStream(
            IAsyncStreamReader <BlockWithTransactions> requestStream, ServerCallContext context)
        {
            Logger.LogDebug($"Block stream started with {context.GetPeerInfo()} - {context.Peer}.");

            try
            {
                var peerPubkey = context.GetPublicKey();
                var peer       = _connectionService.GetPeerByPubkey(peerPubkey);

                if (peer.SyncState != SyncState.Finished)
                {
                    peer.SyncState = SyncState.Finished;
                }

                await requestStream.ForEachAsync(block =>
                {
                    peer.TryAddKnownBlock(block.GetHash());
                    _ = EventBus.PublishAsync(new BlockReceivedEvent(block, peerPubkey));

                    return(Task.CompletedTask);
                });
            }
            catch (Exception e)
            {
                Logger.LogError(e, $"Block stream error - {context.GetPeerInfo()}: ");
                throw;
            }

            Logger.LogDebug($"Block stream finished with {context.GetPeerInfo()} - {context.Peer}.");

            return(new VoidReply());
        }
Example #9
0
        private async Task ProcessTransaction(Transaction tx, ServerCallContext context)
        {
            var chain = await _blockchainService.GetChainAsync();

            // if this transaction's ref block is a lot higher than our chain
            // then don't participate in p2p network
            if (tx.RefBlockNumber > chain.LongestChainHeight + NetworkConstants.DefaultInitialSyncOffset)
            {
                return;
            }

            var peer = _connectionService.GetPeerByPubkey(context.GetPublicKey());

            if (peer == null)
            {
                // if peer already removed, drop.
                return;
            }

            if (!peer.TryAddKnownTransaction(tx.GetHash()))
            {
                return;
            }

            _ = EventBus.PublishAsync(new TransactionsReceivedEvent {
                Transactions = new List <Transaction> {
                    tx
                }
            });
        }
Example #10
0
        public Task ProcessAnnouncement(BlockAnnouncement announcement, ServerCallContext context)
        {
            if (announcement?.BlockHash == null)
            {
                Logger.LogWarning($"Received null announcement or header from {context.GetPeerInfo()}.");
                return(Task.CompletedTask);
            }

            Logger.LogDebug(
                $"Received announce, block hash: {announcement.BlockHash}, block height: {announcement.BlockHeight} from {context.GetPeerInfo()}.");

            var peer = _connectionService.GetPeerByPubkey(context.GetPublicKey());

            if (peer == null)
            {
                // if peer already removed, drop.
                return(Task.CompletedTask);
            }

            if (!peer.TryAddKnownBlock(announcement.BlockHash))
            {
                return(Task.CompletedTask);
            }

            if (peer.SyncState != SyncState.Finished)
            {
                peer.SyncState = SyncState.Finished;
            }

            _ = EventBus.PublishAsync(new AnnouncementReceivedEventData(announcement, context.GetPublicKey()));

            return(Task.CompletedTask);
        }
Example #11
0
        /// <summary>
        /// Clients should call this method to disconnect explicitly.
        /// </summary>
        public override async Task <VoidReply> Disconnect(DisconnectReason request, ServerCallContext context)
        {
            Logger.LogDebug($"Peer {context.GetPeerInfo()} has sent a disconnect request.");

            await _peerPool.RemovePeerAsync(context.GetPublicKey(), false);

            return(new VoidReply());
        }
Example #12
0
        public override Task <TResponse> UnaryServerHandler <TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod <TRequest, TResponse> continuation)
        {
            if (context.Method != GetFullMethodName(nameof(PeerService.PeerServiceBase.Connect)))
            {
                var peer = _peerPool.FindPeerByPublicKey(context.GetPublicKey());

                if (peer == null && context.Method != GetFullMethodName(nameof(PeerService.PeerServiceBase.Ping)))
                {
                    Logger.LogWarning($"Could not find peer {context.GetPublicKey()}");
                    return(Task.FromResult <TResponse>(null));
                }

                context.RequestHeaders.Add(new Metadata.Entry(GrpcConstants.PeerInfoMetadataKey, $"{peer}"));
            }

            return(continuation(request, context));
        }
Example #13
0
        /// <summary>
        /// This method is called when a peer wants to broadcast an announcement.
        /// </summary>
        public override Task <VoidReply> Announce(PeerNewBlockAnnouncement an, ServerCallContext context)
        {
            if (an?.BlockHash == null || an?.BlockTime == null)
            {
                Logger.LogError($"Received null announcement or header from {context.GetPeerInfo()}.");
                return(Task.FromResult(new VoidReply()));
            }

            var peerInPool = _peerPool.FindPeerByPublicKey(context.GetPublicKey());

            peerInPool?.HandlerRemoteAnnounce(an);

            Logger.LogDebug($"Received announce {an.BlockHash} from {context.GetPeerInfo()}.");

            _ = EventBus.PublishAsync(new AnnouncementReceivedEventData(an, context.GetPublicKey()));

            return(Task.FromResult(new VoidReply()));
        }
Example #14
0
        public override async Task <VoidReply> BlockBroadcastStream(IAsyncStreamReader <BlockWithTransactions> requestStream, ServerCallContext context)
        {
            await requestStream.ForEachAsync(r =>
            {
                _ = EventBus.PublishAsync(new BlockReceivedEvent(r, context.GetPublicKey()));
                return(Task.CompletedTask);
            });

            return(new VoidReply());
        }
Example #15
0
        public override async Task <VoidReply> BlockBroadcastStream(
            IAsyncStreamReader <BlockWithTransactions> requestStream, ServerCallContext context)
        {
            Logger.LogDebug($"Block stream started with {context.GetPeerInfo()} - {context.Peer}.");

            await requestStream.ForEachAsync(r =>
            {
                _ = EventBus.PublishAsync(new BlockReceivedEvent(r, context.GetPublicKey()));
                return(Task.CompletedTask);
            });

            Logger.LogDebug($"Block stream finished with {context.GetPeerInfo()} - {context.Peer}.");

            return(new VoidReply());
        }
Example #16
0
        public Task ProcessLibAnnouncement(LibAnnouncement announcement, ServerCallContext context)
        {
            if (announcement?.LibHash == null)
            {
                Logger.LogError($"Received null or empty announcement from {context.GetPeerInfo()}.");
                return(Task.CompletedTask);
            }

            Logger.LogDebug($"Received lib announce hash: {announcement.LibHash}, height {announcement.LibHeight} from {context.GetPeerInfo()}.");

            var peer = _connectionService.GetPeerByPubkey(context.GetPublicKey());

            peer?.UpdateLastKnownLib(announcement);

            return(Task.CompletedTask);
        }
Example #17
0
        public override Task <TResponse> UnaryServerHandler <TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod <TRequest, TResponse> continuation)
        {
            if (context.Method != "/" + nameof(PeerService) + "/" + nameof(PeerService.PeerServiceBase.Connect))
            {
                var peer = _peerPool.FindPeerByPublicKey(context.GetPublicKey());

                if (peer == null)
                {
                    return(Task.FromResult <TResponse>(null));
                }

                context.RequestHeaders.Add(new Metadata.Entry(GrpcConsts.PeerInfoMetadataKey, $"{peer}"));
            }

            return(continuation(request, context));
        }
Example #18
0
        /// <summary>
        /// Clients should call this method to disconnect explicitly.
        /// </summary>
        public override Task <VoidReply> Disconnect(DisconnectReason request, ServerCallContext context)
        {
            Logger.LogDebug($"Peer {context.GetPeerInfo()} has sent a disconnect request.");

            try
            {
                _connectionService.RemovePeer(context.GetPublicKey());
            }
            catch (Exception e)
            {
                Logger.LogError(e, "Disconnect error: ");
                throw;
            }

            return(Task.FromResult(new VoidReply()));
        }
Example #19
0
        public override Task <VoidReply> ConfirmHandshake(ConfirmHandshakeRequest request,
                                                          ServerCallContext context)
        {
            try
            {
                Logger.LogDebug($"Peer {context.GetPeerInfo()} has requested a handshake confirmation.");

                _connectionService.ConfirmHandshake(context.GetPublicKey());
            }
            catch (Exception e)
            {
                Logger.LogError(e, $"Confirm handshake error - {context.GetPeerInfo()}: ");
                throw;
            }

            return(Task.FromResult(new VoidReply()));
        }
Example #20
0
        public Task ProcessAnnouncement(BlockAnnouncement announcement, ServerCallContext context)
        {
            if (announcement?.BlockHash == null)
            {
                Logger.LogError($"Received null announcement or header from {context.GetPeerInfo()}.");

                return(Task.CompletedTask);
            }

            Logger.LogDebug($"Received announce {announcement.BlockHash} from {context.GetPeerInfo()}.");

            var peer = _connectionService.GetPeerByPubkey(context.GetPublicKey());

            peer?.AddKnowBlock(announcement);

            _ = EventBus.PublishAsync(new AnnouncementReceivedEventData(announcement, context.GetPublicKey()));

            return(Task.CompletedTask);
        }
Example #21
0
        public override async Task <VoidReply> TransactionBroadcastStream(IAsyncStreamReader <Transaction> requestStream,
                                                                          ServerCallContext context)
        {
            Logger.LogDebug($"Transaction stream started with {context.GetPeerInfo()} - {context.Peer}.");

            try
            {
                var peerPubkey = context.GetPublicKey();
                await requestStream.ForEachAsync(async tx => await ProcessTransactionAsync(tx, peerPubkey));
            }
            catch (Exception e)
            {
                Logger.LogError(e, $"Transaction stream error - {context.GetPeerInfo()}: ");
                throw;
            }

            Logger.LogDebug($"Transaction stream finished with {context.GetPeerInfo()} - {context.Peer}.");

            return(new VoidReply());
        }
Example #22
0
        public override async Task <VoidReply> LibAnnouncementBroadcastStream(
            IAsyncStreamReader <LibAnnouncement> requestStream, ServerCallContext context)
        {
            Logger.LogDebug($"Lib announcement stream started with {context.GetPeerInfo()} - {context.Peer}.");

            try
            {
                var peerPubkey = context.GetPublicKey();
                await requestStream.ForEachAsync(async r => await ProcessLibAnnouncementAsync(r, peerPubkey));
            }
            catch (Exception e)
            {
                Logger.LogError(e, $"Lib announcement stream error: {context.GetPeerInfo()}");
                throw;
            }

            Logger.LogDebug($"Lib announcement stream finished with {context.GetPeerInfo()} - {context.Peer}.");

            return(new VoidReply());
        }
Example #23
0
 public override async Task <HandshakeReply> DoHandshake(HandshakeRequest request, ServerCallContext context)
 {
     Logger.LogDebug($"Peer {context.GetPeerInfo()} has requested a handshake.");
     return(await _connectionService.CheckIncomingHandshakeAsync(context.GetPublicKey(), request.Handshake));
 }
Example #24
0
 /// <summary>
 /// Clients should call this method to disconnect explicitly.
 /// </summary>
 public override Task <VoidReply> Disconnect(DisconnectReason request, ServerCallContext context)
 {
     Logger.LogDebug($"Peer {context.GetPeerInfo()} has sent a disconnect request.");
     _connectionService.RemovePeer(context.GetPublicKey());
     return(Task.FromResult(new VoidReply()));
 }