@@ -868,13 +868,25 @@ async def get_block_headers(
868868 res = await self .session .send_request ('blockchain.block.headers' , [start_height , count ], timeout = timeout )
869869 # check response
870870 assert_dict_contains_field (res , field_name = 'count' )
871- assert_dict_contains_field (res , field_name = 'hex' )
872871 assert_dict_contains_field (res , field_name = 'max' )
873872 assert_non_negative_integer (res ['count' ])
874873 assert_non_negative_integer (res ['max' ])
875- assert_hex_str (res ['hex' ])
876- if len (res ['hex' ]) != HEADER_SIZE * 2 * res ['count' ]:
877- raise RequestCorrupted ('inconsistent chunk hex and count' )
874+ if self .active_protocol_tuple >= (1 , 6 ):
875+ hex_headers_list = assert_dict_contains_field (res , field_name = 'headers' )
876+ assert_list_or_tuple (hex_headers_list )
877+ for item in hex_headers_list :
878+ assert_hex_str (item )
879+ if len (item ) != HEADER_SIZE * 2 :
880+ raise RequestCorrupted (f"invalid header size. got { len (item )// 2 } , expected { HEADER_SIZE } " )
881+ if len (hex_headers_list ) != res ['count' ]:
882+ raise RequestCorrupted (f"{ len (hex_headers_list )= } != { res ['count' ]= } " )
883+ headers = list (bfh (hex_header ) for hex_header in hex_headers_list )
884+ else : # proto 1.4
885+ hex_headers_concat = assert_dict_contains_field (res , field_name = 'hex' )
886+ assert_hex_str (hex_headers_concat )
887+ if len (hex_headers_concat ) != HEADER_SIZE * 2 * res ['count' ]:
888+ raise RequestCorrupted ('inconsistent chunk hex and count' )
889+ headers = list (util .chunks (bfh (hex_headers_concat ), size = HEADER_SIZE ))
878890 # we never request more than MAX_NUM_HEADERS_IN_REQUEST headers, but we enforce those fit in a single response
879891 if res ['max' ] < MAX_NUM_HEADERS_PER_REQUEST :
880892 raise RequestCorrupted (f"server uses too low 'max' count for block.headers: { res ['max' ]} < { MAX_NUM_HEADERS_PER_REQUEST } " )
@@ -887,7 +899,6 @@ async def get_block_headers(
887899 raise RequestCorrupted (
888900 f"asked for { count } headers but got fewer: { res ['count' ]} . ({ start_height = } , { self .tip = } )" )
889901 # checks done.
890- headers = list (util .chunks (bfh (res ['hex' ]), size = HEADER_SIZE ))
891902 return headers
892903
893904 async def request_chunk_below_max_checkpoint (
@@ -1405,6 +1416,33 @@ async def broadcast_transaction(self, tx: 'Transaction', *, timeout=None) -> Non
14051416 # the status of a scripthash we are subscribed to. Caching here will save a future get_transaction RPC.
14061417 self ._rawtx_cache [txid_calc ] = bytes .fromhex (rawtx )
14071418
1419+ async def broadcast_txpackage (self , txs : Sequence ['Transaction' ]) -> bool :
1420+ assert self .active_protocol_tuple >= (1 , 6 ), f"server using old protocol: { self .active_protocol_tuple } "
1421+ rawtxs = [tx .serialize () for tx in txs ]
1422+ assert all (is_hex_str (rawtx ) for rawtx in rawtxs )
1423+ assert all (tx .txid () is not None for tx in txs )
1424+ timeout = self .network .get_network_timeout_seconds (NetworkTimeout .Urgent )
1425+ for tx in txs :
1426+ if any (DummyAddress .is_dummy_address (txout .address ) for txout in tx .outputs ()):
1427+ raise DummyAddressUsedInTxException ("tried to broadcast tx with dummy address!" )
1428+ try :
1429+ res = await self .session .send_request ('blockchain.transaction.broadcast_package' , [rawtxs ], timeout = timeout )
1430+ except aiorpcx .jsonrpc .CodeMessageError as e :
1431+ self .logger .info (f"broadcast_txpackage error [DO NOT TRUST THIS MESSAGE]: { error_text_str_to_safe_str (repr (e ))} . { rawtxs = } " )
1432+ return False
1433+ success = assert_dict_contains_field (res , field_name = 'success' )
1434+ if not success :
1435+ errors = assert_dict_contains_field (res , field_name = 'errors' )
1436+ self .logger .info (f"broadcast_txpackage error [DO NOT TRUST THIS MESSAGE]: { error_text_str_to_safe_str (repr (errors ))} . { rawtxs = } " )
1437+ return False
1438+ assert success
1439+ # broadcast succeeded.
1440+ # We now cache the rawtx, for *this interface only*. The tx likely touches some ismine addresses, affecting
1441+ # the status of a scripthash we are subscribed to. Caching here will save a future get_transaction RPC.
1442+ for tx , rawtx in zip (txs , rawtxs ):
1443+ self ._rawtx_cache [tx .txid ()] = bytes .fromhex (rawtx )
1444+ return True
1445+
14081446 async def get_history_for_scripthash (self , sh : str ) -> List [dict ]:
14091447 if not is_hash256_str (sh ):
14101448 raise Exception (f"{ repr (sh )} is not a scripthash" )
@@ -1525,10 +1563,14 @@ async def get_donation_address(self) -> str:
15251563 async def get_relay_fee (self ) -> int :
15261564 """Returns the min relay feerate in sat/kbyte."""
15271565 # do request
1528- res = await self .session .send_request ('blockchain.relayfee' )
1566+ if self .active_protocol_tuple >= (1 , 6 ):
1567+ res = await self .session .send_request ('mempool.get_info' )
1568+ minrelaytxfee = assert_dict_contains_field (res , field_name = 'minrelaytxfee' )
1569+ else :
1570+ minrelaytxfee = await self .session .send_request ('blockchain.relayfee' )
15291571 # check response
1530- assert_non_negative_int_or_float (res )
1531- relayfee = int (res * bitcoin .COIN )
1572+ assert_non_negative_int_or_float (minrelaytxfee )
1573+ relayfee = int (minrelaytxfee * bitcoin .COIN )
15321574 relayfee = max (0 , relayfee )
15331575 return relayfee
15341576
0 commit comments