Browse Source

synchronizer/verifier: ensure fairness between wallets (follow-up)

follow-up to 4346d2fc76

It's not just about the Synchronizer, the Verifier should not starve other jobs either...
(previously I thought the Verifier is not too important as it only makes
requests if there are new txs; however with LNWatcher its progress is not persisted)
patch-4
SomberNight 4 years ago
parent
commit
bf7129d57e
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 8
      electrum/lnverifier.py
  2. 3
      electrum/synchronizer.py
  3. 4
      electrum/util.py
  4. 3
      electrum/verifier.py

8
electrum/lnverifier.py

@ -110,8 +110,9 @@ class LNChannelVerifier(NetworkJobOnDefaultServer):
# we are verifying channel announcements as they are from untrusted ln peers. # we are verifying channel announcements as they are from untrusted ln peers.
# we use electrum servers to do this. however we don't trust electrum servers either... # we use electrum servers to do this. however we don't trust electrum servers either...
try: try:
result = await self.network.get_txid_from_txpos( async with self._network_request_semaphore:
block_height, short_channel_id.txpos, True) result = await self.network.get_txid_from_txpos(
block_height, short_channel_id.txpos, True)
except aiorpcx.jsonrpc.RPCError: except aiorpcx.jsonrpc.RPCError:
# the electrum server is complaining about the txpos for given block. # the electrum server is complaining about the txpos for given block.
# it is not clear what to do now, but let's believe the server. # it is not clear what to do now, but let's believe the server.
@ -128,7 +129,8 @@ class LNChannelVerifier(NetworkJobOnDefaultServer):
# the electrum server sent an incorrect proof. blame is on server, not the ln peer # the electrum server sent an incorrect proof. blame is on server, not the ln peer
raise GracefulDisconnect(e) from e raise GracefulDisconnect(e) from e
try: try:
raw_tx = await self.network.get_transaction(tx_hash) async with self._network_request_semaphore:
raw_tx = await self.network.get_transaction(tx_hash)
except aiorpcx.jsonrpc.RPCError as e: except aiorpcx.jsonrpc.RPCError as e:
# the electrum server can't find the tx; but it was the # the electrum server can't find the tx; but it was the
# one who told us about the txid!! blame is on server # one who told us about the txid!! blame is on server

3
electrum/synchronizer.py

@ -61,9 +61,6 @@ class SynchronizerBase(NetworkJobOnDefaultServer):
def __init__(self, network: 'Network'): def __init__(self, network: 'Network'):
self.asyncio_loop = network.asyncio_loop self.asyncio_loop = network.asyncio_loop
self._reset_request_counters() self._reset_request_counters()
# Ensure fairness between Synchronizers. e.g. if multiple wallets
# are open, a large wallet should not starve the small wallets:
self._network_request_semaphore = asyncio.Semaphore(100)
NetworkJobOnDefaultServer.__init__(self, network) NetworkJobOnDefaultServer.__init__(self, network)

4
electrum/util.py

@ -1171,6 +1171,10 @@ class NetworkJobOnDefaultServer(Logger):
self.network = network self.network = network
self.interface = None # type: Interface self.interface = None # type: Interface
self._restart_lock = asyncio.Lock() self._restart_lock = asyncio.Lock()
# Ensure fairness between NetworkJobs. e.g. if multiple wallets
# are open, a large wallet's Synchronizer should not starve the small wallets:
self._network_request_semaphore = asyncio.Semaphore(100)
self._reset() self._reset()
asyncio.run_coroutine_threadsafe(self._restart(), network.asyncio_loop) asyncio.run_coroutine_threadsafe(self._restart(), network.asyncio_loop)
register_callback(self._restart, ['default_server_changed']) register_callback(self._restart, ['default_server_changed'])

3
electrum/verifier.py

@ -96,7 +96,8 @@ class SPV(NetworkJobOnDefaultServer):
async def _request_and_verify_single_proof(self, tx_hash, tx_height): async def _request_and_verify_single_proof(self, tx_hash, tx_height):
try: try:
merkle = await self.network.get_merkle_for_transaction(tx_hash, tx_height) async with self._network_request_semaphore:
merkle = await self.network.get_merkle_for_transaction(tx_hash, tx_height)
except UntrustedServerReturnedError as e: except UntrustedServerReturnedError as e:
if not isinstance(e.original_exception, aiorpcx.jsonrpc.RPCError): if not isinstance(e.original_exception, aiorpcx.jsonrpc.RPCError):
raise raise

Loading…
Cancel
Save