public BlockStoreTests() { this.network = KnownNetworks.StratisMain; this.repositoryTipHashAndHeight = new HashHeightPair(this.network.GenesisHash, 0); this.storeSettings = new StoreSettings(NodeSettings.Default(this.network)); this.random = new Random(); this.listOfSavedBlocks = new Dictionary <uint256, Block>(); this.listOfSavedBlocks.Add(uint256.One, Block.Parse(this.testBlockHex, KnownNetworks.StratisMain.Consensus.ConsensusFactory)); this.chainIndexer = CreateChain(10); this.nodeLifetime = new NodeLifetime(); this.blockRepositoryMock = new Mock <IBlockRepository>(); this.blockRepositoryMock.Setup(x => x.PutBlocks(It.IsAny <HashHeightPair>(), It.IsAny <List <Block> >())) .Callback((HashHeightPair newTip, List <Block> blocks) => { this.repositoryTipHashAndHeight = newTip; this.repositorySavesCount++; this.repositoryTotalBlocksSaved += blocks.Count; }); this.blockRepositoryMock.Setup(x => x.Delete(It.IsAny <HashHeightPair>(), It.IsAny <List <uint256> >())) .Callback((HashHeightPair newTip, List <uint256> blocks) => { this.repositoryTotalBlocksDeleted += blocks.Count; }); this.blockRepositoryMock.Setup(x => x.GetBlock(It.IsAny <uint256>())) .Returns((uint256 hash) => { Block block = null; if (this.listOfSavedBlocks.ContainsKey(hash)) { block = this.listOfSavedBlocks[hash]; } return(block); }); this.blockRepositoryMock.Setup(x => x.TipHashAndHeight).Returns(() => { return(this.repositoryTipHashAndHeight); }); this.chainState = new ChainState(); this.initialBlockDownloadState = new Mock <IInitialBlockDownloadState>(); var blockStoreFlushCondition = new BlockStoreQueueFlushCondition(this.chainState, this.initialBlockDownloadState.Object); this.loggerFactory = new LoggerFactory(); this.signals = new Signals.Signals(this.loggerFactory, null); this.asyncProvider = new AsyncProvider(this.loggerFactory, this.signals, this.nodeLifetime); this.blockStoreQueue = new BlockStoreQueue(this.chainIndexer, this.chainState, blockStoreFlushCondition, this.storeSettings, this.blockRepositoryMock.Object, this.loggerFactory, new Mock <INodeStats>().Object, this.asyncProvider); }
public async Task BatchIsSavedAfterSizeThresholdReachedAsync() { Block block = Block.Load(Encoders.Hex.DecodeData(this.testBlockHex), KnownNetworks.StratisMain.Consensus.ConsensusFactory); int blockSize = block.GetSerializedSize(); this.chainState.ConsensusTip = null; int count = 5 * 1024 * 1024 / blockSize + 2; ChainIndexer longChainIndexer = this.CreateChain(count); this.repositoryTipHashAndHeight = new HashHeightPair(longChainIndexer.Genesis.HashBlock, 0); var blockStoreFlushCondition = new BlockStoreQueueFlushCondition(this.chainState, this.initialBlockDownloadState.Object); this.blockStoreQueue = new BlockStoreQueue(longChainIndexer, this.chainState, blockStoreFlushCondition, this.storeSettings, this.blockRepositoryMock.Object, this.loggerFactory, new Mock <INodeStats>().Object, this.asyncProvider); this.blockStoreQueue.Initialize(); this.chainState.ConsensusTip = longChainIndexer.Tip; // Send all the blocks to the block store except for the last one because that will trigger batch saving because of reaching the tip. for (int i = 1; i < count; i++) { ChainedHeader header = longChainIndexer.GetHeader(i); this.blockStoreQueue.AddToPending(new ChainedHeaderBlock(block, header)); } await WaitUntilQueueIsEmptyAsync().ConfigureAwait(false); Assert.Equal(longChainIndexer.GetHeader(count - 1), this.chainState.BlockStoreTip); Assert.Equal(1, this.repositorySavesCount); }
public BlockStoreTests() { this.network = KnownNetworks.StratisMain; this.repositoryTipHashAndHeight = new HashHeightPair(this.network.GenesisHash, 0); var serializer = new DBreezeSerializer(); serializer.Initialize(new StratisMain()); this.random = new Random(); this.listOfSavedBlocks = new Dictionary <uint256, Block>(); this.listOfSavedBlocks.Add(uint256.One, Block.Parse(this.testBlockHex, KnownNetworks.StratisMain)); this.chain = CreateChain(10); this.nodeLifetime = new NodeLifetime(); this.blockRepositoryMock = new Mock <IBlockRepository>(); this.blockRepositoryMock.Setup(x => x.PutAsync(It.IsAny <HashHeightPair>(), It.IsAny <List <Block> >())) .Returns((HashHeightPair newTip, List <Block> blocks) => { this.repositoryTipHashAndHeight = newTip; this.repositorySavesCount++; this.repositoryTotalBlocksSaved += blocks.Count; return(Task.CompletedTask); }); this.blockRepositoryMock.Setup(x => x.DeleteAsync(It.IsAny <HashHeightPair>(), It.IsAny <List <uint256> >())) .Returns((HashHeightPair newTip, List <uint256> blocks) => { this.repositoryTotalBlocksDeleted += blocks.Count; return(Task.CompletedTask); }); this.blockRepositoryMock.Setup(x => x.GetBlockAsync(It.IsAny <uint256>())) .Returns((uint256 hash) => { Block block = null; if (this.listOfSavedBlocks.ContainsKey(hash)) { block = this.listOfSavedBlocks[hash]; } return(Task.FromResult(block)); }); this.blockRepositoryMock.Setup(x => x.TipHashAndHeight).Returns(() => { return(this.repositoryTipHashAndHeight); }); this.chainState = new ChainState(); var blockStoreFlushCondition = new BlockStoreQueueFlushCondition(this.chainState); this.blockStoreQueue = new BlockStoreQueue(this.chain, this.chainState, blockStoreFlushCondition, new StoreSettings(NodeSettings.Default(this.network)), this.blockRepositoryMock.Object, new LoggerFactory(), new Mock <INodeStats>().Object); }
/// <summary> /// Creates test chain with a consensus loop. /// </summary> public static async Task <TestChainContext> CreateAsync(Network network, string dataDir, Mock <IPeerAddressManager> mockPeerAddressManager = null) { var testChainContext = new TestChainContext() { Network = network }; testChainContext.NodeSettings = new NodeSettings(network, args: new string[] { $"-datadir={dataDir}" }); testChainContext.ConnectionSettings = new ConnectionManagerSettings(testChainContext.NodeSettings); testChainContext.LoggerFactory = testChainContext.NodeSettings.LoggerFactory; testChainContext.DateTimeProvider = DateTimeProvider.Default; network.Consensus.Options = new ConsensusOptions(); new FullNodeBuilderConsensusExtension.PowConsensusRulesRegistration().RegisterRules(network.Consensus); var consensusSettings = new ConsensusSettings(testChainContext.NodeSettings); testChainContext.Checkpoints = new Checkpoints(); testChainContext.ChainIndexer = new ChainIndexer(network); testChainContext.ChainState = new ChainState(); testChainContext.InitialBlockDownloadState = new InitialBlockDownloadState(testChainContext.ChainState, testChainContext.Network, consensusSettings, new Checkpoints()); var inMemoryCoinView = new InMemoryCoinView(testChainContext.ChainIndexer.Tip.HashBlock); var cachedCoinView = new CachedCoinView(inMemoryCoinView, DateTimeProvider.Default, testChainContext.LoggerFactory, new NodeStats(new DateTimeProvider())); var dataFolder = new DataFolder(TestBase.AssureEmptyDir(dataDir)); testChainContext.PeerAddressManager = mockPeerAddressManager == null ? new PeerAddressManager(DateTimeProvider.Default, dataFolder, testChainContext.LoggerFactory, new SelfEndpointTracker(testChainContext.LoggerFactory, testChainContext.ConnectionSettings)) : mockPeerAddressManager.Object; testChainContext.MockConnectionManager = new Mock <IConnectionManager>(); testChainContext.MockReadOnlyNodesCollection = new Mock <IReadOnlyNetworkPeerCollection>(); testChainContext.MockConnectionManager.Setup(s => s.ConnectedPeers).Returns(testChainContext.MockReadOnlyNodesCollection.Object); testChainContext.MockConnectionManager.Setup(s => s.NodeSettings).Returns(testChainContext.NodeSettings); testChainContext.MockConnectionManager.Setup(s => s.ConnectionSettings).Returns(testChainContext.ConnectionSettings); testChainContext.ConnectionManager = testChainContext.MockConnectionManager.Object; var dateTimeProvider = new DateTimeProvider(); testChainContext.PeerBanning = new PeerBanning(testChainContext.ConnectionManager, testChainContext.LoggerFactory, testChainContext.DateTimeProvider, testChainContext.PeerAddressManager); var deployments = new NodeDeployments(testChainContext.Network, testChainContext.ChainIndexer); testChainContext.ConsensusRules = new PowConsensusRuleEngine(testChainContext.Network, testChainContext.LoggerFactory, testChainContext.DateTimeProvider, testChainContext.ChainIndexer, deployments, consensusSettings, testChainContext.Checkpoints, cachedCoinView, testChainContext.ChainState, new InvalidBlockHashStore(dateTimeProvider), new NodeStats(dateTimeProvider)).Register(); testChainContext.HeaderValidator = new HeaderValidator(testChainContext.ConsensusRules, testChainContext.LoggerFactory); testChainContext.IntegrityValidator = new IntegrityValidator(testChainContext.ConsensusRules, testChainContext.LoggerFactory); testChainContext.PartialValidator = new PartialValidator(testChainContext.ConsensusRules, testChainContext.LoggerFactory); testChainContext.FullValidator = new FullValidator(testChainContext.ConsensusRules, testChainContext.LoggerFactory); var dBreezeSerializer = new DBreezeSerializer(network.Consensus.ConsensusFactory); var blockRepository = new BlockRepository(testChainContext.Network, dataFolder, testChainContext.LoggerFactory, dBreezeSerializer); var blockStoreFlushCondition = new BlockStoreQueueFlushCondition(testChainContext.ChainState, testChainContext.InitialBlockDownloadState); var blockStore = new BlockStoreQueue(testChainContext.ChainIndexer, testChainContext.ChainState, blockStoreFlushCondition, new Mock <StoreSettings>().Object, blockRepository, testChainContext.LoggerFactory, new Mock <INodeStats>().Object); blockStore.Initialize(); testChainContext.Consensus = ConsensusManagerHelper.CreateConsensusManager(network, dataDir); await testChainContext.Consensus.InitializeAsync(testChainContext.ChainIndexer.Tip); return(testChainContext); }
public async Task ReorgedBlocksAreDeletedFromRepositoryIfReorgDetectedAsync() { this.chain = CreateChain(1000); this.repositoryTipHashAndHeight = new HashHeightPair(this.chain.Genesis.HashBlock, 0); var blockStoreFlushCondition = new BlockStoreQueueFlushCondition(this.chainState); this.blockStoreQueue = new BlockStoreQueue(this.chain, this.chainState, blockStoreFlushCondition, new StoreSettings(NodeSettings.Default(this.network)), this.blockRepositoryMock.Object, new LoggerFactory(), new Mock <INodeStats>().Object); await this.blockStoreQueue.InitializeAsync().ConfigureAwait(false); this.chainState.ConsensusTip = this.chain.Tip; // Sending 500 blocks to the queue. for (int i = 1; i < 500; i++) { Block block = this.network.Consensus.ConsensusFactory.CreateBlock(); block.GetSerializedSize(); this.blockStoreQueue.AddToPending(new ChainedHeaderBlock(block, this.chain.GetBlock(i))); } // Create alternative chain with fork point at 450. ChainedHeader prevBlock = this.chain.GetBlock(450); var alternativeBlocks = new List <ChainedHeader>(); for (int i = 0; i < 100; i++) { BlockHeader header = this.network.Consensus.ConsensusFactory.CreateBlockHeader(); header.Nonce = RandomUtils.GetUInt32(); header.HashPrevBlock = prevBlock.HashBlock; header.Bits = Target.Difficulty1; var chainedHeader = new ChainedHeader(header, header.GetHash(), prevBlock); alternativeBlocks.Add(chainedHeader); prevBlock = chainedHeader; } ChainedHeader savedHeader = this.chain.Tip; this.chain.SetTip(alternativeBlocks.Last()); this.chainState.ConsensusTip = this.chain.Tip; // Present alternative chain and trigger save. foreach (ChainedHeader header in alternativeBlocks) { Block block = this.network.Consensus.ConsensusFactory.CreateBlock(); block.GetSerializedSize(); if (header == alternativeBlocks.Last()) { this.chainState.IsAtBestChainTip = true; } this.blockStoreQueue.AddToPending(new ChainedHeaderBlock(block, header)); } await WaitUntilQueueIsEmptyAsync().ConfigureAwait(false); this.chainState.IsAtBestChainTip = false; // Make sure only longest chain is saved. Assert.Equal(this.chain.Tip.Height, this.repositoryTotalBlocksSaved); // Present a new longer chain that will reorg the repository. this.chain.SetTip(savedHeader); this.chainState.ConsensusTip = this.chain.Tip; for (int i = 451; i <= this.chain.Height; i++) { Block block = this.network.Consensus.ConsensusFactory.CreateBlock(); block.GetSerializedSize(); if (i == this.chain.Height) { this.chainState.IsAtBestChainTip = true; } this.blockStoreQueue.AddToPending(new ChainedHeaderBlock(block, this.chain.GetBlock(i))); } await WaitUntilQueueIsEmptyAsync().ConfigureAwait(false); // Make sure chain is saved. Assert.Equal(this.chain.Tip.Height + alternativeBlocks.Count, this.repositoryTotalBlocksSaved); Assert.Equal(alternativeBlocks.Count, this.repositoryTotalBlocksDeleted); // Dispose block store. this.nodeLifetime.StopApplication(); this.blockStoreQueue.Dispose(); }