URI: 
       tFix logic bug in blockchain.block.headers and implement cp_height. - 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 b9a1e2f05c4871e9d7a3fa90e01a6548152bf65f
   DIR parent 7d3865cc4ee1682c4188707594389f92c3287838
  HTML Author: parazyd <parazyd@dyne.org>
       Date:   Thu, 15 Apr 2021 12:35:36 +0200
       
       Fix logic bug in blockchain.block.headers and implement cp_height.
       
       Diffstat:
         M obelisk/protocol.py                 |      27 +++++++++++++++++++++++++--
         M tests/test_electrum_protocol.py     |       2 +-
       
       2 files changed, 26 insertions(+), 3 deletions(-)
       ---
   DIR diff --git a/obelisk/protocol.py b/obelisk/protocol.py
       t@@ -251,6 +251,7 @@ class ElectrumProtocol(asyncio.Protocol):  # pylint: disable=R0904,R0902
                    cp_headers.append(data)
        
                # TODO: Review
       +        # TODO: Is index is 0 or last elem?
                branch, root = merkle_branch_and_root(cp_headers, 0)
                return {
                    "result": {
       t@@ -268,20 +269,22 @@ class ElectrumProtocol(asyncio.Protocol):  # pylint: disable=R0904,R0902
                    return JsonRPCError.invalidparams()
                # Electrum doesn't allow max_chunk_size to be less than 2016
                # gopher://bitreich.org/9/memecache/convenience-store.mkv
       -        # TODO: cp_height
                max_chunk_size = 2016
                start_height = query["params"][0]
                count = query["params"][1]
       +        cp_height = query["params"][2] if len(query["params"]) == 3 else 0
        
                if not is_non_negative_integer(start_height):
                    return JsonRPCError.invalidparams()
                if not is_non_negative_integer(count):
                    return JsonRPCError.invalidparams()
       +        if cp_height != 0 and not start_height + (count - 1) <= cp_height:
       +            return JsonRPCError.invalidparams()
        
                count = min(count, max_chunk_size)
                headers = bytearray()
                for i in range(count):
       -            _ec, data = await self.bx.fetch_block_header(i)
       +            _ec, data = await self.bx.fetch_block_header(start_height + i)
                    if _ec and _ec != 0:
                        self.log.debug("Got error: %s", repr(_ec))
                        return JsonRPCError.internalerror()
       t@@ -292,6 +295,26 @@ class ElectrumProtocol(asyncio.Protocol):  # pylint: disable=R0904,R0902
                    "count": len(headers) // 80,
                    "max": max_chunk_size,
                }
       +
       +        # The assumption is to fetch more headers if necessary.
       +        # TODO: Review
       +        if cp_height > 0 and cp_height - start_height > count:
       +            for i in range(cp_height - start_height):
       +                _ec, data = await self.bx.fetch_block_header(start_height +
       +                                                             count + i)
       +                if _ec and _ec != 0:
       +                    self.log.debug("Got error: %s", repr(_ec))
       +                    return JsonRPCError.internalerror()
       +                headers.extend(data)
       +
       +            # TODO: Review
       +            # TODO: Is index is 0 or last elem?
       +            hdr_lst = [headers[i:i + 80] for i in range(0, len(headers), 80)]
       +            print(hdr_lst)
       +            branch, root = merkle_branch_and_root(hdr_lst, 0)
       +            resp["branch"] = [safe_hexlify(i) for i in branch]
       +            resp["root"] = safe_hexlify(root)
       +
                return {"result": resp}
        
            async def blockchain_estimatefee(self, writer, query):  # pylint: disable=W0613
   DIR diff --git a/tests/test_electrum_protocol.py b/tests/test_electrum_protocol.py
       t@@ -40,7 +40,7 @@ async def test_blockchain_block_header(protocol, writer):
        
        
        async def test_blockchain_block_headers(protocol, writer):
       -    expect = "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff001d1aa4ae180100000043497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea330900000000bac8b0fa927c0ac8234287e33c5f74d38d354820e24756ad709d7038fc5f31f020e7494dffff001d03e4b6720100000006128e87be8b1b4dea47a7247d5528d2702c96826c7a648497e773b800000000e241352e3bec0a95a6217e10c3abb54adfa05abb12c126695595580fb92e222032e7494dffff001d00d23534"
       +    expect = "01000000c54675276e0401706aa93db6494dd7d1058b19424f23c8d7c01076da000000001c4375c8056b0ded0fa3d7fc1b5511eaf53216aed72ea95e1b5d19eccbe855f91a184a4dffff001d0336a22601000000bca72b7ccb44f1f0dd803f2c321143c9dda7f5a2a6ed87c76aac918a000000004266985f02f11bdffa559a233f5600c95c04bd70340e75673cadaf3ef6ac72b448194a4dffff001d035c84d801000000769d6d6e4672a620669baa56dd39d066523e461762ad3610fb2055b400000000c50652340352ad79b799b870e3fa2c80804d0fc54063b413e0e2d6dc66ca3f9a55194a4dffff001d022510a4"
            query = {"params": [123, 3]}
            data = await protocol.blockchain_block_headers(writer, query)
            assert data["result"]["hex"] == expect