public void RetrieveDeposits_ReturnsSmallAndNormalDeposits_Scenario5()
        {
            // Create a "chain" of 20 blocks.
            List <ChainedHeaderBlock> blocks = ChainedHeadersHelper.CreateConsecutiveHeadersAndBlocks(20, null, true);

            // Add 4 small deposits to blocks 5 through to 8 (the amounts are less than 10).
            for (int i = 5; i <= 8; i++)
            {
                blocks[i].Block.AddTransaction(new Transaction());
                CreateDepositTransaction(this.targetAddress, blocks[i].Block, Money.Coins(i), this.opReturnBytes);
            }

            // Add 6 normal deposits to block 11 through to 16.
            for (int i = 11; i <= 16; i++)
            {
                blocks[i].Block.AddTransaction(new Transaction());
                CreateDepositTransaction(this.targetAddress, blocks[i].Block, Money.Coins(i), this.opReturnBytes);
            }

            this.consensusManager.GetBlockData(Arg.Any <List <uint256> >()).Returns(delegate(CallInfo info)
            {
                var hashes = (List <uint256>)info[0];
                return(hashes.Select((hash) => blocks.Single(x => x.ChainedHeader.HashBlock == hash)).ToArray());
            });
            this.consensusManager.Tip.Returns(blocks.Last().ChainedHeader);

            var depositExtractor = new DepositExtractor(this.loggerFactory, this.federatedPegSettings, this.opReturnDataReader);

            var maturedBlocksProvider = new MaturedBlocksProvider(this.consensusManager, depositExtractor, this.federatedPegSettings, this.loggerFactory);

            SerializableResult <List <MaturedBlockDepositsModel> > depositsResult = maturedBlocksProvider.RetrieveDeposits(10);

            // Total deposits
            Assert.Empty(depositsResult.Value.SelectMany(b => b.Deposits));
        }
        public void GetMaturedBlocksReturnsDeposits()
        {
            List <ChainedHeaderBlock> blocks = ChainedHeadersHelper.CreateConsecutiveHeadersAndBlocks(10, null, true);

            ChainedHeader tip = blocks.Last().ChainedHeader;

            this.consensusManager.GetBlockData(Arg.Any <List <uint256> >()).Returns(delegate(CallInfo info)
            {
                var hashes = (List <uint256>)info[0];
                return(hashes.Select((hash) => blocks.Single(x => x.ChainedHeader.HashBlock == hash)).ToArray());
            });

            IFederatedPegSettings federatedPegSettings = Substitute.For <IFederatedPegSettings>();

            federatedPegSettings.MinimumConfirmationsNormalDeposits.Returns(0);

            var deposits = new List <IDeposit>()
            {
                new Deposit(new uint256(0), DepositRetrievalType.Normal, 100, "test", 0, new uint256(1))
            };

            IDepositExtractor depositExtractor = Substitute.For <IDepositExtractor>();

            depositExtractor.ExtractBlockDeposits(blocks.First(), DepositRetrievalType.Normal).ReturnsForAnyArgs(new MaturedBlockDepositsModel(new MaturedBlockInfoModel(), deposits));
            this.consensusManager.Tip.Returns(tip);

            // Makes every block a matured block.
            var maturedBlocksProvider = new MaturedBlocksProvider(this.consensusManager, depositExtractor, federatedPegSettings, this.loggerFactory);

            SerializableResult <List <MaturedBlockDepositsModel> > depositsResult = maturedBlocksProvider.RetrieveDeposits(0);

            // This will be double the amount of blocks because the mocked depositExtractor will always return a set of blocks
            // as that is how it has been configured.
            Assert.Equal(33, depositsResult.Value.Count);
        }
예제 #3
0
        public async Task AssignDownloadJobs_PeerThrowsAndHisAssignmentAreReassignedAsync()
        {
            INetworkPeer peer1 = this.helper.CreatePeer(out ExtendedBlockPullerBehavior behavior1);
            INetworkPeer peer2 = this.helper.CreatePeer(out ExtendedBlockPullerBehavior behavior2);

            behavior2.ShouldThrowAtRequestBlocksAsync = true;

            this.puller.SetMaxBlocksBeingDownloaded(int.MaxValue);

            List <ChainedHeader> headers = ChainedHeadersHelper.CreateConsecutiveHeaders(10000);

            this.puller.NewPeerTipClaimed(peer1, headers.Last());
            this.puller.NewPeerTipClaimed(peer2, headers.Last());

            this.puller.RequestBlocksDownload(headers);

            await this.puller.AssignDownloadJobsAsync();

            int headersReassignedFromPeer2Count = headers.Count - this.puller.AssignedDownloadsByHash.Values.Count(x => x.PeerId == peer1.Connection.Id);

            Assert.Single(this.puller.ReassignedJobsQueue);
            Assert.Empty(this.puller.DownloadJobsQueue);
            Assert.Equal(headersReassignedFromPeer2Count, this.puller.ReassignedJobsQueue.Peek().Headers.Count);
            Assert.Single(this.puller.PullerBehaviorsByPeerId);

            await this.puller.AssignDownloadJobsAsync();

            Assert.Empty(this.puller.ReassignedJobsQueue);
            Assert.Empty(this.puller.DownloadJobsQueue);
            Assert.Equal(headers.Count, this.puller.AssignedDownloadsByHash.Count);
            Assert.True(this.puller.AssignedDownloadsByHash.All(x => x.Value.PeerId == peer1.Connection.Id));
            this.VerifyAssignedDownloadsSortedOrder();
        }
예제 #4
0
        public async Task TotalSpeedOfAllPeersBytesPerSec_CalculatedCorrectlyAsync()
        {
            this.puller.SetCallback((hash, block, peerId) => { this.helper.CallbacksCalled.Add(hash, block); });

            Assert.Equal(0, this.puller.GetAverageBlockSizeBytes());
            Assert.Equal(0, this.puller.GetTotalSpeedOfAllPeersBytesPerSec());

            INetworkPeer         peer    = this.helper.CreatePeer(out ExtendedBlockPullerBehavior behavior);
            List <ChainedHeader> headers = ChainedHeadersHelper.CreateConsecutiveHeaders(2);

            this.puller.NewPeerTipClaimed(peer, headers.Last());

            this.puller.RequestBlocksDownload(headers);

            await this.puller.AssignDownloadJobsAsync();

            // Make sure job was assigned.
            foreach (ChainedHeader chainedHeader in headers)
            {
                Assert.True(this.puller.AssignedDownloadsByHash.ContainsKey(chainedHeader.HashBlock));
            }

            this.puller.PushBlock(headers[0].HashBlock, this.helper.GenerateBlock(200), behavior.AttachedPeer.Connection.Id);
            this.puller.PushBlock(headers[1].HashBlock, this.helper.GenerateBlock(400), behavior.AttachedPeer.Connection.Id);

            double averageSize = this.puller.GetAverageBlockSizeBytes();

            Assert.True(this.helper.DoubleEqual(300, averageSize));
        }
        public void DistributeHeaders_EvenlyDistributed()
        {
            INetworkPeer         peer1   = this.helper.CreatePeer(out ExtendedBlockPullerBehavior behavior1);
            INetworkPeer         peer2   = this.helper.CreatePeer(out ExtendedBlockPullerBehavior behavior2);
            List <ChainedHeader> headers = ChainedHeadersHelper.CreateConsecutiveHeaders(10000);

            behavior1.OverrideQualityScore = behavior2.OverrideQualityScore = 1;

            this.puller.NewPeerTipClaimed(peer1, headers.Last());
            this.puller.NewPeerTipClaimed(peer2, headers.Last());

            var job = new DownloadJob()
            {
                Headers = new List <ChainedHeader>(headers), Id = 1
            };
            var failedHashes = new List <uint256>();

            List <AssignedDownload> assignedDownloads = this.puller.DistributeHeadersLocked(job, failedHashes, int.MaxValue);

            Assert.Empty(failedHashes);
            Assert.Equal(headers.Count, assignedDownloads.Count);

            int epsilon = Math.Abs(assignedDownloads.Count(x => x.PeerId == peer1.Connection.Id) - assignedDownloads.Count(x => x.PeerId == peer2.Connection.Id));

            // Amount of jobs assigned to peer 1 shouldn't be more than 10% different comparing to amount assigned to peer 2.
            Assert.True(epsilon < headers.Count * 0.1);
        }
        public async Task AssignDownloadJobs_PeerDisconnectedAndJobFailedAsync()
        {
            this.puller.SetCallback((hash, block, peerId) => { this.helper.CallbacksCalled.Add(hash, block); });

            INetworkPeer peer = this.helper.CreatePeer(out ExtendedBlockPullerBehavior behavior);

            List <ChainedHeader> headers = ChainedHeadersHelper.CreateConsecutiveHeaders(100);

            this.puller.NewPeerTipClaimed(peer, headers.Last());

            this.puller.RequestBlocksDownload(headers);

            this.puller.PeerDisconnected(peer.Connection.Id);

            await this.puller.AssignDownloadJobsAsync();

            Assert.Equal(100, this.helper.CallbacksCalled.Count);
            foreach (ChainedHeader chainedHeader in headers)
            {
                Assert.Null(this.helper.CallbacksCalled[chainedHeader.HashBlock]);
            }

            Assert.Empty(this.puller.AssignedDownloadsByHash);
            Assert.Empty(this.puller.DownloadJobsQueue);
        }
예제 #7
0
        public CoinviewTests()
        {
            this.network          = new StratisMain();
            this.dataFolder       = TestBase.CreateDataFolder(this);
            this.dateTimeProvider = new DateTimeProvider();
            this.loggerFactory    = new ExtendedLoggerFactory();
            this.nodeStats        = new NodeStats(this.dateTimeProvider);

            this.dbreezeCoinview = new DBreezeCoinView(this.network, this.dataFolder, this.dateTimeProvider, this.loggerFactory, this.nodeStats, new DBreezeSerializer(this.network.Consensus.ConsensusFactory));
            this.dbreezeCoinview.Initialize();

            this.chainIndexer    = new ChainIndexer(this.network);
            this.stakeChainStore = new StakeChainStore(this.network, this.chainIndexer, this.dbreezeCoinview, this.loggerFactory);
            this.stakeChainStore.Load();

            this.rewindDataIndexCache = new RewindDataIndexCache(this.dateTimeProvider, this.network);

            this.cachedCoinView = new CachedCoinView(this.dbreezeCoinview, this.dateTimeProvider, this.loggerFactory, this.nodeStats, this.stakeChainStore, this.rewindDataIndexCache);

            this.rewindDataIndexCache.Initialize(this.chainIndexer.Height, this.cachedCoinView);

            this.random = new Random();

            ChainedHeader newTip = ChainedHeadersHelper.CreateConsecutiveHeaders(1000, this.chainIndexer.Tip, true, null, this.network).Last();

            this.chainIndexer.SetTip(newTip);
        }
        public async Task RequestBlocksDownload_AssignedPeerThrows_JobIsFailedAndPeerDisconnectedAsync()
        {
            this.puller.SetCallback((hash, block, peerId) => { this.helper.CallbacksCalled.Add(hash, block); });

            INetworkPeer peer = this.helper.CreatePeer(out ExtendedBlockPullerBehavior behavior);

            behavior.ShouldThrowAtRequestBlocksAsync = true;

            List <ChainedHeader> headers = ChainedHeadersHelper.CreateConsecutiveHeaders(5);

            this.puller.NewPeerTipClaimed(peer, headers.Last());

            this.puller.RequestBlocksDownload(headers);

            Assert.Empty(this.helper.CallbacksCalled);
            Assert.Single(this.puller.PullerBehaviorsByPeerId);

            await this.puller.AssignDownloadJobsAsync();

            Assert.Empty(this.puller.PullerBehaviorsByPeerId);
            Assert.Single(this.puller.ReassignedJobsQueue);
            Assert.Equal(headers.Count, this.puller.ReassignedJobsQueue.Peek().Headers.Count);

            await this.puller.AssignDownloadJobsAsync();

            Assert.Equal(headers.Count, this.helper.CallbacksCalled.Count);

            // Callbacks are called with null.
            foreach (ChainedHeader chainedHeader in headers)
            {
                Assert.Null(this.helper.CallbacksCalled[chainedHeader.HashBlock]);
            }
        }
        public async Task GetMaturedBlockDeposits_Fails_When_Block_Not_In_Chain_Async()
        {
            FederationGatewayController controller = this.CreateController();

            ChainedHeader tip = ChainedHeadersHelper.CreateConsecutiveHeaders(3, null, true)[2];

            this.consensusManager.Tip.Returns(tip);

            IActionResult result = await controller.GetMaturedBlockDepositsAsync(new MaturedBlockRequestModel(1, 1000)).ConfigureAwait(false);

            result.Should().BeOfType <ErrorResult>();

            var error = result as ErrorResult;

            error.Should().NotBeNull();

            var errorResponse = error.Value as ErrorResponse;

            errorResponse.Should().NotBeNull();
            errorResponse.Errors.Should().HaveCount(1);

            errorResponse.Errors.Should().Contain(
                e => e.Status == (int)HttpStatusCode.BadRequest);

            errorResponse.Errors.Should().Contain(
                e => e.Message.Contains("Unable to get deposits for block at height"));
        }
        public async Task GetMaturedBlockDeposits_Gets_All_Matured_Block_Deposits_Async()
        {
            ChainedHeader tip = ChainedHeadersHelper.CreateConsecutiveHeaders(10, null, true).Last();

            this.consensusManager.Tip.Returns(tip);

            FederationGatewayController controller = this.CreateController();

            ChainedHeader earlierBlock = tip.GetAncestor(2);

            int minConfirmations = 2;

            this.depositExtractor.MinimumDepositConfirmations.Returns((uint)minConfirmations);

            int depositExtractorCallCount = 0;

            this.depositExtractor.ExtractBlockDeposits(Arg.Any <ChainedHeaderBlock>()).Returns(new MaturedBlockDepositsModel(null, null));
            this.depositExtractor.When(x => x.ExtractBlockDeposits(Arg.Any <ChainedHeaderBlock>())).Do(info =>
            {
                depositExtractorCallCount++;
            });

            IActionResult result = await controller.GetMaturedBlockDepositsAsync(new MaturedBlockRequestModel(earlierBlock.Height, 1000)).ConfigureAwait(false);

            result.Should().BeOfType <JsonResult>();

            // If the minConfirmations == 0 and this.chain.Height == earlierBlock.Height then expectedCallCount must be 1.
            int expectedCallCount = (tip.Height - minConfirmations) - earlierBlock.Height + 1;

            depositExtractorCallCount.Should().Be(expectedCallCount);
        }
        public async Task ProcessGetHeadersAsync_SendsHeadersIfLocatorIsPartiallyOnAForkAsync()
        {
            this.helper.CreateAndAttachBehavior(this.headers[100]);

            List <ChainedHeader> chainBSuffix = ChainedHeadersHelper.CreateConsecutiveHeaders(50, this.headers[55]);

            var payload = new GetHeadersPayload(new BlockLocator()
            {
                Blocks = new List <uint256>()
                {
                    chainBSuffix.Single(x => x.Height == 90).HashBlock,
                    chainBSuffix.Single(x => x.Height == 60).HashBlock,
                    this.headers[50].HashBlock,
                    this.headers[30].HashBlock,
                    this.headers[10].HashBlock
                }
            });

            await this.helper.ReceivePayloadAsync(payload);

            Assert.Single(this.helper.HeadersPayloadsSent);

            List <BlockHeader> headersSent = this.helper.HeadersPayloadsSent.First().Headers;

            Assert.Equal(50, headersSent.Count);

            for (int i = 51; i < 100; i++)
            {
                Assert.Equal(this.headers[i].Header, headersSent[i - 51]);
            }
        }
예제 #12
0
        public CoinviewTests()
        {
            this.network          = new StraxMain();
            this.dataFolder       = TestBase.CreateDataFolder(this);
            this.dateTimeProvider = new DateTimeProvider();
            this.loggerFactory    = new ExtendedLoggerFactory();
            this.nodeStats        = new NodeStats(this.dateTimeProvider, NodeSettings.Default(this.network), new Mock <IVersionProvider>().Object);

            this.coindb = new DBreezeCoindb(this.network, this.dataFolder, this.dateTimeProvider, this.loggerFactory, this.nodeStats, new DBreezeSerializer(this.network.Consensus.ConsensusFactory));
            this.coindb.Initialize();

            this.chainIndexer    = new ChainIndexer(this.network);
            this.stakeChainStore = new StakeChainStore(this.network, this.chainIndexer, (IStakedb)this.coindb, this.loggerFactory);
            this.stakeChainStore.Load();

            this.rewindDataIndexCache = new RewindDataIndexCache(this.dateTimeProvider, this.network, new FinalizedBlockInfoRepository(new HashHeightPair()), new Checkpoints());

            this.cachedCoinView = new CachedCoinView(this.network, new Checkpoints(), this.coindb, this.dateTimeProvider, this.loggerFactory, this.nodeStats, new ConsensusSettings(new NodeSettings(this.network)), this.stakeChainStore, this.rewindDataIndexCache);

            this.rewindDataIndexCache.Initialize(this.chainIndexer.Height, this.cachedCoinView);

            this.random = new Random();

            ChainedHeader newTip = ChainedHeadersHelper.CreateConsecutiveHeaders(1000, this.chainIndexer.Tip, true, null, this.network).Last();

            this.chainIndexer.SetTip(newTip);
        }
예제 #13
0
        public void GetMaturedBlocksReturnsDeposits()
        {
            this.blocks = ChainedHeadersHelper.CreateConsecutiveHeadersAndBlocks(10, true, this.mainChainNetwork);

            ChainedHeader tip = this.blocks.Last().ChainedHeader;

            IFederatedPegSettings federatedPegSettings = Substitute.For <IFederatedPegSettings>();

            federatedPegSettings.MinimumConfirmationsNormalDeposits.Returns(0);

            var deposits = new List <IDeposit>()
            {
                new Deposit(new uint256(0), DepositRetrievalType.Normal, 100, "test", 0, new uint256(1))
            };

            // Set the first block up to return 100 normal deposits.
            IDepositExtractor depositExtractor = Substitute.For <IDepositExtractor>();

            depositExtractor.ExtractDepositsFromBlock(this.blocks.First().Block, this.blocks.First().ChainedHeader.Height, new[] { DepositRetrievalType.Normal }).ReturnsForAnyArgs(deposits);
            this.consensusManager.Tip.Returns(tip);

            // Makes every block a matured block.
            var maturedBlocksProvider = new MaturedBlocksProvider(this.consensusManager, depositExtractor, federatedPegSettings, this.loggerFactory);

            SerializableResult <List <MaturedBlockDepositsModel> > depositsResult = maturedBlocksProvider.RetrieveDeposits(0);

            Assert.Equal(11, depositsResult.Value.Count);
        }
        public async Task RetrieveDeposits_ReturnsLargeDeposits_Scenario6_Async()
        {
            // Create a "chain" of 20 blocks.
            this.blocks = ChainedHeadersHelper.CreateConsecutiveHeadersAndBlocks(20, true, this.mainChainNetwork);

            // Add 4 small deposits to blocks 5 through to 8 (the amounts are less than 10).
            for (int i = 5; i <= 8; i++)
            {
                this.blocks[i].Block.AddTransaction(new Transaction());
                CreateDepositTransaction(this.targetAddress, this.blocks[i].Block, Money.Coins(i), this.opReturnBytes);
            }

            // Add 6 normal deposits to block 11 through to 16.
            for (int i = 11; i <= 16; i++)
            {
                this.blocks[i].Block.AddTransaction(new Transaction());
                CreateDepositTransaction(this.targetAddress, this.blocks[i].Block, Money.Coins(i), this.opReturnBytes);
            }

            // Add 6 large deposits to block 11 through to 16.
            for (int i = 11; i <= 16; i++)
            {
                this.blocks[i].Block.AddTransaction(new Transaction());
                CreateDepositTransaction(this.targetAddress, this.blocks[i].Block, Money.Coins((long)this.federatedPegSettings.NormalDepositThresholdAmount + 1), this.opReturnBytes);
            }

            this.consensusManager.Tip.Returns(this.blocks.Last().ChainedHeader);
            var depositExtractor      = new DepositExtractor(this.conversionRequestRepository, this.federatedPegSettings, this.network, this.opReturnDataReader);
            var maturedBlocksProvider = new MaturedBlocksProvider(this.consensusManager, depositExtractor, this.federatedPegSettings);

            SerializableResult <List <MaturedBlockDepositsModel> > depositsResult = await maturedBlocksProvider.RetrieveDepositsAsync(10);

            // Total deposits
            Assert.Equal(4, depositsResult.Value.SelectMany(b => b.Deposits).Count());
        }
예제 #15
0
        public void CommonTipCalculatedCorrectlyWhenProvidersAreOnDifferentChains()
        {
            // Chain that forks at block 12
            List <ChainedHeader> altChainHeaders = ChainedHeadersHelper.CreateConsecutiveHeaders(5, this.mainChainHeaders[12]);

            this.tipsManager.Initialize(this.mainChainHeaders.Last());

            var provider1 = new testTipProvider();
            var provider2 = new testTipProvider();
            var provider3 = new testTipProvider();

            this.tipsManager.RegisterTipProvider(provider1);
            this.tipsManager.RegisterTipProvider(provider2);
            this.tipsManager.RegisterTipProvider(provider3);

            this.tipsManager.CommitTipPersisted(provider1, this.mainChainHeaders[15]);
            this.tipsManager.CommitTipPersisted(provider2, this.mainChainHeaders[15]);
            this.tipsManager.CommitTipPersisted(provider3, altChainHeaders[4]);

            Assert.Equal(this.mainChainHeaders[12], this.tipsManager.GetLastCommonTip());

            this.tipsManager.CommitTipPersisted(provider3, this.mainChainHeaders[18]);
            Assert.Equal(this.mainChainHeaders[15], this.tipsManager.GetLastCommonTip());

            this.tipsManager.CommitTipPersisted(provider1, altChainHeaders[2]);
            this.tipsManager.CommitTipPersisted(provider2, altChainHeaders[3]);
            this.tipsManager.CommitTipPersisted(provider3, altChainHeaders[4]);

            Assert.Equal(altChainHeaders[2], this.tipsManager.GetLastCommonTip());
        }
        public async Task RequestBlocksDownload_WhileThereAreNoPeers_JobFailedAsync()
        {
            this.puller.SetCallback((hash, block, pereId) => { this.helper.CallbacksCalled.Add(hash, block); });

            List <ChainedHeader> headers = ChainedHeadersHelper.CreateConsecutiveHeaders(2);

            Assert.Empty(this.puller.DownloadJobsQueue);
            Assert.Empty(this.helper.CallbacksCalled);
            Assert.False(this.puller.ProcessQueuesSignal.IsSet);

            this.puller.RequestBlocksDownload(headers);

            // Headers were added to the jobs queue.
            Assert.Single(this.puller.DownloadJobsQueue);
            Assert.Equal(2, this.puller.DownloadJobsQueue.Peek().Headers.Count);
            Assert.True(this.puller.ProcessQueuesSignal.IsSet);

            await this.puller.AssignDownloadJobsAsync();

            // Callbacks are called with null.
            foreach (ChainedHeader chainedHeader in headers)
            {
                Assert.Null(this.helper.CallbacksCalled[chainedHeader.HashBlock]);
            }
        }
예제 #17
0
        public void GetMaturedBlockDeposits_Fails_When_Block_Height_Greater_Than_Minimum_Deposit_Confirmations_Async()
        {
            ChainedHeader tip = ChainedHeadersHelper.CreateConsecutiveHeaders(5, null, true).Last();

            this.consensusManager.Tip.Returns(tip);

            // Minimum deposit confirmations : 2
            IFederatedPegSettings federatedPegSettings = Substitute.For <IFederatedPegSettings>();

            federatedPegSettings.MinimumConfirmationsNormalDeposits.Returns(2);
            FederationGatewayController controller = this.CreateController(federatedPegSettings);

            int maturedHeight = (int)(tip.Height - 2);

            // Back online at block height : 3
            // 0 - 1 - 2 - 3
            ChainedHeader earlierBlock = tip.GetAncestor(maturedHeight + 1);

            // Mature height = 2 (Chain header height (4) - Minimum deposit confirmations (2))
            IActionResult result = controller.GetMaturedBlockDeposits(earlierBlock.Height);

            // Block height (3) > Mature height (2) - returns error message
            var maturedBlockDepositsResult = (result as JsonResult).Value as SerializableResult <List <MaturedBlockDepositsModel> >;

            maturedBlockDepositsResult.Should().NotBeNull();
            maturedBlockDepositsResult.Value.Count().Should().Be(0);
            Assert.NotNull(maturedBlockDepositsResult.Message);
        }
        public void DistributeHeaders_BetweenTwoPeersWhereOneIsOnADifferentChain()
        {
            INetworkPeer         peer1        = this.helper.CreatePeer(out ExtendedBlockPullerBehavior behavior1);
            INetworkPeer         peer2        = this.helper.CreatePeer(out ExtendedBlockPullerBehavior behavior2);
            List <ChainedHeader> peer1Headers = ChainedHeadersHelper.CreateConsecutiveHeaders(10);
            List <ChainedHeader> peer2Headers = ChainedHeadersHelper.CreateConsecutiveHeaders(5);

            this.puller.NewPeerTipClaimed(peer1, peer1Headers.Last());
            this.puller.NewPeerTipClaimed(peer2, peer2Headers.Last());

            var job = new DownloadJob()
            {
                Headers = new List <ChainedHeader>(peer1Headers), Id = 1
            };
            var failedHashes = new List <uint256>();

            List <AssignedDownload> assignedDownloads = this.puller.DistributeHeadersLocked(job, failedHashes, int.MaxValue);

            // Make sure all jobs were assigned to peer 1.
            foreach (ChainedHeader chainedHeader in peer1Headers)
            {
                Assert.True(assignedDownloads.Exists(x => x.Header == chainedHeader));
            }

            Assert.Equal(peer1Headers.Count, assignedDownloads.Count);
        }
        public void OnNextCore_WhenTransactionsMissingInLongestChain_ReturnsThemToTheMempool()
        {
            var mempoolValidatorMock = new Mock <IMempoolValidator>();
            var loggerFactoryMock    = new Mock <ILoggerFactory>();

            loggerFactoryMock.Setup(i => i.CreateLogger(It.IsAny <string>())).Returns(new Mock <ILogger>().Object);

            Signals.Signals signals = new Signals.Signals();
            var             subject = new BlocksDisconnectedSignaled(mempoolValidatorMock.Object, new MempoolSchedulerLock(), loggerFactoryMock.Object, signals);

            subject.Initialize();

            var block = new Block();
            var genesisChainedHeaderBlock = new ChainedHeaderBlock(block, ChainedHeadersHelper.CreateGenesisChainedHeader());
            var transaction1 = new Transaction();
            var transaction2 = new Transaction();

            block.Transactions = new List <Transaction> {
                transaction1, transaction2
            };

            signals.OnBlockDisconnected.Notify(genesisChainedHeaderBlock);

            mempoolValidatorMock.Verify(x => x.AcceptToMemoryPool(It.IsAny <MempoolValidationState>(), transaction1));
            mempoolValidatorMock.Verify(x => x.AcceptToMemoryPool(It.IsAny <MempoolValidationState>(), transaction2));
        }
        public void DistributeHeaders_DownloadsAreDistributedAccordingToQualityScore()
        {
            INetworkPeer peer1 = this.helper.CreatePeer(out ExtendedBlockPullerBehavior behavior1);
            INetworkPeer peer2 = this.helper.CreatePeer(out ExtendedBlockPullerBehavior behavior2);

            behavior1.OverrideQualityScore = 1;
            behavior2.OverrideQualityScore = 0.1;

            List <ChainedHeader> headers = ChainedHeadersHelper.CreateConsecutiveHeaders(10000);

            this.puller.NewPeerTipClaimed(peer1, headers.Last());
            this.puller.NewPeerTipClaimed(peer2, headers.Last());

            var job = new DownloadJob()
            {
                Headers = new List <ChainedHeader>(headers), Id = 1
            };
            var failedHashes = new List <uint256>();

            List <AssignedDownload> assignedDownloads = this.puller.DistributeHeadersLocked(job, failedHashes, int.MaxValue);

            double margin = (double)assignedDownloads.Count(x => x.PeerId == peer1.Connection.Id) / assignedDownloads.Count(x => x.PeerId == peer2.Connection.Id);

            // Peer A is expected to get 10 times more than peer B. 8 is used to avoid false alarms when randomization is too lucky.
            Assert.True(margin > 8);
        }
        public async Task PushBlock_ByPeerThatWereNotAssignedToIt_NothingHappensAsync()
        {
            INetworkPeer peer1 = this.helper.CreatePeer(out ExtendedBlockPullerBehavior behavior1);
            INetworkPeer peer2 = this.helper.CreatePeer(out ExtendedBlockPullerBehavior behavior2);

            List <ChainedHeader> peer1Headers = ChainedHeadersHelper.CreateConsecutiveHeaders(2);
            List <ChainedHeader> peer2Headers = ChainedHeadersHelper.CreateConsecutiveHeaders(2);

            this.puller.NewPeerTipClaimed(peer1, peer1Headers.Last());
            this.puller.NewPeerTipClaimed(peer2, peer2Headers.Last());

            this.puller.RequestBlocksDownload(peer1Headers);

            await this.puller.AssignDownloadJobsAsync();

            this.puller.PushBlock(peer1Headers.First().HashBlock, this.helper.GenerateBlock(100), peer2.Connection.Id);

            foreach (ChainedHeader chainedHeader in this.puller.AssignedHeadersByPeerId[peer1.Connection.Id])
            {
                Assert.Contains(chainedHeader, peer1Headers);
            }

            Assert.Empty(this.helper.CallbacksCalled);
            Assert.Equal(peer1Headers.Count, this.puller.AssignedDownloadsByHash.Count);
        }
        public async Task RetrieveDeposits_ReturnsSmallAndNormalDeposits_Scenario3_Async()
        {
            // Create a "chain" of 30 blocks.
            this.blocks = ChainedHeadersHelper.CreateConsecutiveHeadersAndBlocks(30, true, this.mainChainNetwork);

            // Add 6 small deposits to blocks 8 through to 13 (the amounts are less than 10).
            for (int i = 8; i <= 13; i++)
            {
                this.blocks[i].Block.AddTransaction(new Transaction());
                CreateDepositTransaction(this.targetAddress, this.blocks[i].Block, Money.Coins(8), this.opReturnBytes);
            }

            // Add 5 normal deposits to block 11 through to 15.
            for (int i = 11; i <= 15; i++)
            {
                this.blocks[i].Block.AddTransaction(new Transaction());
                CreateDepositTransaction(this.targetAddress, this.blocks[i].Block, Money.Coins(i), this.opReturnBytes);
            }

            this.consensusManager.Tip.Returns(this.blocks.Last().ChainedHeader);
            var depositExtractor = new DepositExtractor(this.conversionRequestRepository, this.federatedPegSettings, this.network, this.opReturnDataReader);

            var maturedBlocksProvider = new MaturedBlocksProvider(this.consensusManager, depositExtractor, this.federatedPegSettings);

            SerializableResult <List <MaturedBlockDepositsModel> > depositsResult = await maturedBlocksProvider.RetrieveDepositsAsync(5);

            // Total deposits
            Assert.Equal(11, depositsResult.Value.SelectMany(b => b.Deposits).Count());

            // Small Deposits
            Assert.Equal(6, depositsResult.Value.SelectMany(b => b.Deposits).Where(d => d.RetrievalType == DepositRetrievalType.Small).Count());

            // Normal Deposits
            Assert.Equal(5, depositsResult.Value.SelectMany(b => b.Deposits).Where(d => d.RetrievalType == DepositRetrievalType.Normal).Count());
        }
예제 #23
0
        public async Task Stalling_DoesntAffectPeersThatFailedToDeliverNotImportantBlocksAsync()
        {
            this.puller.SetCallback((hash, block, peerId) => { this.helper.CallbacksCalled.Add(hash, block); });

            INetworkPeer peer1 = this.helper.CreatePeer(out ExtendedBlockPullerBehavior behavior1);
            INetworkPeer peer2 = this.helper.CreatePeer(out ExtendedBlockPullerBehavior behavior2);

            this.puller.SetMaxBlocksBeingDownloaded(int.MaxValue);

            List <ChainedHeader> headers = ChainedHeadersHelper.CreateConsecutiveHeaders(this.puller.ImportantHeightMargin + 10000);

            this.puller.NewPeerTipClaimed(peer1, headers.Last());

            // Assign first ImportantHeightMargin headers to peer 1 so when stalling happens it happens only on peer 1.
            this.puller.RequestBlocksDownload(headers.Take(this.puller.ImportantHeightMargin).ToList());
            await this.puller.AssignDownloadJobsAsync();

            this.puller.NewPeerTipClaimed(peer2, headers.Last());

            this.puller.RequestBlocksDownload(headers.Skip(this.puller.ImportantHeightMargin).ToList());

            behavior1.AddSample(100, 0.1);
            behavior2.AddSample(100, 0.1);

            behavior1.RecalculateQualityScore(10);
            behavior2.RecalculateQualityScore(10);

            Assert.True(this.helper.DoubleEqual(behavior1.QualityScore, behavior2.QualityScore));

            await this.puller.AssignDownloadJobsAsync();

            // Fake assign time to avoid waiting for a long time.
            foreach (AssignedDownload assignedDownload in this.puller.AssignedDownloadsByHash.Values)
            {
                assignedDownload.AssignedTime = (assignedDownload.AssignedTime - TimeSpan.FromSeconds(this.puller.MaxSecondsToDeliverBlock));
            }

            Assert.Empty(this.puller.ReassignedJobsQueue);

            List <AssignedDownload> peer1Assignments = this.puller.AssignedDownloadsByHash.Values.Where(x => x.PeerId == peer1.Connection.Id).ToList();

            this.puller.CheckStalling();

            Assert.True(behavior1.QualityScore < behavior2.QualityScore);

            // Two jobs reassigned from peer 1.
            Assert.Equal(2, this.puller.ReassignedJobsQueue.Count);

            var chainedHeaders = new List <ChainedHeader>();

            foreach (DownloadJob downloadJob in this.puller.ReassignedJobsQueue)
            {
                chainedHeaders.AddRange(downloadJob.Headers);
            }

            Assert.True(chainedHeaders.All(x => peer1Assignments.Exists(y => y.Header == x)));
        }
        public void UpdateBestSentHeader_ChangedIfHeaderIsOnFork()
        {
            ConsensusManagerBehavior behavior = this.helper.CreateAndAttachBehavior(this.headers[20], null, this.headers[10]);

            ChainedHeader headerOnChainB = ChainedHeadersHelper.CreateConsecutiveHeaders(7, this.headers[8]).Last();

            behavior.UpdateBestSentHeader(headerOnChainB);

            Assert.Equal(headerOnChainB, behavior.BestSentHeader);
        }
예제 #25
0
        public void SignalBlockDisconnectedToBlockSignaler()
        {
            Block block = KnownNetworks.StratisMain.CreateBlock();
            ChainedHeader header = ChainedHeadersHelper.CreateGenesisChainedHeader();
            var chainedHeaderBlock = new ChainedHeaderBlock(block, header);

            this.signals.SignalBlockDisconnected(chainedHeaderBlock);

            this.blockDisconnectedSignaler.Verify(b => b.Broadcast(chainedHeaderBlock), Times.Exactly(1));
        }
예제 #26
0
        public TipsManagerTests() : base(KnownNetworks.StratisMain)
        {
            this.loggerFactory = new LoggerFactory();
            string dir = CreateTestDir(this);

            this.keyValueRepo = new KeyValueRepository(dir, new DataStoreSerializer(this.Network.Consensus.ConsensusFactory));

            this.tipsManager = new TipsManager(this.keyValueRepo, this.loggerFactory);

            this.mainChainHeaders = ChainedHeadersHelper.CreateConsecutiveHeaders(20, ChainedHeadersHelper.CreateGenesisChainedHeader(this.Network), true);
        }
예제 #27
0
        public void RequestPeerServices_PeersThatDontSupportNewServicesAreNotAdded()
        {
            this.puller.RequestPeerServices(NetworkPeerServices.NODE_WITNESS);

            Mock <INetworkPeer>  peer1   = this.helper.CreatePeerMock(out ExtendedBlockPullerBehavior behavior1);
            List <ChainedHeader> headers = ChainedHeadersHelper.CreateConsecutiveHeaders(5);

            this.puller.NewPeerTipClaimed(peer1.Object, headers.Last());

            Assert.Equal(0, this.puller.PullerBehaviorsByPeerId.Count);
        }
        public async Task ProcessHeadersAsync_NonConsecutiveHeadersPresentedAsync()
        {
            this.helper.CreateAndAttachBehavior(this.headers[5]);

            List <ChainedHeader> headersToPresent = ChainedHeadersHelper.CreateConsecutiveHeaders(5);

            headersToPresent.AddRange(ChainedHeadersHelper.CreateConsecutiveHeaders(10));

            await this.helper.ReceivePayloadAsync(new HeadersPayload(headersToPresent.Select(x => x.Header)));

            Assert.True(this.helper.PeerWasBanned);
        }
예제 #29
0
        public BlockPullerTestsHelper()
        {
            this.loggerFactory = ExtendedLoggerFactory.Create();

            this.CallbacksCalled = new Dictionary <uint256, Block>();
            this.ChainState      = new ChainState()
            {
                ConsensusTip = ChainedHeadersHelper.CreateGenesisChainedHeader()
            };

            this.Puller = new ExtendedBlockPuller(this.ChainState, new NodeSettings(new StratisMain()), new DateTimeProvider(), new NodeStats(new DateTimeProvider(), this.loggerFactory), this.loggerFactory);
        }
예제 #30
0
        public void OnNextCoreProcessesOnTheWalletSyncManager()
        {
            var           walletSyncManager  = new Mock <IWalletSyncManager>();
            var           observer           = new BlockObserver(walletSyncManager.Object);
            Block         block              = KnownNetworks.StratisMain.CreateBlock();
            ChainedHeader header             = ChainedHeadersHelper.CreateGenesisChainedHeader();
            var           chainedHeaderBlock = new ChainedHeaderBlock(block, header);

            observer.OnNext(chainedHeaderBlock);

            walletSyncManager.Verify(w => w.ProcessBlock(block), Times.Exactly(1));
        }