public void GetChainReturnsConcurrentChainFromDisk() { string dir = CreateTestDir(this); var chain = new ConcurrentChain(KnownNetworks.StratisRegTest); ChainedHeader tip = this.AppendBlock(chain); using (var engine = new DBreezeEngine(dir)) { using (DBreeze.Transactions.Transaction transaction = engine.GetTransaction()) { ChainedHeader toSave = tip; var blocks = new List <ChainedHeader>(); while (toSave != null) { blocks.Insert(0, toSave); toSave = toSave.Previous; } foreach (ChainedHeader block in blocks) { transaction.Insert("Chain", block.Height, this.dBreezeSerializer.Serialize(block.Header)); } transaction.Commit(); } } using (var repo = new ChainRepository(dir, new LoggerFactory(), this.dBreezeSerializer)) { var testChain = new ConcurrentChain(KnownNetworks.StratisRegTest); testChain.SetTip(repo.LoadAsync(testChain.Genesis).GetAwaiter().GetResult()); Assert.Equal(tip, testChain.Tip); } }
/// <summary> /// Initializes the database tables used by the coinview. /// </summary> public Task InitializeAsync() { this.logger.LogTrace("()"); Block genesis = this.network.GetGenesis(); Task task = Task.Run(() => { this.logger.LogTrace("()"); using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { transaction.ValuesLazyLoadingIsOn = false; transaction.SynchronizeTables("BlockHash"); if (this.GetCurrentHash(transaction) == null) { this.SetBlockHash(transaction, genesis.GetHash()); // Genesis coin is unspendable so do not add the coins. transaction.Commit(); } } this.logger.LogTrace("(-)"); }); this.logger.LogTrace("(-)"); return(task); }
private static uint256[] SetupTransactionData(string folder) { using (var engine = new DBreezeEngine(folder)) { var data = new[] { new uint256(3), new uint256(2), new uint256(5), new uint256(10), }; int i = 0; using (DBreeze.Transactions.Transaction tx = engine.GetTransaction()) { foreach (uint256 d in data) { tx.Insert <int, byte[]>("Table", i++, d.ToBytes(false)); } tx.Commit(); } return(data); } }
public void SetBlockHashUpdatesBlockHash() { string dir = CreateTestDir(this); using (var engine = new DBreezeEngine(dir)) { DBreeze.Transactions.Transaction trans = engine.GetTransaction(); trans.Insert <byte[], byte[]>("Common", new byte[0], new uint256(41).ToBytes()); trans.Commit(); } using (IBlockRepository repository = this.SetupRepository(this.Network, dir)) { Task task = repository.SetBlockHashAsync(new uint256(56)); task.Wait(); } using (var engine = new DBreezeEngine(dir)) { DBreeze.Transactions.Transaction trans = engine.GetTransaction(); Row <byte[], byte[]> blockHashKeyRow = trans.Select <byte[], byte[]>("Common", new byte[0]); Assert.Equal(new uint256(56), new uint256(blockHashKeyRow.Value)); } }
/// <inheritdoc /> public virtual void Initialize() { Block genesis = this.network.GetGenesis(); using (DBreeze.Transactions.Transaction transaction = this.DBreeze.GetTransaction()) { bool doCommit = false; if (this.LoadTipHashAndHeight(transaction) == null) { this.SaveTipHashAndHeight(transaction, new HashHeightPair(genesis.GetHash(), 0)); doCommit = true; } if (this.LoadTxIndex(transaction) == null) { this.SaveTxIndex(transaction, false); doCommit = true; } if (doCommit) { transaction.Commit(); } } }
/// <inheritdoc /> public virtual Task InitializeAsync() { Block genesis = this.network.GetGenesis(); Task task = Task.Run(() => { using (DBreeze.Transactions.Transaction transaction = this.DBreeze.GetTransaction()) { bool doCommit = false; if (this.LoadTipHashAndHeight(transaction) == null) { this.SaveTipHashAndHeight(transaction, new HashHeightPair(genesis.GetHash(), 0)); doCommit = true; } if (this.LoadTxIndex(transaction) == null) { this.SaveTxIndex(transaction, false); doCommit = true; } if (doCommit) { transaction.Commit(); } } }); return(task); }
/// <summary>Adds new poll.</summary> public void AddPolls(params Poll[] polls) { lock (this.lockObject) { using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { foreach (Poll pollToAdd in polls.OrderBy(p => p.Id)) { if (pollToAdd.Id != this.highestPollId + 1) { throw new ArgumentException("Id is incorrect. Gaps are not allowed."); } byte[] bytes = this.dBreezeSerializer.Serialize(pollToAdd); transaction.Insert <byte[], byte[]>(TableName, pollToAdd.Id.ToBytes(), bytes); this.highestPollId++; this.SaveHighestPollId(transaction); } transaction.Commit(); } } }
/// <inheritdoc /> public Task <bool> SaveFinalizedBlockHashAndHeightAsync(uint256 hash, int height) { this.logger.LogTrace("({0}:{1})", nameof(height), height); if (this.finalizedBlockInfo != null && height <= this.finalizedBlockInfo.Height) { this.logger.LogTrace("(-)[CANT_GO_BACK]:false"); return(Task.FromResult(false)); } this.finalizedBlockInfo = new HashHeightPair(hash, height); Task <bool> task = Task.Run(() => { this.logger.LogTrace("()"); using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { transaction.Insert <byte[], HashHeightPair>("FinalizedBlock", finalizedBlockKey, this.finalizedBlockInfo); transaction.Commit(); } this.logger.LogTrace("(-):true"); return(true); }); this.logger.LogTrace("(-)"); return(task); }
public void GetAsyncWithExistingBlocksReturnsBlocks() { string dir = CreateTestDir(this); var blocks = new Block[10]; blocks[0] = this.Network.Consensus.ConsensusFactory.CreateBlock(); for (int i = 1; i < blocks.Length; i++) { blocks[i] = this.Network.Consensus.ConsensusFactory.CreateBlock(); blocks[i].Header.HashPrevBlock = blocks[i - 1].Header.GetHash(); } using (var engine = new DBreezeEngine(dir)) { DBreeze.Transactions.Transaction transaction = engine.GetTransaction(); for (int i = 0; i < blocks.Length; i++) { transaction.Insert <byte[], byte[]>("Block", blocks[i].GetHash().ToBytes(), blocks[i].ToBytes()); } transaction.Commit(); } using (IBlockRepository repository = this.SetupRepository(this.Network, dir)) { Task <List <Block> > task = repository.GetBlocksAsync(blocks.Select(b => b.GetHash()).ToList()); task.Wait(); Assert.Equal(blocks.Length, task.Result.Count); for (int i = 0; i < 10; i++) { Assert.Equal(blocks[i].GetHash(), task.Result[i].GetHash()); } } }
/// <inheritdoc /> public Task SaveAsync(ConcurrentChain chain) { Guard.NotNull(chain, nameof(chain)); Task task = Task.Run(() => { using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { ChainedHeader fork = this.locator == null ? null : chain.FindFork(this.locator); ChainedHeader tip = chain.Tip; ChainedHeader toSave = tip; var headers = new List <ChainedHeader>(); while (toSave != fork) { headers.Add(toSave); toSave = toSave.Previous; } // DBreeze is faster on ordered insert. IOrderedEnumerable <ChainedHeader> orderedChainedHeaders = headers.OrderBy(b => b.Height); foreach (ChainedHeader block in orderedChainedHeaders) { transaction.Insert("Chain", block.Height, block.Header); } this.locator = tip.GetLocator(); transaction.Commit(); } }); return(task); }
public void SetTxIndexUpdatesTxIndex() { string dir = CreateTestDir(this); using (var engine = new DBreezeEngine(dir)) { DBreeze.Transactions.Transaction trans = engine.GetTransaction(); trans.Insert <byte[], bool>("Common", new byte[1], true); trans.Commit(); } using (IBlockRepository repository = this.SetupRepository(this.Network, dir)) { Task task = repository.SetTxIndexAsync(false); task.Wait(); } using (var engine = new DBreezeEngine(dir)) { DBreeze.Transactions.Transaction trans = engine.GetTransaction(); Row <byte[], bool> txIndexRow = trans.Select <byte[], bool>("Common", new byte[1]); Assert.False(txIndexRow.Value); } }
/// <inheritdoc /> public Task PutAsync(SortedDictionary <int, ProvenBlockHeader> headers, HashHeightPair newTip) { Guard.NotNull(headers, nameof(headers)); Guard.NotNull(newTip, nameof(newTip)); Guard.Assert(newTip.Hash == headers.Values.Last().GetHash()); Task task = Task.Run(() => { this.logger.LogTrace("({0}.Count():{1})", nameof(headers), headers.Count()); using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { transaction.SynchronizeTables(BlockHashHeightTable, ProvenBlockHeaderTable); this.InsertHeaders(transaction, headers); this.SetTip(transaction, newTip); transaction.Commit(); this.TipHashHeight = newTip; } }); return(task); }
/// <inheritdoc /> public Task InitializeAsync() { Task task = Task.Run(() => { using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { this.TipHashHeight = this.GetTipHash(transaction); if (this.TipHashHeight != null) { return; } var hashHeight = new HashHeightPair(this.network.GetGenesis().GetHash(), 0); this.SetTip(transaction, hashHeight); transaction.Commit(); this.TipHashHeight = hashHeight; } }); return(task); }
/// <inheritdoc /> public Task <bool> SaveFinalizedBlockHeightAsync(int height) { this.logger.LogTrace("({0}:{1})", nameof(height), height); if (height <= this.finalizedHeight) { this.logger.LogTrace("(-)[CANT_GO_BACK]:false"); return(Task.FromResult(false)); } this.finalizedHeight = height; Task <bool> task = Task.Run(() => { this.logger.LogTrace("()"); using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { transaction.Insert <byte[], int>("FinalizedBlock", finalizedBlockKey, height); transaction.Commit(); } this.logger.LogTrace("(-):true"); return(true); }); this.logger.LogTrace("(-)"); return(task); }
public void GetChainReturnsConcurrentChainFromDisk() { string dir = CreateTestDir(this); var chain = new ConcurrentChain(Network.RegTest); var tip = this.AppendBlock(chain); using (var engine = new DBreezeEngine(dir)) { using (DBreeze.Transactions.Transaction transaction = engine.GetTransaction()) { ChainedBlock toSave = tip; List <ChainedBlock> blocks = new List <ChainedBlock>(); while (toSave != null) { blocks.Insert(0, toSave); toSave = toSave.Previous; } foreach (var block in blocks) { transaction.Insert <int, BlockHeader>("Chain", block.Height, block.Header); } transaction.Commit(); } } using (var repo = new ChainRepository(dir)) { var testChain = new ConcurrentChain(Network.RegTest); repo.LoadAsync(testChain).GetAwaiter().GetResult(); Assert.Equal(tip, testChain.Tip); } }
/// <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); }); }
/// <inheritdoc /> public Task PutAsync(List <ProvenBlockHeader> headers, HashHeightPair newTip) { Guard.NotNull(headers, nameof(headers)); Guard.NotNull(newTip, nameof(newTip)); Guard.Assert(newTip.Hash == headers.Last().GetHash()); if ((this.provenBlockHeaderTip != null) && (newTip.Hash == this.provenBlockHeaderTip.GetHash())) { this.logger.LogTrace("(-)[BLOCKHASH_MISMATCH]"); throw new ProvenBlockHeaderException("Invalid new tip hash, tip hash has not changed."); } Task task = Task.Run(() => { this.logger.LogTrace("({0}.Count():{1})", nameof(headers), headers.Count()); using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { transaction.SynchronizeTables(BlockHashHeightTable, ProvenBlockHeaderTable); this.InsertHeaders(transaction, headers); this.SetTip(transaction, newTip); transaction.Commit(); this.TipHashHeight = newTip; } }); return(task); }
/// <inheritdoc /> public async Task PruneAndCompactDatabase(ChainedHeader blockRepositoryTip, Network network, bool nodeInitializing) { this.logger.LogInformation($"Pruning started."); if (this.PrunedTip == null) { Block genesis = network.GetGenesis(); this.PrunedTip = new HashHeightPair(genesis.GetHash(), 0); using (DBreeze.Transactions.Transaction transaction = this.blockRepository.DBreeze.GetTransaction()) { transaction.Insert(BlockRepository.CommonTableName, prunedTipKey, this.dBreezeSerializer.Serialize(this.PrunedTip)); transaction.Commit(); } } if (nodeInitializing) { if (this.IsDatabasePruned()) { return; } this.PrepareDatabaseForCompacting(blockRepositoryTip); } this.CompactDataBase(); this.logger.LogInformation($"Pruning complete."); return; }
public async Task GetAsync_Reads_MultipleProvenBlockHeadersAsync() { string folder = CreateTestDir(this); PosBlock posBlock = CreatePosBlockMock(); ProvenBlockHeader header1 = CreateNewProvenBlockHeaderMock(posBlock); ProvenBlockHeader header2 = CreateNewProvenBlockHeaderMock(posBlock); using (var engine = new DBreezeEngine(folder)) { DBreeze.Transactions.Transaction txn = engine.GetTransaction(); txn.Insert <byte[], ProvenBlockHeader>(ProvenBlockHeaderTable, 1.ToBytes(false), header1); txn.Insert <byte[], ProvenBlockHeader>(ProvenBlockHeaderTable, 2.ToBytes(false), header2); txn.Commit(); } // Query the repository for the item that was inserted in the above code. using (ProvenBlockHeaderRepository repo = this.SetupRepository(this.Network, folder)) { List <ProvenBlockHeader> headersOut = await repo.GetAsync(1, 2).ConfigureAwait(false); headersOut.Count.Should().Be(2); headersOut.First().GetHash().Should().Be(header1.GetHash()); headersOut.Last().GetHash().Should().Be(header2.GetHash()); } }
public async Task GetAsync_WithWrongBlockHeightReturnsNullAsync() { string folder = CreateTestDir(this); using (var engine = new DBreezeEngine(folder)) { DBreeze.Transactions.Transaction txn = engine.GetTransaction(); txn.Insert <byte[], ProvenBlockHeader>(ProvenBlockHeaderTable, 1.ToBytes(false), CreateNewProvenBlockHeaderMock()); txn.Insert <byte[], HashHeightPair>(BlockHashTable, new byte[0], new HashHeightPair(new uint256(), 1)); txn.Commit(); } using (ProvenBlockHeaderRepository repo = this.SetupRepository(this.Network, folder)) { // Select a different block height. ProvenBlockHeader outHeader = await repo.GetAsync(2).ConfigureAwait(false); outHeader.Should().BeNull(); // Select the original item inserted into the table outHeader = await repo.GetAsync(1).ConfigureAwait(false); outHeader.Should().NotBeNull(); } }
public void DoesNotOverwriteExistingBlockAndTxIndexOnFirstLoad() { string dir = CreateTestDir(this); using (var engine = new DBreezeEngine(dir)) { DBreeze.Transactions.Transaction transaction = engine.GetTransaction(); transaction.Insert <byte[], HashHeightPair>("Common", new byte[0], new HashHeightPair(new uint256(56), 1)); transaction.Insert <byte[], bool>("Common", new byte[1], true); transaction.Commit(); } using (IBlockRepository repository = this.SetupRepository(this.Network, dir)) { } using (var engine = new DBreezeEngine(dir)) { DBreeze.Transactions.Transaction transaction = engine.GetTransaction(); Row <byte[], HashHeightPair> blockRow = transaction.Select <byte[], HashHeightPair>("Common", new byte[0]); Row <byte[], bool> txIndexRow = transaction.Select <byte[], bool>("Common", new byte[1]); Assert.Equal(new HashHeightPair(new uint256(56), 1), blockRow.Value); Assert.True(txIndexRow.Value); } }
public void GetTrxAsyncWithTransactionReturnsExistingTransaction() { string dir = CreateTestDir(this); Transaction trans = this.Network.CreateTransaction(); trans.Version = 125; using (var engine = new DBreezeEngine(dir)) { Block block = this.Network.CreateBlock(); block.Header.GetHash(); block.Transactions.Add(trans); DBreeze.Transactions.Transaction transaction = engine.GetTransaction(); transaction.Insert <byte[], byte[]>("Block", block.Header.GetHash().ToBytes(), block.ToBytes()); transaction.Insert <byte[], byte[]>("Transaction", trans.GetHash().ToBytes(), block.Header.GetHash().ToBytes()); transaction.Insert <byte[], HashHeightPair>("Common", new byte[0], new HashHeightPair(uint256.Zero, 1)); transaction.Insert <byte[], bool>("Common", new byte[1], true); transaction.Commit(); } using (IBlockRepository repository = this.SetupRepository(this.Network, dir)) { Task <Transaction> task = repository.GetTrxAsync(trans.GetHash()); task.Wait(); Assert.Equal((uint)125, task.Result.Version); } }
/// <summary> /// Initializes the database tables used by the coinview. /// </summary> public Task InitializeAsync() { this.logger.LogTrace("()"); Block genesis = this.network.GetGenesis(); Task task = Task.Run(() => { this.logger.LogTrace("()"); uint256 currentHash; using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { transaction.ValuesLazyLoadingIsOn = false; transaction.SynchronizeTables("BlockHash"); currentHash = this.GetCurrentHash(transaction); if (currentHash == null) { this.SetBlockHash(transaction, genesis.GetHash(this.network.NetworkOptions)); // Genesis coin is unspendable so do not add the coins. transaction.Commit(); } } ////////Neo ** if (currentHash == null) { var genesisChainedBlock = new ChainedBlock(genesis.Header, this.network.GenesisHash, 0); var chained = this.MakeNext(genesisChainedBlock, this.network); int length = genesis.Transactions.Count; UnspentOutputs[] utxos = new UnspentOutputs[length]; for (int i = 0; i < length; i++) { utxos[i] = new UnspentOutputs(genesis.Transactions[i].GetHash(), new Coins(genesis.Transactions[i], 0)); } //uint256 txId = genesis.Transactions[0].GetHash(); //uint256 txId2 = genesis.Transactions[1].GetHash(); //Coins coins = new Coins(genesis.Transactions[0], 0); //Coins coins2 = new Coins(genesis.Transactions[1], 0); //UnspentOutputs[] utxos = new UnspentOutputs[2]; //utxos[0] = new UnspentOutputs(txId, coins); //utxos[1] = new UnspentOutputs(txId2, coins2); this.SaveChangesAsync(utxos, null, genesisChainedBlock.HashBlock, chained.HashBlock).Wait(); } //this.SaveChangesAsync(new UnspentOutputs[] { new UnspentOutputs(genesis.Transactions[0].GetHash(), new Coins(genesis.Transactions[0], 0)) }, null, genesisChainedBlock.HashBlock, chained.HashBlock).Wait(); //this.SaveChangesAsync(new UnspentOutputs[] { new UnspentOutputs(genesis.Transactions[1].GetHash(), new Coins(genesis.Transactions[1], 0)) }, null, genesisChainedBlock.HashBlock, chained.HashBlock).Wait(); //Assert.NotNull(ctx.PersistentCoinView.FetchCoinsAsync(new[] { genesis.Transactions[0].GetHash() }).Result.UnspentOutputs[0]); /////////////////////////////// this.logger.LogTrace("(-)"); }); this.logger.LogTrace("(-)"); return(task); }
public void Delete(byte[] key) { using (DBreeze.Transactions.Transaction t = this.engine.GetTransaction()) { t.RemoveKey(this.table, key); t.Commit(); } }
/// <summary> /// Only use for testing at the moment. /// </summary> public void Empty() { using (DBreeze.Transactions.Transaction t = this.engine.GetTransaction()) { t.RemoveAllKeys(this.table, false); t.Commit(); } }
public void Put(byte[] key, byte[] val) { using (DBreeze.Transactions.Transaction t = this.engine.GetTransaction()) { t.Insert(this.table, key, val); t.Commit(); } }
/// <summary> /// Persists unsaved POS blocks information to the database. /// </summary> /// <param name="stakeEntries">List of POS block information to be examined and persists if unsaved.</param> public void PutStake(IEnumerable <StakeItem> stakeEntries) { using (DBreeze.Transactions.Transaction transaction = this.CreateTransaction()) { transaction.SynchronizeTables("Stake"); this.PutStakeInternal(transaction, stakeEntries); transaction.Commit(); } }
// TODO: Handle pruning old data in case of reorg. /// <inheritdoc /> public void Store(IEnumerable <Receipt> receipts) { using (DBreeze.Transactions.Transaction t = this.engine.GetTransaction()) { foreach (Receipt receipt in receipts) { t.Insert <byte[], byte[]>(TableName, receipt.TransactionHash.ToBytes(), receipt.ToStorageBytesRlp()); } t.Commit(); } }
public void Reset() { lock (this.lockObject) { using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { ResetLocked(transaction); transaction.Commit(); } } }
/// <inheritdoc /> public void SaveValue <T>(string key, T value) { byte[] keyBytes = Encoding.ASCII.GetBytes(key); using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { transaction.Insert <byte[], byte[]>(TableName, keyBytes, this.dBreezeSerializer.Serialize(value)); transaction.Commit(); } }