Example #1
0
 public LevelDBBlockchain()
 {
     Slice value;
     db = DB.Open(Settings.Default.DataDirectoryPath);
     if (db.TryGet(ReadOptions.Default, SliceBuilder.Begin(DataEntryPrefix.CFG_Initialized), out value) && value.ToBoolean())
     {
         value = db.Get(ReadOptions.Default, SliceBuilder.Begin(DataEntryPrefix.SYS_CurrentBlock));
         this.current_block = new UInt256(value.ToArray().Take(32).ToArray());
         this.current_height = BitConverter.ToUInt32(value.ToArray(), 32);
     }
     else
     {
         WriteBatch batch = new WriteBatch();
         ReadOptions options = new ReadOptions { FillCache = false };
         using (Iterator it = db.NewIterator(options))
         {
             for (it.SeekToFirst(); it.Valid(); it.Next())
             {
                 batch.Delete(it.Key());
             }
         }
         batch.Put(SliceBuilder.Begin(DataEntryPrefix.CFG_Version), 0);
         db.Write(WriteOptions.Default, batch);
         AddBlockToChain(GenesisBlock);
         db.Put(WriteOptions.Default, SliceBuilder.Begin(DataEntryPrefix.CFG_Initialized), true);
     }
     thread_persistence = new Thread(PersistBlocks);
     thread_persistence.Name = "LevelDBBlockchain.PersistBlocks";
     thread_persistence.Start();
     AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
 }
        public static void Put(this LevelDB.WriteBatch batch, byte table, byte[] key, byte[] value)
        {
            Span <byte> dbkey = stackalloc byte[key.Length + 1];

            dbkey[0] = table;
            key.AsSpan().CopyTo(dbkey.Slice(1));

            batch.Put(dbkey.ToArray(), value);
        }
Example #3
0
        public bool TryAddChainedHeader(ChainedHeader chainedHeader)
        {
            var key = MakeHeaderKey(chainedHeader.Hash);

            Slice existingValue;
            if (db.TryGet(ReadOptions.Default, key, out existingValue))
                return false;

            var writeBatch = new WriteBatch();
            try
            {
                writeBatch.Put(key, DataEncoder.EncodeChainedHeader(chainedHeader));
                writeBatch.Put(MakeTotalWorkKey(chainedHeader.Hash, chainedHeader.TotalWork), new byte[1]);

                db.Write(WriteOptions.Default, writeBatch);
            }
            finally
            {
                writeBatch.Dispose();
            }

            return true;
        }
Example #4
0
 public LevelDBBlockchain(string path)
 {
     header_index.Add(GenesisBlock.Hash);
     Version version;
     Slice value;
     db = DB.Open(path, new Options { CreateIfMissing = true });
     if (db.TryGet(ReadOptions.Default, SliceBuilder.Begin(DataEntryPrefix.CFG_Version), out value) && Version.TryParse(value.ToString(), out version) && version >= Version.Parse("0.4"))
     {
         ReadOptions options = new ReadOptions { FillCache = false };
         value = db.Get(options, SliceBuilder.Begin(DataEntryPrefix.SYS_CurrentBlock));
         this.current_block_hash = new UInt256(value.ToArray().Take(32).ToArray());
         this.current_block_height = BitConverter.ToUInt32(value.ToArray(), 32);
         foreach (Block header in db.Find(options, SliceBuilder.Begin(DataEntryPrefix.DATA_HeaderList), (k, v) =>
         {
             using (MemoryStream ms = new MemoryStream(v.ToArray(), false))
             using (BinaryReader r = new BinaryReader(ms))
             {
                 return new
                 {
                     Index = BitConverter.ToUInt32(k.ToArray(), 1),
                     Headers = r.ReadSerializableArray<Block>()
                 };
             }
         }).OrderBy(p => p.Index).SelectMany(p => p.Headers).ToArray())
         {
             if (header.Hash != GenesisBlock.Hash)
             {
                 header_chain.Add(header.Hash, header, header.PrevBlock);
                 header_index.Add(header.Hash);
             }
             stored_header_count++;
         }
         if (stored_header_count == 0)
         {
             Dictionary<UInt256, Block> table = db.Find(options, SliceBuilder.Begin(DataEntryPrefix.DATA_Block), (k, v) => Block.FromTrimmedData(v.ToArray(), 0)).ToDictionary(p => p.PrevBlock);
             for (UInt256 hash = GenesisBlock.Hash; hash != current_block_hash;)
             {
                 Block header = table[hash];
                 header_chain.Add(header.Hash, header, header.PrevBlock);
                 header_index.Add(header.Hash);
                 hash = header.Hash;
             }
         }
         else if (current_block_height >= stored_header_count)
         {
             List<Block> list = new List<Block>();
             for (UInt256 hash = current_block_hash; hash != header_index[(int)stored_header_count - 1];)
             {
                 Block header = Block.FromTrimmedData(db.Get(options, SliceBuilder.Begin(DataEntryPrefix.DATA_Block).Add(hash)).ToArray(), 0);
                 list.Add(header);
                 header_index.Insert((int)stored_header_count, hash);
                 hash = header.PrevBlock;
             }
             for (int i = list.Count - 1; i >= 0; i--)
             {
                 header_chain.Add(list[i].Hash, list[i], list[i].PrevBlock);
             }
         }
         this.current_header_hash = header_index[header_index.Count - 1];
     }
     else
     {
         WriteBatch batch = new WriteBatch();
         ReadOptions options = new ReadOptions { FillCache = false };
         using (Iterator it = db.NewIterator(options))
         {
             for (it.SeekToFirst(); it.Valid(); it.Next())
             {
                 batch.Delete(it.Key());
             }
         }
         db.Write(WriteOptions.Default, batch);
         Persist(GenesisBlock);
         db.Put(WriteOptions.Default, SliceBuilder.Begin(DataEntryPrefix.CFG_Version), Assembly.GetExecutingAssembly().GetName().Version.ToString());
     }
     thread_persistence = new Thread(PersistBlocks);
     thread_persistence.Name = "LevelDBBlockchain.PersistBlocks";
     thread_persistence.Start();
     AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
 }
Example #5
0
 private void OnAddHeader(Block header)
 {
     if (header.PrevBlock == current_header_hash)
     {
         current_header_hash = header.Hash;
         header_index.Add(header.Hash);
         uint height = header_chain.Nodes[current_header_hash].Height;
         if (height % 2000 == 0)
         {
             WriteBatch batch = new WriteBatch();
             while (height - 2000 > stored_header_count)
             {
                 using (MemoryStream ms = new MemoryStream())
                 using (BinaryWriter w = new BinaryWriter(ms))
                 {
                     w.Write(header_index.Skip((int)stored_header_count).Take(2000).Select(p => header_chain[p]).ToArray());
                     w.Flush();
                     batch.Put(SliceBuilder.Begin(DataEntryPrefix.DATA_HeaderList).Add(stored_header_count), ms.ToArray());
                 }
                 stored_header_count += 2000;
             }
             db.Write(WriteOptions.Default, batch);
         }
     }
     else
     {
         TreeNode<Block> main = header_chain.Leaves.OrderByDescending(p => p.Height).First();
         if (main.Item.Hash != current_header_hash)
         {
             TreeNode<Block> fork = header_chain.Nodes[current_header_hash];
             current_header_hash = main.Item.Hash;
             TreeNode<Block> common = header_chain.FindCommonNode(main, fork);
             header_index.RemoveRange((int)common.Height + 1, header_index.Count - (int)common.Height - 1);
             for (TreeNode<Block> i = main; i != common; i = i.Parent)
             {
                 header_index.Insert((int)common.Height + 1, i.Item.Hash);
             }
             if (header_chain.Nodes[current_block_hash].Height > common.Height)
             {
                 Rollback(common.Item.Hash);
             }
         }
     }
 }
Example #6
0
 /// <summary>
 /// Delete the batch of keys.
 /// </summary>
 /// <param name="batch">Batch of keys to delete.</param>
 public void DeleteBatch(IEnumerable<string> batch)
 {
     var writeBatch = new WriteBatch();
     foreach (var key in batch)
     {
         writeBatch.Delete(key);
     }
     writeBatch.Commit(db);
 }
Example #7
0
File: DBTests.cs Project: vebin/BD2
        public void WriteBatch()
        {
            Database.Put ("key1", "value1");

            var writeBatch = new WriteBatch ().
                Delete ("key1").
                Put ("key2", "value2");
            Database.Write (writeBatch);

            var value1 = Database.Get ("key1");
            Assert.IsNull (value1);
            var value2 = Database.Get ("key2");
            Assert.AreEqual ("value2", value2);

            writeBatch.Delete ("key2").Clear ();
            Database.Write (writeBatch);
            value2 = Database.Get ("key2");
            Assert.AreEqual ("value2", value2);
        }
Example #8
0
        public void Batch_PutToDB(LevelDB.WriteBatch batch, LevelDB.DB db, byte[] key)
        {
            var _value = Helper.tagValue_Bytes.Concat(this.Value).ToArray();

            batch.Put(key, _value);
        }
Example #9
0
 /// <summary>
 /// Put the batch of keys and values in the storage.
 /// </summary>
 /// <param name="batch">Batch of keys and values.</param>
 public void PutBatch(Dictionary<string, string> batch)
 {
     var writeBatch = new WriteBatch();
     foreach (var column in batch)
     {
         writeBatch.Put(column.Key, column.Value);
     }
     writeBatch.Commit(db);
 }
Example #10
0
        public bool TryRemoveChainedHeader(UInt256 blockHash)
        {
            var key = MakeHeaderKey(blockHash);

            Slice existingValue;
            if (!db.TryGet(ReadOptions.Default, key, out existingValue))
                return false;

            var chainedHeader = DataDecoder.DecodeChainedHeader(existingValue.ToArray());

            var writeBatch = new WriteBatch();
            try
            {
                writeBatch.Delete(key);
                writeBatch.Delete(MakeTotalWorkKey(blockHash, chainedHeader.TotalWork));

                db.Write(WriteOptions.Default, writeBatch);
            }
            finally
            {
                writeBatch.Dispose();
            }

            return true;
        }
Example #11
0
 public void Write(WriteBatch batch)
 {
     Write(batch, new WriteOptions());
 }
        public void DeleteElements(IEnumerable<KeyValuePair<UInt256, IEnumerable<int>>> blockTxIndices)
        {
            var writeBatch = new WriteBatch();
            try
            {
                foreach (var keyPair in blockTxIndices)
                {
                    var blockHash = keyPair.Key;
                    var txIndices = keyPair.Value;

                    // prune the transactions
                    foreach (var index in txIndices)
                    {
                        writeBatch.Delete(DbEncoder.EncodeBlockHashTxIndex(blockHash, index));
                    }
                }

                db.Write(new WriteOptions(), writeBatch);
            }
            finally
            {
                writeBatch.Dispose();
            }
        }
Example #13
0
 private void Persist(Block block)
 {
     MultiValueDictionary<UInt256, ushort> unspents = new MultiValueDictionary<UInt256, ushort>(p =>
     {
         Slice value = new byte[0];
         db.TryGet(ReadOptions.Default, SliceBuilder.Begin(DataEntryPrefix.IX_Unspent).Add(p), out value);
         return new HashSet<ushort>(value.ToArray().GetUInt16Array());
     });
     MultiValueDictionary<UInt256, ushort> unspent_antshares = new MultiValueDictionary<UInt256, ushort>(p =>
     {
         Slice value = new byte[0];
         db.TryGet(ReadOptions.Default, SliceBuilder.Begin(DataEntryPrefix.IX_AntShare).Add(p), out value);
         return new HashSet<ushort>(value.ToArray().GetUInt16Array());
     });
     MultiValueDictionary<UInt256, ushort> unspent_votes = new MultiValueDictionary<UInt256, ushort>(p =>
     {
         Slice value = new byte[0];
         db.TryGet(ReadOptions.Default, SliceBuilder.Begin(DataEntryPrefix.IX_Vote).Add(p), out value);
         return new HashSet<ushort>(value.ToArray().GetUInt16Array());
     });
     Dictionary<UInt256, Fixed8> quantities = new Dictionary<UInt256, Fixed8>();
     WriteBatch batch = new WriteBatch();
     batch.Put(SliceBuilder.Begin(DataEntryPrefix.DATA_Block).Add(block.Hash), block.Trim());
     foreach (Transaction tx in block.Transactions)
     {
         batch.Put(SliceBuilder.Begin(DataEntryPrefix.DATA_Transaction).Add(tx.Hash), tx.ToArray());
         switch (tx.Type)
         {
             case TransactionType.IssueTransaction:
                 foreach (TransactionResult result in tx.GetTransactionResults().Where(p => p.Amount < Fixed8.Zero))
                 {
                     if (quantities.ContainsKey(result.AssetId))
                     {
                         quantities[result.AssetId] -= result.Amount;
                     }
                     else
                     {
                         quantities.Add(result.AssetId, -result.Amount);
                     }
                 }
                 break;
             case TransactionType.EnrollmentTransaction:
                 {
                     EnrollmentTransaction enroll_tx = (EnrollmentTransaction)tx;
                     batch.Put(SliceBuilder.Begin(DataEntryPrefix.IX_Enrollment).Add(tx.Hash), true);
                 }
                 break;
             case TransactionType.VotingTransaction:
                 unspent_votes.AddEmpty(tx.Hash);
                 for (ushort index = 0; index < tx.Outputs.Length; index++)
                 {
                     if (tx.Outputs[index].AssetId == AntShare.Hash)
                     {
                         unspent_votes.Add(tx.Hash, index);
                     }
                 }
                 break;
             case TransactionType.RegisterTransaction:
                 {
                     RegisterTransaction reg_tx = (RegisterTransaction)tx;
                     batch.Put(SliceBuilder.Begin(DataEntryPrefix.IX_Asset).Add(reg_tx.Hash), true);
                 }
                 break;
         }
         unspents.AddEmpty(tx.Hash);
         unspent_antshares.AddEmpty(tx.Hash);
         for (ushort index = 0; index < tx.Outputs.Length; index++)
         {
             unspents.Add(tx.Hash, index);
             if (tx.Outputs[index].AssetId == AntShare.Hash)
             {
                 unspent_antshares.Add(tx.Hash, index);
             }
         }
     }
     foreach (TransactionInput input in block.Transactions.SelectMany(p => p.GetAllInputs()))
     {
         if (input.PrevIndex == 0)
         {
             batch.Delete(SliceBuilder.Begin(DataEntryPrefix.IX_Enrollment).Add(input.PrevHash));
         }
         unspents.Remove(input.PrevHash, input.PrevIndex);
         unspent_antshares.Remove(input.PrevHash, input.PrevIndex);
         unspent_votes.Remove(input.PrevHash, input.PrevIndex);
     }
     //统计AntCoin的发行量
     {
         Fixed8 amount_in = block.Transactions.SelectMany(p => p.References.Values.Where(o => o.AssetId == AntCoin.Hash)).Sum(p => p.Value);
         Fixed8 amount_out = block.Transactions.SelectMany(p => p.Outputs.Where(o => o.AssetId == AntCoin.Hash)).Sum(p => p.Value);
         if (amount_in != amount_out)
         {
             quantities.Add(AntCoin.Hash, amount_out - amount_in);
         }
     }
     foreach (var unspent in unspents)
     {
         if (unspent.Value.Count == 0)
         {
             batch.Delete(SliceBuilder.Begin(DataEntryPrefix.IX_Unspent).Add(unspent.Key));
         }
         else
         {
             batch.Put(SliceBuilder.Begin(DataEntryPrefix.IX_Unspent).Add(unspent.Key), unspent.Value.ToByteArray());
         }
     }
     foreach (var unspent in unspent_antshares)
     {
         if (unspent.Value.Count == 0)
         {
             batch.Delete(SliceBuilder.Begin(DataEntryPrefix.IX_AntShare).Add(unspent.Key));
         }
         else
         {
             batch.Put(SliceBuilder.Begin(DataEntryPrefix.IX_AntShare).Add(unspent.Key), unspent.Value.ToByteArray());
         }
     }
     foreach (var unspent in unspent_votes)
     {
         if (unspent.Value.Count == 0)
         {
             batch.Delete(SliceBuilder.Begin(DataEntryPrefix.IX_Vote).Add(unspent.Key));
         }
         else
         {
             batch.Put(SliceBuilder.Begin(DataEntryPrefix.IX_Vote).Add(unspent.Key), unspent.Value.ToByteArray());
         }
     }
     foreach (var quantity in quantities)
     {
         batch.Put(SliceBuilder.Begin(DataEntryPrefix.ST_QuantityIssued).Add(quantity.Key), (GetQuantityIssued(quantity.Key) + quantity.Value).GetData());
     }
     current_block_hash = block.Hash;
     current_block_height = block.Hash == GenesisBlock.Hash ? 0 : current_block_height + 1;
     batch.Put(SliceBuilder.Begin(DataEntryPrefix.SYS_CurrentBlock), SliceBuilder.Begin().Add(block.Hash).Add(current_block_height));
     db.Write(WriteOptions.Default, batch);
 }
        private bool TryRemoveBlockInner(UInt256 blockHash, WriteBatch writeBatch)
        {
            // lock all when performing the block write, so count update is thread-safe
            lock (countLock)
            {
                // get the current count
                int count;
                Slice countSlice;
                if (db.TryGet(ReadOptions.Default, COUNT_KEY, out countSlice))
                    count = countSlice.ToInt32();
                else
                    count = 0;

                // check if block exists before writing
                var existsKey = MakeExistsKey(blockHash);
                Slice existsSlice;
                if (db.TryGet(ReadOptions.Default, existsKey, out existsSlice))
                {
                    // update count and remove block existence key
                    writeBatch.Put(COUNT_KEY, count - 1);
                    writeBatch.Delete(existsKey);

                    db.Write(WriteOptions.Default, writeBatch);

                    return true;
                }
                else
                    return false;
            }
        }
        public bool TryRemoveBlockTransactions(UInt256 blockHash)
        {
            if (!ContainsBlock(blockHash))
                return false;

            var writeBatch = new WriteBatch();
            try
            {
                using (var snapshot = db.GetSnapshot())
                {
                    var readOptions = new ReadOptions { Snapshot = snapshot };
                    using (var iterator = db.NewIterator(readOptions))
                    {
                        iterator.Seek(DbEncoder.EncodeBlockHashTxIndex(blockHash, 0));
                        while (iterator.Valid())
                        {
                            var key = iterator.Key().ToArray();

                            UInt256 iteratorBlockHash; int txIndex;
                            DbEncoder.DecodeBlockHashTxIndex(key, out iteratorBlockHash, out txIndex);

                            if (iteratorBlockHash != blockHash)
                                break;

                            writeBatch.Delete(key);

                            iterator.Next();
                        }
                    }
                }

                return TryRemoveBlockInner(blockHash, writeBatch);
            }
            finally
            {
                writeBatch.Dispose();
            }
        }
        public bool TryAddBlockTransactions(UInt256 blockHash, IEnumerable<EncodedTx> blockTxes)
        {
            if (ContainsBlock(blockHash))
                return false;

            var writeBatch = new WriteBatch();
            try
            {
                int txCount;
                using (var snapshot = db.GetSnapshot())
                {
                    var readOptions = new ReadOptions { Snapshot = snapshot };

                    var txIndex = 0;
                    foreach (var tx in blockTxes)
                    {
                        var key = DbEncoder.EncodeBlockHashTxIndex(blockHash, txIndex);

                        Slice existingValue;
                        if (db.TryGet(readOptions, key, out existingValue))
                            return false;

                        var blockTx = new BlockTx(txIndex, tx);
                        var value = DataEncoder.EncodeBlockTxNode(blockTx);

                        writeBatch.Put(key, value);

                        txIndex++;
                    }

                    txCount = txIndex;
                }

                return TryAddBlockInner(blockHash, txCount, writeBatch);
            }
            finally
            {
                writeBatch.Dispose();
            }
        }
Example #17
0
 public void Write(WriteBatch writeBatch)
 {
     Write(null, writeBatch);
 }
Example #18
0
 public void Write(WriteBatch batch)
 {
     Write(batch, _writeOptions);
 }
Example #19
0
 /// <summary>
 /// 将区块链的状态回滚到指定的位置
 /// </summary>
 /// <param name="hash">
 /// 要回滚到的区块的散列值
 /// </param>
 private void Rollback(UInt256 hash)
 {
     if (hash == current_block_hash) return;
     List<Block> blocks = new List<Block>();
     UInt256 current = current_block_hash;
     while (current != hash)
     {
         if (current == GenesisBlock.Hash)
             throw new InvalidOperationException();
         Block block = GetBlockInternal(current, ReadOptions.Default);
         blocks.Add(block);
         current = block.PrevBlock;
     }
     WriteBatch batch = new WriteBatch();
     foreach (Block block in blocks)
     {
         batch.Delete(SliceBuilder.Begin(DataEntryPrefix.DATA_Block).Add(block.Hash));
         foreach (Transaction tx in block.Transactions)
         {
             batch.Delete(SliceBuilder.Begin(DataEntryPrefix.DATA_Transaction).Add(tx.Hash));
             batch.Delete(SliceBuilder.Begin(DataEntryPrefix.IX_Enrollment).Add(tx.Hash));
             batch.Delete(SliceBuilder.Begin(DataEntryPrefix.IX_Unspent).Add(tx.Hash));
             batch.Delete(SliceBuilder.Begin(DataEntryPrefix.IX_AntShare).Add(tx.Hash));
             batch.Delete(SliceBuilder.Begin(DataEntryPrefix.IX_Vote).Add(tx.Hash));
             if (tx.Type == TransactionType.RegisterTransaction)
             {
                 RegisterTransaction reg_tx = (RegisterTransaction)tx;
                 batch.Delete(SliceBuilder.Begin(DataEntryPrefix.IX_Asset).Add(reg_tx.Hash));
             }
         }
     }
     HashSet<UInt256> tx_hashes = new HashSet<UInt256>(blocks.SelectMany(p => p.Transactions).Select(p => p.Hash));
     foreach (var group in blocks.SelectMany(p => p.Transactions).SelectMany(p => p.GetAllInputs()).GroupBy(p => p.PrevHash).Where(g => !tx_hashes.Contains(g.Key)))
     {
         Transaction tx = GetTransaction(group.Key, ReadOptions.Default);
         Slice value = new byte[0];
         db.TryGet(ReadOptions.Default, SliceBuilder.Begin(DataEntryPrefix.IX_Unspent).Add(tx.Hash), out value);
         IEnumerable<ushort> indexes = value.ToArray().GetUInt16Array().Union(group.Select(p => p.PrevIndex));
         batch.Put(SliceBuilder.Begin(DataEntryPrefix.IX_Unspent).Add(tx.Hash), indexes.ToByteArray());
         TransactionInput[] antshares = group.Where(p => tx.Outputs[p.PrevIndex].AssetId == AntShare.Hash).ToArray();
         if (antshares.Length > 0)
         {
             value = new byte[0];
             db.TryGet(ReadOptions.Default, SliceBuilder.Begin(DataEntryPrefix.IX_AntShare).Add(tx.Hash), out value);
             indexes = value.ToArray().GetUInt16Array().Union(antshares.Select(p => p.PrevIndex));
             batch.Put(SliceBuilder.Begin(DataEntryPrefix.IX_AntShare).Add(tx.Hash), indexes.ToByteArray());
         }
         switch (tx.Type)
         {
             case TransactionType.EnrollmentTransaction:
                 if (group.Any(p => p.PrevIndex == 0))
                 {
                     batch.Put(SliceBuilder.Begin(DataEntryPrefix.IX_Enrollment).Add(tx.Hash), true);
                 }
                 break;
             case TransactionType.VotingTransaction:
                 {
                     TransactionInput[] votes = group.Where(p => tx.Outputs[p.PrevIndex].AssetId == AntShare.Hash).ToArray();
                     if (votes.Length > 0)
                     {
                         value = new byte[0];
                         db.TryGet(ReadOptions.Default, SliceBuilder.Begin(DataEntryPrefix.IX_Vote).Add(tx.Hash), out value);
                         indexes = value.ToArray().GetUInt16Array().Union(votes.Select(p => p.PrevIndex));
                         batch.Put(SliceBuilder.Begin(DataEntryPrefix.IX_Vote).Add(tx.Hash), indexes.ToByteArray());
                     }
                 }
                 break;
         }
     }
     //回滚AntCoin的发行量
     {
         Fixed8 amount_in = blocks.SelectMany(p => p.Transactions).SelectMany(p => p.References.Values.Where(o => o.AssetId == Blockchain.AntCoin.Hash)).Sum(p => p.Value);
         Fixed8 amount_out = blocks.SelectMany(p => p.Transactions).SelectMany(p => p.Outputs.Where(o => o.AssetId == Blockchain.AntCoin.Hash)).Sum(p => p.Value);
         if (amount_in != amount_out)
         {
             batch.Put(SliceBuilder.Begin(DataEntryPrefix.ST_QuantityIssued).Add(AntCoin.Hash), (GetQuantityIssued(AntCoin.Hash) - (amount_out - amount_in)).GetData());
         }
     }
     foreach (var result in blocks.SelectMany(p => p.Transactions).Where(p => p.Type == TransactionType.IssueTransaction).SelectMany(p => p.GetTransactionResults()).Where(p => p.Amount < Fixed8.Zero).GroupBy(p => p.AssetId, (k, g) => new
     {
         AssetId = k,
         Amount = -g.Sum(p => p.Amount)
     }))
     {
         batch.Put(SliceBuilder.Begin(DataEntryPrefix.ST_QuantityIssued).Add(result.AssetId), (GetQuantityIssued(result.AssetId) - result.Amount).GetData());
     }
     current_block_hash = current;
     current_block_height -= (uint)blocks.Count;
     batch.Put(SliceBuilder.Begin(DataEntryPrefix.SYS_CurrentBlock), SliceBuilder.Begin().Add(current_block_hash).Add(current_block_height));
     db.Write(WriteOptions.Default, batch);
 }
Example #20
0
 public DbCache(DB db, byte prefix, WriteBatch batch = null)
 {
     this.db     = db;
     this.batch  = batch;
     this.prefix = prefix;
 }