@@ -1067,7 +1067,7 @@ class ElectrumX(SessionBase):
10671067
10681068 PROTOCOL_MIN = (1 , 4 )
10691069 # consider bumping Coin.MIN_REQUIRED_DAEMON_VERSION too when releasing a new protocol version
1070- PROTOCOL_MAX = (1 , 4 , 3 )
1070+ PROTOCOL_MAX = (1 , 6 , 0 )
10711071
10721072 def __init__ (self , * args , ** kwargs ):
10731073 super ().__init__ (* args , ** kwargs )
@@ -1208,7 +1208,7 @@ async def address_status(self, hashX):
12081208
12091209 Status is a hex string, but must be None if there is no history.
12101210 '''
1211- # Note history is ordered and mempool unordered in electrum-server
1211+ # Note both confirmed history and mempool history are ordered
12121212 # For mempool, height is -1 if it has unconfirmed inputs, otherwise 0
12131213 db_history , cost = await self .session_mgr .limited_history (hashX )
12141214 mempool = await self .mempool .transaction_summaries (hashX )
@@ -1278,7 +1278,7 @@ async def scripthash_get_balance(self, scripthash):
12781278 return await self .get_balance (hashX )
12791279
12801280 async def unconfirmed_history (self , hashX ):
1281- # Note unconfirmed history is unordered in electrum-server
1281+ # Note both confirmed history and mempool history are ordered
12821282 # height is -1 if it has unconfirmed inputs, otherwise 0
12831283 result = [{'tx_hash' : hash_to_hex_str (tx .hash ),
12841284 'height' : - tx .has_unconfirmed_inputs ,
@@ -1288,7 +1288,7 @@ async def unconfirmed_history(self, hashX):
12881288 return result
12891289
12901290 async def confirmed_and_unconfirmed_history (self , hashX ):
1291- # Note history is ordered but unconfirmed is unordered in e-s
1291+ # Note both confirmed history and mempool history are ordered
12921292 history , cost = await self .session_mgr .limited_history (hashX )
12931293 self .bump_cost (cost )
12941294 conf = [{'tx_hash' : hash_to_hex_str (tx_hash ), 'height' : height }
@@ -1357,6 +1357,8 @@ async def block_headers(self, start_height, count, cp_height=0):
13571357 start_height and count must be non-negative integers. At most
13581358 MAX_CHUNK_SIZE headers will be returned.
13591359 '''
1360+ if self .protocol_tuple >= (1 , 6 ):
1361+ return await self .block_headers_array (start_height , count , cp_height )
13601362 start_height = non_negative_integer (start_height )
13611363 count = non_negative_integer (count )
13621364 cp_height = non_negative_integer (cp_height )
@@ -1373,6 +1375,38 @@ async def block_headers(self, start_height, count, cp_height=0):
13731375 self .bump_cost (cost )
13741376 return result
13751377
1378+ async def block_headers_array (self , start_height , count , cp_height = 0 ):
1379+ '''Return block headers in an array for the main chain;
1380+ starting at start_height.
1381+ start_height and count must be non-negative integers. At most
1382+ MAX_CHUNK_SIZE headers will be returned.
1383+ '''
1384+ start_height = non_negative_integer (start_height )
1385+ count = non_negative_integer (count )
1386+ cp_height = non_negative_integer (cp_height )
1387+ cost = count / 50
1388+
1389+ max_size = self .MAX_CHUNK_SIZE
1390+ count = min (count , max_size )
1391+ headers , count = await self .db .read_headers (start_height , count )
1392+ result = {'count' : count , 'max' : max_size , 'headers' : []}
1393+ if count and cp_height :
1394+ cost += 1.0
1395+ last_height = start_height + count - 1
1396+ result .update (await self ._merkle_proof (cp_height , last_height ))
1397+
1398+ cursor = 0
1399+ height = 0
1400+ while cursor < len (headers ):
1401+ next_cursor = self .db .header_offset (height + 1 )
1402+ header = headers [cursor :next_cursor ]
1403+ result ['headers' ].append (header .hex ())
1404+ cursor = next_cursor
1405+ height += 1
1406+
1407+ self .bump_cost (cost )
1408+ return result
1409+
13761410 def is_tor (self ):
13771411 '''Try to detect if the connection is to a tor hidden service we are
13781412 running.'''
@@ -1960,36 +1994,41 @@ async def block_header(self, height, cp_height=0):
19601994 return result
19611995
19621996 # Covered by a checkpoint; truncate AuxPoW data
1963- result ['header' ] = self .truncate_auxpow (result ['header' ], height )
1997+ result ['header' ] = self .truncate_auxpow_single (result ['header' ])
19641998 return result
19651999
19662000 async def block_headers (self , start_height , count , cp_height = 0 ):
1967- result = await super ().block_headers (start_height , count , cp_height )
1968-
19692001 # Older protocol versions don't truncate AuxPoW
19702002 if self .protocol_tuple < (1 , 4 , 1 ):
1971- return result
2003+ return await super (). block_headers ( start_height , count , cp_height )
19722004
19732005 # Not covered by a checkpoint; return full AuxPoW data
19742006 if cp_height == 0 :
1975- return result
2007+ return await super ().block_headers (start_height , count , cp_height )
2008+
2009+ result = await super ().block_headers_array (start_height , count , cp_height )
19762010
19772011 # Covered by a checkpoint; truncate AuxPoW data
1978- result ['hex' ] = self .truncate_auxpow (result ['hex' ], start_height )
1979- return result
2012+ result ['headers' ] = self .truncate_auxpow_headers (result ['headers' ])
19802013
1981- def truncate_auxpow (self , headers_full_hex , start_height ):
1982- height = start_height
1983- headers_full = util .hex_to_bytes (headers_full_hex )
1984- cursor = 0
1985- headers = bytearray ()
2014+ # Return headers in array form
2015+ if self .protocol_tuple >= (1 , 6 ):
2016+ return result
19862017
1987- while cursor < len (headers_full ):
1988- headers += headers_full [cursor :cursor + self .coin .TRUNCATED_HEADER_SIZE ]
1989- cursor += self .db .dynamic_header_len (height )
1990- height += 1
2018+ # Return headers in concatenated form
2019+ result ['hex' ] = '' .join (result ['headers' ])
2020+ del result ['headers' ]
2021+ return result
2022+
2023+ def truncate_auxpow_headers (self , headers ):
2024+ result = []
2025+ for header in headers :
2026+ result .append (self .truncate_auxpow_single (header ))
2027+ return result
19912028
1992- return headers .hex ()
2029+ def truncate_auxpow_single (self , header : str ):
2030+ # 2 hex chars per byte
2031+ return header [:2 * self .coin .TRUNCATED_HEADER_SIZE ]
19932032
19942033
19952034class NameIndexElectrumX (ElectrumX ):
0 commit comments