public void Can_resync_if_missed_a_block()
        {
            _remoteBlockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(SyncBatchSize.Max).TestObject;
            ISyncPeer peer = new SyncPeerMock(_remoteBlockTree);

            SemaphoreSlim semaphore = new SemaphoreSlim(0);

            _synchronizer.SyncEvent += (sender, args) =>
            {
                if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed)
                {
                    semaphore.Release(1);
                }
            };
            _pool.Start();
            _synchronizer.Start();
            _pool.AddPeer(peer);

            BlockTreeBuilder.ExtendTree(_remoteBlockTree, SyncBatchSize.Max * 2);
            _syncServer.AddNewBlock(_remoteBlockTree.RetrieveHeadBlock(), peer);

            semaphore.Wait(_standardTimeoutUnit);
            semaphore.Wait(_standardTimeoutUnit);

            Assert.AreEqual(SyncBatchSize.Max * 2 - 1, (int)_blockTree.BestSuggestedHeader.Number);
        }
        public void Can_add_new_block()
        {
            _remoteBlockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(SyncBatchSize.Max).TestObject;
            ISyncPeer peer = new SyncPeerMock(_remoteBlockTree);

            ManualResetEvent resetEvent = new ManualResetEvent(false);

            _synchronizer.SyncEvent += (sender, args) =>
            {
                if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed)
                {
                    resetEvent.Set();
                }
            };

            _pool.Start();
            _synchronizer.Start();
            _pool.AddPeer(peer);

            Block block = Build.A.Block.WithParent(_remoteBlockTree.Head).WithTotalDifficulty((_remoteBlockTree.Head.TotalDifficulty ?? 0) + 1).TestObject;

            _syncServer.AddNewBlock(block, peer);

            resetEvent.WaitOne(_standardTimeoutUnit);

            Assert.AreEqual(SyncBatchSize.Max - 1, (int)_blockTree.BestSuggestedHeader.Number);
        }
        public void  Can_sync_on_split_of_length_6()
        {
            BlockTree miner1Tree = Build.A.BlockTree(_genesisBlock).OfChainLength(6).TestObject;
            ISyncPeer miner1     = new SyncPeerMock(miner1Tree);

            ManualResetEvent resetEvent = new ManualResetEvent(false);

            _synchronizer.SyncEvent += (sender, args) =>
            {
                if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed)
                {
                    resetEvent.Set();
                }
            };

            _pool.Start();
            _synchronizer.Start();
            _pool.AddPeer(miner1);

            resetEvent.WaitOne(_standardTimeoutUnit);

            Assert.AreEqual(miner1Tree.BestSuggestedHeader.Hash, _blockTree.BestSuggestedHeader.Hash, "client agrees with miner before split");

            miner1Tree.AddBranch(7, 0, 1);

            Assert.AreNotEqual(miner1Tree.BestSuggestedHeader.Hash, _blockTree.BestSuggestedHeader.Hash, "client does not agree with miner after split");

            resetEvent.Reset();

            _syncServer.AddNewBlock(miner1Tree.RetrieveHeadBlock(), miner1);

            resetEvent.WaitOne(_standardTimeoutUnit);

            Assert.AreEqual(miner1Tree.BestSuggestedHeader.Hash, _blockTree.BestSuggestedHeader.Hash, "client agrees with miner after split");
        }
Exemple #4
0
        public void Will_inform_connecting_peer_about_the_alternative_branch_with_same_difficulty()
        {
            if (_synchronizerType == SynchronizerType.Fast)
            {
                return;
            }

            SyncPeerMock peerA = new SyncPeerMock("A");

            peerA.AddBlocksUpTo(2);

            SyncPeerMock peerB = new SyncPeerMock("B");

            peerB.AddBlocksUpTo(2, 0, 1);

            When.Syncing
            .AfterProcessingGenesis()
            .AfterPeerIsAdded(peerA)
            .BestSuggestedBlockHasNumber(2)
            .AfterPeerIsAdded(peerB)
            .WaitUntilInitialized()
            .Stop();

            Assert.AreNotEqual(peerB.HeadBlock.Hash, peerA.HeadBlock.Hash);

            Block block = null;

            SpinWait.SpinUntil(() =>
            {
                bool receivedBlock = peerB.ReceivedBlocks.TryPeek(out block);
                return(receivedBlock && block.Hash == peerA.HeadBlock.Hash);
            }, WaitTime);

            Assert.AreEqual(block?.Header.Hash, peerA.HeadBlock.Hash);
        }
Exemple #5
0
        public void Can_stop()
        {
            SyncPeerMock peerA = new SyncPeerMock("A");

            peerA.AddBlocksUpTo(SyncBatchSize.Max);

            When.Syncing
            .Stop();
        }
Exemple #6
0
        public void Can_sync_with_one_peer_straight()
        {
            SyncPeerMock peerA = new SyncPeerMock("A");

            When.Syncing
            .AfterProcessingGenesis()
            .AfterPeerIsAdded(peerA)
            .BestSuggested.BlockIsSameAsGenesis().Stop();
        }
        public void Syncs_with_empty_peer()
        {
            _remoteBlockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(1).TestObject;
            ISyncPeer peer = new SyncPeerMock(_remoteBlockTree);

            _pool.Start();
            _synchronizer.Start();
            _pool.AddPeer(peer);

            Assert.AreEqual(0, (int)_blockTree.BestSuggestedHeader.Number);
        }
Exemple #8
0
        public void Can_sync_with_one_peer_straight_and_extend_chain()
        {
            SyncPeerMock peerA = new SyncPeerMock("A");

            peerA.AddBlocksUpTo(3);

            When.Syncing
            .AfterProcessingGenesis()
            .AfterPeerIsAdded(peerA)
            .BestSuggestedHeaderIs(peerA.HeadHeader).Stop();
        }
Exemple #9
0
        public void Can_sync_more_than_a_batch()
        {
            SyncPeerMock peerA = new SyncPeerMock("A");

            peerA.AddBlocksUpTo(SyncBatchSize.Max * 3);

            When.Syncing
            .AfterProcessingGenesis()
            .AfterPeerIsAdded(peerA)
            .BestSuggestedHeaderIs(peerA.HeadHeader).Stop();
        }
Exemple #10
0
        public void Will_remove_peer_when_init_fails()
        {
            SyncPeerMock peerA = new SyncPeerMock("A", true, true);

            peerA.AddBlocksUpTo(1);

            When.Syncing
            .AfterProcessingGenesis()
            .AfterPeerIsAdded(peerA)
            .WaitAMoment()
            .PeerCountIs(0).Stop();
        }
Exemple #11
0
        public void Can_extend_chain_by_one_on_block_hint_message()
        {
            SyncPeerMock peerA = new SyncPeerMock("A");

            peerA.AddBlocksUpTo(1);

            When.Syncing
            .AfterProcessingGenesis()
            .AfterPeerIsAdded(peerA)
            .WaitUntilInitialized()
            .After(() => peerA.AddBlocksUpTo(2))
            .AfterHintBlockMessage(peerA.HeadBlock, peerA)
            .BestSuggestedHeaderIs(peerA.HeadHeader).Stop();
        }
Exemple #12
0
        public void Will_not_add_same_peer_twice()
        {
            SyncPeerMock peerA = new SyncPeerMock("A");

            peerA.AddBlocksUpTo(1);

            When.Syncing
            .AfterProcessingGenesis()
            .AfterPeerIsAdded(peerA)
            .AfterPeerIsAdded(peerA)
            .WaitUntilInitialized()
            .PeerCountIs(1)
            .BestSuggestedBlockHasNumber(1).Stop();
        }
Exemple #13
0
        public void Will_ignore_new_block_that_is_far_ahead()
        {
            // this test was designed for no sync-timer sync process
            // now it checks something different
            SyncPeerMock peerA = new SyncPeerMock("A");

            peerA.AddBlocksUpTo(1);

            When.Syncing
            .AfterProcessingGenesis()
            .AfterPeerIsAdded(peerA)
            .WaitUntilInitialized()
            .After(() => peerA.AddBlocksUpTo(16))
            .AfterNewBlockMessage(peerA.HeadBlock, peerA)
            .BestSuggestedHeaderIs(peerA.HeadHeader).Stop();
        }
        public void Syncs_when_knows_more_blocks()
        {
            _blockTree       = Build.A.BlockTree(_genesisBlock).OfChainLength(SyncBatchSize.Max * 2).TestObject;
            _remoteBlockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(1).TestObject;
            ISyncPeer peer = new SyncPeerMock(_remoteBlockTree);

            ManualResetEvent resetEvent = new ManualResetEvent(false);

            _synchronizer.SyncEvent += (sender, args) => { resetEvent.Set(); };
            _pool.Start();
            _synchronizer.Start();
            _pool.AddPeer(peer);

            resetEvent.WaitOne(_standardTimeoutUnit);
            Assert.AreEqual(SyncBatchSize.Max * 2 - 1, (int)_blockTree.BestSuggestedHeader.Number);
        }
Exemple #15
0
        public void Can_extend_chain_by_more_than_one_on_new_block_message()
        {
            SyncPeerMock peerA = new SyncPeerMock("A");

            peerA.AddBlocksUpTo(1);

            When.Syncing
            .AfterProcessingGenesis()
            .AfterPeerIsAdded(peerA)
            .WaitUntilInitialized()
            .After(() => peerA.AddBlocksUpTo(8))
            .AfterNewBlockMessage(peerA.HeadBlock, peerA)
            .BestSuggestedHeaderIs(peerA.HeadHeader).Wait().Stop();

            Console.WriteLine("why?");
        }
Exemple #16
0
        public void Can_sync_when_best_peer_is_timing_out()
        {
            SyncPeerMock peerA = new SyncPeerMock("A");

            peerA.AddBlocksUpTo(1);

            SyncPeerMock badPeer = new SyncPeerMock("B", false, false, true);

            badPeer.AddBlocksUpTo(20);

            When.Syncing
            .AfterProcessingGenesis()
            .AfterPeerIsAdded(badPeer)
            .WaitUntilInitialized()
            .AfterPeerIsAdded(peerA)
            .BestSuggestedBlockHasNumber(1).Stop();
        }
Exemple #17
0
        public void Will_not_reorganize_more_than_max_reorg_length()
        {
            SyncPeerMock peerA = new SyncPeerMock("A");

            peerA.AddBlocksUpTo(BlockDownloader.MaxReorganizationLength + 1);

            SyncPeerMock peerB = new SyncPeerMock("B");

            peerB.AddBlocksUpTo(BlockDownloader.MaxReorganizationLength + 2, 0, 1);

            When.Syncing
            .AfterProcessingGenesis()
            .AfterPeerIsAdded(peerA)
            .BestSuggestedHeaderIs(peerA.HeadHeader)
            .AfterPeerIsAdded(peerB)
            .BestSuggestedHeaderIs(peerA.HeadHeader).Stop();
        }
Exemple #18
0
        public void Can_reorg_based_on_total_difficulty()
        {
            SyncPeerMock peerA = new SyncPeerMock("A");

            peerA.AddBlocksUpTo(10);

            SyncPeerMock peerB = new SyncPeerMock("B");

            peerB.AddHighDifficultyBlocksUpTo(6, 0, 1);

            When.Syncing
            .AfterProcessingGenesis()
            .AfterPeerIsAdded(peerA)
            .BestSuggestedHeaderIs(peerA.HeadHeader)
            .AfterPeerIsAdded(peerB)
            .BestSuggestedHeaderIs(peerB.HeadHeader).Stop();
        }
Exemple #19
0
        public void Will_not_reorganize_on_same_chain_length()
        {
            SyncPeerMock peerA = new SyncPeerMock("A");

            peerA.AddBlocksUpTo(10);

            SyncPeerMock peerB = new SyncPeerMock("B");

            peerB.AddBlocksUpTo(10, 0, 1);

            When.Syncing
            .AfterProcessingGenesis()
            .AfterPeerIsAdded(peerA)
            .BestSuggestedHeaderIs(peerA.HeadHeader)
            .AfterPeerIsAdded(peerB)
            .BestSuggestedHeaderIs(peerA.HeadHeader).Stop();
        }
Exemple #20
0
        public void Can_reorg_on_add_peer()
        {
            SyncPeerMock peerA = new SyncPeerMock("A");

            peerA.AddBlocksUpTo(SyncBatchSize.Max);

            SyncPeerMock peerB = new SyncPeerMock("B");

            peerB.AddBlocksUpTo(SyncBatchSize.Max * 2, 0, 1);

            When.Syncing
            .AfterProcessingGenesis()
            .AfterPeerIsAdded(peerA)
            .BestSuggestedHeaderIs(peerA.HeadHeader)
            .AfterPeerIsAdded(peerB)
            .BestSuggestedHeaderIs(peerB.HeadHeader).Stop();
        }
Exemple #21
0
        public void Can_remove_peers()
        {
            SyncPeerMock peerA = new SyncPeerMock("A");
            SyncPeerMock peerB = new SyncPeerMock("B");

            When.Syncing
            .AfterProcessingGenesis()
            .AfterPeerIsAdded(peerA)
            .AfterPeerIsAdded(peerB)
            .WaitAMoment()
            .PeerCountIs(2)
            .AfterPeerIsRemoved(peerB)
            .WaitAMoment()
            .PeerCountIs(1)
            .AfterPeerIsRemoved(peerA)
            .WaitAMoment()
            .PeerCountIs(0).Stop();
        }
Exemple #22
0
        public void Can_reorg_on_hint_block_message()
        {
            SyncPeerMock peerA = new SyncPeerMock("A");

            peerA.AddBlocksUpTo(3);

            SyncPeerMock peerB = new SyncPeerMock("B");

            peerB.AddBlocksUpTo(3);

            When.Syncing
            .AfterProcessingGenesis()
            .AfterPeerIsAdded(peerA)
            .AfterPeerIsAdded(peerB)
            .Wait()
            .After(() => peerB.AddBlocksUpTo(6))
            .AfterHintBlockMessage(peerB.HeadBlock, peerB)
            .BestSuggestedHeaderIs(peerB.HeadHeader).Stop();
        }
        public void Can_sync_on_split_of_length_1()
        {
            BlockTree miner1Tree = Build.A.BlockTree(_genesisBlock).OfChainLength(6).TestObject;
            ISyncPeer miner1     = new SyncPeerMock(miner1Tree);

            ManualResetEvent resetEvent = new ManualResetEvent(false);

            _synchronizer.SyncEvent += (sender, args) =>
            {
                TestContext.WriteLine(args.SyncEvent);
                if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed)
                {
                    resetEvent.Set();
                }
            };

            _pool.Start();
            _synchronizer.Start();
            _pool.AddPeer(miner1);

            resetEvent.WaitOne(_standardTimeoutUnit);

            miner1Tree.BestSuggestedHeader.Should().BeEquivalentTo(_blockTree.BestSuggestedHeader, "client agrees with miner before split");

            Block splitBlock      = Build.A.Block.WithParent(miner1Tree.FindParent(miner1Tree.Head, BlockTreeLookupOptions.TotalDifficultyNotNeeded)).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);

            splitBlockChild.Header.Should().BeEquivalentTo(miner1Tree.BestSuggestedHeader, "split as expected");

            resetEvent.Reset();

            _syncServer.AddNewBlock(splitBlockChild, miner1);

            resetEvent.WaitOne(_standardTimeoutUnit);

            Assert.AreEqual(miner1Tree.BestSuggestedHeader.Hash, _blockTree.BestSuggestedHeader.Hash, "client agrees with miner after split");
        }
Exemple #24
0
        public void Can_extend_chain_on_hint_block_when_high_difficulty_low_number()
        {
            SyncPeerMock peerA = new SyncPeerMock("A");

            peerA.AddBlocksUpTo(10);

            SyncPeerMock peerB = new SyncPeerMock("B");

            peerB.AddHighDifficultyBlocksUpTo(5, 0, 1);

            When.Syncing
            .AfterProcessingGenesis()
            .AfterPeerIsAdded(peerA)
            .Wait()
            .AfterPeerIsAdded(peerB)
            .Wait()
            .After(() => peerB.AddHighDifficultyBlocksUpTo(6, 0, 1))
            .AfterHintBlockMessage(peerB.HeadBlock, peerB)
            .BestSuggestedHeaderIs(peerB.HeadHeader).Stop();
        }
        public async Task Does_not_do_full_sync_when_not_needed_with_split()
        {
            BlockTree minerTree = Build.A.BlockTree(_genesisBlock).OfChainLength(6).TestObject;
            ISyncPeer miner1    = new SyncPeerMock(minerTree);

            AutoResetEvent resetEvent = new AutoResetEvent(false);

            _synchronizer.SyncEvent += (sender, args) =>
            {
                if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed)
                {
                    resetEvent.Set();
                }
            };

            _pool.Start();
            _synchronizer.Start();
            _pool.AddPeer(miner1);
            resetEvent.WaitOne(_standardTimeoutUnit);

            Assert.AreEqual(minerTree.BestSuggestedHeader.Hash, _blockTree.BestSuggestedHeader.Hash, "client agrees with miner before split");

            Block newBlock = Build.A.Block.WithParent(minerTree.Head).TestObject;

            minerTree.SuggestBlock(newBlock);
            minerTree.UpdateMainChain(newBlock);

            ISyncPeer miner2 = Substitute.For <ISyncPeer>();

            miner2.GetHeadBlockHeader(Arg.Any <Keccak>(), Arg.Any <CancellationToken>()).Returns(miner1.GetHeadBlockHeader(null, CancellationToken.None));
            miner2.Node.Id.Returns(TestItem.PublicKeyB);

            Assert.AreEqual(newBlock.Number, await miner2.GetHeadBlockHeader(null, Arg.Any <CancellationToken>()), "number as expected");

            _pool.Start();
            _synchronizer.Start();
            _pool.AddPeer(miner2);
            resetEvent.WaitOne(_standardTimeoutUnit);

            await miner2.Received().GetBlockHeaders(6, 1, 0, default(CancellationToken));
        }
        public void Retrieves_missing_blocks_in_batches()
        {
            _remoteBlockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(SyncBatchSize.Max * 2).TestObject;
            ISyncPeer peer = new SyncPeerMock(_remoteBlockTree);

            ManualResetEvent resetEvent = new ManualResetEvent(false);

            _synchronizer.SyncEvent += (sender, args) =>
            {
                if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed)
                {
                    resetEvent.Set();
                }
            };
            _pool.Start();
            _synchronizer.Start();
            _pool.AddPeer(peer);

            resetEvent.WaitOne(_standardTimeoutUnit);
            Assert.AreEqual(SyncBatchSize.Max * 2 - 1, (int)_blockTree.BestSuggestedHeader.Number);
        }