예제 #1
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));
        }
예제 #2
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));
                }
            }
        }
예제 #3
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);
                    }
                }
            }
        }
예제 #4
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));
            }
        }
예제 #5
0
        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));
        }
예제 #6
0
        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));
                }
            }
        }
예제 #7
0
        private IEnumerator <BlockTxNode> ReadBlockTransactions(UInt256 blockHash, bool requireTx)
        {
            using (var handle = this.cursorCache.TakeItem())
            {
                var cursor = handle.Item;

                using (var jetTx = cursor.jetSession.BeginTransaction())
                {
                    int blockIndex;
                    if (!TryGetBlockIndex(cursor, blockHash, out blockIndex))
                    {
                        throw new MissingDataException(blockHash);
                    }

                    Api.JetSetCurrentIndex(cursor.jetSession, cursor.blocksTableId, "IX_BlockIndexTxIndex");

                    Api.MakeKey(cursor.jetSession, cursor.blocksTableId, blockIndex, MakeKeyGrbit.NewKey);
                    Api.MakeKey(cursor.jetSession, cursor.blocksTableId, 0, MakeKeyGrbit.None);
                    if (!Api.TrySeek(cursor.jetSession, cursor.blocksTableId, SeekGrbit.SeekGE))
                    {
                        throw new MissingDataException(blockHash);
                    }

                    Api.MakeKey(cursor.jetSession, cursor.blocksTableId, blockIndex, MakeKeyGrbit.NewKey);
                    Api.MakeKey(cursor.jetSession, cursor.blocksTableId, int.MaxValue, MakeKeyGrbit.None);
                    if (!Api.TrySetIndexRange(cursor.jetSession, cursor.blocksTableId, SetIndexRangeGrbit.RangeUpperLimit))
                    {
                        throw new MissingDataException(blockHash);
                    }

                    do
                    {
                        var txIndexColumn = new Int32ColumnValue {
                            Columnid = cursor.txIndexColumnId
                        };
                        var blockDepthColumn = new Int32ColumnValue {
                            Columnid = cursor.blockDepthColumnId
                        };
                        var blockTxHashColumn = new BytesColumnValue {
                            Columnid = cursor.blockTxHashColumnId
                        };
                        var blockTxBytesColumn = new BytesColumnValue {
                            Columnid = cursor.blockTxBytesColumnId
                        };
                        Api.RetrieveColumns(cursor.jetSession, cursor.blocksTableId, txIndexColumn, blockDepthColumn, blockTxHashColumn, blockTxBytesColumn);

                        var txIndex = txIndexColumn.Value.Value;
                        var depth   = blockDepthColumn.Value.Value;
                        var txHash  = DbEncoder.DecodeUInt256(blockTxHashColumn.Value);
                        var txBytes = blockTxBytesColumn.Value;

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

                        if (pruned && requireTx)
                        {
                            throw new MissingDataException(blockHash);
                        }

                        var blockTxNode = new BlockTxNode(txIndex, depth, txHash, pruned, txBytes?.ToImmutableArray());

                        yield return(blockTxNode);
                    }while (Api.TryMoveNext(cursor.jetSession, cursor.blocksTableId));
                }
            }
        }