diff --git a/docs/PROTOCOL.rst b/docs/PROTOCOL.rst index ea409a2..5f979d7 100644 --- a/docs/PROTOCOL.rst +++ b/docs/PROTOCOL.rst @@ -927,14 +927,50 @@ Get a list of features and services supported by the server. Protocol Version 1.2 -------------------- -Protocol version 1.2 is the same as version `1.1` except for the -addition of a new method `mempool.get_fee_histogram`. +Protocol version 1.2 introduces new methods `blockcahin.block.get_chunk`, +`mempool.get_fee_histogram`. -All methods with taking addresses are deprecated, and will be removed -at some point in the future. You should update your code to use -`Script Hashes`_ and the scripthash methods introduced in protocol 1.1 -instead. +`blockchain.block.get_chunk` and all methods beginning + `blockchain.address.` are deprecated and support will be removed in + some future protocol version. You should update your code to use + `blockchain.block.headers` and `Script Hashes`_ with the scripthash + methods introduced in protocol 1.1 instead. +blockchain.block.headers +======================== + +Return concatenated block headers as hexadecimal from the main chain. + + blockchain.block.headers(**start_height**, **count**) + + **start_height** + + The height of the first header requested, a non-negative integer. + + **count** + + The number of headers requested, a non-negative integer. + +**Response** + + A dictionary with at least 3 members: + +* **count** + + The number of headers returned, between zero and the number + requested. If the chain has not extended sufficiently far, only + the available headers will be returned. If more headers than + **max** were requested at most **max** will be returned. + +* **hex** + + The binary block headers concatenated together as hexadecimal + strings, in order. + +* **max** + + The maximum number of headers the server will return in a single + request. mempool.get_fee_histogram ========================= diff --git a/server/controller.py b/server/controller.py index 7379186..454de2b 100644 --- a/server/controller.py +++ b/server/controller.py @@ -747,13 +747,16 @@ class Controller(ServerBase): return await self.run_in_executor(job) - def get_chunk(self, index): - '''Return header chunk as hex. Index is a non-negative integer.''' - chunk_size = self.coin.CHUNK_SIZE - start_height = index * chunk_size - count = chunk_size - headers, n = self.bp.read_headers(start_height, count).hex() - return headers + def block_headers(self, start_height, count): + '''Read count block headers starting at start_height; both + must be non-negative. + + The return value is (hex, n), where hex is the hex encoding of + the concatenated headers, and n is the number of headers read + (0 <= n <= count). + ''' + headers, n = self.bp.read_headers(start_height, count) + return headers.hex(), n # Client RPC "blockchain" command handlers diff --git a/server/session.py b/server/session.py index a487ed4..788e9e9 100644 --- a/server/session.py +++ b/server/session.py @@ -25,6 +25,8 @@ class SessionBase(JSONSession): sessions. ''' + MAX_CHUNK_SIZE = 2016 + def __init__(self, controller, kind): # Force v2 as a temporary hack for old Coinomi wallets # Remove in April 2017 @@ -255,13 +257,17 @@ class ElectrumX(SessionBase): return self.env.server_features() def block_headers(self, start_height, count): - '''Return concatenated block headers as hex for the main chain; - count headers starting at start_height. + '''Return count concatenated block headers as hex for the main chain; + starting at start_height. - start_height and count must be non-negative integers.''' + start_height and count must be non-negative integers. At most + MAX_CHUNK_SIZE headers will be returned. + ''' start_height = self.controller.non_negative_integer(start_height) count = self.controller.non_negative_integer(count) - return self.controller.block_headers(start_height, count).hex() + count = min(count, self.MAX_CHUNK_SIZE) + hex_str, n = self.controller.block_headers(start_height, count) + return {'hex': hex_str, 'count': n, 'max': self.MAX_CHUNK_SIZE} def block_get_chunk(self, index): '''Return a chunk of block headers as a hexadecimal string. @@ -270,9 +276,8 @@ class ElectrumX(SessionBase): index = self.controller.non_negative_integer(index) chunk_size = self.coin.CHUNK_SIZE start_height = index * chunk_size - count = chunk_size - - return self.controller.block_headers(start_height, count).hex() + hex_str, n = self.controller.block_headers(start_height, chunk_size) + return hex_str def block_get_chunk(self, index): '''Return a chunk of block headers as a hexadecimal string. @@ -462,7 +467,9 @@ class ElectrumX(SessionBase): if ptuple >= (1, 2): # New handler as of 1.2 handlers.update({ - 'mempool.get_fee_histogram': controller.mempool_get_fee_histogram, + 'mempool.get_fee_histogram': + controller.mempool_get_fee_histogram, + 'blockchain.block.headers': self.block_headers, }) self.electrumx_handlers = handlers