|
|
@ -45,7 +45,7 @@ from .bitcoin import COIN |
|
|
|
from . import constants |
|
|
|
from . import blockchain |
|
|
|
from .blockchain import Blockchain, HEADER_SIZE |
|
|
|
from .interface import Interface, serialize_server, deserialize_server |
|
|
|
from .interface import Interface, serialize_server, deserialize_server, RequestTimedOut |
|
|
|
from .version import PROTOCOL_VERSION |
|
|
|
from .simple_config import SimpleConfig |
|
|
|
|
|
|
@ -638,13 +638,34 @@ class Network(PrintError): |
|
|
|
with b.lock: |
|
|
|
b.update_size() |
|
|
|
|
|
|
|
async def get_merkle_for_transaction(self, tx_hash, tx_height): |
|
|
|
def best_effort_reliable(func): |
|
|
|
async def make_reliable_wrapper(self, *args, **kwargs): |
|
|
|
for i in range(10): |
|
|
|
iface = self.interface |
|
|
|
session = iface.session if iface else None |
|
|
|
if not session: |
|
|
|
# no main interface; try again |
|
|
|
await asyncio.sleep(0.1) |
|
|
|
continue |
|
|
|
try: |
|
|
|
return await func(self, *args, **kwargs) |
|
|
|
except RequestTimedOut: |
|
|
|
if self.interface != iface: |
|
|
|
# main interface changed; try again |
|
|
|
continue |
|
|
|
raise |
|
|
|
raise Exception('no interface to do request on... gave up.') |
|
|
|
return make_reliable_wrapper |
|
|
|
|
|
|
|
@best_effort_reliable |
|
|
|
async def get_merkle_for_transaction(self, tx_hash: str, tx_height: int) -> dict: |
|
|
|
return await self.interface.session.send_request('blockchain.transaction.get_merkle', [tx_hash, tx_height]) |
|
|
|
|
|
|
|
@best_effort_reliable |
|
|
|
async def broadcast_transaction(self, tx, timeout=10): |
|
|
|
try: |
|
|
|
out = await self.interface.session.send_request('blockchain.transaction.broadcast', [str(tx)], timeout=timeout) |
|
|
|
except asyncio.TimeoutError as e: |
|
|
|
except RequestTimedOut as e: |
|
|
|
return False, "error: operation timed out" |
|
|
|
except Exception as e: |
|
|
|
return False, "error: " + str(e) |
|
|
@ -653,10 +674,27 @@ class Network(PrintError): |
|
|
|
return False, "error: " + out |
|
|
|
return True, out |
|
|
|
|
|
|
|
@best_effort_reliable |
|
|
|
async def request_chunk(self, height, tip=None, *, can_return_early=False): |
|
|
|
return await self.interface.request_chunk(height, tip=tip, can_return_early=can_return_early) |
|
|
|
|
|
|
|
def blockchain(self): |
|
|
|
@best_effort_reliable |
|
|
|
async def get_transaction(self, tx_hash: str) -> str: |
|
|
|
return await self.interface.session.send_request('blockchain.transaction.get', [tx_hash]) |
|
|
|
|
|
|
|
@best_effort_reliable |
|
|
|
async def get_history_for_scripthash(self, sh: str) -> List[dict]: |
|
|
|
return await self.interface.session.send_request('blockchain.scripthash.get_history', [sh]) |
|
|
|
|
|
|
|
@best_effort_reliable |
|
|
|
async def listunspent_for_scripthash(self, sh: str) -> List[dict]: |
|
|
|
return await self.interface.session.send_request('blockchain.scripthash.listunspent', [sh]) |
|
|
|
|
|
|
|
@best_effort_reliable |
|
|
|
async def get_balance_for_scripthash(self, sh: str) -> dict: |
|
|
|
return await self.interface.session.send_request('blockchain.scripthash.get_balance', [sh]) |
|
|
|
|
|
|
|
def blockchain(self) -> Blockchain: |
|
|
|
interface = self.interface |
|
|
|
if interface and interface.blockchain is not None: |
|
|
|
self.blockchain_index = interface.blockchain.forkpoint |
|
|
|