/// <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);
}