Пример #1
0
        /// <summary>
        /// Sends a message to the connected peer requesting specific data.
        /// </summary>
        /// <param name="getDataPayload">Specification of the data to download - <see cref="GetDataPayload"/>.</param>
        /// <returns><c>true</c> if the message was successfully sent to the peer, <c>false</c> if the peer got disconnected.</returns>
        /// <remarks>Caller is responsible to add the puller to the map if necessary.</remarks>
        internal async Task <bool> StartDownloadAsync(GetDataPayload getDataPayload)
        {
            this.logger.LogTrace("()");

            INetworkPeer attachedNode = this.AttachedPeer;

            if ((attachedNode == null) || (attachedNode.State != NetworkPeerState.HandShaked) || !this.puller.Requirements.Check(attachedNode.PeerVersion))
            {
                this.logger.LogTrace("(-)[ATTACHED_PEER]:false");
                return(false);
            }

            foreach (InventoryVector inv in getDataPayload.Inventory)
            {
                inv.Type = attachedNode.AddSupportedOptions(inv.Type);
            }

            try
            {
                await attachedNode.SendMessageAsync(getDataPayload).ConfigureAwait(false);

                // In case job is assigned to a peer with low quality score-
                // give it enough score so the job is not reassigned right away.
                this.UpdateQualityScore(BlockPulling.QualityScore.MaxScore / 10);
            }
            catch (OperationCanceledException)
            {
                this.logger.LogTrace("(-)[CANCELLED]:false");
                return(false);
            }

            this.logger.LogTrace("(-):true");
            return(true);
        }
Пример #2
0
        /// <inheritdoc/>
        public async Task RequestBlocksAsync(List <uint256> hashes)
        {
            var getDataPayload = new GetDataPayload();

            INetworkPeer peer = this.AttachedPeer;

            if (peer == null)
            {
                this.logger.LogTrace("(-)[PEER_DETACHED]");
                throw new OperationCanceledException("Peer is detached already!");
            }

            foreach (uint256 uint256 in hashes)
            {
                var vector = new InventoryVector(InventoryType.MSG_BLOCK, uint256);
                vector.Type = peer.AddSupportedOptions(vector.Type);

                getDataPayload.Inventory.Add(vector);
            }

            if (peer.State != NetworkPeerState.HandShaked)
            {
                this.logger.LogTrace("(-)[ATTACHED_PEER]");
                throw new OperationCanceledException("Peer is in the wrong state!");
            }

            await peer.SendMessageAsync(getDataPayload).ConfigureAwait(false);
        }
Пример #3
0
        /// <summary>
        /// If there are any more blocks the node wants to download, this method assigns and starts
        /// a new download task for a specific peer that this behavior represents.
        /// </summary>
        private async Task AssignPendingVectorAsync()
        {
            this.logger.LogTrace("()");

            INetworkPeer attachedNode = this.AttachedPeer;

            if ((attachedNode == null) || (attachedNode.State != NetworkPeerState.HandShaked) || !this.puller.Requirements.Check(attachedNode.PeerVersion))
            {
                this.logger.LogTrace("(-)[ATTACHED_NODE]");
                return;
            }

            uint256 block = null;

            if (this.puller.AssignPendingDownloadTaskToPeer(this, out block))
            {
                try
                {
                    var getDataPayload = new GetDataPayload(new InventoryVector(attachedNode.AddSupportedOptions(InventoryType.MSG_BLOCK), block));
                    await attachedNode.SendMessageAsync(getDataPayload).ConfigureAwait(false);
                }
                catch (OperationCanceledException)
                {
                }
            }

            this.logger.LogTrace("(-)");
        }
        /// <summary>
        /// Sends a message to the connected peer requesting specific data.
        /// </summary>
        /// <param name="getDataPayload">Specification of the data to download - <see cref="GetDataPayload"/>.</param>
        /// <returns><c>true</c> if the message was successfully sent to the peer, <c>false</c> if the peer got disconnected.</returns>
        /// <remarks>Caller is responsible to add the puller to the map if necessary.</remarks>
        internal async Task <bool> StartDownloadAsync(GetDataPayload getDataPayload)
        {
            this.logger.LogTrace("()");

            INetworkPeer attachedNode = this.AttachedPeer;

            if ((attachedNode == null) || (attachedNode.State != NetworkPeerState.HandShaked) || !this.puller.Requirements.Check(attachedNode.PeerVersion))
            {
                this.logger.LogTrace("(-)[ATTACHED_PEER]:false");
                return(false);
            }

            foreach (InventoryVector inv in getDataPayload.Inventory)
            {
                inv.Type = attachedNode.AddSupportedOptions(inv.Type);
            }

            try
            {
                await attachedNode.SendMessageAsync(getDataPayload).ConfigureAwait(false);
            }
            catch (OperationCanceledException)
            {
                this.logger.LogTrace("(-)[CANCELLED]:false");
                return(false);
            }

            this.logger.LogTrace("(-):true");
            return(true);
        }
Пример #5
0
        /// <summary>
        /// Processing of inventory payload message from the peer.
        /// Adds inventory to known inventory then sends GetDataPayload to the attached peer.
        /// </summary>
        /// <param name="peer">The peer sending the message.</param>
        /// <param name="invPayload">The inventory payload in the message.</param>
        private async Task ProcessInvAsync(INetworkPeer peer, InvPayload invPayload)
        {
            Guard.NotNull(peer, nameof(peer));
            this.logger.LogTrace("({0}:'{1}',{2}.{3}.{4}:{5})", nameof(peer), peer.RemoteSocketEndpoint, nameof(invPayload), nameof(invPayload.Inventory), nameof(invPayload.Inventory.Count), invPayload.Inventory.Count);

            if (invPayload.Inventory.Count > ConnectionManager.MaxInventorySize)
            {
                this.logger.LogTrace("(-)[MAX_INV_SZ]");
                //Misbehaving(pfrom->GetId(), 20); // TODO: Misbehaving
                return; //error("message inv size() = %u", vInv.size());
            }

            if (this.initialBlockDownloadState.IsInitialBlockDownload())
            {
                this.logger.LogTrace("(-)[IS_IBD]");
                return;
            }

            //uint32_t nFetchFlags = GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus());

            var send = new GetDataPayload();

            foreach (InventoryVector inv in invPayload.Inventory.Where(inv => inv.Type.HasFlag(InventoryType.MSG_TX)))
            {
                //inv.type |= nFetchFlags;

                // TODO: This is incorrect, in blocks only mode we should just add to known inventory but not relay
                if (this.isBlocksOnlyMode)
                {
                    this.logger.LogInformation("Transaction ID '{0}' inventory sent in violation of protocol peer '{1}'.", inv.Hash, peer.RemoteSocketEndpoint);
                }

                if (await this.orphans.AlreadyHaveAsync(inv.Hash))
                {
                    this.logger.LogDebug("Transaction ID '{0}' already in orphans, skipped.", inv.Hash);
                    continue;
                }

                send.Inventory.Add(new InventoryVector(peer.AddSupportedOptions(InventoryType.MSG_TX), inv.Hash));
            }

            // add to known inventory
            lock (this.lockObject)
            {
                foreach (InventoryVector inventoryVector in send.Inventory)
                {
                    this.filterInventoryKnown.Add(inventoryVector.Hash);
                }
            }

            if (peer.IsConnected)
            {
                this.logger.LogTrace("Asking for transaction data from peer '{0}'.", peer.RemoteSocketEndpoint);
                await peer.SendMessageAsync(send).ConfigureAwait(false);
            }

            this.logger.LogTrace("(-)");
        }
Пример #6
0
        /// <summary>
        /// Processing of inventory payload message from the peer.
        /// Adds inventory to known inventory then sends GetDataPayload to the attached peer.
        /// </summary>
        /// <param name="peer">The peer sending the message.</param>
        /// <param name="invPayload">The inventory payload in the message.</param>
        private async Task ProcessInvAsync(INetworkPeer peer, InvPayload invPayload)
        {
            Guard.NotNull(peer, nameof(peer));

            if (invPayload.Inventory.Count > ConnectionManager.MaxInventorySize)
            {
                this.logger.LogTrace("(-)[MAX_INV_SZ]");
                //Misbehaving(pfrom->GetId(), 20); // TODO: Misbehaving
                return; //error("message inv size() = %u", vInv.size());
            }

            //uint32_t nFetchFlags = GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus());

            var inventoryTxs = invPayload.Inventory.Where(inv => inv.Type.HasFlag(InventoryType.MSG_TX));

            lock (this.lockObject)
            {
                foreach (var inv in inventoryTxs)
                {
                    this.filterInventoryKnown.Add(inv.Hash);
                }
            }

            var send = new GetDataPayload();

            foreach (var inv in inventoryTxs)
            {
                if (await this.orphans.AlreadyHaveAsync(inv.Hash).ConfigureAwait(false))
                {
                    this.logger.LogDebug("Transaction ID '{0}' already in orphans, skipped.", inv.Hash);
                    continue;
                }

                if (this.isBlocksOnlyMode)
                {
                    this.logger.LogDebug("Transaction ID '{0}' inventory sent in violation of protocol peer '{1}'.", inv.Hash, peer.RemoteSocketEndpoint);
                    continue;
                }

                send.Inventory.Add(new InventoryVector(peer.AddSupportedOptions(InventoryType.MSG_TX), inv.Hash));
            }

            if (peer.IsConnected && (send.Inventory.Count > 0))
            {
                this.logger.LogDebug("Asking for transaction data from peer '{0}'.", peer.RemoteSocketEndpoint);
                await peer.SendMessageAsync(send).ConfigureAwait(false);
            }
        }
        /// <summary>
        /// Sends transactions as inventory to attached peer.
        /// </summary>
        /// <param name="peer">Peer to send transactions to.</param>
        /// <param name="trxList">List of transactions.</param>
        private async Task SendAsTxInventoryAsync(INetworkPeer peer, List <uint256> trxList)
        {
            var queue = new Queue <InventoryVector>(trxList.Select(s => new InventoryVector(peer.AddSupportedOptions(InventoryType.MSG_TX), s)));

            while (queue.Count > 0)
            {
                InventoryVector[] items = queue.TakeAndRemove(ConnectionManager.MaxInventorySize).ToArray();
                if (peer.IsConnected)
                {
                    this.logger.LogTrace("Sending transaction inventory to peer '{0}'.", peer.RemoteSocketEndpoint);
                    await peer.SendMessageAsync(new InvPayload(items)).ConfigureAwait(false);
                }
            }
        }