query.py (2853B)
1 #!/usr/bin/env python3 2 # electrum-obelisk 3 # Copyright (C) 2020-2021 Ivan J. <parazyd@dyne.org> 4 # 5 # This program is free software: you can redistribute it and/or modify 6 # it under the terms of the GNU Affero General Public License as published by 7 # the Free Software Foundation, either version 3 of the License, or 8 # (at your option) any later version. 9 # 10 # This program is distributed in the hope that it will be useful, 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU Affero General Public License for more details. 14 # 15 # You should have received a copy of the GNU Affero General Public License 16 # along with this program. If not, see <http://www.gnu.org/licenses/>. 17 """ zmq interfacing """ 18 from binascii import unhexlify 19 from struct import pack, unpack 20 21 import zmq 22 23 24 def q_fetch_header_by_height(endp, height): 25 """ Fetch and return a block header at height as raw bytes """ 26 context = zmq.Context() 27 socket = context.socket(zmq.REQ) # pylint: disable=E1101 28 socket.connect(endp) 29 socket.send(b'blockchain.fetch_block_header', zmq.SNDMORE) 30 socket.send(pack('I', 42), zmq.SNDMORE) 31 socket.send(pack('I', int(height))) 32 _ = socket.recv() 33 _ = socket.recv() 34 response_body = socket.recv() 35 _ec = unpack('<I', response_body[0:4])[0] 36 if _ec != 0: 37 return None 38 return response_body[4:] 39 40 41 def q_fetch_headers_by_height_count(endp, start_height, count): 42 """ Fetch and return count concatenated headers by height as raw bytes """ 43 # Implemented to reuse the socket rather than opening a new one 44 # for each header requested (e.g. by looping q_fetch_header_by_height()). 45 context = zmq.Context() 46 socket = context.socket(zmq.REQ) # pylint: disable=E1101 47 socket.connect(endp) 48 _id = 42 49 res = bytearray() 50 for i in range(count): 51 socket.send(b'blockchain.fetch_block_header', zmq.SNDMORE) 52 socket.send(pack('I', _id), zmq.SNDMORE) 53 socket.send(pack('I', start_height+i)) 54 _ = socket.recv() 55 _ = socket.recv() 56 response_body = socket.recv() 57 _ec = unpack('<I', response_body[0:4])[0] 58 if not response_body or _ec != 0: 59 break 60 res.extend(response_body[4:]) 61 return res 62 63 64 def q_fetch_tx_by_txid(endp, txid): 65 """ Fetch and return a transaction by txid as raw bytes """ 66 context = zmq.Context() 67 socket = context.socket(zmq.REQ) # pylint: disable=E1101 68 socket.connect(endp) 69 socket.send(b'blockchain.fetch_transaction2', zmq.SNDMORE) 70 socket.send(pack('I', 42), zmq.SNDMORE) 71 socket.send(unhexlify(txid)[::-1]) 72 _ = socket.recv() 73 _ = socket.recv() 74 response_body = socket.recv() 75 _ec = unpack('<I', response_body[0:4])[0] 76 if _ec != 0: 77 return None 78 return response_body[4:]