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);
        }
示例#2
0
        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);
        }
示例#4
0
        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");
        }
示例#5
0
        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);
        }
示例#7
0
        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);
        }
示例#8
0
        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");
        }
示例#12
0
        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);
        }
示例#13
0
        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);
        }
示例#15
0
        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");
        }
示例#16
0
        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));
        }