def get_next_segwit_tx_size(buf, off, tail=-1): """ Returns the size of the next transaction in the. Returns -1 if there's a parsing error or the end goes beyond the tail. """ end = off + btc_constants.TX_VERSION_LEN + btc_constants.TX_SEGWIT_FLAG_LEN io_size, txin_c, _ = btc_common_utils.get_tx_io_count_and_size( buf, end, tail) if io_size < 0: return -1 end += io_size for _ in range(txin_c): witness_count, size = btc_common_utils.btc_varint_to_int(buf, end) end += size for _ in range(witness_count): witness_len, size = btc_common_utils.btc_varint_to_int(buf, end) end += size + witness_len end += btc_constants.TX_LOCK_TIME_LEN if end > tail > 0: return -1 return end - off
def indices(self) -> List[int]: if self._indices is None: off = BTC_HDR_COMMON_OFF + 32 num_indices, size = btc_varint_to_int(self.buf, off) off += size self._indices = [] index = -1 for _ in range(num_indices): diff_index, size = btc_varint_to_int(self.buf, off) index += diff_index + 1 self._indices.append(index) off += size return self._indices
def parse_bx_block_header( bx_block: memoryview, block_pieces: Deque[Union[bytearray, memoryview]]) -> BlockHeaderInfo: block_offsets = compact_block_short_ids_serializer.get_bx_block_offsets( bx_block) short_ids, short_ids_len = compact_block_short_ids_serializer.deserialize_short_ids_from_buffer( bx_block, block_offsets.short_id_offset) # Compute block header hash block_header_size = \ block_offsets.block_begin_offset + \ btc_constants.BTC_HDR_COMMON_OFF + \ btc_constants.BTC_BLOCK_HDR_SIZE block_hash = BtcObjectHash(buf=crypto.bitcoin_hash( bx_block[block_offsets.block_begin_offset + btc_constants.BTC_HDR_COMMON_OFF:block_header_size]), length=btc_constants.BTC_SHA_HASH_LEN) offset = block_header_size # Add header piece txn_count, txn_count_size = btc_common_utils.btc_varint_to_int( bx_block, block_header_size) offset += txn_count_size block_pieces.append(bx_block[block_offsets.block_begin_offset:offset]) return BlockHeaderInfo(block_offsets, short_ids, short_ids_len, block_hash, offset, txn_count)
def __iter__(self): off = BTC_HDR_COMMON_OFF self._header_count, size = btc_varint_to_int(self.buf, off) off += size for _ in range(self._header_count): yield self._memoryview[off:off + 81] off += 81
def __iter__(self): off = BTC_HDR_COMMON_OFF + 4 # For the version field. b_count, size = btc_varint_to_int(self.buf, off) off += size for i in range(b_count): yield BtcObjectHash(buf=self.buf, offset=off, length=BTC_SHA_HASH_LEN) off += 32
def tx_in(self): if self._tx_in is None: off = BTC_HDR_COMMON_OFF + 4 self._tx_in_count, size = btc_common_utils.btc_varint_to_int( self.buf, off) off += size self._tx_in = [] start = off end = off for _ in range(self._tx_in_count): end += 36 script_len, size = btc_common_utils.btc_varint_to_int( self.buf, end) end += size + script_len + 4 self._tx_in.append(self.rawbytes()[start:end]) start = end off = end self._tx_out_count, size = btc_common_utils.btc_varint_to_int( self.buf, off) self._tx_out = [] off += size start = off end = off for _ in range(self._tx_out_count): end += 8 script_len, size = btc_common_utils.btc_varint_to_int( self.buf, end) end += size + script_len self._tx_out.append(self.rawbytes()[start:end]) off = end self._lock_time, = struct.unpack_from('<I', self.buf, off) return self._tx_in
def version(self): if self._version is None: off = 0 self._version = struct.unpack_from('<I', self.buf, off)[0] off += 4 self._prev_block = BtcObjectHash(self.buf, off, 32) off += 32 self._merkle_root = self._memoryview[off:off + 32] off += 32 self._timestamp, self._bits, self._nonce = struct.unpack_from( '<III', self.buf, off) self._txn_count, size = btc_varint_to_int(self.buf, off) return self._version
def pre_filled_transactions(self) -> Dict[int, memoryview]: if self._pre_filled_transactions is None: off = BTC_HDR_COMMON_OFF + BTC_BLOCK_HDR_SIZE + BTC_SHORT_NONCE_SIZE self._short_id_c, size = btc_varint_to_int(self.buf, off) off += size + BTC_COMPACT_BLOCK_SHORT_ID_LEN * self._short_id_c self._pre_filled_tx_count, size = btc_varint_to_int(self.buf, off) off += size self._pre_filled_transactions = {} index = -1 # pyre-fixme[6]: Expected `int` for 1st param but got `None`. for _ in range(self._pre_filled_tx_count): diff, size = btc_varint_to_int(self.buf, off) off += size size = get_next_tx_size(self.buf, off) buf = self._memoryview[off:off + size] off += size index += diff + 1 self._pre_filled_transactions[index] = buf return self._pre_filled_transactions
def short_ids(self) -> Dict[bytes, int]: if self._short_ids is None: off = BTC_HDR_COMMON_OFF + BTC_BLOCK_HDR_SIZE + BTC_SHORT_NONCE_SIZE self._short_id_c, size = btc_varint_to_int(self.buf, off) off += size self._short_ids = {} for idx in range(self._short_id_c): self._short_ids[bytes( self._memoryview[off:off + BTC_COMPACT_BLOCK_SHORT_ID_LEN])] = idx off += BTC_COMPACT_BLOCK_SHORT_ID_LEN return self._short_ids
def transactions(self) -> List[memoryview]: if self._transactions is None: self._transactions = [] off = BTC_HDR_COMMON_OFF + BTC_SHA_HASH_LEN tx_len, size = btc_varint_to_int(self.buf, off) off += size for _ in range(tx_len): size = get_next_tx_size(self.buf, off) tx = self._memoryview[off:off + size] off += size self._transactions.append(tx) return self._transactions # pyre-ignore
def __iter__(self) -> Iterator[Tuple[int, BtcObjectHash]]: off = btc_constants.BTC_HDR_COMMON_OFF num_items, size = btc_common_utils.btc_varint_to_int(self.buf, off) off += size # pyre-fixme[16]: `InventoryBtcMessage` has no attribute `_num_items`. self._num_items = num_items # pyre-fixme[16]: `InventoryBtcMessage` has no attribute `_items`. self._items = list() for _ in range(num_items): inv_type, = struct.unpack_from("<L", self.buf, off) off += 4 yield (inv_type, BtcObjectHash(buf=self.buf, offset=off, length=btc_constants.BTC_SHA_HASH_LEN)) off += 32
def version(self): if self._version is None: off = BTC_HDR_COMMON_OFF self._version = struct.unpack_from('<I', self.buf, off)[0] off += 4 self._prev_block = BtcObjectHash(self.buf, off, 32) off += 32 self._merkle_root = BtcObjectHash(self.buf, off, 32) off += 32 self._timestamp, self._bits, self._nonce = struct.unpack_from( '<III', self.buf, off) off += 12 self._txn_count, size = btc_varint_to_int(self.buf, off) off += size self._tx_offset = off self._header = self._memoryview[0:self._tx_offset] return self._version
def ont_varint_to_int(buf: Union[memoryview, bytearray], off: int) -> Tuple[int, int]: return btc_varint_to_int(buf, off)
def hash_count(self): if self._header_count is None: off = BTC_HDR_COMMON_OFF self._header_count, size = btc_varint_to_int(self.buf, off) return self._header_count
def count(self): off = btc_constants.BTC_HDR_COMMON_OFF num_items, size = btc_common_utils.btc_varint_to_int(self.buf, off) return num_items