public void ProcessBlock_NewBlock_BlockNotOnBestChain_ReOrgWalletManagerUsingBlockStoreCache()
        {
            var result = WalletTestsHelpers.GenerateForkedChainAndBlocksWithHeight(5, Network.StratisMain, 2);
            // left side chain containing the 'old' fork.
            var leftChain = result.LeftChain;

            // right side chain containing the 'new' fork. Work on this.
            this.chain = result.RightChain;
            var walletSyncManager = new WalletSyncManagerOverride(this.LoggerFactory.Object, this.walletManager.Object, this.chain, Network.StratisMain,
                                                                  this.blockStoreCache.Object, this.storeSettings, this.nodeLifetime.Object);

            // setup blockstorecache to return blocks on the chain.
            this.blockStoreCache.Setup(b => b.GetBlockAsync(It.IsAny <uint256>()))
            .ReturnsAsync((uint256 hashblock) =>
            {
                return(result.LeftForkBlocks.Union(result.RightForkBlocks).Single(b => b.GetHash() == hashblock));
            });

            // set 4th block of the old chain as tip. 2 ahead of the fork thus not being on the right chain.
            walletSyncManager.SetWalletTip(leftChain.GetBlock(result.LeftForkBlocks[3].Header.GetHash()));
            //process 5th block from the right side of the fork in the list does not have same prevhash as which is loaded.
            var blockToProcess = result.RightForkBlocks[4];

            walletSyncManager.ProcessBlock(blockToProcess);

            // walletmanager removes all blocks up to the fork.
            this.walletManager.Verify(w => w.RemoveBlocks(ExpectChainedBlock(this.chain.GetBlock(2))));
            var expectedBlockHash = this.chain.GetBlock(5).Header.GetHash();

            Assert.Equal(expectedBlockHash, walletSyncManager.WalletTip.Header.GetHash());

            //verify manager processes each missing block until caught up.
            // height 3
            this.walletManager.Verify(w => w.ProcessBlock(ExpectBlock(result.RightForkBlocks[2]), ExpectChainedBlock(this.chain.GetBlock(3))));
            // height 4
            this.walletManager.Verify(w => w.ProcessBlock(ExpectBlock(result.RightForkBlocks[3]), ExpectChainedBlock(this.chain.GetBlock(4))));
            // height 5
            this.walletManager.Verify(w => w.ProcessBlock(ExpectBlock(result.RightForkBlocks[4]), ExpectChainedBlock(this.chain.GetBlock(5))), Times.Exactly(2));
        }
        public void ProcessBlock_NewBlock_BlockNotOnBestChain_ReOrgWalletManagerUsingBlockStoreCache()
        {
            (ChainIndexer LeftChain, ChainIndexer RightChain, List <Block> LeftForkBlocks, List <Block> RightForkBlocks)result = WalletTestsHelpers.GenerateForkedChainAndBlocksWithHeight(5, KnownNetworks.StratisMain, 2);
            // left side chain containing the 'old' fork.
            ChainIndexer leftChainIndexer = result.LeftChain;

            // right side chain containing the 'new' fork. Work on this.
            this.chainIndexer = result.RightChain;
            var walletSyncManager = new WalletSyncManagerOverride(this.LoggerFactory.Object, this.walletManager.Object, this.chainIndexer, KnownNetworks.StratisMain,
                                                                  this.blockStore.Object, this.storeSettings, this.signals, this.asyncProvider);

            // setup blockstore to return blocks on the chain.
            this.blockStore.Setup(b => b.GetBlock(It.IsAny <uint256>()))
            .Returns((uint256 hashblock) =>
            {
                return(result.LeftForkBlocks.Union(result.RightForkBlocks).Single(b => b.GetHash() == hashblock));
            });

            // set 4th block of the old chain as tip. 2 ahead of the fork thus not being on the right chain.
            walletSyncManager.SetWalletTip(leftChainIndexer.GetHeader(result.LeftForkBlocks[3].Header.GetHash()));
            //process 5th block from the right side of the fork in the list does not have same prevhash as which is loaded.
            Block blockToProcess = result.RightForkBlocks[4];

            blockToProcess.SetPrivatePropertyValue("BlockSize", 1L);

            walletSyncManager.ProcessBlock(blockToProcess);

            this.AssertTipBlockHash(walletSyncManager, 5);

            // walletmanager removes all blocks up to the fork.
            this.walletManager.Verify(w => w.RemoveBlocks(ExpectChainedBlock(this.chainIndexer.GetHeader(2))));

            //verify manager processes each missing block until caught up.
            // height 3
            this.walletManager.Verify(w => w.ProcessBlock(ExpectBlock(result.RightForkBlocks[2]), ExpectChainedBlock(this.chainIndexer.GetHeader(3))));
            // height 4
            this.walletManager.Verify(w => w.ProcessBlock(ExpectBlock(result.RightForkBlocks[3]), ExpectChainedBlock(this.chainIndexer.GetHeader(4))));
            // height 5
            this.walletManager.Verify(w => w.ProcessBlock(ExpectBlock(result.RightForkBlocks[4]), ExpectChainedBlock(this.chainIndexer.GetHeader(5))), Times.Exactly(2));
        }
        public void ProcessBlock_NewBlock_BlockNotOnBestChain_ReOrgWalletManagerUsingBlockStoreCache()
        {
            (ChainIndexer LeftChain, ChainIndexer RightChain, List <Block> LeftForkBlocks, List <Block> RightForkBlocks)result = WalletTestsHelpers.GenerateForkedChainAndBlocksWithHeight(5, new StraxMain(), 2);

            // Left side chain containing the 'old' fork.
            ChainIndexer leftChainIndexer = result.LeftChain;

            // Right side chain containing the 'new' fork. Work on this.
            this.SetupMockObjects(result.RightChain);

            // Setup blockstore to return blocks on the chain.
            var blockDict = result.LeftForkBlocks.Concat(result.RightForkBlocks).Distinct().ToDictionary(b => b.GetHash(), b => b);

            this.blockStore.Setup(b => b.GetBlocks(It.IsAny <List <uint256> >()))
            .Returns((List <uint256> blockHashes) => blockHashes.Select(h => blockDict[h]).ToList());

            // Set 4th block of the old chain as tip. 2 ahead of the fork thus not being on the right chain.
            this.walletManager.Object.RewindWallet(this.walletName, leftChainIndexer.GetHeader(result.LeftForkBlocks[3].Header.GetHash()));

            // Rewind identifies height 2 as the last common block instead.
            Assert.Equal(2, this.walletTip.Height);

            // Sync will start at block 3 and end at block 5 which is the last block on the "right" chain.
            this.walletSyncManager.OrchestrateWalletSync();

            this.walletRepository.Verify(r => r.ProcessBlocks(
                                             It.Is <IEnumerable <(ChainedHeader header, Block block)> >(c => string.Join(",", c.Select(b => b.header.Height)) == "3,4,5"),
                                             It.IsAny <string>()));
        }