Example #1
0
        public override async Task <NodeList> GetNodes(NodesRequest request, ServerCallContext context)
        {
            if (request == null)
            {
                return(new NodeList());
            }

            Logger.LogDebug($"Peer {context.GetPeerInfo()} requested {request.MaxCount} nodes.");

            NodeList nodes;

            try
            {
                nodes = await _peerDiscoveryService.GetNodesAsync(request.MaxCount);
            }
            catch (Exception e)
            {
                Logger.LogError(e, "Get nodes error: ");
                throw;
            }

            Logger.LogDebug($"Sending {nodes.Nodes.Count} to {context.GetPeerInfo()}.");

            return(nodes);
        }
Example #2
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 #3
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 #4
0
        public override async Task <VoidReply> AnnouncementBroadcastStream(
            IAsyncStreamReader <BlockAnnouncement> requestStream, ServerCallContext context)
        {
            Logger.LogDebug($"Announcement stream started with {context.GetPeerInfo()} - {context.Peer}.");

            await requestStream.ForEachAsync(async r => await ProcessAnnouncement(r, context));

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

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

            await requestStream.ForEachAsync(async tx => await ProcessTransaction(tx, context));

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

            return(new VoidReply());
        }
Example #6
0
        public override async Task <NodeList> GetNodes(NodesRequest request, ServerCallContext context)
        {
            if (request == null)
            {
                return(new NodeList());
            }

            Logger.LogDebug($"Peer {context.GetPeerInfo()} requested {request.MaxCount} nodes.");

            var nodes = await _peerDiscoveryService.GetNodesAsync(request.MaxCount);

            Logger.LogDebug($"Sending {nodes.Nodes.Count} to {context.GetPeerInfo()}.");

            return(nodes);
        }
Example #7
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 #8
0
        public override async Task <BlockList> RequestBlocks(BlocksRequest request, ServerCallContext context)
        {
            if (request == null ||
                request.PreviousBlockHash == null ||
                _syncStateService.SyncState != SyncState.Finished ||
                request.Count == 0 ||
                request.Count > GrpcConstants.MaxSendBlockCountLimit)
            {
                return(new BlockList());
            }

            Logger.LogDebug(
                $"Peer {context.GetPeerInfo()} requested {request.Count} blocks from {request.PreviousBlockHash}.");

            var blockList = new BlockList();

            try
            {
                var blocks =
                    await _blockchainService.GetBlocksWithTransactions(request.PreviousBlockHash, request.Count);

                if (blocks == null)
                {
                    return(blockList);
                }

                blockList.Blocks.AddRange(blocks);

                if (NetworkOptions.CompressBlocksOnRequest)
                {
                    var headers = new Metadata
                    {
                        new Metadata.Entry(GrpcConstants.GrpcRequestCompressKey, GrpcConstants.GrpcGzipConst)
                    };
                    await context.WriteResponseHeadersAsync(headers);
                }

                Logger.LogTrace(
                    $"Replied to {context.GetPeerInfo()} with {blockList.Blocks.Count}, request was {request}");
            }
            catch (Exception e)
            {
                Logger.LogError(e, $"Request blocks error - {context.GetPeerInfo()} - request {request}: ");
                throw;
            }

            return(blockList);
        }
Example #9
0
        public override async Task <BlockList> RequestBlocks(BlocksRequest request, ServerCallContext context)
        {
            if (request == null || request.PreviousBlockHash == null)
            {
                return(new BlockList());
            }

            Logger.LogDebug($"Peer {context.GetPeerInfo()} requested {request.Count} blocks from {request.PreviousBlockHash}.");

            var blockList = new BlockList();

            var blocks = await _blockChainService.GetBlocksInBestChainBranchAsync(request.PreviousBlockHash, request.Count);

            if (blocks == null)
            {
                return(blockList);
            }

            blockList.Blocks.AddRange(blocks);

            if (blockList.Blocks.Count != request.Count)
            {
                Logger.LogTrace($"Replied with {blockList.Blocks.Count} blocks for request {request}");
            }

            if (_netOpts.CompressBlocksOnRequest)
            {
                var headers = new Metadata {
                    new Metadata.Entry(GrpcConsts.GrpcRequestCompressKey, GrpcConsts.GrpcGzipConst)
                };
                await context.WriteResponseHeadersAsync(headers);
            }

            return(blockList);
        }
Example #10
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 #11
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 #12
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 #13
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 #14
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 #15
0
        public override async Task <VoidReply> LibAnnouncementBroadcastStream(IAsyncStreamReader <LibAnnouncement> requestStream, ServerCallContext context)
        {
            Logger.LogDebug($"Lib announcement stream started with {context.GetPeerInfo()} - {context.Peer}.");

            try
            {
                await requestStream.ForEachAsync(async r => await ProcessLibAnnouncement(r, context));
            }
            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 #16
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 #17
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 #18
0
        public override async Task <VoidReply> TransactionBroadcastStream(IAsyncStreamReader <Transaction> requestStream,
                                                                          ServerCallContext context)
        {
            Logger.LogTrace($"Transaction stream started with {context.GetPeerInfo()} - {context.Peer}.");

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

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

            return(new VoidReply());
        }
Example #19
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}.");

            var block = await _blockchainService.GetBlockWithTransactionsByHash(request.Hash);

            if (block == null)
            {
                Logger.LogDebug($"Could not find block {request.Hash} for {context.GetPeerInfo()}.");
            }

            return(new BlockReply {
                Block = block
            });
        }
Example #20
0
        /// <summary>
        /// This method returns a block. The parameter is a <see cref="BlockRequest"/> object, if the value
        /// of <see cref="BlockRequest.Id"/> 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)
            {
                return(new BlockReply());
            }

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

            var block = await _blockChainService.GetBlockByHashAsync(request.Hash);

            if (block == null)
            {
                Logger.LogDebug($"Could not find block {request.Hash} for {context.GetPeerInfo()}.");
            }

            return(new BlockReply {
                Block = block
            });
        }
Example #21
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();
                await requestStream.ForEachAsync(async block => await ProcessBlockAsync(block, peerPubkey));
            }
            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 #22
0
        /// <summary>
        /// This method is called when a peer wants to broadcast an announcement.
        /// </summary>
        public override async Task <VoidReply> SendAnnouncement(BlockAnnouncement an, ServerCallContext context)
        {
            try
            {
                await ProcessAnnouncement(an, context);
            }
            catch (Exception e)
            {
                Logger.LogError(e, $"Process announcement error: {context.GetPeerInfo()}");
                throw;
            }

            return(new VoidReply());
        }
Example #23
0
        /// <summary>
        /// This method is called when another peer broadcasts a transaction.
        /// </summary>
        public override async Task <VoidReply> SendTransaction(Transaction tx, ServerCallContext context)
        {
            try
            {
                await ProcessTransaction(tx, context);
            }
            catch (Exception e)
            {
                Logger.LogError(e, $"SendTransaction error - {context.GetPeerInfo()}: ");
                throw;
            }

            return(new VoidReply());
        }
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.");

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

            return(Task.FromResult(new VoidReply()));
        }
Example #25
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 #26
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 #27
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()));
 }