Browse Source

cosigner pool: use single thread to send messages

ServerProxy does not seem to be thread-safe.
For e.g. a 2of3 multisig wallet, which would send two messages,
one msg would get sent but the other might error out. See trace:

E | plugins.cosigner_pool.qt.Plugin | on_failure
Traceback (most recent call last):
  File "...\electrum\electrum\gui\qt\util.py", line 832, in run
    result = task.task()
  File "...\electrum\electrum\plugins\cosigner_pool\qt.py", line 199, in <lambda>
    task = lambda: server.put(_hash, message)
  File "...\Python38\lib\xmlrpc\client.py", line 1109, in __call__
    return self.__send(self.__name, args)
  File "...\Python38\lib\xmlrpc\client.py", line 1450, in __request
    response = self.__transport.request(
  File "...\Python38\lib\xmlrpc\client.py", line 1153, in request
    return self.single_request(host, handler, request_body, verbose)
  File "...\Python38\lib\xmlrpc\client.py", line 1165, in single_request
    http_conn = self.send_request(host, handler, request_body, verbose)
  File "...\Python38\lib\xmlrpc\client.py", line 1271, in send_request
    connection.putrequest("POST", handler, skip_accept_encoding=True)
  File "...\Python38\lib\http\client.py", line 1088, in putrequest
    raise CannotSendRequest(self.__state)
http.client.CannotSendRequest: Request-sent
bip39-recovery
SomberNight 5 years ago
parent
commit
7a6ec23b6e
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 20
      electrum/plugins/cosigner_pool/qt.py

20
electrum/plugins/cosigner_pool/qt.py

@ -188,17 +188,27 @@ class Plugin(BasePlugin):
except OSError: pass
window.show_error(_("Failed to send transaction to cosigning pool") + ':\n' + repr(e))
buffer = []
some_window = None
# construct messages
for window, xpub, K, _hash in self.cosigner_list:
if not self.cosigner_can_sign(tx, xpub):
continue
# construct message
some_window = window
raw_tx_bytes = tx.serialize_as_bytes()
public_key = ecc.ECPubkey(K)
message = public_key.encrypt_message(raw_tx_bytes).decode('ascii')
# send message
task = lambda: server.put(_hash, message)
msg = _('Sending transaction to cosigning pool...')
WaitingDialog(window, msg, task, on_success, on_failure)
buffer.append((_hash, message))
if not buffer:
return
# send messages
# note: we send all messages sequentially on the same thread
def send_messages_task():
for _hash, message in buffer:
server.put(_hash, message)
msg = _('Sending transaction to cosigning pool...')
WaitingDialog(some_window, msg, send_messages_task, on_success, on_failure)
def on_receive(self, keyhash, message):
self.logger.info(f"signal arrived for {keyhash}")

Loading…
Cancel
Save