public async Task Can_add_new_block() { _remoteBlockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(QueueBasedSyncManager.MaxBatchSize).TestObject; ISynchronizationPeer peer = new SynchronizationPeerMock(_remoteBlockTree); ManualResetEvent resetEvent = new ManualResetEvent(false); _manager.SyncEvent += (sender, args) => { if (args.SyncStatus == SyncStatus.Completed || args.SyncStatus == SyncStatus.Failed) { resetEvent.Set(); } }; _manager.Start(); Task addPeerTask = _manager.AddPeer(peer); Task firstToComplete = await Task.WhenAny(addPeerTask, Task.Delay(_standardTimeoutUnit)); Assert.AreSame(addPeerTask, firstToComplete); Block block = Build.A.Block.WithParent(_remoteBlockTree.Head).TestObject; _manager.AddNewBlock(block, peer.NodeId); resetEvent.WaitOne(_standardTimeoutUnit); Assert.AreEqual(QueueBasedSyncManager.MaxBatchSize - 1, (int)_blockTree.BestSuggested.Number); }
public void Can_sync_on_split_of_length_6() { BlockTree miner1Tree = Build.A.BlockTree(_genesisBlock).OfChainLength(6).TestObject; ISynchronizationPeer miner1 = new SynchronizationPeerMock(miner1Tree); ManualResetEvent resetEvent = new ManualResetEvent(false); _manager.SyncEvent += (sender, args) => { if (args.SyncStatus == SyncStatus.Completed || args.SyncStatus == SyncStatus.Failed) { resetEvent.Set(); } }; _manager.Start(); _manager.AddPeer(miner1); resetEvent.WaitOne(_standardTimeoutUnit); Assert.AreEqual(miner1Tree.BestSuggested.Hash, _blockTree.BestSuggested.Hash, "client agrees with miner before split"); miner1Tree.AddBranch(7, 0, 1); Assert.AreNotEqual(miner1Tree.BestSuggested.Hash, _blockTree.BestSuggested.Hash, "client does not agree with miner after split"); resetEvent.Reset(); _manager.AddNewBlock(miner1Tree.RetrieveHeadBlock(), miner1.Node.Id); resetEvent.WaitOne(_standardTimeoutUnit); Assert.AreEqual(miner1Tree.BestSuggested.Hash, _blockTree.BestSuggested.Hash, "client agrees with miner after split"); }
public async Task Can_resync_if_missed_a_block() { _remoteBlockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(QueueBasedSyncManager.MaxBatchSize).TestObject; ISynchronizationPeer peer = new SynchronizationPeerMock(_remoteBlockTree); SemaphoreSlim semaphore = new SemaphoreSlim(0); _manager.SyncEvent += (sender, args) => { if (args.SyncStatus == SyncStatus.Completed || args.SyncStatus == SyncStatus.Failed) { semaphore.Release(1); } }; _manager.Start(); Task addPeerTask = _manager.AddPeer(peer); Task firstToComplete = await Task.WhenAny(addPeerTask, Task.Delay(_standardTimeoutUnit)); Assert.AreSame(addPeerTask, firstToComplete); BlockTreeBuilder.ExtendTree(_remoteBlockTree, QueueBasedSyncManager.MaxBatchSize * 2); _manager.AddNewBlock(_remoteBlockTree.RetrieveHeadBlock(), peer.NodeId); semaphore.Wait(_standardTimeoutUnit); semaphore.Wait(_standardTimeoutUnit); Assert.AreEqual(QueueBasedSyncManager.MaxBatchSize * 2 - 1, (int)_blockTree.BestSuggested.Number); }
public async Task Can_sync_on_split_of_length_6() { BlockTree miner1Tree = Build.A.BlockTree(_genesisBlock).OfChainLength(6).TestObject; ISynchronizationPeer miner1 = new SynchronizationPeerMock(miner1Tree); ManualResetEvent resetEvent = new ManualResetEvent(false); _manager.SyncEvent += (sender, args) => { resetEvent.Set(); }; Task addMiner1Task = _manager.AddPeer(miner1); await Task.WhenAll(addMiner1Task); resetEvent.WaitOne(TimeSpan.FromSeconds(1)); Assert.AreEqual(miner1Tree.BestSuggested.Hash, _blockTree.BestSuggested.Hash, "client agrees with miner before split"); miner1Tree.AddBranch(7, 0, 1); Assert.AreNotEqual(miner1Tree.BestSuggested.Hash, _blockTree.BestSuggested.Hash, "client does not agree with miner after split"); resetEvent.Reset(); _manager.AddNewBlock(miner1Tree.RetrieveHeadBlock(), miner1.NodeId); resetEvent.WaitOne(TimeSpan.FromSeconds(1)); Assert.AreEqual(miner1Tree.BestSuggested.Hash, _blockTree.BestSuggested.Hash, "client agrees with miner after split"); }
public void Syncs_with_empty_peer() { _remoteBlockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(1).TestObject; ISynchronizationPeer peer = new SynchronizationPeerMock(_remoteBlockTree); _manager.Start(); _manager.AddPeer(peer); Assert.AreEqual(0, (int)_blockTree.BestSuggested.Number); }
public async Task Syncs_with_empty_peer() { _remoteBlockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(0).TestObject; ISynchronizationPeer peer = new SynchronizationPeerMock(_remoteBlockTree); _manager.Start(); Task addPeerTask = _manager.AddPeer(peer); Task firstToComplete = await Task.WhenAny(addPeerTask, Task.Delay(_standardTimeoutUnit)); Assert.AreSame(addPeerTask, firstToComplete); Assert.AreEqual(0, (int)_blockTree.BestSuggested.Number); }
public void Syncs_when_knows_more_blocks() { _blockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(QueueBasedSyncManager.MaxBatchSize * 2).TestObject; _remoteBlockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(1).TestObject; ISynchronizationPeer peer = new SynchronizationPeerMock(_remoteBlockTree); ManualResetEvent resetEvent = new ManualResetEvent(false); _manager.SyncEvent += (sender, args) => { resetEvent.Set(); }; _manager.Start(); _manager.AddPeer(peer); resetEvent.WaitOne(_standardTimeoutUnit); Assert.AreEqual(QueueBasedSyncManager.MaxBatchSize * 2 - 1, (int)_blockTree.BestSuggested.Number); }
public async Task Syncs_with_empty_peer() { _remoteBlockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(0).TestObject; ISynchronizationPeer peer = new SynchronizationPeerMock(_remoteBlockTree); ManualResetEvent resetEvent = new ManualResetEvent(false); _manager.SyncEvent += (sender, args) => { resetEvent.Set(); }; Task addPeerTask = _manager.AddPeer(peer); Task firstToComplete = await Task.WhenAny(addPeerTask, Task.Delay(2000)); Assert.AreSame(addPeerTask, firstToComplete); _manager.Start(); resetEvent.WaitOne(TimeSpan.FromMilliseconds(2000)); Assert.AreEqual(0, (int)_blockTree.BestSuggested.Number); }
public async Task Syncs_when_knows_more_blocks() { _blockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(QueueBasedSyncManager.MaxBatchSize * 2).TestObject; _remoteBlockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(0).TestObject; ISynchronizationPeer peer = new SynchronizationPeerMock(_remoteBlockTree); ManualResetEvent resetEvent = new ManualResetEvent(false); _manager.SyncEvent += (sender, args) => { resetEvent.Set(); }; _manager.Start(); Task addPeerTask = _manager.AddPeer(peer); Task firstToComplete = await Task.WhenAny(addPeerTask, Task.Delay(_standardTimeoutUnit)); Assert.AreSame(addPeerTask, firstToComplete); resetEvent.WaitOne(_standardTimeoutUnit); Assert.AreEqual(QueueBasedSyncManager.MaxBatchSize * 2 - 1, (int)_blockTree.BestSuggested.Number); }
public async Task Does_not_do_full_sync_when_not_needed_with_split() { BlockTree minerTree = Build.A.BlockTree(_genesisBlock).OfChainLength(6).TestObject; ISynchronizationPeer miner1 = new SynchronizationPeerMock(minerTree); AutoResetEvent resetEvent = new AutoResetEvent(false); _manager.SyncEvent += (sender, args) => { if (args.SyncStatus == SyncStatus.Completed || args.SyncStatus == SyncStatus.Failed) { resetEvent.Set(); } }; _manager.Start(); Task addMiner1Task = _manager.AddPeer(miner1); await Task.WhenAll(addMiner1Task); resetEvent.WaitOne(_standardTimeoutUnit); Assert.AreEqual(minerTree.BestSuggested.Hash, _blockTree.BestSuggested.Hash, "client agrees with miner before split"); Block newBlock = Build.A.Block.WithParent(minerTree.Head).TestObject; minerTree.SuggestBlock(newBlock); minerTree.UpdateMainChain(newBlock); ISynchronizationPeer miner2 = Substitute.For <ISynchronizationPeer>(); miner2.GetHeadBlockNumber(Arg.Any <CancellationToken>()).Returns(miner1.GetHeadBlockNumber(CancellationToken.None)); miner2.GetHeadBlockHash(Arg.Any <CancellationToken>()).Returns(miner1.GetHeadBlockHash(CancellationToken.None)); miner2.NodeId.Returns(new NodeId(TestObject.PublicKeyB)); Assert.AreEqual(newBlock.Number, await miner2.GetHeadBlockNumber(Arg.Any <CancellationToken>()), "number as expected"); Assert.AreEqual(newBlock.Hash, await miner2.GetHeadBlockHash(default(CancellationToken)), "hash as expected"); await _manager.AddPeer(miner2); resetEvent.WaitOne(_standardTimeoutUnit); await miner2.Received().GetBlockHeaders(6, 1, 0, default(CancellationToken)); }
public async Task Can_sync_on_split_of_length_1() { BlockTree miner1Tree = Build.A.BlockTree(_genesisBlock).OfChainLength(6).TestObject; ISynchronizationPeer miner1 = new SynchronizationPeerMock(miner1Tree); ManualResetEvent resetEvent = new ManualResetEvent(false); _manager.SyncEvent += (sender, args) => { if (args.SyncStatus == SyncStatus.Completed || args.SyncStatus == SyncStatus.Failed) { resetEvent.Set(); } }; _manager.Start(); Task addMiner1Task = _manager.AddPeer(miner1); await Task.WhenAll(addMiner1Task); resetEvent.WaitOne(_standardTimeoutUnit); Assert.AreEqual(miner1Tree.BestSuggested.Hash, _blockTree.BestSuggested.Hash, "client agrees with miner before split"); Block splitBlock = Build.A.Block.WithParent(miner1Tree.FindParent(miner1Tree.Head)).WithDifficulty(miner1Tree.Head.Difficulty - 1).TestObject; Block splitBlockChild = Build.A.Block.WithParent(splitBlock).TestObject; miner1Tree.SuggestBlock(splitBlock); miner1Tree.UpdateMainChain(splitBlock); miner1Tree.SuggestBlock(splitBlockChild); miner1Tree.UpdateMainChain(splitBlockChild); Assert.AreEqual(splitBlockChild.Hash, miner1Tree.BestSuggested.Hash, "split as expected"); resetEvent.Reset(); _manager.AddNewBlock(splitBlockChild, miner1.NodeId); resetEvent.WaitOne(_standardTimeoutUnit); Assert.AreEqual(miner1Tree.BestSuggested.Hash, _blockTree.BestSuggested.Hash, "client agrees with miner after split"); }
public async Task Can_resync_if_missed_a_block() { _remoteBlockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(SynchronizationManager.BatchSize).TestObject; ISynchronizationPeer peer = new SynchronizationPeerMock(_remoteBlockTree); ManualResetEvent resetEvent = new ManualResetEvent(false); _manager.SyncEvent += (sender, args) => { resetEvent.Set(); }; Task addPeerTask = _manager.AddPeer(peer); Task firstToComplete = await Task.WhenAny(addPeerTask, Task.Delay(2000)); Assert.AreSame(addPeerTask, firstToComplete); _manager.Start(); resetEvent.WaitOne(TimeSpan.FromMilliseconds(2000)); BlockTreeBuilder.ExtendTree(_remoteBlockTree, SynchronizationManager.BatchSize * 2); _manager.AddNewBlock(_remoteBlockTree.RetrieveHeadBlock(), peer.NodeId); Assert.AreEqual(SynchronizationManager.BatchSize * 2 - 1, (int)_blockTree.BestSuggested.Number); }
public void Retrieves_missing_blocks_in_batches() { _remoteBlockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(QueueBasedSyncManager.MaxBatchSize * 2).TestObject; ISynchronizationPeer peer = new SynchronizationPeerMock(_remoteBlockTree); ManualResetEvent resetEvent = new ManualResetEvent(false); _manager.SyncEvent += (sender, args) => { if (args.SyncStatus == SyncStatus.Completed || args.SyncStatus == SyncStatus.Failed) { resetEvent.Set(); } }; _manager.Start(); _manager.AddPeer(peer); resetEvent.WaitOne(_standardTimeoutUnit); Assert.AreEqual(QueueBasedSyncManager.MaxBatchSize * 2 - 1, (int)_blockTree.BestSuggested.Number); }
public async Task Retrieves_missing_blocks_in_batches() { _remoteBlockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(SynchronizationManager.MaxBatchSize * 2).TestObject; ISynchronizationPeer peer = new SynchronizationPeerMock(_remoteBlockTree); ManualResetEvent resetEvent = new ManualResetEvent(false); _manager.SyncEvent += (sender, args) => { if (args.SyncStatus == SyncStatus.Completed || args.SyncStatus == SyncStatus.Failed) { resetEvent.Set(); } }; _manager.Start(); Task addPeerTask = _manager.AddPeer(peer); Task firstToComplete = await Task.WhenAny(addPeerTask, Task.Delay(_standardTimeoutUnit)); Assert.AreSame(addPeerTask, firstToComplete); resetEvent.WaitOne(_standardTimeoutUnit); Assert.AreEqual(SynchronizationManager.MaxBatchSize * 2 - 1, (int)_blockTree.BestSuggested.Number); }
public async Task Can_sync_on_split_of_length_1() { BlockTree miner1Tree = Build.A.BlockTree(_genesisBlock).OfChainLength(6).TestObject; ISynchronizationPeer miner1 = new SynchronizationPeerMock(miner1Tree); ManualResetEvent resetEvent = new ManualResetEvent(false); _manager.SyncEvent += (sender, args) => { resetEvent.Set(); }; Task addMiner1Task = _manager.AddPeer(miner1); await Task.WhenAll(addMiner1Task); resetEvent.WaitOne(TimeSpan.FromSeconds(1)); Assert.AreEqual(miner1Tree.BestSuggested.Hash, _blockTree.BestSuggested.Hash, "client agrees with miner before split"); Block splitBlock = Build.A.Block.WithParent(miner1Tree.FindParent(miner1Tree.Head)).WithDifficulty(miner1Tree.Head.Difficulty - 1).TestObject; Block splitBlockChild = Build.A.Block.WithParent(splitBlock).TestObject; miner1Tree.SuggestBlock(splitBlock); miner1Tree.MarkAsProcessed(splitBlock.Hash); miner1Tree.MoveToMain(splitBlock.Hash); miner1Tree.SuggestBlock(splitBlockChild); miner1Tree.MarkAsProcessed(splitBlockChild.Hash); miner1Tree.MoveToMain(splitBlockChild.Hash); Assert.AreEqual(splitBlockChild.Hash, miner1Tree.BestSuggested.Hash, "split as expected"); resetEvent.Reset(); _manager.AddNewBlock(splitBlockChild, miner1.NodeId); resetEvent.WaitOne(TimeSpan.FromSeconds(1)); Assert.AreEqual(miner1Tree.BestSuggested.Hash, _blockTree.BestSuggested.Hash, "client agrees with miner after split"); }
public async Task Does_not_do_full_sync_when_not_needed_with_split() { BlockTree minerTree = Build.A.BlockTree(_genesisBlock).OfChainLength(6).TestObject; ISynchronizationPeer miner1 = new SynchronizationPeerMock(minerTree); ManualResetEvent resetEvent = new ManualResetEvent(false); _manager.SyncEvent += (sender, args) => { resetEvent.Set(); }; Task addMiner1Task = _manager.AddPeer(miner1); await Task.WhenAll(addMiner1Task); resetEvent.WaitOne(TimeSpan.FromSeconds(1)); Assert.AreEqual(minerTree.BestSuggested.Hash, _blockTree.BestSuggested.Hash, "client agrees with miner before split"); Block newBlock = Build.A.Block.WithParent(minerTree.Head).TestObject; minerTree.SuggestBlock(newBlock); minerTree.MarkAsProcessed(newBlock.Hash); minerTree.MoveToMain(newBlock.Hash); ISynchronizationPeer miner2 = Substitute.For <ISynchronizationPeer>(); miner2.GetHeadBlockNumber(Arg.Any <CancellationToken>()).Returns(miner1.GetHeadBlockNumber(Arg.Any <CancellationToken>())); miner2.GetHeadBlockHash(Arg.Any <CancellationToken>()).Returns(miner1.GetHeadBlockHash(default(CancellationToken))); miner2.NodeId.Returns(new NodeId(TestObject.PublicKeyB)); Assert.AreEqual(newBlock.Number, await miner2.GetHeadBlockNumber(Arg.Any <CancellationToken>()), "number as expected"); Assert.AreEqual(newBlock.Hash, await miner2.GetHeadBlockHash(default(CancellationToken)), "hash as expected"); await _manager.AddPeer(miner2); await miner2.Received().GetBlockHeaders(6, 1, 0, default(CancellationToken)); }