Exemple #1
0
        /// <summary>
        /// Asks the connected peer for the block of the given hash, and returns a Future representing the answer.
        /// If you want the block right away and don't mind waiting for it, just call .get() on the result. Your thread
        /// will block until the peer answers. You can also use the Future object to wait with a timeout, or just check
        /// whether it's done later.
        /// </summary>
        /// <param name="blockHash">Hash of the block you were requesting.</param>
        /// <exception cref="IOException"/>
        public IAsyncResult BeginGetBlock(Sha256Hash blockHash, AsyncCallback callback, object state)
        {
            var getdata       = new GetDataMessage(_params);
            var inventoryItem = new InventoryItem(InventoryItem.ItemType.Block, blockHash);

            getdata.AddItem(inventoryItem);
            var future = new GetDataFuture <Block>(inventoryItem, callback, state);

            // Add to the list of things we're waiting for. It's important this come before the network send to avoid
            // race conditions.
            lock (_pendingGetBlockFutures)
            {
                _pendingGetBlockFutures.Add(future);
            }
            _conn.WriteMessage(getdata);
            return(future);
        }
Exemple #2
0
        /// <exception cref="IOException"/>
        private void ProcessInv(InventoryMessage inv)
        {
            // This should be called in the network loop thread for this peer

            // The peer told us about some blocks or transactions they have. For now we only care about blocks.
            // Note that as we don't actually want to store the entire block chain or even the headers of the block
            // chain, we may end up requesting blocks we already requested before. This shouldn't (in theory) happen
            // enough to be a problem.
            var topBlock = _blockChain.UnconnectedBlock;
            var topHash  = (topBlock != null ? topBlock.Hash : null);
            var items    = inv.Items;

            if (items.Count == 1 && items[0].Type == InventoryItem.ItemType.Block && topHash != null &&
                items[0].Hash.Equals(topHash))
            {
                // An inv with a single hash containing our most recent unconnected block is a special inv,
                // it's kind of like a tickle from the peer telling us that it's time to download more blocks to catch up to
                // the block chain. We could just ignore this and treat it as a regular inv but then we'd download the head
                // block over and over again after each batch of 500 blocks, which is wasteful.
                BlockChainDownload(topHash);
                return;
            }
            var getdata = new GetDataMessage(_params);
            var dirty   = false;

            foreach (var item in items)
            {
                if (item.Type != InventoryItem.ItemType.Block)
                {
                    continue;
                }
                getdata.AddItem(item);
                dirty = true;
            }
            // No blocks to download. This probably contained transactions instead, but right now we can't prove they are
            // valid so we don't bother downloading transactions that aren't in blocks yet.
            if (!dirty)
            {
                return;
            }
            // This will cause us to receive a bunch of block messages.
            _conn.WriteMessage(getdata);
        }