tImplement blockchain.scripthash.subscribe - obelisk - Electrum server using libbitcoin as its backend
 (HTM) git clone https://git.parazyd.org/obelisk
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 614407fd1362c82a2af813a48ebbdecd4670838e
 (DIR) parent 901c92c3a40271b74cf91c45cbb5eb9aaee1dd49
 (HTM) Author: parazyd <parazyd@dyne.org>
       Date:   Fri,  9 Apr 2021 00:09:35 +0200
       
       Implement blockchain.scripthash.subscribe
       
       What's left to do for it is the tx subscription and sending status
       notifications.
       
       Diffstat:
         M electrumobelisk/protocol.py         |      32 +++++++++++++++++++++++++++++--
         M electrumobelisk/zeromq.py           |       2 ++
       
       2 files changed, 32 insertions(+), 2 deletions(-)
       ---
 (DIR) diff --git a/electrumobelisk/protocol.py b/electrumobelisk/protocol.py
       t@@ -21,7 +21,7 @@ import asyncio
        import json
        from binascii import unhexlify
        
       -from electrumobelisk.hashes import double_sha256, hash_to_hex_str
       +from electrumobelisk.hashes import sha256, double_sha256, hash_to_hex_str
        from electrumobelisk.merkle import merkle_branch
        from electrumobelisk.util import (
            block_to_header,
       t@@ -62,6 +62,7 @@ class ElectrumProtocol(asyncio.Protocol):  # pylint: disable=R0904,R0902
                # Consider renaming bx to something else
                self.bx = Client(log, endpoints, self.loop)
                self.block_queue = None
       +        self.tx_queue = None
                # TODO: Clean up on client disconnect
                self.tasks = []
                self.sh_subscriptions = {}
       t@@ -331,7 +332,34 @@ class ElectrumProtocol(asyncio.Protocol):  # pylint: disable=R0904,R0902
                """Method: blockchain.scripthash.subscribe
                Subscribe to a script hash.
                """
       -        return
       +        if "params" not in query or len(query["params"]) != 1:
       +            return {"error": "malformed request"}
       +
       +        scripthash = query["params"][0]
       +        if not is_hash256_str(scripthash):
       +            return {"error": "invalid scripthash"}
       +
       +        _ec, history = await self.bx.fetch_history4(scripthash)
       +        if _ec and _ec != 0:
       +            return {"error": "request corrupted"}
       +
       +        # TODO: task for tx subscription
       +        self.sh_subscriptions[scripthash] = "foo"
       +
       +        if len(history) < 1:
       +            return {"result": None}
       +
       +        # TODO: Check how history4 acts for mempool/unconfirmed
       +        status = []
       +        for i in history:
       +            kind = "received" if "received" in i else "spent"
       +            status.append(safe_hexlify(i[kind]["hash"][::-1]))
       +            status.append(str(i[kind]["height"]))  # str because of join
       +
       +        # TODO: Check if trailing colon is necessary
       +        concat = ":".join(status) + ":"
       +        res = hash_to_hex_str(sha256(concat.encode()))
       +        return {"result": res}
        
            async def blockchain_scripthash_unsubscribe(self, writer, query):  # pylint: disable=W0613
                """Method: blockchain.scripthash.unsubscribe
 (DIR) diff --git a/electrumobelisk/zeromq.py b/electrumobelisk/zeromq.py
       t@@ -364,6 +364,8 @@ class Client:
                rows = unpack_table("<BI32sIQ", raw_points)
                points = [make_tuple(row) for row in rows]
                correlated_points = Client.__correlate(points)
       +        # self.log.debug("history points: %s", points)
       +        # self.log.debug("history correlated: %s", correlated_points)
                return error_code, correlated_points
        
            async def broadcast_transaction(self, rawtx):