Implement merkle proof for blockchain.block.headers
This commit is contained in:
parent
46d8e0c608
commit
061cac51a8
@ -56,6 +56,8 @@ With *cp_height* zero:
|
||||
|
||||
"0100000085144a84488ea88d221c8bd6c059da090e88f8a2c99690ee55dbba4e00000000e11c48fecdd9e72510ca84f023370c9a38bf91ac5cae88019bee94d24528526344c36649ffff001d1d03e477"
|
||||
|
||||
.. _cp_height example:
|
||||
|
||||
With *cp_height* 8 on the Bitcoin Cash chain::
|
||||
|
||||
{
|
||||
@ -135,6 +137,9 @@ Return a concatenated chunk of block headers from the main chain.
|
||||
|
||||
**Example Response**
|
||||
|
||||
See :ref:`here <cp_height example>` for an example of *root* and
|
||||
*branch* keys.
|
||||
|
||||
::
|
||||
|
||||
{
|
||||
|
||||
@ -297,29 +297,31 @@ class ElectrumX(SessionBase):
|
||||
hashX = self.controller.scripthash_to_hashX(scripthash)
|
||||
return await self.hashX_subscribe(hashX, scripthash)
|
||||
|
||||
def block_header(self, height, cp_height=0):
|
||||
'''Return a raw block header as a hexadecimal string.
|
||||
def _merkle_proof(self, cp_height, height):
|
||||
max_height = self.height()
|
||||
if not height <= cp_height <= max_height:
|
||||
raise RPCError(BAD_REQUEST,
|
||||
f'require header height {height:,d} <= '
|
||||
f'cp_height {cp_height:,d} <= '
|
||||
f'chain height {max_height:,d}')
|
||||
branch, root = self.controller.header_mc.branch_and_root(
|
||||
cp_height + 1, height)
|
||||
return {
|
||||
'branch': [hash_to_hex_str(elt) for elt in branch],
|
||||
'root': hash_to_hex_str(root),
|
||||
}
|
||||
|
||||
height: the header's height'''
|
||||
def block_header(self, height, cp_height=0):
|
||||
'''Return a raw block header as a hexadecimal string, or as a
|
||||
dictionary with a merkle proof.'''
|
||||
height = self.controller.non_negative_integer(height)
|
||||
cp_height = self.controller.non_negative_integer(cp_height)
|
||||
raw_header_hex = self.controller.raw_header(height).hex()
|
||||
if cp_height == 0:
|
||||
return raw_header_hex
|
||||
if height > cp_height:
|
||||
raise RPCError(BAD_REQUEST,
|
||||
f'height {height:,d} > cp_height {cp_height:,d}')
|
||||
max_height = self.height()
|
||||
if cp_height > max_height:
|
||||
raise RPCError(BAD_REQUEST, f'cp_height {cp_height:,d} > '
|
||||
f'max height {max_height:,d}')
|
||||
header_mc = self.controller.header_mc
|
||||
branch, root = header_mc.branch_and_root(cp_height + 1, height)
|
||||
return {
|
||||
'branch': [hash_to_hex_str(elt) for elt in branch],
|
||||
'header': raw_header_hex,
|
||||
'root': hash_to_hex_str(root),
|
||||
}
|
||||
result = {'header': raw_header_hex}
|
||||
result.update(self._merkle_proof(cp_height, height))
|
||||
return result
|
||||
|
||||
def block_header_13(self, height):
|
||||
'''Return a raw block header as a hexadecimal string.
|
||||
@ -327,7 +329,7 @@ class ElectrumX(SessionBase):
|
||||
height: the header's height'''
|
||||
return self.block_header(height)
|
||||
|
||||
def block_headers(self, start_height, count):
|
||||
def block_headers(self, start_height, count, cp_height=0):
|
||||
'''Return count concatenated block headers as hex for the main chain;
|
||||
starting at start_height.
|
||||
|
||||
@ -336,9 +338,18 @@ class ElectrumX(SessionBase):
|
||||
'''
|
||||
start_height = self.controller.non_negative_integer(start_height)
|
||||
count = self.controller.non_negative_integer(count)
|
||||
cp_height = self.controller.non_negative_integer(cp_height)
|
||||
|
||||
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}
|
||||
hex_str, count = self.controller.block_headers(start_height, count)
|
||||
result = {'hex': hex_str, 'count': count, 'max': self.MAX_CHUNK_SIZE}
|
||||
if count and cp_height:
|
||||
last_height = start_height + count - 1
|
||||
result.update(self._merkle_proof(cp_height, last_height))
|
||||
return result
|
||||
|
||||
def block_headers_12(self, start_height, count):
|
||||
return self.block_headers(start_height, count)
|
||||
|
||||
def block_get_chunk(self, index):
|
||||
'''Return a chunk of block headers as a hexadecimal string.
|
||||
@ -495,13 +506,14 @@ class ElectrumX(SessionBase):
|
||||
handlers.update({
|
||||
'mempool.get_fee_histogram':
|
||||
controller.mempool_get_fee_histogram,
|
||||
'blockchain.block.headers': self.block_headers,
|
||||
'blockchain.block.headers': self.block_headers_12,
|
||||
'server.ping': self.ping,
|
||||
})
|
||||
|
||||
if ptuple >= (1, 4):
|
||||
handlers.update({
|
||||
'blockchain.block.header': self.block_header,
|
||||
'blockchain.block.headers': self.block_headers,
|
||||
'blockchain.headers.subscribe': self.headers_subscribe,
|
||||
})
|
||||
elif ptuple >= (1, 3):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user