Exemple #1
0
        private void AddTransaction(int blockIndex, int txIndex, UInt256 txHash, byte[] txBytes, EsentBlockTxesCursor cursor)
        {
            using (var jetUpdate = cursor.jetSession.BeginUpdate(cursor.blocksTableId, JET_prep.Insert))
            {
                Api.SetColumns(cursor.jetSession, cursor.blocksTableId,
                               new Int32ColumnValue {
                    Columnid = cursor.blockIndexColumnId, Value = blockIndex
                },
                               new Int32ColumnValue {
                    Columnid = cursor.txIndexColumnId, Value = txIndex
                },
                               //TODO i'm using -1 depth to mean not pruned, this should be interpreted as depth 0
                               new Int32ColumnValue {
                    Columnid = cursor.blockDepthColumnId, Value = -1
                },
                               new BytesColumnValue {
                    Columnid = cursor.blockTxHashColumnId, Value = DbEncoder.EncodeUInt256(txHash)
                },
                               new BytesColumnValue {
                    Columnid = cursor.blockTxBytesColumnId, Value = txBytes
                });

                jetUpdate.Save();
            }
        }
        public bool TryAddHeader(ChainedHeader header)
        {
            CheckWriteTransaction();

            try
            {
                using (SetSessionContext())
                    using (var jetUpdate = this.jetSession.BeginUpdate(this.headersTableId, JET_prep.Insert))
                    {
                        Api.SetColumns(this.jetSession, this.headersTableId,
                                       new BytesColumnValue {
                            Columnid = this.headerBlockHashColumnId, Value = DbEncoder.EncodeUInt256(header.Hash)
                        },
                                       new BytesColumnValue {
                            Columnid = this.headerBytesColumnId, Value = DataEncoder.EncodeChainedHeader(header)
                        });

                        jetUpdate.Save();
                    }

                return(true);
            }
            catch (EsentKeyDuplicateException)
            {
                return(false);
            }
        }
        public bool TryAddBlockUnmintedTxes(UInt256 blockHash, IImmutableList <UnmintedTx> unmintedTxes)
        {
            CheckWriteTransaction();

            try
            {
                using (SetSessionContext())
                    using (var jetUpdate = this.jetSession.BeginUpdate(this.unmintedTxTableId, JET_prep.Insert))
                    {
                        byte[] unmintedTxesBytes;
                        using (var stream = new MemoryStream())
                            using (var writer = new BinaryWriter(stream))
                            {
                                writer.WriteList(unmintedTxes, unmintedTx => DataEncoder.EncodeUnmintedTx(writer, unmintedTx));
                                unmintedTxesBytes = stream.ToArray();
                            }

                        Api.SetColumns(this.jetSession, this.unmintedTxTableId,
                                       new BytesColumnValue {
                            Columnid = this.unmintedBlockHashColumnId, Value = DbEncoder.EncodeUInt256(blockHash)
                        },
                                       new BytesColumnValue {
                            Columnid = this.unmintedDataColumnId, Value = unmintedTxesBytes
                        });

                        jetUpdate.Save();
                    }

                return(true);
            }
            catch (EsentKeyDuplicateException)
            {
                return(false);
            }
        }
        public bool TryAddUnspentTxOutput(TxOutputKey txOutputKey, TxOutput txOutput)
        {
            CheckWriteTransaction();

            using (SetSessionContext())
            {
                try
                {
                    using (var jetUpdate = this.jetSession.BeginUpdate(this.unspentTxOutputTableId, JET_prep.Insert))
                    {
                        Api.SetColumns(this.jetSession, this.unspentTxOutputTableId,
                                       new BytesColumnValue {
                            Columnid = this.txOutputKeyColumnId, Value = DbEncoder.EncodeTxOutputKey(txOutputKey)
                        },
                                       new BytesColumnValue {
                            Columnid = this.txOutputBytesColumnId, Value = DataEncoder.EncodeTxOutput(txOutput)
                        });

                        jetUpdate.Save();
                    }

                    return(true);
                }
                catch (EsentKeyDuplicateException)
                {
                    return(false);
                }
            }
        }
Exemple #5
0
        public bool TryRemoveUnspentTx(UInt256 txHash)
        {
            if (!this.inTransaction)
            {
                throw new InvalidOperationException();
            }

            Api.JetSetCurrentIndex(this.jetSession, this.unspentTxTableId, "IX_TxHash");
            Api.MakeKey(this.jetSession, this.unspentTxTableId, DbEncoder.EncodeUInt256(txHash), MakeKeyGrbit.NewKey);
            if (Api.TrySeek(this.jetSession, this.unspentTxTableId, SeekGrbit.SeekEQ))
            {
                var addedBlockIndex = Api.RetrieveColumnAsInt32(this.jetSession, this.unspentTxTableId, this.blockIndexColumnId).Value;
                var txIndex         = Api.RetrieveColumnAsInt32(this.jetSession, this.unspentTxTableId, this.txIndexColumnId).Value;
                var outputStates    = DataEncoder.DecodeOutputStates(Api.RetrieveColumn(this.jetSession, this.unspentTxTableId, this.outputStatesColumnId));

                Api.JetDelete(this.jetSession, this.unspentTxTableId);

                // decrease unspent tx count
                Api.EscrowUpdate(this.jetSession, this.globalsTableId, this.unspentTxCountColumnId, -1);

                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemple #6
0
        public BlockTxNode ReadNode()
        {
            var blockIndexColumn = new Int32ColumnValue {
                Columnid = cursor.blockIndexColumnId
            };
            var txIndexColumn = new Int32ColumnValue {
                Columnid = cursor.txIndexColumnId
            };
            var depthColumn = new Int32ColumnValue {
                Columnid = cursor.blockDepthColumnId
            };
            var txHashColumn = new BytesColumnValue {
                Columnid = cursor.blockTxHashColumnId
            };

            Api.RetrieveColumns(cursor.jetSession, cursor.blocksTableId, blockIndexColumn, txIndexColumn, depthColumn, txHashColumn);

            if (this.blockIndex != blockIndexColumn.Value.Value)
            {
                throw new InvalidOperationException();
            }

            var txIndex = txIndexColumn.Value.Value;
            var depth   = depthColumn.Value.Value;
            var txHash  = DbEncoder.DecodeUInt256(txHashColumn.Value);

            var pruned = depth >= 0;

            depth = Math.Max(0, depth);

            return(new BlockTxNode(txIndex, depth, txHash, pruned, encodedTx: null));
        }
        public bool TryRemoveChainedHeader(UInt256 blockHash)
        {
            using (var handle = this.cursorCache.TakeItem())
            {
                var cursor = handle.Item;

                using (var jetTx = cursor.jetSession.BeginTransaction())
                {
                    bool removed;

                    Api.JetSetCurrentIndex(cursor.jetSession, cursor.blockHeadersTableId, "IX_BlockHash");
                    Api.MakeKey(cursor.jetSession, cursor.blockHeadersTableId, DbEncoder.EncodeUInt256(blockHash), MakeKeyGrbit.NewKey);
                    if (Api.TrySeek(cursor.jetSession, cursor.blockHeadersTableId, SeekGrbit.SeekEQ))
                    {
                        Api.JetDelete(cursor.jetSession, cursor.blockHeadersTableId);
                        removed = true;
                    }
                    else
                    {
                        removed = false;
                    }

                    jetTx.CommitLazy();
                    return(removed);
                }
            }
        }
        public bool TryUpdateUnspentTx(UnspentTx unspentTx)
        {
            CheckWriteTransaction();

            using (SetSessionContext())
            {
                Api.JetSetCurrentIndex(this.jetSession, this.unspentTxTableId, "IX_TxHash");
                Api.MakeKey(this.jetSession, this.unspentTxTableId, DbEncoder.EncodeUInt256(unspentTx.TxHash), MakeKeyGrbit.NewKey);

                if (Api.TrySeek(this.jetSession, this.unspentTxTableId, SeekGrbit.SeekEQ))
                {
                    using (var jetUpdate = this.jetSession.BeginUpdate(this.unspentTxTableId, JET_prep.Replace))
                    {
                        Api.SetColumn(this.jetSession, this.unspentTxTableId, this.outputStatesColumnId, DataEncoder.EncodeOutputStates(unspentTx.OutputStates));

                        jetUpdate.Save();
                    }

                    return(true);
                }
                else
                {
                    return(false);
                }
            }
        }
        public void MarkBlockInvalid(UInt256 blockHash)
        {
            using (var handle = this.cursorCache.TakeItem())
            {
                var cursor = handle.Item;

                using (var jetTx = cursor.jetSession.BeginTransaction())
                {
                    Api.JetSetCurrentIndex(cursor.jetSession, cursor.blockHeadersTableId, "IX_BlockHash");
                    Api.MakeKey(cursor.jetSession, cursor.blockHeadersTableId, DbEncoder.EncodeUInt256(blockHash), MakeKeyGrbit.NewKey);

                    if (!Api.TrySeek(cursor.jetSession, cursor.blockHeadersTableId, SeekGrbit.SeekEQ))
                    {
                        throw new MissingDataException(blockHash);
                    }

                    using (var jetUpdate = cursor.jetSession.BeginUpdate(cursor.blockHeadersTableId, JET_prep.Replace))
                    {
                        Api.SetColumn(cursor.jetSession, cursor.blockHeadersTableId, cursor.blockHeaderValidColumnId, false);

                        jetUpdate.Save();
                    }

                    jetTx.CommitLazy();
                }
            }
        }
Exemple #10
0
        private IEnumerable <BlockTx> ReadBlockTransactions(UInt256 blockHash, int blockId)
        {
            using (var handle = this.cursorCache.TakeItem())
            {
                var cursor = handle.Item;

                using (var jetTx = cursor.jetSession.BeginTransaction())
                {
                    var sha256 = new SHA256Managed();

                    Api.JetSetCurrentIndex(cursor.jetSession, cursor.blocksTableId, "IX_BlockIdTxIndex");
                    Api.MakeKey(cursor.jetSession, cursor.blocksTableId, blockId, MakeKeyGrbit.NewKey);
                    Api.MakeKey(cursor.jetSession, cursor.blocksTableId, -1, MakeKeyGrbit.None);

                    if (!Api.TrySeek(cursor.jetSession, cursor.blocksTableId, SeekGrbit.SeekGE))
                    {
                        yield break;
                    }

                    do
                    {
                        if (blockId != Api.RetrieveColumnAsInt32(cursor.jetSession, cursor.blocksTableId, cursor.blockIdColumnId).Value)
                        {
                            yield break;
                        }

                        var txIndex = Api.RetrieveColumnAsInt32(cursor.jetSession, cursor.blocksTableId, cursor.blockTxIndexColumnId).Value;
                        var depth   = Api.RetrieveColumnAsInt32(cursor.jetSession, cursor.blocksTableId, cursor.blockDepthColumnId).Value;
                        var txHash  = DbEncoder.DecodeUInt256(Api.RetrieveColumn(cursor.jetSession, cursor.blocksTableId, cursor.blockTxHashColumnId));
                        var txBytes = Api.RetrieveColumn(cursor.jetSession, cursor.blocksTableId, cursor.blockTxBytesColumnId);

                        // determine if transaction is pruned by its depth
                        var pruned = depth >= 0;
                        depth = Math.Max(0, depth);

                        Transaction tx;
                        if (!pruned)
                        {
                            // verify transaction is not corrupt
                            if (txHash != new UInt256(sha256.ComputeDoubleHash(txBytes)))
                            {
                                throw new MissingDataException(blockHash);
                            }

                            tx = DataEncoder.DecodeTransaction(txBytes);
                        }
                        else
                        {
                            tx = null;
                        }

                        var blockTx = new BlockTx(txIndex, depth, txHash, pruned, tx);

                        yield return(blockTx);
                    } while (Api.TryMoveNext(cursor.jetSession, cursor.blocksTableId));
                }
            }
        }
        public bool ContainsUnspentTxOutput(TxOutputKey txOutputKey)
        {
            CheckTransaction();

            using (SetSessionContext())
            {
                Api.JetSetCurrentIndex(this.jetSession, this.unspentTxOutputTableId, "IX_TxOutputKey");
                Api.MakeKey(this.jetSession, this.unspentTxOutputTableId, DbEncoder.EncodeTxOutputKey(txOutputKey), MakeKeyGrbit.NewKey);
                return(Api.TrySeek(this.jetSession, this.unspentTxOutputTableId, SeekGrbit.SeekEQ));
            }
        }
        public bool ContainsBlockUnmintedTxes(UInt256 blockHash)
        {
            CheckTransaction();

            using (SetSessionContext())
            {
                Api.JetSetCurrentIndex(this.jetSession, this.unmintedTxTableId, "IX_UnmintedBlockHash");
                Api.MakeKey(this.jetSession, this.unmintedTxTableId, DbEncoder.EncodeUInt256(blockHash), MakeKeyGrbit.NewKey);
                return(Api.TrySeek(this.jetSession, this.unmintedTxTableId, SeekGrbit.SeekEQ));
            }
        }
        public bool ContainsUnspentTx(UInt256 txHash)
        {
            CheckTransaction();

            using (SetSessionContext())
            {
                Api.JetSetCurrentIndex(this.jetSession, this.unspentTxTableId, "IX_TxHash");
                Api.MakeKey(this.jetSession, this.unspentTxTableId, DbEncoder.EncodeUInt256(txHash), MakeKeyGrbit.NewKey);
                return(Api.TrySeek(this.jetSession, this.unspentTxTableId, SeekGrbit.SeekEQ));
            }
        }
        public bool ContainsChainedHeader(UInt256 blockHash)
        {
            using (var handle = this.cursorCache.TakeItem())
            {
                var cursor = handle.Item;

                Api.JetSetCurrentIndex(cursor.jetSession, cursor.blockHeadersTableId, "IX_BlockHash");
                Api.MakeKey(cursor.jetSession, cursor.blockHeadersTableId, DbEncoder.EncodeUInt256(blockHash), MakeKeyGrbit.NewKey);

                return(Api.TrySeek(cursor.jetSession, cursor.blockHeadersTableId, SeekGrbit.SeekEQ));
            }
        }
Exemple #15
0
        private void DeleteBlockIndex(EsentBlockTxesCursor cursor, UInt256 blockHash)
        {
            Api.JetSetCurrentIndex(cursor.jetSession, cursor.blockIndexTableId, "IX_BlockHash");
            Api.MakeKey(cursor.jetSession, cursor.blockIndexTableId, DbEncoder.EncodeUInt256(blockHash), MakeKeyGrbit.NewKey);

            if (Api.TrySeek(cursor.jetSession, cursor.blockIndexTableId, SeekGrbit.SeekEQ))
            {
                Api.JetDelete(cursor.jetSession, cursor.blockIndexTableId);
            }
            else
            {
                throw new InvalidOperationException();
            }
        }
Exemple #16
0
        public bool ContainsBlock(UInt256 blockHash)
        {
            using (var handle = this.cursorCache.TakeItem())
            {
                var cursor = handle.Item;

                using (var jetTx = cursor.jetSession.BeginTransaction())
                {
                    Api.JetSetCurrentIndex(cursor.jetSession, cursor.blockIndexTableId, "IX_BlockHash");
                    Api.MakeKey(cursor.jetSession, cursor.blockIndexTableId, DbEncoder.EncodeUInt256(blockHash), MakeKeyGrbit.NewKey);

                    return(Api.TrySeek(cursor.jetSession, cursor.blockIndexTableId, SeekGrbit.SeekEQ));
                }
            }
        }
Exemple #17
0
        public bool TryGetTransaction(UInt256 blockHash, int txIndex, out BlockTx transaction)
        {
            using (var handle = this.cursorCache.TakeItem())
            {
                var cursor = handle.Item;

                using (var jetTx = cursor.jetSession.BeginTransaction())
                {
                    int blockIndex;
                    if (!TryGetBlockIndex(cursor, blockHash, out blockIndex))
                    {
                        transaction = null;
                        return(false);
                    }

                    Api.JetSetCurrentIndex(cursor.jetSession, cursor.blocksTableId, "IX_BlockIndexTxIndex");
                    Api.MakeKey(cursor.jetSession, cursor.blocksTableId, blockIndex, MakeKeyGrbit.NewKey);
                    Api.MakeKey(cursor.jetSession, cursor.blocksTableId, txIndex, MakeKeyGrbit.None);
                    if (Api.TrySeek(cursor.jetSession, cursor.blocksTableId, SeekGrbit.SeekEQ))
                    {
                        var blockTxHashColumn = new BytesColumnValue {
                            Columnid = cursor.blockTxHashColumnId
                        };
                        var blockTxBytesColumn = new BytesColumnValue {
                            Columnid = cursor.blockTxBytesColumnId
                        };
                        Api.RetrieveColumns(cursor.jetSession, cursor.blocksTableId, blockTxHashColumn, blockTxBytesColumn);

                        if (blockTxBytesColumn.Value != null)
                        {
                            var txHash = DbEncoder.DecodeUInt256(blockTxHashColumn.Value);
                            transaction = new BlockTx(txIndex, txHash, blockTxBytesColumn.Value.ToImmutableArray());
                            return(true);
                        }
                        else
                        {
                            transaction = null;
                            return(false);
                        }
                    }
                    else
                    {
                        transaction = null;
                        return(false);
                    }
                }
            }
        }
Exemple #18
0
        private bool TryGetBlockIndex(EsentBlockTxesCursor cursor, UInt256 blockHash, out int blockIndex)
        {
            Api.JetSetCurrentIndex(cursor.jetSession, cursor.blockIndexTableId, "IX_BlockHash");
            Api.MakeKey(cursor.jetSession, cursor.blockIndexTableId, DbEncoder.EncodeUInt256(blockHash), MakeKeyGrbit.NewKey);

            if (Api.TrySeek(cursor.jetSession, cursor.blockIndexTableId, SeekGrbit.SeekEQ))
            {
                blockIndex = Api.RetrieveColumnAsInt32(cursor.jetSession, cursor.blockIndexTableId, cursor.blockIndexBlockIndexColumnId).Value;
                return(true);
            }
            else
            {
                blockIndex = -1;
                return(false);
            }
        }
Exemple #19
0
        public bool TryRemoveBlockTransactions(UInt256 blockHash)
        {
            using (var handle = this.cursorCache.TakeItem())
            {
                var cursor = handle.Item;

                using (var jetTx = cursor.jetSession.BeginTransaction())
                {
                    Api.JetSetCurrentIndex(cursor.jetSession, cursor.blockIdsTableId, "IX_BlockHash");
                    Api.MakeKey(cursor.jetSession, cursor.blockIdsTableId, DbEncoder.EncodeUInt256(blockHash), MakeKeyGrbit.NewKey);

                    if (Api.TrySeek(cursor.jetSession, cursor.blockIdsTableId, SeekGrbit.SeekEQ))
                    {
                        var blockId = Api.RetrieveColumnAsInt32(cursor.jetSession, cursor.blockIdsTableId, cursor.blockIdsIdColumnId).Value;

                        // remove block id
                        Api.JetDelete(cursor.jetSession, cursor.blockIdsTableId);

                        // remove transactions
                        Api.JetSetCurrentIndex(cursor.jetSession, cursor.blocksTableId, "IX_BlockIdTxIndex");
                        Api.MakeKey(cursor.jetSession, cursor.blocksTableId, blockId, MakeKeyGrbit.NewKey);
                        Api.MakeKey(cursor.jetSession, cursor.blocksTableId, -1, MakeKeyGrbit.None);

                        if (Api.TrySeek(cursor.jetSession, cursor.blocksTableId, SeekGrbit.SeekGE) &&
                            blockId == Api.RetrieveColumnAsInt32(cursor.jetSession, cursor.blocksTableId, cursor.blockIdColumnId).Value)
                        {
                            do
                            {
                                Api.JetDelete(cursor.jetSession, cursor.blocksTableId);
                            } while (Api.TryMoveNext(cursor.jetSession, cursor.blocksTableId) &&
                                     blockId == Api.RetrieveColumnAsInt32(cursor.jetSession, cursor.blocksTableId, cursor.blockIdColumnId).Value);
                        }

                        // decrease block count
                        Api.EscrowUpdate(cursor.jetSession, cursor.globalsTableId, cursor.blockCountColumnId, -1);

                        jetTx.CommitLazy();
                        return(true);
                    }
                    else
                    {
                        // transactions are already removed
                        return(false);
                    }
                }
            }
        }
        public MerkleTreeNode ReadNode()
        {
            if (this.blockId != Api.RetrieveColumnAsInt32(cursor.jetSession, cursor.blocksTableId, cursor.blockIdColumnId).Value)
            {
                throw new InvalidOperationException();
            }

            var index  = Api.RetrieveColumnAsInt32(cursor.jetSession, cursor.blocksTableId, cursor.blockTxIndexColumnId).Value;
            var depth  = Api.RetrieveColumnAsInt32(cursor.jetSession, cursor.blocksTableId, cursor.blockDepthColumnId).Value;
            var txHash = DbEncoder.DecodeUInt256(Api.RetrieveColumn(cursor.jetSession, cursor.blocksTableId, cursor.blockTxHashColumnId));

            var pruned = depth >= 0;

            depth = Math.Max(0, depth);

            return(new MerkleTreeNode(index, depth, txHash, pruned));
        }
Exemple #21
0
        public bool TryGetUnspentTx(UInt256 txHash, out UnspentTx unspentTx)
        {
            Api.JetSetCurrentIndex(this.jetSession, this.unspentTxTableId, "IX_TxHash");
            Api.MakeKey(this.jetSession, this.unspentTxTableId, DbEncoder.EncodeUInt256(txHash), MakeKeyGrbit.NewKey);
            if (Api.TrySeek(this.jetSession, this.unspentTxTableId, SeekGrbit.SeekEQ))
            {
                var blockIndex   = Api.RetrieveColumnAsInt32(this.jetSession, this.unspentTxTableId, this.blockIndexColumnId).Value;
                var txIndex      = Api.RetrieveColumnAsInt32(this.jetSession, this.unspentTxTableId, this.txIndexColumnId).Value;
                var outputStates = DataEncoder.DecodeOutputStates(Api.RetrieveColumn(this.jetSession, this.unspentTxTableId, this.outputStatesColumnId));

                unspentTx = new UnspentTx(txHash, blockIndex, txIndex, outputStates);
                return(true);
            }

            unspentTx = default(UnspentTx);
            return(false);
        }
Exemple #22
0
        public IEnumerable <UnspentTx> ReadUnspentTransactions()
        {
            Api.JetSetCurrentIndex(this.jetSession, this.unspentTxTableId, "IX_TxHash");

            if (Api.TryMoveFirst(this.jetSession, this.unspentTxTableId))
            {
                do
                {
                    var txHash       = DbEncoder.DecodeUInt256(Api.RetrieveColumn(this.jetSession, this.unspentTxTableId, this.txHashColumnId));
                    var blockIndex   = Api.RetrieveColumnAsInt32(this.jetSession, this.unspentTxTableId, this.blockIndexColumnId).Value;
                    var txIndex      = Api.RetrieveColumnAsInt32(this.jetSession, this.unspentTxTableId, this.txIndexColumnId).Value;
                    var outputStates = DataEncoder.DecodeOutputStates(Api.RetrieveColumn(this.jetSession, this.unspentTxTableId, this.outputStatesColumnId));

                    yield return(new UnspentTx(txHash, blockIndex, txIndex, outputStates));
                } while (Api.TryMoveNext(this.jetSession, this.unspentTxTableId));
            }
        }
        private IEnumerable <UnspentTx> ReadUnspentTransactionsInner()
        {
            using (SetSessionContext())
            {
                Api.JetSetCurrentIndex(this.jetSession, this.unspentTxTableId, "IX_TxHash");

                if (Api.TryMoveFirst(this.jetSession, this.unspentTxTableId))
                {
                    do
                    {
                        var txHashColumn = new BytesColumnValue {
                            Columnid = this.txHashColumnId
                        };
                        var blockIndexColumn = new Int32ColumnValue {
                            Columnid = this.blockIndexColumnId
                        };
                        var txIndexColumn = new Int32ColumnValue {
                            Columnid = this.txIndexColumnId
                        };
                        var txVersionColumn = new UInt32ColumnValue {
                            Columnid = this.txVersionColumnId
                        };
                        var isCoinbaseColumn = new BoolColumnValue {
                            Columnid = this.isCoinbaseColumnId
                        };
                        var outputStatesColumn = new BytesColumnValue {
                            Columnid = this.outputStatesColumnId
                        };
                        var txOutputBytesColumn = new BytesColumnValue {
                            Columnid = this.txOutputBytesColumnId
                        };
                        Api.RetrieveColumns(this.jetSession, this.unspentTxTableId, txHashColumn, blockIndexColumn, txIndexColumn, txVersionColumn, isCoinbaseColumn, outputStatesColumn, txOutputBytesColumn);

                        var txHash       = DbEncoder.DecodeUInt256(txHashColumn.Value);
                        var blockIndex   = blockIndexColumn.Value.Value;
                        var txIndex      = txIndexColumn.Value.Value;
                        var txVersion    = txVersionColumn.Value.Value;
                        var isCoinbase   = isCoinbaseColumn.Value.Value;
                        var outputStates = DataDecoder.DecodeOutputStates(outputStatesColumn.Value);

                        yield return(new UnspentTx(txHash, blockIndex, txIndex, txVersion, isCoinbase, outputStates));
                    }while (Api.TryMoveNext(this.jetSession, this.unspentTxTableId));
                }
            }
        }
        public bool TryGetUnspentTx(UInt256 txHash, out UnspentTx unspentTx)
        {
            CheckTransaction();

            using (SetSessionContext())
            {
                Api.JetSetCurrentIndex(this.jetSession, this.unspentTxTableId, "IX_TxHash");
                Api.MakeKey(this.jetSession, this.unspentTxTableId, DbEncoder.EncodeUInt256(txHash), MakeKeyGrbit.NewKey);
                if (Api.TrySeek(this.jetSession, this.unspentTxTableId, SeekGrbit.SeekEQ))
                {
                    var blockIndexColumn = new Int32ColumnValue {
                        Columnid = this.blockIndexColumnId
                    };
                    var txIndexColumn = new Int32ColumnValue {
                        Columnid = this.txIndexColumnId
                    };
                    var txVersionColumn = new UInt32ColumnValue {
                        Columnid = this.txVersionColumnId
                    };
                    var isCoinbaseColumn = new BoolColumnValue {
                        Columnid = this.isCoinbaseColumnId
                    };
                    var outputStatesColumn = new BytesColumnValue {
                        Columnid = this.outputStatesColumnId
                    };
                    var txOutputBytesColumn = new BytesColumnValue {
                        Columnid = this.txOutputBytesColumnId
                    };
                    Api.RetrieveColumns(this.jetSession, this.unspentTxTableId, blockIndexColumn, txIndexColumn, txVersionColumn, isCoinbaseColumn, outputStatesColumn, txOutputBytesColumn);

                    var blockIndex   = blockIndexColumn.Value.Value;
                    var txIndex      = txIndexColumn.Value.Value;
                    var txVersion    = txVersionColumn.Value.Value;
                    var isCoinbase   = isCoinbaseColumn.Value.Value;
                    var outputStates = DataDecoder.DecodeOutputStates(outputStatesColumn.Value);

                    unspentTx = new UnspentTx(txHash, blockIndex, txIndex, txVersion, isCoinbase, outputStates);
                    return(true);
                }

                unspentTx = default(UnspentTx);
                return(false);
            }
        }
        public bool TryAddChainedHeader(ChainedHeader chainedHeader)
        {
            try
            {
                using (var handle = this.cursorCache.TakeItem())
                {
                    var cursor = handle.Item;

                    using (var jetTx = cursor.jetSession.BeginTransaction())
                    {
                        using (var jetUpdate = cursor.jetSession.BeginUpdate(cursor.blockHeadersTableId, JET_prep.Insert))
                        {
                            Api.SetColumns(cursor.jetSession, cursor.blockHeadersTableId,
                                           new BytesColumnValue {
                                Columnid = cursor.blockHeaderHashColumnId, Value = DbEncoder.EncodeUInt256(chainedHeader.Hash)
                            },
                                           new BytesColumnValue {
                                Columnid = cursor.blockHeaderPreviousHashColumnId, Value = DbEncoder.EncodeUInt256(chainedHeader.PreviousBlockHash)
                            },
                                           new Int32ColumnValue {
                                Columnid = cursor.blockHeaderHeightColumnId, Value = chainedHeader.Height
                            },
                                           new BytesColumnValue {
                                Columnid = cursor.blockHeaderTotalWorkColumnId, Value = DataEncoder.EncodeTotalWork(chainedHeader.TotalWork)
                            },
                                           new BytesColumnValue {
                                Columnid = cursor.blockHeaderBytesColumnId, Value = DataEncoder.EncodeChainedHeader(chainedHeader)
                            });

                            jetUpdate.Save();
                        }

                        jetTx.CommitLazy();
                        return(true);
                    }
                }
            }
            catch (EsentKeyDuplicateException)
            {
                return(false);
            }
        }
        public bool TryGetChainedHeader(UInt256 blockHash, out ChainedHeader chainedHeader)
        {
            using (var handle = this.cursorCache.TakeItem())
            {
                var cursor = handle.Item;

                Api.JetSetCurrentIndex(cursor.jetSession, cursor.blockHeadersTableId, "IX_BlockHash");
                Api.MakeKey(cursor.jetSession, cursor.blockHeadersTableId, DbEncoder.EncodeUInt256(blockHash), MakeKeyGrbit.NewKey);
                if (Api.TrySeek(cursor.jetSession, cursor.blockHeadersTableId, SeekGrbit.SeekEQ))
                {
                    chainedHeader = DataDecoder.DecodeChainedHeader(Api.RetrieveColumn(cursor.jetSession, cursor.blockHeadersTableId, cursor.blockHeaderBytesColumnId));
                    return(true);
                }
                else
                {
                    chainedHeader = default(ChainedHeader);
                    return(false);
                }
            }
        }
        public bool TryRemoveUnspentTxOutput(TxOutputKey txOutputKey)
        {
            CheckWriteTransaction();

            using (SetSessionContext())
            {
                Api.JetSetCurrentIndex(this.jetSession, this.unspentTxOutputTableId, "IX_TxOutputKey");
                Api.MakeKey(this.jetSession, this.unspentTxOutputTableId, DbEncoder.EncodeTxOutputKey(txOutputKey), MakeKeyGrbit.NewKey);
                if (Api.TrySeek(this.jetSession, this.unspentTxOutputTableId, SeekGrbit.SeekEQ))
                {
                    Api.JetDelete(this.jetSession, this.unspentTxOutputTableId);

                    return(true);
                }
                else
                {
                    return(false);
                }
            }
        }
        public bool TryGetHeader(UInt256 blockHash, out ChainedHeader header)
        {
            CheckTransaction();

            using (SetSessionContext())
            {
                Api.JetSetCurrentIndex(this.jetSession, this.headersTableId, "IX_BlockHash");
                Api.MakeKey(this.jetSession, this.headersTableId, DbEncoder.EncodeUInt256(blockHash), MakeKeyGrbit.NewKey);
                if (Api.TrySeek(this.jetSession, this.headersTableId, SeekGrbit.SeekEQ))
                {
                    var headerBytes = Api.RetrieveColumn(this.jetSession, this.headersTableId, this.headerBytesColumnId);

                    header = DataDecoder.DecodeChainedHeader(headerBytes);
                    return(true);
                }

                header = default(ChainedHeader);
                return(false);
            }
        }
        public bool TryRemoveHeader(UInt256 blockHash)
        {
            CheckWriteTransaction();

            using (SetSessionContext())
            {
                Api.JetSetCurrentIndex(this.jetSession, this.headersTableId, "IX_BlockHash");
                Api.MakeKey(this.jetSession, this.headersTableId, DbEncoder.EncodeUInt256(blockHash), MakeKeyGrbit.NewKey);
                if (Api.TrySeek(this.jetSession, this.headersTableId, SeekGrbit.SeekEQ))
                {
                    Api.JetDelete(this.jetSession, this.headersTableId);

                    return(true);
                }
                else
                {
                    return(false);
                }
            }
        }
        public bool TryAddUnspentTx(UnspentTx unspentTx)
        {
            CheckWriteTransaction();

            using (SetSessionContext())
            {
                try
                {
                    using (var jetUpdate = this.jetSession.BeginUpdate(this.unspentTxTableId, JET_prep.Insert))
                    {
                        Api.SetColumns(this.jetSession, this.unspentTxTableId,
                                       new BytesColumnValue {
                            Columnid = this.txHashColumnId, Value = DbEncoder.EncodeUInt256(unspentTx.TxHash)
                        },
                                       new Int32ColumnValue {
                            Columnid = this.blockIndexColumnId, Value = unspentTx.BlockIndex
                        },
                                       new Int32ColumnValue {
                            Columnid = this.txIndexColumnId, Value = unspentTx.TxIndex
                        },
                                       new UInt32ColumnValue {
                            Columnid = this.txVersionColumnId, Value = unspentTx.TxVersion
                        },
                                       new BoolColumnValue {
                            Columnid = this.isCoinbaseColumnId, Value = unspentTx.IsCoinbase
                        },
                                       new BytesColumnValue {
                            Columnid = this.outputStatesColumnId, Value = DataEncoder.EncodeOutputStates(unspentTx.OutputStates)
                        });

                        jetUpdate.Save();
                    }

                    return(true);
                }
                catch (EsentKeyDuplicateException)
                {
                    return(false);
                }
            }
        }