Exemplo n.º 1
0
        /// <summary>
        /// Initializing Root Node
        /// </summary>
        /// <param name="DBreezeTableName">Real table name in DBreeze, that will hold the structure, must be synchronized with other tables in transaction</param>
        /// <param name="tran"></param>
        /// <param name="maximalInsertSpeed">will use DBreeze Technical_SetTable_OverwriteIsNotAllowed among transaction for DBreezeTableName</param>
        public DataAsTree(string DBreezeTableName, DBreeze.Transactions.Transaction tran, bool maximalInsertSpeed = false)
        {
            if (tran == null)
                throw new Exception("Transaction is null");

            if (RootNode != null)
                throw new Exception("Can't be more then one root node, use other constructor");

            //Setting up RootNode
            this.RootNode = this;

            this.Transaction = tran;
            this.maximalInsertSpeed = maximalInsertSpeed;
            this.DBreezeTableName = DBreezeTableName;
            this.NodeId = 0;
            this.ParentNodeId = 0;
        }
Exemplo n.º 2
0
 private void SetBlockHash(DBreeze.Transactions.Transaction transaction, HashHeightPair nextBlockHash)
 {
     this.blockHash = nextBlockHash;
     transaction.Insert <byte[], byte[]>("BlockHash", blockHashKey, nextBlockHash.ToBytes());
 }
 public void SaveCurrentTip(DBreeze.Transactions.Transaction transaction, ChainedHeader tip)
 {
     SaveCurrentTip(transaction, (tip == null) ? null : new HashHeightPair(tip));
 }
 protected virtual void OnInsertTransactions(DBreeze.Transactions.Transaction dbreezeTransaction, List <(Transaction, Block)> transactions)
        /// <inheritdoc />
        public void SaveChanges(IList <UnspentOutputs> unspentOutputs, IEnumerable <TxOut[]> originalOutputs, uint256 oldBlockHash, uint256 nextBlockHash, int height, List <RewindData> rewindDataList = null)
        {
            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.LogDebug("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.LogDebug("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), this.dBreezeSerializer.Serialize(coin.ToCoins()));
                    }

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

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

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

            this.performanceCounter.AddInsertedEntities(insertedEntities);
        }
Exemplo n.º 6
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);
        }
Exemplo n.º 7
0
 public abstract long GetLastServerSyncTimeStamp(DBreeze.Transactions.Transaction tran);
        /// <summary>
        /// Set's the hash and height tip of the new <see cref="ProvenBlockHeader"/>.
        /// </summary>
        /// <param name="transaction"> Open DBreeze transaction.</param>
        /// <param name="newTip"> Hash height pair of the new block tip.</param>
        private void SetTip(DBreeze.Transactions.Transaction transaction, HashHeightPair newTip)
        {
            Guard.NotNull(newTip, nameof(newTip));

            transaction.Insert(BlockHashHeightTable, blockHashHeightKey, this.dBreezeSerializer.Serialize(newTip));
        }
Exemplo n.º 9
0
        /// <summary>
        /// <para>Adding children to the node</para>
        /// Table, storing data structure, must be in tran.SynchronizeTables list.
        /// Then transaction must be Committed in the end by the programmer.
        /// </summary>
        /// <param name="nodes">Nodes to add to current node</param>
        /// <param name="tran">Existing transaction. Table, storing data structure, must be in tran.SynchronizeTables list</param>
        /// <param name="maximalSpeed">set it to true to gain maximal saving speed</param>
        /// <returns>return node with setup parent id</returns>
        public DataAsTree AddNode(DataAsTree node, DBreeze.Transactions.Transaction tran, bool maximalSpeed = false)
        {
            CheckTransaction(tran);

            if (node == null)
            {
                throw new Exception("Nodes is not supplied");
            }

            SetupWriteTables(tran, maximalSpeed);

            byte[] val = null;

            long maxId = tran.Select <byte[], long>(this.DBreezeTableName, new byte[] { 1 }).Value;

            bool skipToFillNameIndex = false;

            if (node.NodeId == 0)
            {
                //Insert
                node.ParentNodeId = this.NodeId;
                maxId++;
                node.NodeId = maxId;
            }
            else
            {
                //Update

                var oldRow = nt2Write.Select <byte[], byte[]>(node.ParentNodeId.To_8_bytes_array_BigEndian().Concat(node.NodeId.To_8_bytes_array_BigEndian()));
                if (oldRow.Exists)
                {
                    var oldNode = SetupNodeFromRow(oldRow);

                    if (!oldNode.NodeName.Equals(node.NodeName, StringComparison.OrdinalIgnoreCase))
                    {
                        RemoveOldNodeFromNameIndex(oldNode.NodeName, node.ParentNodeId.To_8_bytes_array_BigEndian().Concat(node.NodeId.To_8_bytes_array_BigEndian()));
                    }
                    else
                    {
                        skipToFillNameIndex = true;
                    }
                }
                else
                {
                    //Fake? We create new row
                    node.ParentNodeId = this.NodeId;
                    maxId++;
                    node.NodeId = maxId;
                }
            }


            //ParentNodeId(long),NodeId(long)
            byte[] key = node.ParentNodeId.To_8_bytes_array_BigEndian()
                         .Concat(node.NodeId.To_8_bytes_array_BigEndian());

            if (node.NodeContent != null)
            {
                node.ContentRef = nt2Write.InsertDataBlock(node.ContentRef, node.NodeContent);
            }
            else
            {
                node.ContentRef = null;
            }

            val = SetupValueRowFromNode(node, 1);

            CopyInternals(node);

            nt2Write.Insert <byte[], byte[]>(key, val);

            /*node.NodeName index support*/
            if (!skipToFillNameIndex)
            {
                DBreeze.DataTypes.Row <string, byte[]> nodeNameIndexRow = null;
                byte[] btNodeNameIndex = null;

                nodeNameIndexRow = nt3Write.Select <string, byte[]>(node.NodeName.ToLower());
                if (nodeNameIndexRow.Exists)
                {
                    btNodeNameIndex = nodeNameIndexRow.Value.Concat(key);
                }
                else
                {
                    btNodeNameIndex = key;
                }
                nt3Write.Insert <string, byte[]>(node.NodeName.ToLower(), btNodeNameIndex);
            }
            /*-----------------------------*/


            //Latest used Id
            tran.Insert <byte[], long>(this.DBreezeTableName, new byte[] { 1 }, maxId);

            return(node);
        }//eo func
Exemplo n.º 10
0
 /// <summary>
 ///  Removes node
 /// </summary>
 /// <param name="node"></param>
 /// <param name="tran"></param>
 /// <param name="maximalSpeed"></param>
 public void RemoveNode(DataAsTree node, DBreeze.Transactions.Transaction tran, bool maximalSpeed = false)
 {
     this.RemoveNode(node.ParentNodeId, node.NodeId, tran, maximalSpeed);
 }
Exemplo n.º 11
0
        private void CreateIndex(string name, bool multiValue, string builder, string[] dependencies, DBreeze.Transactions.Transaction transaction)
        {
            if (this.Indexes.ContainsKey(name))
            {
                throw new IndexStoreException("The '" + name + "' index already exists");
            }

            var index = new Index(this, name, multiValue, builder, dependencies);

            this.Indexes[name] = index;

            var dbIndex = transaction.Select <string, string>("Common", index.Table);

            if (dbIndex.Exists)
            {
                transaction.RemoveAllKeys(index.Table, true);
            }

            if (!this.tableNames.Contains(index.Table))
            {
                this.tableNames.Add(index.Table);
            }

            var transactions = new List <(Transaction, Block)>();

            foreach (var row in transaction.SelectForward <byte[], Block>("Block"))
            {
                var block = row.Value;
                var key   = block.GetHash().ToBytes();

                foreach (var transaction2 in block.Transactions)
                {
                    transactions.Add((transaction2, block));
                }

                if (transactions.Count >= 5000)
                {
                    index.IndexTransactionDetails(transactions);
                    transactions.Clear();
                }
            }

            index.IndexTransactionDetails(transactions);
            transaction.Insert <string, string>("Common", index.Table, index.ToString());
        }
Exemplo n.º 12
0
        public static byte[] Get(DBreeze.Transactions.Transaction dbTx, byte[] contactHash)
        {
            var row = dbTx.Select <byte[], byte[]>(TABLE, contactHash);

            return(row.Exists ? row.Value : null);
        }
Exemplo n.º 13
0
 public static void Add(DBreeze.Transactions.Transaction dbTx, byte[] contactHash, byte[] txHash)
 {
     dbTx.Insert <byte[], byte[]>(TABLE, contactHash, txHash);
 }
        public byte[] GetLast(DBreeze.Transactions.Transaction dbTx)
        {
            var record = dbTx.SelectBackward <uint, byte[]>(TABLE).First();

            return(record == null ? null : record.Value);
        }
 public void Add(DBreeze.Transactions.Transaction dbTx, uint blockNumber, byte[] block)
 {
     dbTx.Insert <uint, byte[]>(TABLE, blockNumber, block);
 }
        /// <summary>
        /// Set's the hash and height tip of the new <see cref="ProvenBlockHeader"/>.
        /// </summary>
        /// <param name="transaction"> Open DBreeze transaction.</param>
        /// <param name="newTip"> Hash height pair of the new block tip.</param>
        private void SetTip(DBreeze.Transactions.Transaction transaction, HashHeightPair newTip)
        {
            Guard.NotNull(newTip, nameof(newTip));

            transaction.Insert <byte[], HashHeightPair>(BlockHashHeightTable, blockHashHeightKey, newTip);
        }
Exemplo n.º 17
0
 private void PutStakeInternal(DBreeze.Transactions.Transaction transaction, IEnumerable <StakeItem> stakeEntries)
 {
     throw new NotImplementedException();
 }
Exemplo n.º 18
0
            /// <summary>
            /// 
            /// </summary>
            /// <param name="_tran"></param>
            /// <param name="_DocumentsStorageTablesPrefix"></param>
            public InTran_DocumentAppender(DBreeze.Transactions.Transaction _tran, string _DocumentsStorageTablesPrefix)
            {
                if(_tran == null)
                    throw new Exception("DocumentAppender transaction is null");

                tran = _tran;
                //documentSpaceId = _documentSpaceId;
                DocumentsStorageTablesPrefix = _DocumentsStorageTablesPrefix;
            }
Exemplo n.º 19
0
 public abstract List <SyncOperation> GetSyncOperations(DBreeze.Transactions.Transaction tran, out bool repeatSync);
Exemplo n.º 20
0
 protected override void OnInsertTransactions(DBreeze.Transactions.Transaction dbreezeTransaction, List <(Transaction, Block)> transactions)
Exemplo n.º 21
0
 private void SaveHighestPollId(DBreeze.Transactions.Transaction transaction)
 {
     transaction.Insert <byte[], int>(TableName, RepositoryHighestIndexKey, this.highestPollId);
 }
Exemplo n.º 22
0
 public int IndexTransactionDetails(DBreeze.Transactions.Transaction dbreezeTransaction, List <(Transaction, Block)> transactions, bool remove = false)
Exemplo n.º 23
0
        /// <inheritdoc />
        public 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();
            var 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.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 (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);
        }
Exemplo n.º 24
0
 private void AddBusinessType(DBreeze.Transactions.Transaction t, BusinessTypeModel _model)
 {
     t.Insert <string, string>(Datalog._Business_Type, _model.key, _model.remark);
 }
Exemplo n.º 25
0
        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();

            block2.Header.Nonce = 11;
            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[], byte[]>("Common", new byte[0], this.DBreezeSerializer.Serialize(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[], byte[]>        blockHashKeyRow = trans.Select <byte[], byte[]>("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), this.DBreezeSerializer.Deserialize <HashHeightPair>(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));
                }
            }
        }
Exemplo n.º 26
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);
 }
 private void ResetLocked(DBreeze.Transactions.Transaction transaction)
 {
     this.highestPollId = -1;
     transaction.RemoveAllKeys(DataTable, true);
     this.CurrentTip = null;
 }
Exemplo n.º 28
0
 private void AddBusinessData(DBreeze.Transactions.Transaction t, BusinessDataModel _model)
 {
     t.Insert <string, string>(_model.tableName, _model.key, _model.content);
 }
        public void Initialize()
        {
            // Load highest index.
            lock (this.lockObject)
            {
                using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction())
                {
                    try
                    {
                        List <Poll> polls = GetAllPolls(transaction);

                        // If the polls repository contains duplicate polls then reset the highest poll id and
                        // set the tip to null.
                        // This will trigger the VotingManager to rebuild the voting and polls repository as the
                        // polls repository tip is null. This happens later during startup, see VotingManager.Synchronize()
                        var uniquePolls = new HashSet <Poll>(polls);
                        if (uniquePolls.Count != polls.Count)
                        {
                            this.logger.LogWarning("The polls repository contains {0} duplicate polls, it will be rebuilt.", polls.Count - uniquePolls.Count);

                            this.ResetLocked(transaction);
                            transaction.Commit();
                            return;
                        }

                        // Check to see if a polls repository tip is saved, if not rebuild the repo.
                        Row <byte[], byte[]> rowTip = transaction.Select <byte[], byte[]>(DataTable, RepositoryTipKey);
                        if (!rowTip.Exists)
                        {
                            this.logger.LogInformation("The polls repository tip is unknown, it will be rebuilt.");
                            this.ResetLocked(transaction);
                            transaction.Commit();
                            return;
                        }

                        // Check to see if the polls repo tip exists in chain.
                        // The node could have been rewound so we need to rebuild the repo from that point.
                        this.CurrentTip = this.dBreezeSerializer.Deserialize <HashHeightPair>(rowTip.Value);
                        ChainedHeader chainedHeaderTip = this.chainIndexer.GetHeader(this.CurrentTip.Hash);
                        if (chainedHeaderTip != null)
                        {
                            this.highestPollId = (polls.Count > 0) ? polls.Max(p => p.Id) : -1;
                            this.logger.LogInformation("Polls repository tip exists on chain; initializing at height {0}; highest poll id: {1}.", this.CurrentTip.Height, this.highestPollId);
                            return;
                        }

                        this.logger.LogInformation("The polls repository tip {0} was not found in the consensus chain, determining fork.", this.CurrentTip);

                        // The polls repository tip could not be found in the chain.
                        // Look at all other known hash/height pairs to find something in common with the consensus chain.
                        // We will take that as the last known valid height.
                        int maxGoodHeight = -1;
                        foreach (Poll poll in polls)
                        {
                            if (poll.PollStartBlockData.Height > maxGoodHeight && this.chainIndexer.GetHeader(poll.PollStartBlockData.Hash) != null)
                            {
                                maxGoodHeight = poll.PollStartBlockData.Height;
                            }
                            if (poll.PollExecutedBlockData?.Height > maxGoodHeight && this.chainIndexer.GetHeader(poll.PollExecutedBlockData.Hash) != null)
                            {
                                maxGoodHeight = poll.PollExecutedBlockData.Height;
                            }
                            if (poll.PollVotedInFavorBlockData?.Height > maxGoodHeight && this.chainIndexer.GetHeader(poll.PollVotedInFavorBlockData.Hash) != null)
                            {
                                maxGoodHeight = poll.PollVotedInFavorBlockData.Height;
                            }
                        }

                        if (maxGoodHeight == -1)
                        {
                            this.logger.LogInformation("No common blocks found; the repo will be rebuilt from scratch.");
                            this.ResetLocked(transaction);
                            transaction.Commit();
                            return;
                        }

                        this.CurrentTip = new HashHeightPair(this.chainIndexer.GetHeader(maxGoodHeight));

                        this.logger.LogInformation("Common block found at height {0}; the repo will be rebuilt from there.", this.CurrentTip.Height);

                        // Trim polls to tip.
                        HashSet <Poll> pollsToDelete = new HashSet <Poll>();
                        foreach (Poll poll in polls)
                        {
                            if (poll.PollStartBlockData.Height > this.CurrentTip.Height)
                            {
                                pollsToDelete.Add(poll);
                                this.logger.LogDebug("Poll {0} will be deleted.", poll.Id);
                                continue;
                            }

                            bool modified = false;

                            if (poll.PubKeysHexVotedInFavor.Any(v => v.Height > this.CurrentTip.Height))
                            {
                                poll.PubKeysHexVotedInFavor = poll.PubKeysHexVotedInFavor.Where(v => v.Height <= this.CurrentTip.Height).ToList();
                                modified = true;
                            }

                            if (poll.PollExecutedBlockData?.Height > this.CurrentTip.Height)
                            {
                                poll.PollExecutedBlockData = null;
                                modified = true;
                            }

                            if (poll.PollVotedInFavorBlockData?.Height > this.CurrentTip.Height)
                            {
                                poll.PollVotedInFavorBlockData = null;
                                modified = true;
                            }

                            // Check if the current tip is before the poll expiry activation block,
                            // if so un-expire it.
                            if (poll.IsExpired && !IsPollExpiredAt(poll, chainedHeaderTip, this.network))
                            {
                                this.logger.LogDebug("Un-expiring poll {0}.", poll.Id);
                                poll.IsExpired = false;

                                modified = true;
                            }

                            if (modified)
                            {
                                UpdatePoll(transaction, poll);
                            }
                        }

                        DeletePollsAndSetHighestPollId(transaction, pollsToDelete.Select(p => p.Id).ToArray());
                        SaveCurrentTip(transaction, this.CurrentTip);
                        transaction.Commit();

                        this.logger.LogInformation("Polls repository initialized at height {0}; highest poll id: {1}.", this.CurrentTip.Height, this.highestPollId);
                    }
                    catch (Exception err) when(err.Message == "No more byte to read")
                    {
                        this.logger.LogWarning("There was an error reading the polls repository, it will be rebuild.");
                        this.ResetLocked(transaction);
                        transaction.Commit();
                    }
                }
            }
        }
Exemplo n.º 30
0
 private void DeleteBusinessData(DBreeze.Transactions.Transaction t, BusinessDataModel businessDataModel)
 {
     t.RemoveKey <string>(businessDataModel.tableName, businessDataModel.key, out bool wasremoved);
 }
Exemplo n.º 31
0
 /// <summary>
 /// Set's the tip of the coinview to a new block hash.
 /// </summary>
 /// <param name="transaction">Open DBreeze transaction.</param>
 /// <param name="nextBlockHash">Hash of the block to become the new tip.</param>
 private void SetBlockHash(DBreeze.Transactions.Transaction transaction, uint256 nextBlockHash)
 {
     this.blockHash = nextBlockHash;
     transaction.Insert <byte[], uint256>("BlockHash", blockHashKey, nextBlockHash);
 }
Exemplo n.º 32
0
        public override List <SyncOperation> GetSyncOperations(DBreeze.Transactions.Transaction tran, out bool repeatSync)
        {
            var syncList = new List <SyncOperation>();

            _newLocalSyncTimeStamp = DateTime.UtcNow.Ticks; //This value will be applied if there is nothing to synchronize
            repeatSync             = false;

            var changedEntities = new Dictionary <long, Tuple <long, bool> >();    //Key is entityId, Value is Synctimestamp
            var entityType      = typeof(T).FullName;

            var lastLocalSyncTimeStamp = tran.Select <byte[], long>(_entitySync.entityTable, new byte[] { LocalSyncTS, 1 }).Value;

            foreach (var row in
                     tran.SelectForwardFromTo <byte[], byte[]>(_entitySync.entityTable,
                                                               new byte[] { SyncLog }.ConcatMany((lastLocalSyncTimeStamp + 1).To_8_bytes_array_BigEndian(), long.MinValue.To_8_bytes_array_BigEndian()),
                                                               true, //true, but LastLocalSyncTimeStamp+1 is used
                                                               new byte[] { SyncLog }.ConcatMany(long.MaxValue.To_8_bytes_array_BigEndian(), long.MaxValue.To_8_bytes_array_BigEndian()),
                                                               true))
            {
                if (changedEntities.Count > _entitySync.LimitationOfEntitesPerRound)
                {
                    repeatSync = true;
                    break;
                }

                //We will leave only last update of the particular entity
                if (!changedEntities.TryGetValue(row.Key.Substring(9, 8).To_Int64_BigEndian(), out var tpl1))
                {
                    changedEntities[row.Key.Substring(9, 8).To_Int64_BigEndian()] = new Tuple <long, bool>(row.Key.Substring(1, 8).To_Int64_BigEndian(),
                                                                                                           (row.Value?.Length >= 1 && row.Value[0] == 1) ? true : false) //indicating that new entity was inserted
                    ;
                }
                else
                {
                    changedEntities[row.Key.Substring(9, 8).To_Int64_BigEndian()] = new Tuple <long, bool>(row.Key.Substring(1, 8).To_Int64_BigEndian(),
                                                                                                           (tpl1.Item2 || (row.Value?.Length >= 1 && row.Value[0] == 1)) ? true : false) //indicating that new entity was inserted (from any of inserts that must be done for the id)
                    ;
                }

                _newLocalSyncTimeStamp = row.Key.Substring(1, 8).To_Int64_BigEndian();
            }

            foreach (var ent in changedEntities.OrderBy(r => r.Key))
            {
                var rowEntity = tran.Select <byte[], byte[]>(_entitySync.entityTable, new byte[] { Entity }.Concat(ent.Key.To_8_bytes_array_BigEndian()));

                var syncOperation = new SyncOperation()
                {
                    ExternalId    = ent.Value.Item2 ? 0 : ent.Key, //if entity new ExternalId will be 0 otherwise will equal to InternalId and higher than 0
                    InternalId    = ent.Key,
                    Operation     = rowEntity.Exists ? SyncOperation.eOperation.INSERT : SyncOperation.eOperation.REMOVE,
                    Type          = entityType,
                    SyncTimestamp = ent.Value.Item1
                };
                if (rowEntity.Exists)
                {
                    syncOperation.SerializedObject = rowEntity.GetDataBlockWithFixedAddress <byte[]>();
                }
                syncList.Add(syncOperation);
            }
            return(syncList);
        }