URI: 
       tprotocol: Implement scripthash status notifications. - obelisk - Electrum server using libbitcoin as its backend
  HTML git clone https://git.parazyd.org/obelisk
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 3b7ae8f951235c59ae57b40eeb39116a044eaee5
   DIR parent bc14baed27380fe6140fc25cb18f951ad942b33f
  HTML Author: parazyd <parazyd@dyne.org>
       Date:   Mon, 19 Apr 2021 13:39:48 +0200
       
       protocol: Implement scripthash status notifications.
       
       This seems to only work for confirmed transactions so I left a mempool
       TODO in the function.
       
       Diffstat:
         M obelisk/protocol.py                 |      35 +++++++++++++++++++++++--------
       
       1 file changed, 26 insertions(+), 9 deletions(-)
       ---
   DIR diff --git a/obelisk/protocol.py b/obelisk/protocol.py
       t@@ -19,9 +19,11 @@ https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html
        """
        import asyncio
        import json
       +import struct
        from binascii import unhexlify
        
        from obelisk.errors_jsonrpc import JsonRPCError
       +from obelisk.errors_libbitcoin import ErrorCode
        from obelisk.merkle import merkle_branch, merkle_branch_and_root
        from obelisk.util import (
            bh2u,
       t@@ -427,16 +429,31 @@ class ElectrumProtocol(asyncio.Protocol):  # pylint: disable=R0904,R0902
                return {"result": ret}
        
            async def scripthash_notifier(self, writer, scripthash):
       -        # TODO: Figure out how this actually works
       -        _ec, sh_queue = await self.bx.subscribe_scripthash(scripthash)
       -        if _ec and _ec != 0:
       -            self.log.error("bx.subscribe_scripthash failed:", repr(_ec))
       -            return
       -
       +        # TODO: Mempool
       +        method = "blockchain.scripthash.subscribe"
                while True:
       -            # item = (seq, height, block_data)
       +            _ec, sh_queue = await self.bx.subscribe_scripthash(scripthash)
       +            if _ec and _ec != 0:
       +                self.log.error("bx.subscribe_scripthash failed: %s", repr(_ec))
       +                return
       +
                    item = await sh_queue.get()
       -            self.log.debug("sh_subscription item: %s", item)
       +            _ec, height, txid = struct.unpack("<HI32s", item)
       +
       +            if (_ec == ErrorCode.service_stopped.value and height == 0 and
       +                    not self.stopped):
       +                # Subscription expired
       +                continue
       +
       +            self.sh_subscriptions[scripthash]["status"].append(
       +                (hash_to_hex_str(txid), height))
       +
       +            params = [
       +                scripthash,
       +                ElectrumProtocol.__scripthash_status_encode(
       +                    self.sh_subscriptions[scripthash]["status"]),
       +            ]
       +            await self._send_notification(writer, method, params)
        
            async def scripthash_subscribe(self, writer, query):  # pylint: disable=W0613
                """Method: blockchain.scripthash.subscribe
       t@@ -540,7 +557,7 @@ class ElectrumProtocol(asyncio.Protocol):  # pylint: disable=R0904,R0902
        
                # _ec, rawtx = await self.bx.fetch_blockchain_transaction(tx_hash)
                _ec, rawtx = await self.bx.fetch_mempool_transaction(tx_hash)
       -        if _ec and _ec != 0:
       +        if _ec and _ec != 0 and _ec != ErrorCode.not_found.value:
                    self.log.debug("Got error: %s", repr(_ec))
                    return JsonRPCError.internalerror()