/// <exception cref="IOException"/>
private void ProcessBlock(Block m)
{
// This should called in the network loop thread for this peer
try
{
// Was this block requested by getblock?
lock (_pendingGetBlockFutures)
{
for (var i = 0; i < _pendingGetBlockFutures.Count; i++)
{
var f = _pendingGetBlockFutures[i];
if (f.Item.Hash.Equals(m.Hash))
{
// Yes, it was. So pass it through the future.
f.SetResult(m);
// Blocks explicitly requested don't get sent to the block chain.
_pendingGetBlockFutures.RemoveAt(i);
return;
}
}
}
// Otherwise it's a block sent to us because the peer thought we needed it, so add it to the block chain.
// This call will synchronize on blockChain.
if (_blockChain.Add(m))
{
// The block was successfully linked into the chain. Notify the user of our progress.
if (BlocksDownloaded != null)
{
BlocksDownloaded(this, new BlocksDownloadedEventArgs(m, GetPeerBlocksToGet()));
}
}
else
{
// This block is unconnected - we don't know how to get from it back to the genesis block yet. That
// must mean that there are blocks we are missing, so do another getblocks with a new block locator
// to ask the peer to send them to us. This can happen during the initial block chain download where
// the peer will only send us 500 at a time and then sends us the head block expecting us to request
// the others.
// TODO: Should actually request root of orphan chain here.
BlockChainDownload(m.Hash);
}
}
catch (VerificationException e)
{
// We don't want verification failures to kill the thread.
_log.Warn("Block verification failed", e);
}
catch (ScriptException e)
{
// We don't want script failures to kill the thread.
_log.Warn("Script exception", e);
}
}