""" Module implementing actions that can be taken on network-serialized bitcoin blocks. """ from jmbase import hextobin from bitcointx.core import CBitcoinTransaction from bitcointx.core.serialize import VarIntSerializer def decode_varint(data): n, tail = VarIntSerializer.deserialize_partial(data) head = data[0: len(data) - len(tail)] return n, len(head) def get_transactions_in_block(block): """ `block` is hex output from RPC `getblock`. Return: yields the block's transactions, type CBitcoinTransaction """ block = hextobin(block) # Skipping the header transaction_data = block[80:] # Decoding the number of transactions, offset is the size of # the varint (1 to 9 bytes) n_transactions, offset = decode_varint(transaction_data) for i in range(n_transactions): # This 'strat' of reading in small chunks optimistically is taken from: # https://github.com/alecalve/python-bitcoin-blockchain-parser/blob/7a9e15c236b10d2a6dff5e696801c0641af72628/blockchain_parser/utils.py # Try from 1024 (1KiB) -> 1073741824 (1GiB) slice widths for j in range(0, 20): try: offset_e = offset + (1024 * 2 ** j) transaction = CBitcoinTransaction.deserialize( transaction_data[offset:offset_e], allow_padding=True) yield transaction break except: continue # Skipping to the next transaction offset += len(transaction.serialize()) """ Example block from a regtest: # Found using `getblockhash 222` followed by `getblock 0`: 0000003066327ecf2f3e72ec43f358c9c7b34f47374f23f4fcce965d4e18273a5b98f325d11b3b9c3a592c830d49f6281d4055f5732a79a19f9bd8d4afad729772cbf393fa7bdf5fffff7f2000000000010200000 00001010000000000000000000000000000000000000000000000000000000000000000ffffffff0502de000101ffffffff0200f902950000000017a914d2e1d0ea5135f0cbeb4aef06e3cee785d394876a870000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000 Gives (x = above block): y = list(btc.get_block_transactions(x)) >>> y[0] CBitcoinTransaction([CBitcoinTxIn(CBitcoinOutPoint(), CBitcoinScript([x('de00'), x('01')]), 0xffffffff)], [CBitcoinTxOut(25.0*COIN, CBitcoinScript([OP_HASH160, x('d2e1d0ea5135f0cbeb4aef06e3cee785d394876a'), OP_EQUAL])), CBitcoinTxOut(0.0*COIN, CBitcoinScript([OP_RETURN, x('aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf9')]))], 0, 2, CBitcoinTxWitness([CBitcoinTxInWitness(CScriptWitness([x('0000000000000000000000000000000000000000000000000000000000000000')]))])) (coinbase transaction) """