8000 bug: qml: function called on wrong thread when saving psbt to wallet · Issue #9829 · spesmilo/electrum · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
8000

bug: qml: function called on wrong thread when saving psbt to wallet #9829

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
f321x opened this issue May 15, 2025 · 4 comments
Closed

bug: qml: function called on wrong thread when saving psbt to wallet #9829

f321x opened this issue May 15, 2025 · 4 comments

Comments

@f321x
Copy link
Member
f321x commented May 15, 2025

Description

The following exception occurred to me when saving a PSBT received as cosigner to the wallet history:

 107.60 | I | plugins.psbt_nostr.qml.QmlCosignerWallet.[psbt_multisig] | new event e3629f975e776d539fa194fed958fc302064ea0450a029341f5271cb321064ed
107.60 | I | plugins.psbt_nostr.qml.QmlCosignerWallet.[psbt_multisig] | received PSBT from 8970e204fb5f2d7461104d38167efe3620b1c44849107cea80e6139e76ad2e34
111.55 | D | gui.qml.qetxdetails | rawtx set -> cHNidP8BALACAAAAA0bh5rgUbrigQAuox1DIMkCy/YpvWvrodsP+3JmRihE9AAAAAAD9////aROpnh6wXM0H2MffIR2zHvs2sZNR5Jd7hg06mCeCH3oAAAAAAP3///9pE6meHrBczQfYx98hHbMe+zaxk1Hkl3uGDTqYJ4IfegEAAAAA/f///wFkHQAAAAAAACIAIBsv5OsZDG2sjIH1pH0wZlFEly8jq18vRZQMmNLNX5Bxg9gDAAABAStkAAAAAAAAACIAIIBzNpl4cPIEqaEuYlSjjHroQfA/H8UIYwCG3VV7K/mfIgIDoKYUiBpivmUPwIsPmfZ7HKBy/ugjHMKlMrwYK2c+7OJHMEQCIBmUjIPr7Vjv2En/MGFd31ocFG5xrAbYQQ/1XN5rB9KOAiAt9Oa/MGWh6HnDDqW7FSBOyZMOmDfVfE2VGHXDKJ+MswEBBUdSIQJ9htwT0+33YMDtR/sf1peFSJayk8Cx6xEOjQbvv9km4SEDoKYUiBpivmUPwIsPmfZ7HKBy/ugjHMKlMrwYK2c+7OJSriIGAn2G3BPT7fdgwO1H+x/Wl4VIlrKTwLHrEQ6NBu+/2SbhELVCxU0BAACAAAAAABUAAAAiBgOgphSIGmK+ZQ/Aiw+Z9nscoHL+6CMcwqUyvBgrZz7s4hDek6uNAQAAgAAAAAAVAAAAAAEBK2QAAAAAAAAAIgAgwN3n2nPACDrNVbfo8DK5H86VKqLkDK7K7zJn8inDpo0iAgIQ6E8vmeNcba+ULpcHpFpsm0EahLGszky1Cuj9F8FSeEcwRAIgG5MrB+W/qIlfsrethI0R0IQ7OmTeg7QBEgGUbif+ek4CIFaDVzRp5yogzbU+TCDj85UmPdxZv4zbwFoaB86ioOOIAQEFR1IhAhDoTy+Z41xtr5QulwekWmybQRqEsazOTLUK6P0XwVJ4IQOSVVvsZlvllmiGyT0GXZRdSFjKDaC2LXP6/4fisLgKsVKuIgYCEOhPL5njXG2vlC6XB6RabJtBGoSxrM5MtQro/RfBUngQ3pOrjQEAAIAAAAAAGQAAACIGA5JVW+xmW+WWaIbJPQZdlF1IWMoNoLYtc/r/h+KwuAqxELVCxU0BAACAAAAAABkAAAAAAQErFB4AAAAAAAAiACCR4WUMKU9PGhr+aotwkWNJ62+Ts/16xzGaTnHLGXlpByICAuNfT5o0bRm2bVJa83qUzLRBhG1sGKykLJshT/FVpefORzBEAiACqas/OB8zwIygFB1pkytW1jjIkUfr2Ym3YbQ6WRz3HQIgSTjKcP4ppkcFXAzBe3FTYF8rnA/MDucCDeB/AhgOStEBAQVHUiECxhsD+i84KK3TjzIyo26gVlFSsarRni/Jd6q8r5zWxY4hAuNfT5o0bRm2bVJa83qUzLRBhG1sGKykLJshT/FVpefOUq4iBgLGGwP6LzgordOPMjKjbqBWUVKxqtGeL8l3qryvnNbFjhC1QsVNAQAAgAEAAAABAAAAIgYC419PmjRtGbZtUlrzepTMtEGEbWwYrKQsmyFP8VWl584Q3pOrjQEAAIABAAAAAQAAAAABAUdSIQJ4YuwLDK2PqkdAoK97JanU2FX0BiahkfCfQUyr2vkL7SED2k9kORAfRn00H0BM9iGNDJO7gWi06OABEJJvU74NFz1SriICAnhi7AsMrY+qR0Cgr3slqdTYVfQGJqGR8J9BTKva+QvtELVCxU0BAACAAAAAABoAAAAiAgPaT2Q5EB9GfTQfQEz2IY0Mk7uBaLTo4AEQkm9Tvg0XPRDek6uNAQAAgAAAAAAaAAAAAA==
111.55 | D | gui.qml.qetxdetails | adding info from wallet
111.60 | D | n/network | got error from server for Network.get_transaction: '<UntrustedServerReturnedError [DO NOT TRUST THIS MESSAGE] original_exception: \'RPCError(2, "daemon error: DaemonError({\\\'code\\\': -5, \\\'message\\\': \\\'No such mempool or blockchain transaction. Use gettransaction for wallet transactions.\\\'})")\'>'
111.60 | D | n/network | got error from server for Network.get_transaction: '<UntrustedServerReturnedError [DO NOT TRUST THIS MESSAGE] original_exception: \'RPCError(2, "daemon error: DaemonError({\\\'code\\\': -5, \\\'message\\\': \\\'No such mempool or blockchain transaction. Use gettransaction for wallet transactions.\\\'})")\'>'
111.60 | I | transaction | got network error getting input txn. err: <UntrustedServerReturnedError 'The server returned an error.'>. txid: 7a1f8227983a0d867b97e45193b136fb1eb31d21dfc7d807cd5cb01e9ea91369. if you are intentionally offline, consider using the --offline flag
111.60 | I | transaction | got network error getting input txn. err: <UntrustedServerReturnedError 'The server returned an error.'>. txid: 7a1f8227983a0d867b97e45193b136fb1eb31d21dfc7d807cd5cb01e9ea91369. if you are intentionally offline, consider using the --offline flag
111.60 | D | n/network | got error from server for Network.get_transaction: '<UntrustedServerReturnedError [DO NOT TRUST THIS MESSAGE] original_exception: \'RPCError(2, "daemon error: DaemonError({\\\'code\\\': -5, \\\'message\\\': \\\'No such mempool or blockchain transaction. Use gettransaction for wallet transactions.\\\'})")\'>'
111.60 | I | transaction | got network error getting input txn. err: <UntrustedServerReturnedError 'The server returned an error.'>. txid: 3d118a9199dcfec376e8fa5a6f8afdb24032c850c7a80b40a0b86e14b8e6e146. if you are intentionally offline, consider using the --offline flag
111.60 | D | gui.qml.qetxdetails | TxWalletDetails(txid='781f136f6382f171e2ee0fd5de13a56ef532dc0e3cfe06b582e27bdd0a120bf0', status='Partially signed (3/6)', label='', can_broadcast=False, can_bump=False, can_cpfp=False, can_dscancel=False, can_save_as_local=True, amount=0, fee=376, tx_mined_status=TxMinedInfo(height=-2, conf=0, timestamp=None, txpos=None, header_hash=None, wanted_height=None), mempool_depth_bytes=None, can_remove=False, is_lightning_funding_tx=False, is_related_to_wallet=True)
115.63 | I | wallet_db.WalletDB | appending 22 pending changes
115.64 | D | gui.qml.qetxdetails | new_transaction event for our txid 781f136f6382f171e2ee0fd5de13a56ef532dc0e3cfe06b582e27bdd0a120bf0
115.64 | D | gui.qml.qetxdetails | adding info from wallet
115.64 | D | plugins.psbt_nostr.qml.QmlCosignerWallet.[psbt_multisig] | marking event rcvd
115.64 | D | gui.qml.qetransactionlistmodel | retrieving history
115.64 | D | util.profiler | Abstract_Wallet.get_full_history 0.0007 sec
115.66 | E | util | func errored. func=functools.partial(<bound method Abstract_Wallet.on_event_adb_added_tx of <electrum.wallet.Multisig_Wallet object at 0x7fcab5416a50>>, <electrum.address_synchronizer.AddressSynchronizer object at 0x7fcab5416ba0>, '781f136f6382f171e2ee0fd5de13a56ef532dc0e3cfe06b582e27bdd0a120bf0', <electrum.transaction.PartialTransaction object at 0x7fca88571050>). exc=AssertionError('must not be called from asyncio thread')
  File "/home/user/code/electrum-fork/./run_electrum", line 583, in <module>
    main()
  File "/home/user/code/electrum-fork/./run_electrum", line 467, in main
    handle_cmd(
  File "/home/user/code/electrum-fork/./run_electrum", line 484, in handle_cmd
    d.run_gui()
  File "/home/user/code/electrum-fork/electrum/daemon.py", line 602, in run_gui
    self.gui_object.main()
  File "/home/user/code/electrum-fork/electrum/gui/qml/__init__.py", line 102, in main
    self.app.exec()
  File "/home/user/code/electrum-fork/electrum/gui/qml/qetxdetails.py", line 502, in save
    if self._wallet.save_tx(self._tx):
  File "/home/user/code/electrum-fork/electrum/gui/qml/qewallet.py", line 643, in save_tx
    if not self.wallet.adb.add_transaction(tx):
  File "/home/user/code/electrum-fork/electrum/address_synchronizer.py", line 373, in add_transaction
    util.trigger_callback('adb_added_tx', self, tx_hash, tx)
  File "/home/user/code/electrum-fork/electrum/util.py", line 1919, in trigger_callback
    run_sync_function_on_asyncio_thread(partial(callback, *args), block=False)
Traceback (most recent call last):
  File "/home/user/code/electrum-fork/electrum/util.py", line 1717, in wrapper
    return func()
  File "/home/user/code/electrum-fork/electrum/wallet.py", line 604, in on_event_adb_added_tx
    util.trigger_callback('new_transaction', self, tx)
    ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/code/electrum-fork/electrum/util.py", line 1919, in trigger_callback
    run_sync_function_on_asyncio_thread(partial(callback, *args), block=False)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/code/electrum-fork/electrum/util.py", line 1714, in run_sync_function_on_asyncio_thread
    func()
    ~~~~^^
  File "/home/user/code/electrum-fork/electrum/gui/qml/qetxdetails.py", line 88, in on_event_new_transaction
    self.update()
    ~~~~~~~~~~~^^
  File "/home/user/code/electrum-fork/electrum/gui/qml/qetxdetails.py", line 300, in update
    Network.run_from_another_thread(
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        self._tx.add_info_from_network(self._wallet.wallet.network, timeout=10))  # FIXME is this needed?...
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/code/electrum-fork/electrum/network.py", line 471, in run_from_another_thread
    assert util.get_running_loop() != loop, 'must not be called from asyncio thread'
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: must not be called from asyncio thread
/usr/lib64/python3.13/asyncio/base_events.py:2019: RuntimeWarning: coroutine 'Transaction.add_info_from_network' was never awaited
  handle = self._ready.popleft()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
115.68 | D | gui.qml.qetransactionlistmodel | retrieving history
115.68 | D | util.profiler | Abstract_Wallet.get_full_history 0.0005 sec
115.73 | I | gui.qml.qewallet.[psbt_multisig] | new transaction 781f136f6382f171e2ee0fd5de13a56ef532dc0e3cfe06b582e27bdd0a120bf0
115.73 | D | gui.qml.qewallet.[psbt_multisig] | new transaction event
@accumulator
Copy link
Member

A solution could be to replace @event_listener with @qt_event_listener in funcs where update() is called, but this could block the UI thread when calling Network.run_from_another_thread

@accumulator
Copy link
Member
accumulator commented May 15, 2025

Anyway, the root cause looks to be triggering a callback from another callback handler, which puts the triggering on the asyncio thread

@ecdsa ecdsa added this to the 4.6.0 milestone May 15, 2025
@ecdsa
Copy link
Member
ecdsa commented May 16, 2025

Anyway, the root cause looks to be triggering a callback from another callback handler, which puts the triggering on the asyncio thread

I doubt this is the root cause. why don't you use similar flow as in qt/transaction_dialog.py ?
(actually, you only need the async path, because qml does not have hardware wallet support)

@f321x
Copy link
Member Author
f321x commented May 16, 2025

The trigger for this seems to be saving a cosigning psbt that builds on top of another local tx.

@ecdsa ecdsa closed this as completed May 16, 2025
@ecdsa ecdsa reopened this May 16, 2025
@ecdsa ecdsa closed this as completed May 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants
0