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"
|
"0100000085144a84488ea88d221c8bd6c059da090e88f8a2c99690ee55dbba4e00000000e11c48fecdd9e72510ca84f023370c9a38bf91ac5cae88019bee94d24528526344c36649ffff001d1d03e477"
|
||||||
|
|
||||||
|
.. _cp_height example:
|
||||||
|
|
||||||
With *cp_height* 8 on the Bitcoin Cash chain::
|
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**
|
**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)
|
hashX = self.controller.scripthash_to_hashX(scripthash)
|
||||||
return await self.hashX_subscribe(hashX, scripthash)
|
return await self.hashX_subscribe(hashX, scripthash)
|
||||||
|
|
||||||
def block_header(self, height, cp_height=0):
|
def _merkle_proof(self, cp_height, height):
|
||||||
'''Return a raw block header as a hexadecimal string.
|
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)
|
height = self.controller.non_negative_integer(height)
|
||||||
cp_height = self.controller.non_negative_integer(cp_height)
|
cp_height = self.controller.non_negative_integer(cp_height)
|
||||||
raw_header_hex = self.controller.raw_header(height).hex()
|
raw_header_hex = self.controller.raw_header(height).hex()
|
||||||
if cp_height == 0:
|
if cp_height == 0:
|
||||||
return raw_header_hex
|
return raw_header_hex
|
||||||
if height > cp_height:
|
result = {'header': raw_header_hex}
|
||||||
raise RPCError(BAD_REQUEST,
|
result.update(self._merkle_proof(cp_height, height))
|
||||||
f'height {height:,d} > cp_height {cp_height:,d}')
|
return result
|
||||||
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),
|
|
||||||
}
|
|
||||||
|
|
||||||
def block_header_13(self, height):
|
def block_header_13(self, height):
|
||||||
'''Return a raw block header as a hexadecimal string.
|
'''Return a raw block header as a hexadecimal string.
|
||||||
@ -327,7 +329,7 @@ class ElectrumX(SessionBase):
|
|||||||
height: the header's height'''
|
height: the header's height'''
|
||||||
return self.block_header(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;
|
'''Return count concatenated block headers as hex for the main chain;
|
||||||
starting at start_height.
|
starting at start_height.
|
||||||
|
|
||||||
@ -336,9 +338,18 @@ class ElectrumX(SessionBase):
|
|||||||
'''
|
'''
|
||||||
start_height = self.controller.non_negative_integer(start_height)
|
start_height = self.controller.non_negative_integer(start_height)
|
||||||
count = self.controller.non_negative_integer(count)
|
count = self.controller.non_negative_integer(count)
|
||||||
|
cp_height = self.controller.non_negative_integer(cp_height)
|
||||||
|
|
||||||
count = min(count, self.MAX_CHUNK_SIZE)
|
count = min(count, self.MAX_CHUNK_SIZE)
|
||||||
hex_str, n = self.controller.block_headers(start_height, count)
|
hex_str, count = self.controller.block_headers(start_height, count)
|
||||||
return {'hex': hex_str, 'count': n, 'max': self.MAX_CHUNK_SIZE}
|
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):
|
def block_get_chunk(self, index):
|
||||||
'''Return a chunk of block headers as a hexadecimal string.
|
'''Return a chunk of block headers as a hexadecimal string.
|
||||||
@ -495,13 +506,14 @@ class ElectrumX(SessionBase):
|
|||||||
handlers.update({
|
handlers.update({
|
||||||
'mempool.get_fee_histogram':
|
'mempool.get_fee_histogram':
|
||||||
controller.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,
|
'server.ping': self.ping,
|
||||||
})
|
})
|
||||||
|
|
||||||
if ptuple >= (1, 4):
|
if ptuple >= (1, 4):
|
||||||
handlers.update({
|
handlers.update({
|
||||||
'blockchain.block.header': self.block_header,
|
'blockchain.block.header': self.block_header,
|
||||||
|
'blockchain.block.headers': self.block_headers,
|
||||||
'blockchain.headers.subscribe': self.headers_subscribe,
|
'blockchain.headers.subscribe': self.headers_subscribe,
|
||||||
})
|
})
|
||||||
elif ptuple >= (1, 3):
|
elif ptuple >= (1, 3):
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user