Пример #1
0
        public async Task BroadcastBlock_OnePeerKnowsBlock_Test()
        {
            var blockHeader           = OsCoreTestHelper.CreateFakeBlockHeader(1, 2);
            var blockWithTransactions = new BlockWithTransactions {
                Header = blockHeader
            };

            _peerPool.FindPeerByPublicKey("Pubkey0").TryAddKnownBlock(blockWithTransactions.GetHash());

            await _networkService.BroadcastBlockWithTransactionsAsync(blockWithTransactions);

            foreach (var peer in _testContext.MockedPeers)
            {
                peer.Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once());
            }

            _testContext.MockedPeers[0].Verify(
                p => p.EnqueueBlock(blockWithTransactions, It.IsAny <Action <NetworkException> >()),
                Times.Never);
            _testContext.MockedPeers[1].Verify(
                p => p.EnqueueBlock(blockWithTransactions, It.IsAny <Action <NetworkException> >()),
                Times.Once());
            _testContext.MockedPeers[2].Verify(
                p => p.EnqueueBlock(blockWithTransactions, It.IsAny <Action <NetworkException> >()),
                Times.Once());
        }
Пример #2
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));
        }
Пример #3
0
        public void GetPeersByPubKey()
        {
            var pubkey   = "NormalPeer";
            var peerInfo = _networkService.GetPeerByPubkey(pubkey);

            peerInfo.ShouldNotBeNull();

            var peer = _peerPool.FindPeerByPublicKey(pubkey);

            peerInfo.IpAddress.ShouldBe(peer.RemoteEndpoint.ToString());
            peerInfo.Pubkey.ShouldBe(peer.Info.Pubkey);
            peerInfo.LastKnownLibHeight.ShouldBe(peer.LastKnownLibHeight);
            peerInfo.ProtocolVersion.ShouldBe(peer.Info.ProtocolVersion);
            peerInfo.ConnectionTime.ShouldBe(peer.Info.ConnectionTime.Seconds);
            peerInfo.ConnectionStatus.ShouldBe(peer.ConnectionStatus);
            peerInfo.Inbound.ShouldBe(peer.Info.IsInbound);
            peerInfo.SyncState.ShouldBe(peer.SyncState);
            peerInfo.BufferedAnnouncementsCount.ShouldBe(peer.BufferedAnnouncementsCount);
            peerInfo.BufferedBlocksCount.ShouldBe(peer.BufferedBlocksCount);
            peerInfo.BufferedTransactionsCount.ShouldBe(peer.BufferedTransactionsCount);

            var fakePubkey = Cryptography.CryptoHelper.GenerateKeyPair().PublicKey.ToHex();

            peerInfo = _networkService.GetPeerByPubkey(fakePubkey);
            peerInfo.ShouldBeNull();
        }
Пример #4
0
        public void AddedPeer_IsFindable_ByAddressAndPubkey()
        {
            var peer = CreatePeer();

            _peerPool.TryAddPeer(peer);

            _peerPool.PeerCount.ShouldBe(1);
            _peerPool.FindPeerByEndpoint(peer.RemoteEndpoint).ShouldNotBeNull();
            _peerPool.FindPeerByPublicKey(peer.Info.Pubkey).ShouldNotBeNull();
        }
Пример #5
0
        public async Task <bool> RemovePeerByPubkeyAsync(string peerPubkey, int removalSeconds = NetworkConstants.DefaultPeerRemovalSeconds)
        {
            var peer = _peerPool.FindPeerByPublicKey(peerPubkey);

            if (!await TryRemovePeerAsync(peer, removalSeconds))
            {
                Logger.LogWarning($"Remove peer failed. Peer pubkey: {peerPubkey}");
                return(false);
            }

            return(true);
        }
Пример #6
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));
        }
Пример #7
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));
        }
Пример #8
0
        public async Task <List <Block> > GetBlocksAsync(Hash previousBlock, long previousHeight, int count, string peerPubKey = null, bool tryOthersIfFail = false)
        {
            // try get the block from the specified peer.
            if (!string.IsNullOrWhiteSpace(peerPubKey))
            {
                IPeer peer = _peerPool.FindPeerByPublicKey(peerPubKey);

                if (peer == null)
                {
                    // if the peer was specified but we can't find it
                    // we don't try any further.
                    Logger.LogWarning($"Specified peer was not found.");
                    return(null);
                }

                var blocks = await RequestAsync(peer, p => p.GetBlocksAsync(previousBlock, count));

                if (blocks != null && blocks.Count > 0)
                {
                    return(blocks);
                }

                if (!tryOthersIfFail)
                {
                    Logger.LogWarning($"{peerPubKey} does not have blocks {nameof(tryOthersIfFail)} is false.");
                    return(null);
                }
            }

            // shuffle the peers that can give us the blocks
            var shuffledPeers = _peerPool.GetPeers()
                                .Where(p => p.CurrentBlockHeight >= previousHeight)
                                .OrderBy(a => Guid.NewGuid());

            foreach (var peer in shuffledPeers)
            {
                var blocks = await RequestAsync(peer, p => p.GetBlocksAsync(previousBlock, count));

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

            return(null);
        }
Пример #9
0
        public async Task <bool> RemovePeerByPubkeyAsync(string peerPubKey, bool blacklistPeer = false)
        {
            var peer = _peerPool.FindPeerByPublicKey(peerPubKey);

            if (peer == null)
            {
                Logger.LogWarning($"Could not find peer: {peerPubKey}");
                return(false);
            }

            if (blacklistPeer)
            {
                _blackListedPeerProvider.AddHostToBlackList(peer.RemoteEndpoint.Host);
                Logger.LogDebug($"Blacklisted {peer.RemoteEndpoint.Host} ({peerPubKey})");
            }

            await _networkServer.DisconnectAsync(peer);

            return(true);
        }
Пример #10
0
        public async Task SendDiscoveryJob_NoNode_Test()
        {
            var peer = _peerPool.FindPeerByPublicKey("PeerWithNoNode");

            await SendDiscoveryJobAsync(peer);

            var nodes = await _nodeManager.GetRandomNodesAsync(10);

            nodes.Nodes.Count.ShouldBe(0);
        }
        public async Task <IBlockIndex> FindLastLastIrreversibleBlockAsync(string senderPubKey)
        {
            var senderPeer = _peerPool.FindPeerByPublicKey(senderPubKey);

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

            var orderedBlocks = senderPeer.RecentBlockHeightAndHashMappings.OrderByDescending(p => p.Key).ToList();

            var chain = await _blockchainService.GetChainAsync();

            var chainContext = new ChainContext {
                BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight
            };
            var pubkeyList = (await _dpoSInformationProvider.GetCurrentMinerList(chainContext)).ToList();

            var peers = _peerPool.GetPeers().Where(p => pubkeyList.Contains(p.Info.Pubkey)).ToList();

            var pubKey = (await _accountService.GetPublicKeyAsync()).ToHex();

            if (peers.Count == 0 && !pubkeyList.Contains(pubKey))
            {
                return(null);
            }

            foreach (var block in orderedBlocks)
            {
                var peersHadBlockAmount = peers.Where(p =>
                {
                    p.RecentBlockHeightAndHashMappings.TryGetValue(block.Key, out var hash);
                    return(hash == block.Value);
                }).Count();
                if (pubkeyList.Contains(pubKey) &&
                    _knownBlockCacheProvider.TryGetBlockByHeight(block.Key, out var blockHash) &&
                    blockHash == block.Value)
                {
                    peersHadBlockAmount++;
                }

                var sureAmount = pubkeyList.Count.Mul(2).Div(3) + 1;
                if (peersHadBlockAmount >= sureAmount)
                {
                    Logger.LogDebug($"LIB found in network layer: height {block.Key}");
                    return(new BlockIndex(block.Value, block.Key));
                }
            }

            return(null);
        }
Пример #12
0
        public async Task LibAnnouncementBroadcastStream_Test()
        {
            var chain = await _blockchainService.GetChainAsync();

            var irreversibleBlockHeight = (int)chain.LastIrreversibleBlockHeight;
            var bestBlockHeight         = (int)chain.BestChainHeight;
            var requestLibAnnouncements = new List <LibAnnouncement>();
            var preBlockHash            = chain.LastIrreversibleBlockHash;
            var preBlockHeight          = irreversibleBlockHeight;

            for (var i = irreversibleBlockHeight + 1; i <= bestBlockHeight; i++)
            {
                var libBlock = _osTestHelper.GenerateBlock(preBlockHash, preBlockHeight);
                requestLibAnnouncements.Add(new LibAnnouncement
                {
                    LibHeight = preBlockHeight,
                    LibHash   = preBlockHash
                });
                preBlockHash = libBlock.GetHash();
                preBlockHeight++;
            }

            var      requestStream = new TestAsyncStreamReader <LibAnnouncement>(requestLibAnnouncements);
            var      pubKey        = NetworkTestConstants.FakePubkey2;
            Metadata metadata      = new Metadata {
                { GrpcConstants.PubkeyMetadataKey, pubKey }
            };
            var context = BuildServerCallContext(metadata);
            var result  = await _serverService.LibAnnouncementBroadcastStream(requestStream, context);

            result.ShouldBe(new VoidReply());

            var peer      = _peerPool.FindPeerByPublicKey(pubKey);
            var lastBlock = requestLibAnnouncements.Last();

            peer.LastKnownLibHash.ShouldBe(lastBlock.LibHash);
            peer.LastKnownLibHeight.ShouldBe(lastBlock.LibHeight);
        }
        public async Task Connect_PeerAlreadyInPoolAndIsInvalid_Test()
        {
            var peer = CreatePeerAndAddToPeerPool(NetworkTestConstants.GoodPeerEndpoint, NetworkTestConstants.FakePubkey2);

            peer.IsConnected         = false;
            peer.Info.ConnectionTime = TimestampHelper.GetUtcNow()
                                       .AddMilliseconds(-NetworkConstants.PeerConnectionTimeout - 1000);

            var added = await _connectionService.ConnectAsync(peer.RemoteEndpoint);

            added.ShouldBeTrue();

            var currentPeer = _peerPool.FindPeerByPublicKey(NetworkTestConstants.FakePubkey);

            currentPeer.ShouldNotBeNull();
        }
Пример #14
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));
        }
Пример #15
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()));
        }
Пример #16
0
        public async Task RequestBlock_WillAddToPeersBlockCache_Test()
        {
            var      pubKey   = "SomePubKey";
            Metadata metadata = new Metadata {
                { GrpcConstants.PubkeyMetadataKey, pubKey }
            };

            var reqBlockCtxt = BuildServerCallContext(metadata);

            _peerPool.TryAddPeer(GrpcTestPeerHelpers.CreateBasicPeer("127.0.0.1:1245", pubKey));

            var chain = await _blockchainService.GetChainAsync();

            var reply = await _serverService.RequestBlock(new BlockRequest { Hash = chain.LongestChainHash }, reqBlockCtxt);

            _peerPool.FindPeerByPublicKey(reqBlockCtxt.GetPublicKey());

            Assert.NotNull(reply.Block);
            Assert.True(reply.Block.GetHash() == chain.LongestChainHash);
        }
Пример #17
0
        public void QueryPeers_Test()
        {
            var    commonHost     = "12.34.56.67";
            string commonPort     = "1900";
            string commonEndpoint = commonHost + ":" + commonPort;

            var peer1 = CreatePeer(commonEndpoint);

            _peerPool.TryAddPeer(peer1);
            var peer2 = CreatePeer(commonEndpoint);

            _peerPool.TryAddPeer(peer2);
            var peer3 = CreatePeer("12.34.56.64:1900");

            _peerPool.TryAddPeer(peer3);
            var peer4 = CreatePeer("12.34.56.61:1900", isReady: false);

            _peerPool.TryAddPeer(peer4);

            var peers = _peerPool.GetPeers();

            peers.Count.ShouldBe(3);

            peers = _peerPool.GetPeers(true);
            peers.Count.ShouldBe(4);

            peers = _peerPool.GetPeersByHost(commonHost);
            peers.Count.ShouldBe(2);
            peers.ShouldContain(peer1);
            peers.ShouldContain(peer2);

            var peer = _peerPool.FindPeerByEndpoint(peer3.RemoteEndpoint);

            peer.ShouldBe(peer3);

            peer = _peerPool.FindPeerByPublicKey(peer3.Info.Pubkey);
            peer.ShouldBe(peer3);
        }
        public async Task ProcessPeerInvalidTransaction_Test()
        {
            var peer1 = _peerPool.FindPeerByPublicKey("Peer1");
            var peer3 = _peerPool.FindPeerByPublicKey("Peer3");

            bool isInBlackList;

            for (var i = 0; i < 5; i++)
            {
                var txId = HashHelper.ComputeFrom("Tx" + i + "Peer3");
                await _peerInvalidTransactionProcessingService.ProcessPeerInvalidTransactionAsync(txId);

                isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer3.RemoteEndpoint.Host);
                isInBlackList.ShouldBeFalse();
            }

            await _peerInvalidTransactionProcessingService.ProcessPeerInvalidTransactionAsync(HashHelper.ComputeFrom("Tx" + 5 + "Peer3"));

            isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer3.RemoteEndpoint.Host);
            isInBlackList.ShouldBeTrue();

            isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer1.RemoteEndpoint.Host);
            isInBlackList.ShouldBeFalse();
        }
Пример #19
0
        public PeerInfo GetPeerByPubkey(string peerPubkey)
        {
            var peer = _peerPool.FindPeerByPublicKey(peerPubkey);

            return(peer == null ? null : PeerInfoHelper.FromNetworkPeer(peer));
        }
Пример #20
0
 public GrpcPeer GetPeerByPubkey(string pubkey)
 {
     return(_peerPool.FindPeerByPublicKey(pubkey) as GrpcPeer);
 }