Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Potential Fix for stuck nodes: Don't lose future blocks if multiple future blocks received at the same height #489

Merged
merged 6 commits into from
Nov 30, 2018
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions neo/Ledger/Blockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public class ImportCompleted { }
private readonly List<UInt256> header_index = new List<UInt256>();
private uint stored_header_count = 0;
private readonly Dictionary<UInt256, Block> block_cache = new Dictionary<UInt256, Block>();
private readonly Dictionary<uint, Block> block_cache_unverified = new Dictionary<uint, Block>();
private readonly Dictionary<uint, LinkedList<Block>> block_cache_unverified = new Dictionary<uint, LinkedList<Block>>();
private readonly MemoryPool mem_pool = new MemoryPool(50_000);
private readonly ConcurrentDictionary<UInt256, Transaction> mem_pool_unverified = new ConcurrentDictionary<UInt256, Transaction>();
internal readonly RelayCache RelayCache = new RelayCache(100);
Expand Down Expand Up @@ -253,6 +253,14 @@ private void OnImport(IEnumerable<Block> blocks)
Sender.Tell(new ImportCompleted());
}

private void AddUnverifiedBlockToCache(Block block)
{
if (!block_cache_unverified.TryGetValue(block.Index, out LinkedList<Block> blocks))
blocks = new LinkedList<Block>();

blocks.AddLast(block);
}

private RelayResultReason OnNewBlock(Block block)
{
if (block.Index <= Height)
Expand All @@ -261,11 +269,22 @@ private RelayResultReason OnNewBlock(Block block)
return RelayResultReason.AlreadyExists;
if (block.Index - 1 >= header_index.Count)
{
block_cache_unverified[block.Index] = block;
AddUnverifiedBlockToCache(block);
return RelayResultReason.UnableToVerify;
}
if (block.Index == header_index.Count)
{
if (block.Index > Height + 1)
{
// This could be a couple blocks ahead, and though it doesn't verify against our current
// snapshot, it may verify later. If we were to lose this block and not add it to
// block_cache_unverified here it will never be tried again because knownHashes in TaskManager
// will already have the hash so won't attempt to get the data again. (This code being missing
// is very likely why nodes were getting stuck)

AddUnverifiedBlockToCache(block);
return RelayResultReason.UnableToVerify;
}
if (!block.Verify(currentSnapshot))
return RelayResultReason.Invalid;
}
Expand Down Expand Up @@ -300,8 +319,12 @@ private RelayResultReason OnNewBlock(Block block)
system.LocalNode.Tell(new LocalNode.RelayDirectly { Inventory = block });
}
SaveHeaderHashList();
if (block_cache_unverified.TryGetValue(Height + 1, out block_persist))
Self.Tell(block_persist, ActorRefs.NoSender);

if (block_cache_unverified.TryGetValue(Height + 1, out LinkedList<Block> unverifiedBlocks))
{
foreach (var unverifiedBlock in unverifiedBlocks)
Self.Tell(unverifiedBlock, ActorRefs.NoSender);
}
}
else
{
Expand Down