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 TryGetTransaction(UInt256 blockHash, int txIndex, out Transaction transaction) { int blockId; if (!this.TryGetBlockId(blockHash, out blockId)) { transaction = default(Transaction); return(false); } using (var handle = this.cursorCache.TakeItem()) { var cursor = handle.Item; using (var jetTx = cursor.jetSession.BeginTransaction()) { Api.JetSetCurrentIndex(cursor.jetSession, cursor.blocksTableId, "IX_BlockIdTxIndex"); Api.MakeKey(cursor.jetSession, cursor.blocksTableId, blockId, MakeKeyGrbit.NewKey); Api.MakeKey(cursor.jetSession, cursor.blocksTableId, txIndex, MakeKeyGrbit.None); if (Api.TrySeek(cursor.jetSession, cursor.blocksTableId, SeekGrbit.SeekEQ)) { var txBytes = Api.RetrieveColumn(cursor.jetSession, cursor.blocksTableId, cursor.blockTxBytesColumnId); if (txBytes != null) { transaction = DataEncoder.DecodeTransaction(txBytes); return(true); } else { transaction = default(Transaction); return(false); } } else { transaction = default(Transaction); return(false); } } } }
public TransactionStorage(string baseDirectory) : base(baseDirectory, "Transactions", tx => DataEncoder.EncodeTransaction(tx), (txHash, bytes) => DataEncoder.DecodeTransaction(bytes, txHash)) { }
private Message WireDecodeMessage(UInt32 magic, Stream stream) { byte[] payload; Message message; using (var reader = new BinaryReader(stream, Encoding.ASCII, leaveOpen: true)) { var command = reader.ReadFixedString(12); var payloadSize = reader.ReadUInt32(); var payloadChecksum = reader.ReadUInt32(); payload = reader.ReadBytes(payloadSize.ToIntChecked()); if (!Messaging.VerifyPayloadChecksum(payloadChecksum, payload)) { throw new Exception(string.Format("Checksum failed for {0}", command)); } message = new Message ( Magic: magic, Command: command, PayloadSize: payloadSize, PayloadChecksum: payloadChecksum, Payload: payload.ToImmutableArray() ); } switch (message.Command) { case "addr": { var addressPayload = NodeEncoder.DecodeAddressPayload(payload); var handler = this.OnReceivedAddresses; if (handler != null) { handler(addressPayload.NetworkAddresses); } } break; case "alert": { var alertPayload = NodeEncoder.DecodeAlertPayload(payload); } break; case "block": { var block = DataEncoder.DecodeBlock(payload); var handler = this.OnBlock; if (handler != null) { handler(this.owner, block); } } break; case "getblocks": { var getBlocksPayload = NodeEncoder.DecodeGetBlocksPayload(payload); var handler = this.OnGetBlocks; if (handler != null) { handler(getBlocksPayload); } } break; case "getheaders": { var getHeadersPayload = NodeEncoder.DecodeGetBlocksPayload(payload); var handler = this.OnGetHeaders; if (handler != null) { handler(getHeadersPayload); } } break; case "getdata": { var invPayload = NodeEncoder.DecodeInventoryPayload(payload); var handler = this.OnGetData; if (handler != null) { handler(invPayload); } } break; case "headers": { var blockHeaders = ImmutableList.CreateBuilder <BlockHeader>(); using (var headerStream = new MemoryStream(payload)) using (var reader = new BinaryReader(headerStream)) { var headerCount = reader.ReadVarInt().ToIntChecked(); for (var i = 0; i < headerCount; i++) { var blockHeader = DataEncoder.DecodeBlockHeader(headerStream); //TODO wiki says this is a byte and a var int, which is it? var txCount = reader.ReadVarInt(); blockHeaders.Add(blockHeader); } } var handler = this.OnBlockHeaders; if (handler != null) { handler(this.owner, blockHeaders.ToImmutable()); } } break; case "inv": { var invPayload = NodeEncoder.DecodeInventoryPayload(payload); var handler = this.OnInventoryVectors; if (handler != null) { handler(invPayload.InventoryVectors); } } break; case "notfound": { var invPayload = NodeEncoder.DecodeInventoryPayload(payload); var handler = this.OnNotFound; if (handler != null) { handler(invPayload.InventoryVectors); } } break; case "ping": { var handler = this.OnPing; if (handler != null) { handler(payload.ToImmutableArray()); } } break; case "tx": { var tx = DataEncoder.DecodeTransaction(payload); var handler = this.OnTransaction; if (handler != null) { handler(tx); } } break; case "version": { var versionPayload = NodeEncoder.DecodeVersionPayload(payload, payload.Length); var handler = this.OnVersion; if (handler != null) { handler(versionPayload); } } break; case "verack": { var handler = this.OnVersionAcknowledged; if (handler != null) { handler(); } } break; default: { this.logger.Warn("Unhandled incoming message: {0}".Format2(message.Command)); } break; } //TODO //if (payloadStream.Position != payloadStream.Length) //{ // var exMessage = string.Format("Wrong number of bytes read for {0}, parser error: read {1} bytes from a {2} byte payload", message.Command, payloadStream.Position, payloadStream.Length); // Debug.WriteLine(exMessage); // throw new Exception(exMessage); //} return(message); }
public void TestWireDecodeTransaction() { var actual = DataEncoder.EncodeTransaction(DataEncoder.DecodeTransaction(TRANSACTION_1_BYTES.ToArray())); CollectionAssert.AreEqual(TRANSACTION_1_BYTES.ToList(), actual.ToList()); }