1
0

logging: basics

This commit is contained in:
SomberNight
2019-04-26 18:52:26 +02:00
parent 4d64e132d7
commit 3385a94753
68 changed files with 681 additions and 563 deletions

View File

@@ -9,19 +9,23 @@ from PyQt5.QtWidgets import (QComboBox, QGridLayout, QLabel, QPushButton)
from electrum.plugin import BasePlugin, hook
from electrum.gui.qt.util import WaitingDialog, EnterButton, WindowModalDialog, read_QIcon
from electrum.util import print_msg, print_error
from electrum.i18n import _
from electrum.logging import get_logger
_logger = get_logger(__name__)
try:
import amodem.audio
import amodem.main
import amodem.config
print_error('Audio MODEM is available.')
_logger.info('Audio MODEM is available.')
amodem.log.addHandler(amodem.logging.StreamHandler(sys.stderr))
amodem.log.setLevel(amodem.logging.INFO)
except ImportError:
amodem = None
print_error('Audio MODEM is not found.')
_logger.info('Audio MODEM is not found.')
class Plugin(BasePlugin):
@@ -100,7 +104,7 @@ class Plugin(BasePlugin):
dst = interface.player()
amodem.main.send(config=self.modem_config, src=src, dst=dst)
print_msg('Sending:', repr(blob))
_logger.info(f'Sending: {repr(blob)}')
blob = zlib.compress(blob.encode('ascii'))
kbps = self.modem_config.modem_bps / 1e3
@@ -118,7 +122,7 @@ class Plugin(BasePlugin):
def on_finished(blob):
if blob:
blob = zlib.decompress(blob).decode('ascii')
print_msg('Received:', repr(blob))
_logger.info(f'Received: {repr(blob)}')
parent.setText(blob)
kbps = self.modem_config.modem_bps / 1e3

View File

@@ -1,6 +1,12 @@
from electrum.plugin import hook
from electrum.util import print_msg, raw_input, print_stderr
from electrum.logging import get_logger
from .coldcard import ColdcardPlugin
from electrum.util import print_msg, print_error, raw_input, print_stderr
_logger = get_logger(__name__)
class ColdcardCmdLineHandler:
@@ -24,10 +30,10 @@ class ColdcardCmdLineHandler:
print_stderr(msg)
def show_error(self, msg, blocking=False):
print_error(msg)
print_stderr(msg)
def update_status(self, b):
print_error('hw device status', b)
_logger.info(f'hw device status {b}')
def finished(self):
pass

View File

@@ -13,12 +13,17 @@ from electrum.keystore import Hardware_KeyStore, xpubkey_to_pubkey, Xpub
from electrum.transaction import Transaction
from electrum.wallet import Standard_Wallet
from electrum.crypto import hash_160
from electrum.util import print_error, bfh, bh2u, versiontuple, UserFacingException
from electrum.util import bfh, bh2u, versiontuple, UserFacingException
from electrum.base_wizard import ScriptTypeNotSupported
from electrum.logging import get_logger
from ..hw_wallet import HW_PluginBase
from ..hw_wallet.plugin import LibraryFoundButUnusable
_logger = get_logger(__name__)
try:
import hid
from ckcc.protocol import CCProtocolPacker, CCProtocolUnpacker
@@ -114,10 +119,10 @@ class CKCCClient:
or (self.dev.master_fingerprint != expected_xfp)
or (self.dev.master_xpub != expected_xpub)):
# probably indicating programing error, not hacking
print_error("[coldcard]", f"xpubs. reported by device: {self.dev.master_xpub}. "
f"stored in file: {expected_xpub}")
raise RuntimeError("Expecting 0x%08x but that's not whats connected?!" %
expected_xfp)
_logger.info(f"xpubs. reported by device: {self.dev.master_xpub}. "
f"stored in file: {expected_xpub}")
raise RuntimeError("Expecting 0x%08x but that's not what's connected?!" %
expected_xfp)
# check signature over session key
# - mitm might have lied about xfp and xpub up to here
@@ -127,7 +132,7 @@ class CKCCClient:
self._expected_device = ex
print_error("[coldcard]", "Successfully verified against MiTM")
_logger.info("Successfully verified against MiTM")
def is_pairable(self):
# can't do anything w/ devices that aren't setup (but not normally reachable)
@@ -181,7 +186,7 @@ class CKCCClient:
def get_xpub(self, bip32_path, xtype):
assert xtype in ColdcardPlugin.SUPPORTED_XTYPES
print_error('[coldcard]', 'Derive xtype = %r' % xtype)
_logger.info('Derive xtype = %r' % xtype)
xpub = self.dev.send_recv(CCProtocolPacker.get_xpub(bip32_path), timeout=5000)
# TODO handle timeout?
# change type of xpub to the requested type
@@ -296,7 +301,7 @@ class Coldcard_KeyStore(Hardware_KeyStore):
return rv
def give_error(self, message, clear_client=False):
print_error(message)
self.logger.info(message)
if not self.ux_busy:
self.handler.show_error(message)
else:
@@ -363,7 +368,7 @@ class Coldcard_KeyStore(Hardware_KeyStore):
except (CCUserRefused, CCBusyError) as exc:
self.handler.show_error(str(exc))
except CCProtoError as exc:
traceback.print_exc(file=sys.stderr)
self.logger.exception('Error showing address')
self.handler.show_error('{}\n\n{}'.format(
_('Error showing address') + ':', str(exc)))
except Exception as e:
@@ -546,11 +551,11 @@ class Coldcard_KeyStore(Hardware_KeyStore):
self.handler.finished()
except (CCUserRefused, CCBusyError) as exc:
print_error('[coldcard]', 'Did not sign:', str(exc))
self.logger.info(f'Did not sign: {exc}')
self.handler.show_error(str(exc))
return
except BaseException as e:
traceback.print_exc(file=sys.stderr)
self.logger.exception('')
self.give_error(e, True)
return
@@ -581,11 +586,11 @@ class Coldcard_KeyStore(Hardware_KeyStore):
finally:
self.handler.finished()
except CCProtoError as exc:
traceback.print_exc(file=sys.stderr)
self.logger.exception('Error showing address')
self.handler.show_error('{}\n\n{}'.format(
_('Error showing address') + ':', str(exc)))
except BaseException as exc:
traceback.print_exc(file=sys.stderr)
self.logger.exception('')
self.handler.show_error(exc)
@@ -651,7 +656,7 @@ class ColdcardPlugin(HW_PluginBase):
is_simulator=(device.product_key[1] == CKCC_SIMULATED_PID))
return rv
except:
self.print_error('late failure connecting to device?')
self.logger.info('late failure connecting to device?')
return None
def setup_device(self, device_info, wizard, purpose):

View File

@@ -74,12 +74,12 @@ class Listener(util.DaemonThread):
try:
message = server.get(keyhash)
except Exception as e:
self.print_error("cannot contact cosigner pool")
self.logger.info("cannot contact cosigner pool")
time.sleep(30)
continue
if message:
self.received.add(keyhash)
self.print_error("received message for", keyhash)
self.logger.info(f"received message for {keyhash}")
self.parent.obj.cosigner_receive_signal.emit(
keyhash, message)
# poll every 30 seconds
@@ -121,11 +121,11 @@ class Plugin(BasePlugin):
if type(wallet) != Multisig_Wallet:
return
if self.listener is None:
self.print_error("starting listener")
self.logger.info("starting listener")
self.listener = Listener(self)
self.listener.start()
elif self.listener:
self.print_error("shutting down listener")
self.logger.info("shutting down listener")
self.listener.stop()
self.listener = None
self.keys = []
@@ -176,7 +176,7 @@ class Plugin(BasePlugin):
_("Open your cosigner wallet to retrieve it."))
def on_failure(exc_info):
e = exc_info[1]
try: traceback.print_exception(*exc_info)
try: self.logger.error("on_failure", exc_info=exc_info)
except OSError: pass
window.show_error(_("Failed to send transaction to cosigning pool") + ':\n' + str(e))
@@ -193,12 +193,12 @@ class Plugin(BasePlugin):
WaitingDialog(window, msg, task, on_success, on_failure)
def on_receive(self, keyhash, message):
self.print_error("signal arrived for", keyhash)
self.logger.info("signal arrived for", keyhash)
for key, _hash, window in self.keys:
if _hash == keyhash:
break
else:
self.print_error("keyhash not found")
self.logger.info("keyhash not found")
return
wallet = window.wallet
@@ -225,7 +225,7 @@ class Plugin(BasePlugin):
privkey = BIP32Node.from_xkey(xprv).eckey
message = bh2u(privkey.decrypt_message(message))
except Exception as e:
traceback.print_exc(file=sys.stdout)
self.logger.exception('')
window.show_error(_('Error decrypting message') + ':\n' + str(e))
return

View File

@@ -27,9 +27,14 @@ from electrum.transaction import Transaction
from electrum.i18n import _
from electrum.keystore import Hardware_KeyStore
from ..hw_wallet import HW_PluginBase
from electrum.util import print_error, to_string, UserCancelled, UserFacingException
from electrum.util import to_string, UserCancelled, UserFacingException
from electrum.base_wizard import ScriptTypeNotSupported, HWD_SETUP_NEW_WALLET
from electrum.network import Network
from electrum.logging import get_logger
_logger = get_logger(__name__)
try:
import hid
@@ -406,7 +411,7 @@ class DigitalBitbox_Client():
r = to_string(r, 'utf8')
reply = json.loads(r)
except Exception as e:
print_error('Exception caught ' + repr(e))
_logger.info(f'Exception caught {repr(e)}')
return reply
@@ -431,7 +436,7 @@ class DigitalBitbox_Client():
if 'error' in reply:
self.password = None
except Exception as e:
print_error('Exception caught ' + repr(e))
_logger.info(f'Exception caught {repr(e)}')
return reply
@@ -679,7 +684,7 @@ class DigitalBitbox_KeyStore(Hardware_KeyStore):
except BaseException as e:
self.give_error(e, True)
else:
print_error("Transaction is_complete", tx.is_complete())
_logger.info("Transaction is_complete {tx.is_complete()}")
tx.raw = tx.serialize()
@@ -746,7 +751,7 @@ class DigitalBitboxPlugin(HW_PluginBase):
)
try:
text = Network.send_http_on_proxy('post', url, body=args.encode('ascii'), headers={'content-type': 'application/x-www-form-urlencoded'})
print_error('digitalbitbox reply from server', text)
_logger.info(f'digitalbitbox reply from server {text}')
except Exception as e:
self.handler.show_error(repr(e)) # repr because str(Exception()) == ''

View File

@@ -41,19 +41,21 @@ from PyQt5.QtCore import QObject, pyqtSignal, QThread
from PyQt5.QtWidgets import (QVBoxLayout, QLabel, QGridLayout, QLineEdit,
QInputDialog)
from electrum.gui.qt.util import (EnterButton, Buttons, CloseButton, OkButton,
WindowModalDialog, get_parent_main_window)
from electrum.plugin import BasePlugin, hook
from electrum.paymentrequest import PaymentRequest
from electrum.i18n import _
from electrum.util import PrintError
from ...gui.qt.util import (EnterButton, Buttons, CloseButton, OkButton,
WindowModalDialog, get_parent_main_window)
from electrum.logging import Logger
class Processor(threading.Thread, PrintError):
class Processor(threading.Thread, Logger):
polling_interval = 5*60
def __init__(self, imap_server, username, password, callback):
threading.Thread.__init__(self)
Logger.__init__(self)
self.daemon = True
self.username = username
self.password = password
@@ -90,7 +92,7 @@ class Processor(threading.Thread, PrintError):
self.M = imaplib.IMAP4_SSL(self.imap_server)
self.M.login(self.username, self.password)
except BaseException as e:
self.print_error('connecting failed: {}'.format(repr(e)))
self.logger.info(f'connecting failed: {repr(e)}')
self.connect_wait *= 2
else:
self.reset_connect_wait()
@@ -99,7 +101,7 @@ class Processor(threading.Thread, PrintError):
try:
self.poll()
except BaseException as e:
self.print_error('polling failed: {}'.format(repr(e)))
self.logger.info(f'polling failed: {repr(e)}')
break
time.sleep(self.polling_interval)
time.sleep(random.randint(0, self.connect_wait))
@@ -120,7 +122,7 @@ class Processor(threading.Thread, PrintError):
s.sendmail(self.username, [recipient], msg.as_string())
s.quit()
except BaseException as e:
self.print_error(e)
self.logger.info(e)
class QEmailSignalObject(QObject):
@@ -151,7 +153,7 @@ class Plugin(BasePlugin):
self.wallets = set()
def on_receive(self, pr_str):
self.print_error('received payment request')
self.logger.info('received payment request')
self.pr = PaymentRequest(pr_str)
self.obj.email_new_invoice_signal.emit()
@@ -188,12 +190,12 @@ class Plugin(BasePlugin):
return
recipient = str(recipient)
payload = pr.SerializeToString()
self.print_error('sending mail to', recipient)
self.logger.info(f'sending mail to {recipient}')
try:
# FIXME this runs in the GUI thread and blocks it...
self.processor.send(recipient, message, payload)
except BaseException as e:
traceback.print_exc(file=sys.stderr)
self.logger.exception('')
window.show_message(str(e))
else:
window.show_message(_('Request sent.'))

View File

@@ -105,8 +105,7 @@ class Plugin(BasePlugin):
else:
d.show_warning(_('{} is not covered by GreenAddress instant confirmation').format(tx.txid()), title=_('Verification failed!'))
except BaseException as e:
import traceback
traceback.print_exc(file=sys.stdout)
self.logger.exception('')
d.show_error(str(e))
finally:
d.verify_button.setText(self.button_label)

View File

@@ -1,4 +1,8 @@
from electrum.util import print_error, print_stderr, raw_input
from electrum.util import print_stderr, raw_input
from electrum.logging import get_logger
_logger = get_logger(__name__)
class CmdLineHandler:
@@ -40,7 +44,7 @@ class CmdLineHandler:
print_stderr(msg)
def update_status(self, b):
print_error('hw device status', b)
_logger.info(f'hw device status {b}')
def finished(self):
pass

View File

@@ -111,7 +111,7 @@ class HW_PluginBase(BasePlugin):
_("Library version for '{}' is incompatible.").format(self.name)
+ '\nInstalled: {}, Needed: {} <= x < {}'
.format(library_version, version_str(self.minimum_library), max_version_str))
self.print_stderr(self.libraries_available_message)
self.logger.warning(self.libraries_available_message)
return False
return True

View File

@@ -35,11 +35,12 @@ from electrum.gui.qt.util import (read_QIcon, WWLabel, OkButton, WindowModalDial
Buttons, CancelButton, TaskThread)
from electrum.i18n import _
from electrum.util import PrintError
from electrum.logging import Logger
# The trickiest thing about this handler was getting windows properly
# parented on macOS.
class QtHandlerBase(QObject, PrintError):
class QtHandlerBase(QObject, Logger):
'''An interface between the GUI (here, QT) and the device handling
logic for handling I/O.'''
@@ -53,7 +54,8 @@ class QtHandlerBase(QObject, PrintError):
status_signal = pyqtSignal(object)
def __init__(self, win, device):
super(QtHandlerBase, self).__init__()
QObject.__init__(self)
Logger.__init__(self)
self.clear_signal.connect(self.clear_dialog)
self.error_signal.connect(self.error_dialog)
self.message_signal.connect(self.message_dialog)

View File

@@ -3,9 +3,10 @@ from struct import pack
from electrum import ecc
from electrum.i18n import _
from electrum.util import PrintError, UserCancelled
from electrum.util import UserCancelled
from electrum.keystore import bip39_normalize_passphrase
from electrum.bip32 import BIP32Node, convert_bip32_path_to_list_of_uint32
from electrum.logging import Logger
class GuiMixin(object):
@@ -93,7 +94,7 @@ class GuiMixin(object):
return self.proto.CharacterAck(**char_info)
class KeepKeyClientBase(GuiMixin, PrintError):
class KeepKeyClientBase(GuiMixin, Logger):
def __init__(self, handler, plugin, proto):
assert hasattr(self, 'tx_api') # ProtocolMixin already constructed?
@@ -104,6 +105,7 @@ class KeepKeyClientBase(GuiMixin, PrintError):
self.types = plugin.types
self.msg = None
self.creating_wallet = False
Logger.__init__(self)
self.used()
def __str__(self):
@@ -137,7 +139,7 @@ class KeepKeyClientBase(GuiMixin, PrintError):
def timeout(self, cutoff):
'''Time out the client if the last operation was before cutoff.'''
if self.last_operation < cutoff:
self.print_error("timed out")
self.logger.info("timed out")
self.clear_session()
@staticmethod
@@ -190,13 +192,13 @@ class KeepKeyClientBase(GuiMixin, PrintError):
def clear_session(self):
'''Clear the session to force pin (and passphrase if enabled)
re-entry. Does not leak exceptions.'''
self.print_error("clear session:", self)
self.logger.info(f"clear session: {self}")
self.prevent_timeouts()
try:
super(KeepKeyClientBase, self).clear_session()
except BaseException as e:
# If the device was removed it has the same effect...
self.print_error("clear_session: ignoring error", str(e))
self.logger.info(f"clear_session: ignoring error {e}")
def get_public_node(self, address_n, creating):
self.creating_wallet = creating
@@ -204,7 +206,7 @@ class KeepKeyClientBase(GuiMixin, PrintError):
def close(self):
'''Called when Our wallet was closed or the device removed.'''
self.print_error("closing client")
self.logger.info("closing client")
self.clear_session()
# Release the device
self.transport.close()

View File

@@ -108,7 +108,7 @@ class KeepKeyPlugin(HW_PluginBase):
return WebUsbTransport(device)
def _try_hid(self, device):
self.print_error("Trying to connect over USB...")
self.logger.info("Trying to connect over USB...")
if device.interface_number == 1:
pair = [None, device.path]
else:
@@ -119,15 +119,15 @@ class KeepKeyPlugin(HW_PluginBase):
except BaseException as e:
# see fdb810ba622dc7dbe1259cbafb5b28e19d2ab114
# raise
self.print_error("cannot connect at", device.path, str(e))
self.logger.info(f"cannot connect at {device.path} {e}")
return None
def _try_webusb(self, device):
self.print_error("Trying to connect over WebUSB...")
self.logger.info("Trying to connect over WebUSB...")
try:
return self.webusb_transport(device)
except BaseException as e:
self.print_error("cannot connect at", device.path, str(e))
self.logger.info(f"cannot connect at {device.path} {e}")
return None
def create_client(self, device, handler):
@@ -137,10 +137,10 @@ class KeepKeyPlugin(HW_PluginBase):
transport = self._try_hid(device)
if not transport:
self.print_error("cannot connect to device")
self.logger.info("cannot connect to device")
return
self.print_error("connected to device at", device.path)
self.logger.info(f"connected to device at {device.path}")
client = self.client_class(transport, handler, self)
@@ -148,14 +148,14 @@ class KeepKeyPlugin(HW_PluginBase):
try:
client.ping('t')
except BaseException as e:
self.print_error("ping failed", str(e))
self.logger.info(f"ping failed {e}")
return None
if not client.atleast_version(*self.minimum_firmware):
msg = (_('Outdated {} firmware for device labelled {}. Please '
'download the updated firmware from {}')
.format(self.device, client.label(), self.firmware_URL))
self.print_error(msg)
self.logger.info(msg)
if handler:
handler.show_error(msg)
else:
@@ -215,7 +215,7 @@ class KeepKeyPlugin(HW_PluginBase):
except UserCancelled:
exit_code = 1
except BaseException as e:
traceback.print_exc(file=sys.stderr)
self.logger.exception('')
handler.show_error(str(e))
exit_code = 1
finally:

View File

@@ -8,4 +8,4 @@ class Plugin(LabelsPlugin):
self.start_wallet(wallet)
def on_pulled(self, wallet):
self.print_error('labels pulled from server')
self.logger.info('labels pulled from server')

View File

@@ -9,6 +9,6 @@ class Plugin(LabelsPlugin):
self.start_wallet(wallet)
def on_pulled(self, wallet):
self.print_error('on pulled')
self.logger.info('on pulled')
self.window._trigger_update_history()

View File

@@ -53,7 +53,7 @@ class LabelsPlugin(BasePlugin):
return nonce
def set_nonce(self, wallet, nonce):
self.print_error("set", wallet.basename(), "nonce to", nonce)
self.logger.info(f"set {wallet.basename()} nonce to {nonce}")
wallet.storage.put("wallet_nonce", nonce)
@hook
@@ -109,7 +109,7 @@ class LabelsPlugin(BasePlugin):
encoded_key = self.encode(wallet, key)
encoded_value = self.encode(wallet, value)
except:
self.print_error('cannot encode', repr(key), repr(value))
self.logger.info(f'cannot encode {repr(key)} {repr(value)}')
continue
bundle["labels"].append({'encryptedLabel': encoded_value,
'externalId': encoded_key})
@@ -121,13 +121,13 @@ class LabelsPlugin(BasePlugin):
raise Exception('Wallet {} not loaded'.format(wallet))
wallet_id = wallet_data[2]
nonce = 1 if force else self.get_nonce(wallet) - 1
self.print_error("asking for labels since nonce", nonce)
self.logger.info(f"asking for labels since nonce {nonce}")
try:
response = await self.do_get("/labels/since/%d/for/%s" % (nonce, wallet_id))
except Exception as e:
raise ErrorConnectingServer(e) from e
if response["labels"] is None:
self.print_error('no new labels')
self.logger.info('no new labels')
return
result = {}
for label in response["labels"]:
@@ -140,7 +140,7 @@ class LabelsPlugin(BasePlugin):
json.dumps(key)
json.dumps(value)
except:
self.print_error('error: no json', key)
self.logger.info(f'error: no json {key}')
continue
result[key] = value
@@ -148,7 +148,7 @@ class LabelsPlugin(BasePlugin):
if force or not wallet.labels.get(key):
wallet.labels[key] = value
self.print_error("received %d labels" % len(response))
self.logger.info(f"received {len(response)} labels")
# do not write to disk because we're in a daemon thread
wallet.storage.put('labels', wallet.labels)
self.set_nonce(wallet, response["nonce"] + 1)
@@ -160,7 +160,7 @@ class LabelsPlugin(BasePlugin):
try:
await self.pull_thread(wallet, force)
except ErrorConnectingServer as e:
self.print_error(str(e))
self.logger.info(str(e))
def pull(self, wallet, force):
if not wallet.network: raise Exception(_('You are offline.'))
@@ -173,7 +173,7 @@ class LabelsPlugin(BasePlugin):
def start_wallet(self, wallet):
if not wallet.network: return # 'offline' mode
nonce = self.get_nonce(wallet)
self.print_error("wallet", wallet.basename(), "nonce is", nonce)
self.logger.info(f"wallet {wallet.basename()} nonce is {nonce}")
mpk = wallet.get_fingerprint()
if not mpk:
return

View File

@@ -58,9 +58,9 @@ class Plugin(LabelsPlugin):
def done_processing_success(self, dialog, result):
dialog.show_message(_("Your labels have been synchronised."))
def done_processing_error(self, dialog, result):
traceback.print_exception(*result, file=sys.stderr)
dialog.show_error(_("Error synchronising labels") + ':\n' + str(result[:2]))
def done_processing_error(self, dialog, exc_info):
self.logger.error("Error synchronising labels", exc_info=exc_info)
dialog.show_error(_("Error synchronising labels") + f':\n{repr(exc_info[1])}')
@hook
def load_wallet(self, wallet, window):

View File

@@ -13,10 +13,13 @@ from PyQt5.QtCore import QThread, pyqtSignal
from btchip.btchip import BTChipException
from electrum.i18n import _
from electrum.util import print_msg
from electrum import constants, bitcoin
from electrum.gui.qt.qrcodewidget import QRCodeWidget
from electrum.i18n import _
from electrum import constants, bitcoin
from electrum.logging import get_logger
_logger = get_logger(__name__)
DEBUG = False
@@ -354,4 +357,5 @@ class LedgerWebSocket(QThread):
def debug_msg(*args):
if DEBUG:
print_msg(*args)
str_ = " ".join([str(item) for item in args])
_logger.debug(str_)

View File

@@ -10,12 +10,17 @@ from electrum.i18n import _
from electrum.keystore import Hardware_KeyStore
from electrum.transaction import Transaction
from electrum.wallet import Standard_Wallet
from electrum.util import print_error, bfh, bh2u, versiontuple, UserFacingException
from electrum.util import bfh, bh2u, versiontuple, UserFacingException
from electrum.base_wizard import ScriptTypeNotSupported
from electrum.logging import get_logger
from ..hw_wallet import HW_PluginBase
from ..hw_wallet.plugin import is_any_tx_output_on_change_branch
_logger = get_logger(__name__)
try:
import hid
from btchip.btchipComm import HIDDongleHIDAPI, DongleWait
@@ -236,7 +241,7 @@ class Ledger_KeyStore(Hardware_KeyStore):
return self.plugin.get_client(self)
def give_error(self, message, clear_client = False):
print_error(message)
_logger.info(message)
if not self.signing:
self.handler.show_error(message)
else:
@@ -499,10 +504,10 @@ class Ledger_KeyStore(Hardware_KeyStore):
elif e.sw == 0x6982:
raise # pin lock. decorator will catch it
else:
traceback.print_exc(file=sys.stderr)
self.logger.exception('')
self.give_error(e, True)
except BaseException as e:
traceback.print_exc(file=sys.stdout)
self.logger.exception('')
self.give_error(e, True)
finally:
self.handler.finished()
@@ -533,10 +538,10 @@ class Ledger_KeyStore(Hardware_KeyStore):
e,
_('Your device might not have support for this functionality.')))
else:
traceback.print_exc(file=sys.stderr)
self.logger.exception('')
self.handler.show_error(e)
except BaseException as e:
traceback.print_exc(file=sys.stderr)
self.logger.exception('')
self.handler.show_error(e)
finally:
self.handler.finished()

View File

@@ -137,7 +137,7 @@ class Plugin(RevealerPlugin):
try:
self.make_digital(self.d)
except Exception:
traceback.print_exc(file=sys.stdout)
self.logger.exception('')
else:
self.cypherseed_dialog(window)

View File

@@ -3,9 +3,10 @@ from struct import pack
from electrum import ecc
from electrum.i18n import _
from electrum.util import PrintError, UserCancelled
from electrum.util import UserCancelled
from electrum.keystore import bip39_normalize_passphrase
from electrum.bip32 import BIP32Node, convert_bip32_path_to_list_of_uint32
from electrum.logging import Logger
class GuiMixin(object):
@@ -95,7 +96,7 @@ class GuiMixin(object):
return self.proto.WordAck(word=word)
class SafeTClientBase(GuiMixin, PrintError):
class SafeTClientBase(GuiMixin, Logger):
def __init__(self, handler, plugin, proto):
assert hasattr(self, 'tx_api') # ProtocolMixin already constructed?
@@ -106,6 +107,7 @@ class SafeTClientBase(GuiMixin, PrintError):
self.types = plugin.types
self.msg = None
self.creating_wallet = False
Logger.__init__(self)
self.used()
def __str__(self):
@@ -139,7 +141,7 @@ class SafeTClientBase(GuiMixin, PrintError):
def timeout(self, cutoff):
'''Time out the client if the last operation was before cutoff.'''
if self.last_operation < cutoff:
self.print_error("timed out")
self.logger.info("timed out")
self.clear_session()
@staticmethod
@@ -192,13 +194,13 @@ class SafeTClientBase(GuiMixin, PrintError):
def clear_session(self):
'''Clear the session to force pin (and passphrase if enabled)
re-entry. Does not leak exceptions.'''
self.print_error("clear session:", self)
self.logger.info(f"clear session: {self}")
self.prevent_timeouts()
try:
super(SafeTClientBase, self).clear_session()
except BaseException as e:
# If the device was removed it has the same effect...
self.print_error("clear_session: ignoring error", str(e))
self.logger.info(f"clear_session: ignoring error {e}")
def get_public_node(self, address_n, creating):
self.creating_wallet = creating
@@ -206,7 +208,7 @@ class SafeTClientBase(GuiMixin, PrintError):
def close(self):
'''Called when Our wallet was closed or the device removed.'''
self.print_error("closing client")
self.logger.info("closing client")
self.clear_session()
# Release the device
self.transport.close()

View File

@@ -115,31 +115,31 @@ class SafeTPlugin(HW_PluginBase):
def create_client(self, device, handler):
try:
self.print_error("connecting to device at", device.path)
self.logger.info(f"connecting to device at {device.path}")
transport = self.transport_handler.get_transport(device.path)
except BaseException as e:
self.print_error("cannot connect at", device.path, str(e))
self.logger.info(f"cannot connect at {device.path} {e}")
return None
if not transport:
self.print_error("cannot connect at", device.path)
self.logger.info(f"cannot connect at {device.path}")
return
self.print_error("connected to device at", device.path)
self.logger.info(f"connected to device at {device.path}")
client = self.client_class(transport, handler, self)
# Try a ping for device sanity
try:
client.ping('t')
except BaseException as e:
self.print_error("ping failed", str(e))
self.logger.info(f"ping failed {e}")
return None
if not client.atleast_version(*self.minimum_firmware):
msg = (_('Outdated {} firmware for device labelled {}. Please '
'download the updated firmware from {}')
.format(self.device, client.label(), self.firmware_URL))
self.print_error(msg)
self.logger.info(msg)
if handler:
handler.show_error(msg)
else:
@@ -199,7 +199,7 @@ class SafeTPlugin(HW_PluginBase):
except UserCancelled:
exit_code = 1
except BaseException as e:
traceback.print_exc(file=sys.stderr)
self.logger.exception('')
handler.show_error(str(e))
exit_code = 1
finally:

View File

@@ -1,7 +1,10 @@
from electrum.util import PrintError
from electrum.logging import get_logger
class SafeTTransport(PrintError):
_logger = get_logger(__name__)
class SafeTTransport:
@staticmethod
def all_transports():
@@ -71,8 +74,7 @@ class SafeTTransport(PrintError):
try:
new_devices = transport.enumerate()
except BaseException as e:
self.print_error('enumerate failed for {}. error {}'
.format(transport.__name__, str(e)))
_logger.info(f'enumerate failed for {transport.__name__}. error {e}')
else:
devices.extend(new_devices)
return devices

View File

@@ -3,9 +3,10 @@ from struct import pack
from electrum import ecc
from electrum.i18n import _
from electrum.util import PrintError, UserCancelled, UserFacingException
from electrum.util import UserCancelled, UserFacingException
from electrum.keystore import bip39_normalize_passphrase
from electrum.bip32 import BIP32Node, convert_bip32_path_to_list_of_uint32 as parse_path
from electrum.logging import Logger
from trezorlib.client import TrezorClient
from trezorlib.exceptions import TrezorFailure, Cancelled, OutdatedFirmwareError
@@ -26,12 +27,13 @@ MESSAGES = {
}
class TrezorClientBase(PrintError):
class TrezorClientBase(Logger):
def __init__(self, transport, handler, plugin):
self.client = TrezorClient(transport, ui=self)
self.plugin = plugin
self.device = plugin.device
self.handler = handler
Logger.__init__(self)
self.msg = None
self.creating_wallet = False
@@ -111,7 +113,7 @@ class TrezorClientBase(PrintError):
def timeout(self, cutoff):
'''Time out the client if the last operation was before cutoff.'''
if self.last_operation < cutoff:
self.print_error("timed out")
self.logger.info("timed out")
self.clear_session()
def i4b(self, x):
@@ -158,17 +160,17 @@ class TrezorClientBase(PrintError):
def clear_session(self):
'''Clear the session to force pin (and passphrase if enabled)
re-entry. Does not leak exceptions.'''
self.print_error("clear session:", self)
self.logger.info(f"clear session: {self}")
self.prevent_timeouts()
try:
self.client.clear_session()
except BaseException as e:
# If the device was removed it has the same effect...
self.print_error("clear_session: ignoring error", str(e))
self.logger.info(f"clear_session: ignoring error {e}")
def close(self):
'''Called when Our wallet was closed or the device removed.'''
self.print_error("closing client")
self.logger.info("closing client")
self.clear_session()
def is_uptodate(self):

View File

@@ -11,11 +11,15 @@ from electrum.plugin import Device
from electrum.transaction import deserialize, Transaction
from electrum.keystore import Hardware_KeyStore, is_xpubkey, parse_xpubkey
from electrum.base_wizard import ScriptTypeNotSupported, HWD_SETUP_NEW_WALLET
from electrum.logging import get_logger
from ..hw_wallet import HW_PluginBase
from ..hw_wallet.plugin import (is_any_tx_output_on_change_branch, trezor_validate_op_return_output_and_get_data,
LibraryFoundButUnusable)
_logger = get_logger(__name__)
try:
import trezorlib
import trezorlib.transport
@@ -32,8 +36,7 @@ try:
TREZORLIB = True
except Exception as e:
import traceback
traceback.print_exc()
_logger.exception('error importing trezorlib')
TREZORLIB = False
RECOVERY_TYPE_SCRAMBLED_WORDS, RECOVERY_TYPE_MATRIX = range(2)
@@ -145,17 +148,17 @@ class TrezorPlugin(HW_PluginBase):
def create_client(self, device, handler):
try:
self.print_error("connecting to device at", device.path)
self.logger.info(f"connecting to device at {device.path}")
transport = trezorlib.transport.get_transport(device.path)
except BaseException as e:
self.print_error("cannot connect at", device.path, str(e))
self.logger.info(f"cannot connect at {device.path} {e}")
return None
if not transport:
self.print_error("cannot connect at", device.path)
self.logger.info(f"cannot connect at {device.path}")
return
self.print_error("connected to device at", device.path)
self.logger.info(f"connected to device at {device.path}")
# note that this call can still raise!
return TrezorClientBase(transport, handler, self)
@@ -208,7 +211,7 @@ class TrezorPlugin(HW_PluginBase):
except UserCancelled:
exit_code = 1
except BaseException as e:
traceback.print_exc(file=sys.stderr)
self.logger.exception('')
handler.show_error(str(e))
exit_code = 1
finally:

View File

@@ -34,12 +34,12 @@ class Plugin(TrustedCoinPlugin):
if not isinstance(wallet, self.wallet_class):
return
if not wallet.can_sign_without_server():
self.print_error("twofactor:sign_tx")
self.logger.info("twofactor:sign_tx")
auth_code = None
if wallet.keystores['x3/'].get_tx_derivations(tx):
msg = _('Please enter your Google Authenticator code:')
auth_code = int(input(msg))
else:
self.print_error("twofactor: xpub3 not needed")
self.logger.info("twofactor: xpub3 not needed")
wallet.auth_code = auth_code

View File

@@ -41,7 +41,9 @@ from electrum.gui.qt.main_window import StatusBarButton
from electrum.gui.qt.installwizard import InstallWizard
from electrum.i18n import _
from electrum.plugin import hook
from electrum.util import PrintError, is_valid_email
from electrum.util import is_valid_email
from electrum.logging import Logger
from .trustedcoin import TrustedCoinPlugin, server
@@ -50,12 +52,13 @@ class TOS(QTextEdit):
error_signal = pyqtSignal(object)
class HandlerTwoFactor(QObject, PrintError):
class HandlerTwoFactor(QObject, Logger):
def __init__(self, plugin, window):
super().__init__()
QObject.__init__(self)
self.plugin = plugin
self.window = window
Logger.__init__(self)
def prompt_user_for_otp(self, wallet, tx, on_success, on_failure):
if not isinstance(wallet, self.plugin.wallet_class):
@@ -63,7 +66,7 @@ class HandlerTwoFactor(QObject, PrintError):
if wallet.can_sign_without_server():
return
if not wallet.keystores['x3/'].get_tx_derivations(tx):
self.print_error("twofactor: xpub3 not needed")
self.logger.info("twofactor: xpub3 not needed")
return
window = self.window.top_level_window()
auth_code = self.plugin.auth_dialog(window)
@@ -243,8 +246,7 @@ class Plugin(TrustedCoinPlugin):
try:
tos = server.get_terms_of_service()
except Exception as e:
import traceback
traceback.print_exc(file=sys.stderr)
self.logger.exception('Could not retrieve Terms of Service')
tos_e.error_signal.emit(_('Could not retrieve Terms of Service:')
+ '\n' + str(e))
return

View File

@@ -37,17 +37,19 @@ from aiohttp import ClientResponse
from electrum import ecc, constants, keystore, version, bip32, bitcoin
from electrum.bitcoin import TYPE_ADDRESS
from electrum.bip32 import CKD_pub, BIP32Node, xpub_type
from electrum.bip32 import BIP32Node, xpub_type
from electrum.crypto import sha256
from electrum.transaction import TxOutput
from electrum.mnemonic import Mnemonic, seed_type, is_any_2fa_seed_type
from electrum.wallet import Multisig_Wallet, Deterministic_Wallet
from electrum.i18n import _
from electrum.plugin import BasePlugin, hook
from electrum.util import NotEnoughFunds, UserFacingException, PrintError
from electrum.util import NotEnoughFunds, UserFacingException
from electrum.storage import STO_EV_USER_PW
from electrum.network import Network
from electrum.base_wizard import BaseWizard
from electrum.logging import Logger
def get_signing_xpub(xtype):
if not constants.net.TESTNET:
@@ -117,11 +119,12 @@ class ErrorConnectingServer(Exception):
return f"{header}:\n{reason}" if reason else header
class TrustedCoinCosignerClient(PrintError):
class TrustedCoinCosignerClient(Logger):
def __init__(self, user_agent=None, base_url='https://api.trustedcoin.com/2/'):
self.base_url = base_url
self.debug = False
self.user_agent = user_agent
Logger.__init__(self)
async def handle_response(self, resp: ClientResponse):
if resp.status != 200:
@@ -142,7 +145,7 @@ class TrustedCoinCosignerClient(PrintError):
raise ErrorConnectingServer('You are offline.')
url = urljoin(self.base_url, relative_url)
if self.debug:
self.print_error(f'<-- {method} {url} {data}')
self.logger.debug(f'<-- {method} {url} {data}')
headers = {}
if self.user_agent:
headers['user-agent'] = self.user_agent
@@ -167,7 +170,7 @@ class TrustedCoinCosignerClient(PrintError):
raise ErrorConnectingServer(e)
else:
if self.debug:
self.print_error(f'--> {response}')
self.logger.debug(f'--> {response}')
return response
def get_terms_of_service(self, billing_plan='electrum-per-tx-otp'):
@@ -327,14 +330,14 @@ class Wallet_2fa(Multisig_Wallet):
tx = mk_tx(outputs)
if tx.input_value() >= fee:
raise
self.print_error("not charging for this tx")
self.logger.info("not charging for this tx")
else:
tx = mk_tx(outputs)
return tx
def on_otp(self, tx, otp):
if not otp:
self.print_error("sign_transaction: no auth code")
self.logger.info("sign_transaction: no auth code")
return
otp = int(otp)
long_user_id, short_id = self.get_user_id()
@@ -349,7 +352,7 @@ class Wallet_2fa(Multisig_Wallet):
if r:
raw_tx = r.get('transaction')
tx.update(raw_tx)
self.print_error("twofactor: is complete", tx.is_complete())
self.logger.info(f"twofactor: is complete {tx.is_complete()}")
# reset billing_info
self.billing_info = None
self.plugin.start_request_thread(self)
@@ -451,7 +454,7 @@ class TrustedCoinPlugin(BasePlugin):
if wallet.can_sign_without_server():
return
if not wallet.keystores['x3/'].get_tx_derivations(tx):
self.print_error("twofactor: xpub3 not needed")
self.logger.info("twofactor: xpub3 not needed")
return
def wrapper(tx):
self.prompt_user_for_otp(wallet, tx, on_success, on_failure)
@@ -477,12 +480,12 @@ class TrustedCoinPlugin(BasePlugin):
def request_billing_info(self, wallet: 'Wallet_2fa', *, suppress_connection_error=True):
if wallet.can_sign_without_server():
return
self.print_error("request billing info")
self.logger.info("request billing info")
try:
billing_info = server.get(wallet.get_user_id()[1])
except ErrorConnectingServer as e:
if suppress_connection_error:
self.print_error(str(e))
self.logger.info(str(e))
return
raise
billing_index = billing_info['billing_index']