コード例 #1
0
        /// <inheritdoc />
        public override Task <uint256> Rewind()
        {
            Task <uint256> task = Task.Run(() =>
            {
                this.logger.LogTrace("()");

                uint256 res = null;
                using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction())
                {
                    transaction.SynchronizeTables("BlockHash", "Coins", "Rewind");
                    if (this.GetRewindIndex(transaction) == -1)
                    {
                        transaction.RemoveAllKeys("Coins", true);
                        this.SetBlockHash(transaction, this.network.GenesisHash);

                        res = this.network.GenesisHash;
                    }
                    else
                    {
                        transaction.ValuesLazyLoadingIsOn = false;

                        Row <int, RewindData> firstRow = transaction.SelectBackward <int, RewindData>("Rewind").FirstOrDefault();
                        transaction.RemoveKey("Rewind", firstRow.Key);
                        this.SetBlockHash(transaction, firstRow.Value.PreviousBlockHash);

                        foreach (uint256 txId in firstRow.Value.TransactionsToRemove)
                        {
                            this.logger.LogTrace("Outputs of transaction ID '{0}' will be removed.", txId);
                            transaction.RemoveKey("Coins", txId.ToBytes(false));
                        }

                        foreach (UnspentOutputs coin in firstRow.Value.OutputsToRestore)
                        {
                            this.logger.LogTrace("Outputs of transaction ID '{0}' will be restored.", coin.TransactionId);
                            transaction.Insert("Coins", coin.TransactionId.ToBytes(false), coin.ToCoins());
                        }

                        res = firstRow.Value.PreviousBlockHash;
                    }

                    transaction.Commit();
                }

                this.logger.LogTrace("(-):'{0}'", res);
                return(res);
            });

            return(task);
        }
コード例 #2
0
ファイル: DBreezeByteStore.cs プロジェクト: georgepinca/src
 public void Delete(byte[] key)
 {
     using (DBreeze.Transactions.Transaction t = this.engine.GetTransaction())
     {
         t.RemoveKey(this.table, key);
         t.Commit();
     }
 }
コード例 #3
0
        /// <inheritdoc />
        public HashHeightPair Rewind()
        {
            HashHeightPair res = null;

            using (DBreeze.Transactions.Transaction transaction = this.CreateTransaction())
            {
                transaction.SynchronizeTables("BlockHash", "Coins", "Rewind");

                transaction.ValuesLazyLoadingIsOn = false;

                HashHeightPair current = this.GetTipHash(transaction);

                Row <int, byte[]> row = transaction.Select <int, byte[]>("Rewind", current.Height);

                if (!row.Exists)
                {
                    throw new InvalidOperationException($"No rewind data found for block `{current}`");
                }

                transaction.RemoveKey("Rewind", row.Key);

                var rewindData = this.dBreezeSerializer.Deserialize <RewindData>(row.Value);

                this.SetBlockHash(transaction, rewindData.PreviousBlockHash);

                foreach (OutPoint outPoint in rewindData.OutputsToRemove)
                {
                    this.logger.LogTrace("Outputs of outpoint '{0}' will be removed.", outPoint);
                    transaction.RemoveKey("Coins", outPoint.ToBytes());
                }

                foreach (RewindDataOutput rewindDataOutput in rewindData.OutputsToRestore)
                {
                    this.logger.LogTrace("Outputs of outpoint '{0}' will be restored.", rewindDataOutput.OutPoint);
                    transaction.Insert("Coins", rewindDataOutput.OutPoint.ToBytes(), this.dBreezeSerializer.Serialize(rewindDataOutput.Coins));
                }

                res = rewindData.PreviousBlockHash;

                transaction.Commit();
            }

            return(res);
        }
コード例 #4
0
        /// <inheritdoc />
        public uint256 Rewind()
        {
            uint256 res = null;

            using (DBreeze.Transactions.Transaction transaction = this.CreateTransaction())
            {
                transaction.SynchronizeTables("BlockHash", "Coins", "Rewind");
                if (this.GetRewindIndex(transaction) == 0)
                {
                    transaction.RemoveAllKeys("Coins", true);
                    this.SetBlockHash(transaction, this.network.GenesisHash);

                    res = this.network.GenesisHash;
                }
                else
                {
                    transaction.ValuesLazyLoadingIsOn = false;

                    Row <int, byte[]> firstRow = transaction.SelectBackward <int, byte[]>("Rewind").FirstOrDefault();
                    transaction.RemoveKey("Rewind", firstRow.Key);
                    var rewindData = this.dBreezeSerializer.Deserialize <RewindData>(firstRow.Value);
                    this.SetBlockHash(transaction, rewindData.PreviousBlockHash);

                    foreach (uint256 txId in rewindData.TransactionsToRemove)
                    {
                        this.logger.LogDebug("Outputs of transaction ID '{0}' will be removed.", txId);
                        transaction.RemoveKey("Coins", txId.ToBytes(false));
                    }

                    foreach (UnspentOutputs coin in rewindData.OutputsToRestore)
                    {
                        this.logger.LogDebug("Outputs of transaction ID '{0}' will be restored.", coin.TransactionId);
                        transaction.Insert("Coins", coin.TransactionId.ToBytes(false), this.dBreezeSerializer.Serialize(coin.ToCoins()));
                    }

                    res = rewindData.PreviousBlockHash;
                }

                transaction.Commit();
            }

            return(res);
        }
コード例 #5
0
        /// <summary>Removes polls for the provided ids.</summary>
        /// <param name="transaction">See <see cref="DBreeze.Transactions.Transaction"/>.</param>
        /// <param name="ids">The ids of the polls to remove.</param>
        public void DeletePollsAndSetHighestPollId(DBreeze.Transactions.Transaction transaction, params int[] ids)
        {
            lock (this.lockObject)
            {
                foreach (int pollId in ids.OrderBy(a => a))
                {
                    transaction.RemoveKey <byte[]>(DataTable, pollId.ToBytes());
                }

                List <Poll> polls = GetAllPolls(transaction);
                this.highestPollId = (polls.Count == 0) ? -1 : polls.Max(a => a.Id);
            }
        }
コード例 #6
0
        private void DropIndex(string name, DBreeze.Transactions.Transaction transaction)
        {
            var indexTableName = IndexTableName(name);

            if (transaction.Select <string, string>("Common", indexTableName).Exists)
            {
                transaction.RemoveAllKeys(indexTableName, true);
                transaction.RemoveKey <string>("Common", indexTableName);
                if (this.tableNames.Contains(indexTableName))
                {
                    this.tableNames.Remove(indexTableName);
                }
            }
        }
コード例 #7
0
        /// <summary>Removes polls under provided ids.</summary>
        /// <param name="transaction">See <see cref="DBreeze.Transactions.Transaction"/>.</param>
        /// <param name="ids">The ids of the polls to remove.</param>
        public void RemovePolls(DBreeze.Transactions.Transaction transaction, params int[] ids)
        {
            lock (this.lockObject)
            {
                foreach (int pollId in ids.OrderBy(id => id).Reverse())
                {
                    if (this.highestPollId != pollId)
                    {
                        throw new ArgumentException("Only deletion of the most recent item is allowed!");
                    }

                    transaction.RemoveKey <byte[]>(DataTable, pollId.ToBytes());

                    this.highestPollId--;
                }
            }
        }
コード例 #8
0
        /// <summary>Removes polls under provided ids.</summary>
        public void RemovePolls(params int[] ids)
        {
            using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction())
            {
                foreach (int pollId in ids.Reverse())
                {
                    if (this.highestPollId != pollId)
                    {
                        throw new ArgumentException("Only deletion of the most recent item is allowed!");
                    }

                    transaction.RemoveKey <byte[]>(TableName, pollId.ToBytes());

                    this.highestPollId--;
                    this.SaveHighestPollId(transaction);
                }

                transaction.Commit();
            }
        }
コード例 #9
0
        private void DropIndex(string name, DBreeze.Transactions.Transaction transaction)
        {
            Guard.NotNull(name, nameof(name));
            Guard.NotNull(transaction, nameof(transaction));

            string indexTableName = GetIndexTableName(name);

            if (transaction.Select <string, string>("Common", indexTableName).Exists)
            {
                transaction.RemoveAllKeys(indexTableName, true);
                transaction.RemoveKey <string>("Common", indexTableName);
                if (this.tableNames.Contains(indexTableName))
                {
                    this.tableNames.Remove(indexTableName);
                }

                if (this.Indexes.ContainsKey(name))
                {
                    this.Indexes.TryRemove(name, out Index index);
                }
            }
        }
コード例 #10
0
        /// <summary>Removes polls for the provided ids.</summary>
        public void DeletePollsAndSetHighestPollId(params int[] ids)
        {
            lock (this.lockObject)
            {
                using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction())
                {
                    foreach (int pollId in ids.OrderBy(a => a))
                    {
                        transaction.RemoveKey <byte[]>(TableName, pollId.ToBytes());
                    }

                    transaction.Commit();
                }

                List <Poll> polls = GetAllPolls();
                this.highestPollId = (polls.Count == 0) ? -1 : polls.Max(a => a.Id);
                using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction())
                {
                    SaveHighestPollId(transaction);
                    transaction.Commit();
                }
            }
        }
コード例 #11
0
        /// <inheritdoc />
        public override Task SaveChangesAsync(IEnumerable <UnspentOutputs> unspentOutputs, IEnumerable <TxOut[]> originalOutputs, uint256 oldBlockHash, uint256 nextBlockHash)
        {
            this.logger.LogTrace("({0}.Count():{1},{2}.Count():{3},{4}:'{5}',{6}:'{7}')", nameof(unspentOutputs), unspentOutputs?.Count(), nameof(originalOutputs), originalOutputs?.Count(), nameof(oldBlockHash), oldBlockHash, nameof(nextBlockHash), nextBlockHash);

            RewindData rewindData       = originalOutputs != null ? new RewindData(oldBlockHash) : null;
            int        insertedEntities = 0;

            List <UnspentOutputs>         all = unspentOutputs.ToList();
            Dictionary <uint256, TxOut[]> unspentToOriginal = new Dictionary <uint256, TxOut[]>(all.Count);

            using (new StopwatchDisposable(o => this.PerformanceCounter.AddInsertTime(o)))
            {
                if (originalOutputs != null)
                {
                    IEnumerator <TxOut[]> originalEnumerator = originalOutputs.GetEnumerator();
                    foreach (UnspentOutputs output in all)
                    {
                        originalEnumerator.MoveNext();
                        unspentToOriginal.Add(output.TransactionId, originalEnumerator.Current);
                    }
                }
            }

            Task task = Task.Run(() =>
            {
                this.logger.LogTrace("()");

                using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction())
                {
                    transaction.ValuesLazyLoadingIsOn = false;
                    transaction.SynchronizeTables("BlockHash", "Coins", "Rewind");
                    transaction.Technical_SetTable_OverwriteIsNotAllowed("Coins");

                    using (new StopwatchDisposable(o => this.PerformanceCounter.AddInsertTime(o)))
                    {
                        uint256 current = this.GetCurrentHash(transaction);
                        if (current != oldBlockHash)
                        {
                            this.logger.LogTrace("(-)[BLOCKHASH_MISMATCH]");
                            throw new InvalidOperationException("Invalid oldBlockHash");
                        }

                        this.SetBlockHash(transaction, nextBlockHash);

                        all.Sort(UnspentOutputsComparer.Instance);
                        foreach (UnspentOutputs coin in all)
                        {
                            this.logger.LogTrace("Outputs of transaction ID '{0}' are {1} and will be {2} to the database.", coin.TransactionId, coin.IsPrunable ? "PRUNABLE" : "NOT PRUNABLE", coin.IsPrunable ? "removed" : "inserted");
                            if (coin.IsPrunable)
                            {
                                transaction.RemoveKey("Coins", coin.TransactionId.ToBytes(false));
                            }
                            else
                            {
                                transaction.Insert("Coins", coin.TransactionId.ToBytes(false), coin.ToCoins());
                            }

                            if (originalOutputs != null)
                            {
                                TxOut[] original = null;
                                unspentToOriginal.TryGetValue(coin.TransactionId, out original);
                                if (original == null)
                                {
                                    // This one haven't existed before, if we rewind, delete it.
                                    rewindData.TransactionsToRemove.Add(coin.TransactionId);
                                }
                                else
                                {
                                    // We'll need to restore the original outputs.
                                    UnspentOutputs clone = coin.Clone();
                                    clone._Outputs       = original.ToArray();
                                    rewindData.OutputsToRestore.Add(clone);
                                }
                            }
                        }

                        if (rewindData != null)
                        {
                            int nextRewindIndex = this.GetRewindIndex(transaction) + 1;
                            this.logger.LogTrace("Rewind state #{0} created.", nextRewindIndex);
                            transaction.Insert("Rewind", nextRewindIndex, rewindData);
                        }

                        insertedEntities += all.Count;
                        transaction.Commit();
                    }
                }

                this.PerformanceCounter.AddInsertedEntities(insertedEntities);
                this.logger.LogTrace("(-)");
            });

            this.logger.LogTrace("(-)");
            return(task);
        }
コード例 #12
0
        /// <inheritdoc />
        public Task SaveChangesAsync(IList <UnspentOutputs> unspentOutputs, IEnumerable <TxOut[]> originalOutputs, uint256 oldBlockHash, uint256 nextBlockHash, int height, List <RewindData> rewindDataList = null)
        {
            Task task = Task.Run(() =>
            {
                int insertedEntities = 0;

                using (DBreeze.Transactions.Transaction transaction = this.CreateTransaction())
                {
                    transaction.ValuesLazyLoadingIsOn = false;
                    transaction.SynchronizeTables("BlockHash", "Coins", "Rewind");

                    // Speed can degrade when keys are in random order and, especially, if these keys have high entropy.
                    // This settings helps with speed, see dBreeze documentations about details.
                    // We should double check if this settings help in our scenario, or sorting keys and operations is enough.
                    // Refers to issue #2483. https://github.com/stratisproject/StratisBitcoinFullNode/issues/2483
                    transaction.Technical_SetTable_OverwriteIsNotAllowed("Coins");

                    using (new StopwatchDisposable(o => this.performanceCounter.AddInsertTime(o)))
                    {
                        uint256 current = this.GetTipHash(transaction);
                        if (current != oldBlockHash)
                        {
                            this.logger.LogTrace("(-)[BLOCKHASH_MISMATCH]");
                            throw new InvalidOperationException("Invalid oldBlockHash");
                        }

                        this.SetBlockHash(transaction, nextBlockHash);

                        // Here we'll add items to be inserted in a second pass.
                        List <UnspentOutputs> toInsert = new List <UnspentOutputs>();

                        foreach (var coin in unspentOutputs.OrderBy(utxo => utxo.TransactionId, new UInt256Comparer()))
                        {
                            if (coin.IsPrunable)
                            {
                                this.logger.LogTrace("Outputs of transaction ID '{0}' are prunable and will be removed from the database.", coin.TransactionId);
                                transaction.RemoveKey("Coins", coin.TransactionId.ToBytes(false));
                            }
                            else
                            {
                                // Add the item to another list that will be used in the second pass.
                                // This is for performance reasons: dBreeze is optimized to run the same kind of operations, sorted.
                                toInsert.Add(coin);
                            }
                        }

                        for (int i = 0; i < toInsert.Count; i++)
                        {
                            var coin = toInsert[i];
                            this.logger.LogTrace("Outputs of transaction ID '{0}' are NOT PRUNABLE and will be inserted into the database. {1}/{2}.", coin.TransactionId, i, toInsert.Count);

                            transaction.Insert("Coins", coin.TransactionId.ToBytes(false), coin.ToCoins());
                        }

                        if (rewindDataList != null)
                        {
                            int nextRewindIndex = this.GetRewindIndex(transaction) + 1;
                            foreach (RewindData rewindData in rewindDataList)
                            {
                                this.logger.LogTrace("Rewind state #{0} created.", nextRewindIndex);

                                transaction.Insert("Rewind", nextRewindIndex, rewindData);
                                nextRewindIndex++;
                            }
                        }

                        insertedEntities += unspentOutputs.Count;
                        transaction.Commit();
                    }
                }

                this.performanceCounter.AddInsertedEntities(insertedEntities);
            });

            return(task);
        }
コード例 #13
0
        /// <inheritdoc />
        public Task SaveChangesAsync(IEnumerable <UnspentOutputs> unspentOutputs, IEnumerable <TxOut[]> originalOutputs, uint256 oldBlockHash, uint256 nextBlockHash, List <RewindData> rewindDataList = null)
        {
            List <UnspentOutputs> all = unspentOutputs.ToList();

            this.logger.LogTrace("({0}.Count():{1},{2}:'{3}',{4}:'{5}')", nameof(unspentOutputs), all.Count, nameof(oldBlockHash), oldBlockHash, nameof(nextBlockHash), nextBlockHash);

            int insertedEntities = 0;

            Task task = Task.Run(() =>
            {
                this.logger.LogTrace("()");

                using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction())
                {
                    transaction.ValuesLazyLoadingIsOn = false;
                    transaction.SynchronizeTables("BlockHash", "Coins", "Rewind");
                    //transaction.Technical_SetTable_OverwriteIsNotAllowed("Coins"); // Why it was there and what is it for? No one knows.

                    using (new StopwatchDisposable(o => this.PerformanceCounter.AddInsertTime(o)))
                    {
                        uint256 current = this.GetTipHash(transaction);
                        if (current != oldBlockHash)
                        {
                            this.logger.LogTrace("(-)[BLOCKHASH_MISMATCH]");
                            throw new InvalidOperationException("Invalid oldBlockHash");
                        }

                        this.SetBlockHash(transaction, nextBlockHash);

                        all.Sort(UnspentOutputsComparer.Instance);
                        foreach (UnspentOutputs coin in all)
                        {
                            this.logger.LogTrace("Outputs of transaction ID '{0}' are {1} and will be {2} to the database.", coin.TransactionId, coin.IsPrunable ? "PRUNABLE" : "NOT PRUNABLE", coin.IsPrunable ? "removed" : "inserted");

                            if (coin.IsPrunable)
                            {
                                transaction.RemoveKey("Coins", coin.TransactionId.ToBytes(false));
                            }
                            else
                            {
                                transaction.Insert("Coins", coin.TransactionId.ToBytes(false), coin.ToCoins());
                            }
                        }

                        if (rewindDataList != null)
                        {
                            int nextRewindIndex = this.GetRewindIndex(transaction) + 1;
                            foreach (RewindData rewindData in rewindDataList)
                            {
                                this.logger.LogTrace("Rewind state #{0} created.", nextRewindIndex);

                                transaction.Insert("Rewind", nextRewindIndex, rewindData);
                                nextRewindIndex++;
                            }
                        }

                        insertedEntities += all.Count;
                        transaction.Commit();
                    }
                }

                this.PerformanceCounter.AddInsertedEntities(insertedEntities);
                this.logger.LogTrace("(-)");
            });

            this.logger.LogTrace("(-)");
            return(task);
        }
コード例 #14
0
 private void DeleteBusinessData(DBreeze.Transactions.Transaction t, BusinessDataModel businessDataModel)
 {
     t.RemoveKey <string>(businessDataModel.tableName, businessDataModel.key, out bool wasremoved);
 }
コード例 #15
0
 private void DeleteBusinessType(DBreeze.Transactions.Transaction t, BusinessTypeModel _model)
 {
     t.RemoveKey(Datalog._Business_Type, _model.key, out bool wasremoved);
     t.RemoveAllKeys(_model.key, true);
 }