/// <summary>
        /// Compacts the block and transaction database by recreating the tables without the deleted references.
        /// </summary>
        private void CompactDataBase()
        {
            Task task = Task.Run(() =>
            {
                using (DBreeze.Transactions.Transaction dbreezeTransaction = this.blockRepository.DBreeze.GetTransaction())
                {
                    dbreezeTransaction.SynchronizeTables(BlockRepository.BlockTableName, BlockRepository.TransactionTableName);

                    var tempBlocks = dbreezeTransaction.SelectDictionary <byte[], byte[]>(BlockRepository.BlockTableName);

                    if (tempBlocks.Count != 0)
                    {
                        this.logger.LogInformation($"{tempBlocks.Count} blocks will be copied to the pruned table.");

                        dbreezeTransaction.RemoveAllKeys(BlockRepository.BlockTableName, true);
                        dbreezeTransaction.InsertDictionary(BlockRepository.BlockTableName, tempBlocks, false);

                        var tempTransactions = dbreezeTransaction.SelectDictionary <byte[], byte[]>(BlockRepository.TransactionTableName);
                        if (tempTransactions.Count != 0)
                        {
                            this.logger.LogInformation($"{tempTransactions.Count} transactions will be copied to the pruned table.");
                            dbreezeTransaction.RemoveAllKeys(BlockRepository.TransactionTableName, true);
                            dbreezeTransaction.InsertDictionary(BlockRepository.TransactionTableName, tempTransactions, false);
                        }

                        // Save the hash and height of where the node was pruned up to.
                        dbreezeTransaction.Insert(BlockRepository.CommonTableName, prunedTipKey, this.dBreezeSerializer.Serialize(this.PrunedTip));
                    }

                    dbreezeTransaction.Commit();
                }

                return(Task.CompletedTask);
            });
        }
Beispiel #2
0
        public async Task PutAsync_Inserts_MultipleProvenBlockHeadersAsync()
        {
            string folder = CreateTestDir(this);

            PosBlock          posBlock = CreatePosBlockMock();
            ProvenBlockHeader header1  = CreateNewProvenBlockHeaderMock(posBlock);
            ProvenBlockHeader header2  = CreateNewProvenBlockHeaderMock(posBlock);

            var items = new List <ProvenBlockHeader> {
                header1, header2
            };

            // Put the items in the repository.
            using (IProvenBlockHeaderRepository repo = this.SetupRepository(this.Network, folder))
            {
                await repo.PutAsync(items, new HashHeightPair(header2.GetHash(), items.Count - 1));
            }

            // Check the ProvenBlockHeader exists in the database.
            using (var engine = new DBreezeEngine(folder))
            {
                DBreeze.Transactions.Transaction txn = engine.GetTransaction();
                txn.SynchronizeTables(ProvenBlockHeaderTable);
                txn.ValuesLazyLoadingIsOn = false;

                var headersOut = txn.SelectDictionary <byte[], ProvenBlockHeader>(ProvenBlockHeaderTable);

                headersOut.Keys.Count.Should().Be(2);
                headersOut.First().Value.GetHash().Should().Be(items[0].GetHash());
                headersOut.Last().Value.GetHash().Should().Be(items[1].GetHash());
            }
        }
        public void ReIndexAsync_TxIndex_OffToOn()
        {
            string      dir         = CreateTestDir(this);
            Block       block       = this.Network.CreateBlock();
            Transaction transaction = this.Network.CreateTransaction();

            block.Transactions.Add(transaction);

            // Set up database to mimic that created when TxIndex was off. No transactions stored.
            using (var engine = new DBreezeEngine(dir))
            {
                DBreeze.Transactions.Transaction dbreezeTransaction = engine.GetTransaction();
                dbreezeTransaction.Insert <byte[], byte[]>("Block", block.GetHash().ToBytes(), block.ToBytes());
                dbreezeTransaction.Commit();
            }

            // Turn TxIndex on and then reindex database, as would happen on node startup if -txindex and -reindex are set.
            using (IBlockRepository repository = this.SetupRepository(this.Network, dir))
            {
                Task setIndexTask = repository.SetTxIndexAsync(true);
                setIndexTask.Wait();

                Task reindexTask = repository.ReIndexAsync();
                reindexTask.Wait();
            }

            // Check that after indexing database, the transaction inside the block is now indexed.
            using (var engine = new DBreezeEngine(dir))
            {
                DBreeze.Transactions.Transaction dbreezeTransaction = engine.GetTransaction();
                Dictionary <byte[], Block>       blockDict          = dbreezeTransaction.SelectDictionary <byte[], Block>("Block");
                Dictionary <byte[], byte[]>      transDict          = dbreezeTransaction.SelectDictionary <byte[], byte[]>("Transaction");

                // Block stored as expected.
                Assert.Single(blockDict);
                Assert.Equal(block.GetHash(), blockDict.FirstOrDefault().Value.GetHash());

                // Transaction row in database stored as expected.
                Assert.Single(transDict);
                KeyValuePair <byte[], byte[]> savedTransactionRow = transDict.FirstOrDefault();
                Assert.Equal(transaction.GetHash().ToBytes(), savedTransactionRow.Key);
                Assert.Equal(block.GetHash().ToBytes(), savedTransactionRow.Value);
            }
        }
        public void ReIndexAsync_TxIndex_OnToOff()
        {
            string      dir         = CreateTestDir(this);
            Block       block       = this.Network.CreateBlock();
            Transaction transaction = this.Network.CreateTransaction();

            block.Transactions.Add(transaction);

            // Set up database to mimic that created when TxIndex was on. Transaction from block is stored.
            using (var engine = new DBreezeEngine(dir))
            {
                DBreeze.Transactions.Transaction dbreezeTransaction = engine.GetTransaction();
                dbreezeTransaction.Insert <byte[], byte[]>("Block", block.GetHash().ToBytes(), block.ToBytes());
                dbreezeTransaction.Insert <byte[], byte[]>("Transaction", transaction.GetHash().ToBytes(), block.GetHash().ToBytes());
                dbreezeTransaction.Commit();
            }

            // Turn TxIndex off and then reindex database, as would happen on node startup if -txindex=0 and -reindex are set.
            using (IBlockRepository repository = this.SetupRepository(this.Network, dir))
            {
                Task setIndexTask = repository.SetTxIndexAsync(false);
                setIndexTask.Wait();

                Task reindexTask = repository.ReIndexAsync();
                reindexTask.Wait();
            }

            // Check that after indexing database, the transaction is no longer stored.
            using (var engine = new DBreezeEngine(dir))
            {
                DBreeze.Transactions.Transaction dbreezeTransaction = engine.GetTransaction();
                Dictionary <byte[], byte[]>      blockDict          = dbreezeTransaction.SelectDictionary <byte[], byte[]>("Block");
                Dictionary <byte[], byte[]>      transDict          = dbreezeTransaction.SelectDictionary <byte[], byte[]>("Transaction");

                // Block still stored as expected.
                Assert.Single(blockDict);
                Assert.Equal(block.GetHash(), this.DBreezeSerializer.Deserialize <Block>(blockDict.FirstOrDefault().Value).GetHash());

                // No transactions indexed.
                Assert.Empty(transDict);
            }
        }
        /// <summary>Loads all polls from the database.</summary>
        /// <param name="transaction">See <see cref="DBreeze.Transactions.Transaction"/>.</param>
        /// <returns>A list of retrieved <see cref="Poll"/> entries.</returns>
        public List <Poll> GetAllPolls(DBreeze.Transactions.Transaction transaction)
        {
            lock (this.lockObject)
            {
                Dictionary <byte[], byte[]> data = transaction.SelectDictionary <byte[], byte[]>(DataTable);

                return(data
                       .Where(d => d.Key.Length == 4)
                       .Select(d => this.dBreezeSerializer.Deserialize <Poll>(d.Value))
                       .ToList());
            }
        }
        public void DeleteAsyncRemovesBlocksAndTransactions()
        {
            string dir   = CreateTestDir(this);
            Block  block = this.Network.CreateBlock();

            block.Transactions.Add(this.Network.CreateTransaction());

            using (var engine = new DBreezeEngine(dir))
            {
                DBreeze.Transactions.Transaction transaction = engine.GetTransaction();
                transaction.Insert <byte[], byte[]>("Block", block.GetHash().ToBytes(), block.ToBytes());
                transaction.Insert <byte[], byte[]>("Transaction", block.Transactions[0].GetHash().ToBytes(), block.GetHash().ToBytes());
                transaction.Insert <byte[], bool>("Common", new byte[1], true);
                transaction.Commit();
            }

            var tip = new HashHeightPair(new uint256(45), 100);

            using (IBlockRepository repository = this.SetupRepository(this.Network, dir))
            {
                Task task = repository.DeleteAsync(tip, new List <uint256> {
                    block.GetHash()
                });
                task.Wait();
            }

            using (var engine = new DBreezeEngine(dir))
            {
                DBreeze.Transactions.Transaction trans = engine.GetTransaction();

                Row <byte[], HashHeightPair> blockHashKeyRow = trans.Select <byte[], HashHeightPair>("Common", new byte[0]);
                Dictionary <byte[], byte[]>  blockDict       = trans.SelectDictionary <byte[], byte[]>("Block");
                Dictionary <byte[], byte[]>  transDict       = trans.SelectDictionary <byte[], byte[]>("Transaction");

                Assert.Equal(tip, blockHashKeyRow.Value);
                Assert.Empty(blockDict);
                Assert.Empty(transDict);
            }
        }
Beispiel #7
0
        public void Initialize()
        {
            // Load highest index.
            lock (this.lockObject)
            {
                using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction())
                {
                    Dictionary <byte[], byte[]> data = transaction.SelectDictionary <byte[], byte[]>(DataTable);

                    Poll[] polls = data
                                   .Where(d => d.Key.Length == 4)
                                   .Select(d => this.dBreezeSerializer.Deserialize <Poll>(d.Value))
                                   .ToArray();

                    this.highestPollId = (polls.Length > 0) ? polls.Max(p => p.Id) : -1;

                    Row <byte[], byte[]> rowTip = transaction.Select <byte[], byte[]>(DataTable, RepositoryTipKey);

                    if (rowTip.Exists)
                    {
                        this.CurrentTip = this.dBreezeSerializer.Deserialize <HashHeightPair>(rowTip.Value);
                        if (this.chainIndexer != null && this.chainIndexer.GetHeader(this.CurrentTip.Hash) == null)
                        {
                            this.CurrentTip = null;
                        }
                    }
                    else
                    {
                        this.ResetLocked(transaction);
                        transaction.Commit();
                    }
                }
            }

            this.logger.LogDebug("Polls repo initialized with highest id: {0}.", this.highestPollId);
        }
        public void PutAsyncWritesBlocksAndTransactionsToDbAndSavesNextBlockHash()
        {
            string dir = CreateTestDir(this);

            var         nextBlockHash = new uint256(1241256);
            var         blocks        = new List <Block>();
            Block       block         = this.Network.Consensus.ConsensusFactory.CreateBlock();
            BlockHeader blockHeader   = block.Header;

            blockHeader.Bits = new Target(12);
            Transaction transaction = this.Network.CreateTransaction();

            transaction.Version = 32;
            block.Transactions.Add(transaction);
            transaction         = this.Network.CreateTransaction();
            transaction.Version = 48;
            block.Transactions.Add(transaction);
            blocks.Add(block);

            Block block2 = this.Network.Consensus.ConsensusFactory.CreateBlock();

            transaction         = this.Network.CreateTransaction();
            transaction.Version = 15;
            block2.Transactions.Add(transaction);
            blocks.Add(block2);

            using (var engine = new DBreezeEngine(dir))
            {
                DBreeze.Transactions.Transaction trans = engine.GetTransaction();
                trans.Insert <byte[], HashHeightPair>("Common", new byte[0], new HashHeightPair(uint256.Zero, 1));
                trans.Insert <byte[], bool>("Common", new byte[1], true);
                trans.Commit();
            }

            using (IBlockRepository repository = this.SetupRepository(this.Network, dir))
            {
                Task task = repository.PutAsync(new HashHeightPair(nextBlockHash, 100), blocks);
                task.Wait();
            }

            using (var engine = new DBreezeEngine(dir))
            {
                DBreeze.Transactions.Transaction trans = engine.GetTransaction();

                Row <byte[], HashHeightPair> blockHashKeyRow = trans.Select <byte[], HashHeightPair>("Common", new byte[0]);
                Dictionary <byte[], byte[]>  blockDict       = trans.SelectDictionary <byte[], byte[]>("Block");
                Dictionary <byte[], byte[]>  transDict       = trans.SelectDictionary <byte[], byte[]>("Transaction");

                Assert.Equal(new HashHeightPair(nextBlockHash, 100), blockHashKeyRow.Value);
                Assert.Equal(2, blockDict.Count);
                Assert.Equal(3, transDict.Count);

                foreach (KeyValuePair <byte[], byte[]> item in blockDict)
                {
                    Block bl = blocks.Single(b => b.GetHash() == new uint256(item.Key));
                    Assert.Equal(bl.Header.GetHash(), Block.Load(item.Value, this.Network).Header.GetHash());
                }

                foreach (KeyValuePair <byte[], byte[]> item in transDict)
                {
                    Block bl = blocks.Single(b => b.Transactions.Any(t => t.GetHash() == new uint256(item.Key)));
                    Assert.Equal(bl.GetHash(), new uint256(item.Value));
                }
            }
        }