Пример #1
0
import time
from typing import List, Optional

import requests
from bitcoinx import Headers, MissingHeader, CheckPoint, bits_to_work, P2PKH_Address, \
    hash_to_hex_str
from urllib3.exceptions import NewConnectionError

from electrumsv.bitcoin import COINBASE_MATURITY

from electrumsv.networks import Net, BLOCK_HEIGHT_OUT_OF_RANGE_ERROR
from electrumsv.logs import logs

MAX_BITS = 0x1d00ffff

logger = logs.get_logger("app_state")

# Makes this code docker-friendly (can access a node on host with "host.docker.internal"
BITCOIN_NODE_HOST = os.environ.get("BITCOIN_NODE_HOST") or "127.0.0.1"
BITCOIN_NODE_PORT = os.environ.get("BITCOIN_NODE_PORT") or 18332
BITCOIN_NODE_RPCUSER = os.environ.get("BITCOIN_NODE_RPCUSER") or "rpcuser"
BITCOIN_NODE_RPCPASSWORD = os.environ.get("BITCOIN_NODE_RPCPASSWORD") or "rpcpassword"
BITCOIN_NODE_URI = f"http://{BITCOIN_NODE_RPCUSER}:{BITCOIN_NODE_RPCPASSWORD}" \
                   f"@{BITCOIN_NODE_HOST}:{BITCOIN_NODE_PORT}"


class HeadersRegTestMod(Headers):

    def connect(self, raw_header):
        """overwrite Headers method to skip checking of difficulty target"""
        header = self.coin.deserialized_header(raw_header, -1)
Пример #2
0
from PyQt5.QtGui import QDesktopServices
from PyQt5.QtWidgets import (QWidget, QGridLayout, QLabel, QPushButton,
                             QHBoxLayout, QVBoxLayout, QProgressDialog)
from bitcoinx import TxOutput

from electrumsv.app_state import app_state
from electrumsv.constants import ADDRESSABLE_SCRIPT_TYPES, RECEIVING_SUBPATH
from electrumsv.i18n import _
from electrumsv.logs import logs
from electrumsv.networks import Net
from electrumsv.wallet import AbstractAccount

from .main_window import ElectrumWindow
from . import util

logger = logs.get_logger("coinsplitting")

TX_DESC_PREFIX = _("ElectrumSV coin splitting")

RESULT_DUST_TIMEOUT = -2
RESULT_DIALOG_CLOSED = -1
RESULT_READY_FOR_SPLIT = 0

STAGE_INACTIVE = -1
STAGE_PREPARING = 0
STAGE_OBTAINING_DUST = 1
STAGE_SPLITTING = 2

STAGE_NAMES = {
    STAGE_INACTIVE: _("Inactive") + ".",
    STAGE_PREPARING: _("Preparing") + "..",
Пример #3
0
    QDialog, QVBoxLayout, QLabel, QPushButton, QHBoxLayout, QTextEdit, QToolTip
)

from bitcoinx import PublicKey, Address, hash_to_hex_str

from electrumsv.app_state import app_state
from electrumsv.bitcoin import base_encode
from electrumsv.i18n import _
from electrumsv.logs import logs
from electrumsv.platform import platform
from electrumsv.transaction import tx_output_to_display_text
from electrumsv.util import bfh
from .util import MessageBoxMixin, ButtonsLineEdit, Buttons, ColorScheme, read_QIcon


logger = logs.get_logger("tx_dialog")


class TxDialog(QDialog, MessageBoxMixin):

    def __init__(self, tx, parent, desc, prompt_if_unsaved):
        '''Transactions in the wallet will show their description.
        Pass desc to give a description for txs not yet in the wallet.
        '''
        # We want to be a top-level window
        QDialog.__init__(self, parent=None)
        # Take a copy; it might get updated in the main window by the FX thread.  If this
        # happens during or after a long sign operation the signatures are lost.
        self.tx = copy.deepcopy(tx)
        self.main_window = parent
        self.parent_wallet = parent.parent_wallet
Пример #4
0
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
'''Platform-specific customization for ElectrumSV'''

import os
import platform
import sys

from electrumsv.i18n import _
from electrumsv.logs import logs

logger = logs.get_logger("platform")


class Platform(object):

    module_map = {
        'PyQt5': 'PyQt5',
        'SimpleWebSocketServer': 'SimpleWebSocketServer',
        'dns': 'dnspython',
        'ecdsa': 'ecdsa',
        'jsonrpclib': 'jsonrpclib-pelix',
        'protobuf': 'protobuf',
        'pyaes': 'pyaes',
        'qrcode': 'qrcode',
        'requests': 'requests',
        'socks': 'PySocks',
Пример #5
0
                             QGridLayout, QLineEdit, QCheckBox, QLabel,
                             QComboBox, QSizePolicy)

from aiorpcx import NetAddress
from bitcoinx import hash_to_hex_str

from electrumsv.app_state import app_state
from electrumsv.i18n import _
from electrumsv.logs import logs
from electrumsv.network import SVServer, SVProxy, SVUserAuth
from electrumsv.networks import Net

from .password_dialog import PasswordLineEdit
from .util import Buttons, CloseButton, HelpButton, read_QIcon, MessageBox

logger = logs.get_logger("networkui")


class NetworkDialog(QDialog):
    network_updated_signal = pyqtSignal()

    def __init__(self, network, config):
        QDialog.__init__(self)
        self.setWindowTitle(_('Network'))
        self.setMinimumSize(500, 200)
        self.resize(560, 400)
        self.nlayout = NetworkChoiceLayout(network, config)
        vbox = QVBoxLayout(self)
        vbox.setSizeConstraint(QVBoxLayout.SetFixedSize)
        vbox.addLayout(self.nlayout.layout())
        vbox.addLayout(Buttons(CloseButton(self)))
Пример #6
0
from electrumsv.app_state import app_state
from electrumsv.constants import DATABASE_EXT, IntFlag, StorageKind
from electrumsv.exceptions import DatabaseMigrationError, IncompatibleWalletError
from electrumsv.i18n import _
from electrumsv.logs import logs
from electrumsv.storage import WalletStorage, categorise_file
from electrumsv.util import get_wallet_name_from_path, read_resource_text
from electrumsv.version import PACKAGE_VERSION
from electrumsv.wallet import Wallet

from .util import (AspectRatioPixmapLabel, can_show_in_file_explorer,
                   create_new_wallet, icon_path, MessageBox,
                   show_in_file_explorer)
from .wizard_common import BaseWizard, HelpContext

logger = logs.get_logger('wizard-wallet')

PASSWORD_MISSING_TEXT = _(
    "This wallet is an older format that does not have a password. To "
    "be able to import it, you need to provide a password so that key data can be "
    "secured.")
PASSWORD_NEW_TEXT = _(
    "Your password only encrypts your private keys and other essential data, "
    "only your choice of location secures the privacy of the rest of your wallet data."
)
PASSWORD_EXISTING_TEXT = _(
    "Your wallet has a password, you will need to provide that password "
    "in order to access it. You will also be asked to provide it later, when your permission "
    "is needed for secure operations.")

PASSWORD_REQUEST_TEXT = _(
Пример #7
0
from struct import pack
import time

from electrumsv.bip32 import bip32_path_to_uints, serialize_xpub
from electrumsv.exceptions import UserCancelled
from electrumsv.i18n import _
from electrumsv.keystore import bip39_normalize_passphrase
from electrumsv.logs import logs

from trezorlib.client import TrezorClient
from trezorlib.exceptions import TrezorFailure, Cancelled, OutdatedFirmwareError
from trezorlib.messages import WordRequestType, RecoveryDeviceType
import trezorlib.btc
import trezorlib.device

logger = logs.get_logger("plugin.trezor")

MESSAGES = {
    3:
    _("Confirm the transaction output on your {} device"),
    4:
    _("Confirm internal entropy on your {} device to begin"),
    5:
    _("Write down the seed word shown on your {}"),
    6:
    _("Confirm on your {} that you want to wipe it clean"),
    7:
    _("Confirm on your {} device the message to sign"),
    8:
    _("Confirm the total amount spent and the transaction fee on your {} device"
      ),
Пример #8
0
import os
import re
import sys
import traceback

from PyQt5 import QtCore, QtWidgets
from PyQt5.QtGui import QFont, QTextCursor, QTextOption

from electrumsv import util
from electrumsv.i18n import _
from electrumsv.logs import logs
from electrumsv.platform import platform


logger = logs.get_logger("console")


class OverlayLabel(QtWidgets.QLabel):
    STYLESHEET = '''
    QLabel, QLabel link {
        color: rgb(0, 0, 0);
        background-color: rgb(248, 240, 200);
        border: 1px solid;
        border-color: rgb(255, 114, 47);
        padding: 2px;
    }
    '''

    def __init__(self, text, parent):
        super().__init__(text, parent)
Пример #9
0
 def __init__(self, account: "AbstractAccount") -> None:
     self._account = weakref.proxy(account)
     self._logger = logs.get_logger("key-service")
Пример #10
0
    def __init__(self, parent: QWidget, main_window: ElectrumWindow) -> None:
        super().__init__(parent)

        self._main_window = weakref.proxy(main_window)
        self._logger = logs.get_logger("transaction-list")
        self._wallet = main_window._wallet
        self._account_id: Optional[int] = None
        self._account: Optional[AbstractAccount] = None
        self._update_lock = threading.Lock()

        self._invoice_icon = read_QIcon(ICON_NAME_INVOICE_PAYMENT)

        self._headers = COLUMN_NAMES

        self.verticalHeader().setVisible(False)
        self.setAlternatingRowColors(True)

        self._pending_state: Dict[bytes, EventFlags] = {}
        self._pending_actions = set([ ListActions.RESET ])

        self._main_window.transaction_state_signal.connect(self._on_transaction_state_change)
        self._main_window.transaction_added_signal.connect(self._on_transaction_added)
        self._main_window.transaction_deleted_signal.connect(self._on_transaction_deleted)
        self._main_window.account_change_signal.connect(self._on_account_changed)

        model = _ItemModel(self, self._headers)
        model.set_data([])
        self._base_model = model

        # If the underlying model changes, observe it in the sort.
        proxy_model = _SortFilterProxyModel()
        proxy_model.setDynamicSortFilter(True)
        proxy_model.setSortRole(QT_SORT_ROLE)
        proxy_model.setSourceModel(model)
        self.setModel(proxy_model)

        fx = app_state.fx
        self._set_fiat_columns_enabled(fx and fx.get_fiat_address_config())

        # Sort by type then by index, by making sure the initial sort is our type column.
        self.sortByColumn(DATE_ADDED_COLUMN, Qt.AscendingOrder)
        self.setSortingEnabled(True)

        self.horizontalHeader().setSectionResizeMode(LABEL_COLUMN, QHeaderView.Stretch)
        for i in range(FIAT_VALUE_COLUMN):
            if i != LABEL_COLUMN:
                self.horizontalHeader().setSectionResizeMode(i, QHeaderView.ResizeToContents)
        self.horizontalHeader().setMinimumSectionSize(20)

        verticalHeader = self.verticalHeader()
        verticalHeader.setSectionResizeMode(QHeaderView.Fixed)
        # This value will get pushed out if the contents are larger, so it does not have to be
        # correct, it just has to be minimal.
        lineHeight = QFontMetrics(app_state.app.font()).height()
        verticalHeader.setDefaultSectionSize(lineHeight)

        self.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        # New selections clear existing selections, unless the user holds down control.
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)

        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self._event_create_menu)

        app_state.app.base_unit_changed.connect(self._on_balance_display_change)
        app_state.app.fiat_balance_changed.connect(self._on_fiat_balance_display_change)
        app_state.app.fiat_ccy_changed.connect(self._on_fiat_balance_display_change)
        app_state.app.labels_changed_signal.connect(self.update_labels)
        app_state.app.num_zeros_changed.connect(self._on_balance_display_change)

        self.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.doubleClicked.connect(self._event_double_clicked)

        self._last_not_synced = 0
        self._timer = QTimer(self)
        self._timer.setSingleShot(False)
        self._timer.setInterval(1000)
        self._timer.timeout.connect(self._on_update_check)
Пример #11
0
 def __init__(self, device_kind):
     self.device = self.keystore_class.device
     self.name = device_kind
     self.logger = logs.get_logger(device_kind)
Пример #12
0
    from .qt import Ledger_Handler
    from electrumsv.wallet_database.tables import MasterKeyRow

try:
    import hid
    from btchip.btchipComm import HIDDongleHIDAPI
    from btchip.btchip import btchip
    from btchip.btchipUtils import compress_public_key
    from btchip.btchipFirmwareWizard import checkFirmware
    from btchip.btchipException import BTChipException
    BTCHIP = True
    BTCHIP_DEBUG = logs.is_debug_level()
except ImportError:
    BTCHIP = False

logger = logs.get_logger("plugin.ledger")

BITCOIN_CASH_SUPPORT = (1, 1, 8)


class YInput(NamedTuple):
    value: Optional[int]
    script_sig: bytes
    txin_xpub_idx: int
    sequence: int


class Ledger_Client():
    handler: 'Ledger_Handler'

    def __init__(self, hidDevice):
Пример #13
0
from PyQt5.QtCore import QAbstractItemModel, QModelIndex, QVariant, Qt, QSortFilterProxyModel
from PyQt5.QtGui import QFont, QBrush, QColor
from PyQt5.QtWidgets import QTableView, QAbstractItemView, QHeaderView, QMenu

from electrumsv.app_state import app_state
from electrumsv.i18n import _
from electrumsv.logs import logs
from electrumsv.platform import platform
from electrumsv.transaction import Transaction
from electrumsv.util import timestamp_to_datetime, profiler, format_time
from electrumsv.wallet import Abstract_Wallet
import electrumsv.web as web

from .util import read_QIcon, get_source_index

logger = logs.get_logger("history-list")

TX_ICONS = [
    "unconfirmed.png",
    "unconfirmed.png",
    "unconfirmed.png",
    "unconfirmed.png",
    "clock1.png",
    "clock2.png",
    "clock3.png",
    "clock4.png",
    "clock5.png",
    "confirmed.png",
]

TX_STATUS = [
Пример #14
0
MSG_BODY_UNSTABLE_AVAILABLE = (
    "<br/><br/>" +
    "The latest unstable release {unstable_version} was released on " +
    "{unstable_date:%Y/%m/%d %I:%M%p}.")
MSG_BODY_NO_SIGNEDS_AVAILABLE = (
    "<img src='" + icon_path("icons8-warning-shield-32.png") + "'/>" +
    "<br/><br/>" +
    "The update check located unverifiable release information.<br/><br/>" +
    "This either means the developers forgot to sign the release information, or the web site has "
    +
    "been compromised. If updates are identified by later update checks, this means that there "
    +
    "are valid releases available, otherwise it is advised you avoid updating."
)

logger = logs.get_logger("update_check.ui")


class UpdateCheckDialog(WindowModalDialog):
    _timer = None

    def __init__(self, parent: ElectrumWindow) -> None:
        super().__init__(parent, 'ElectrumSV - ' + _('Update Check'))

        self.resize(600, 400)

        widget: QWidget = read_qt_ui("updater_widget.ui")

        layout: QVBoxLayout = widget.findChild(QVBoxLayout, "vertical_layout")
        self._title_label: QLabel = widget.findChild(QLabel, "title_label")
        self._title_label.setText(_(MSG_TITLE_CHECK))
Пример #15
0
import copy
from typing import Dict, Any

from PyQt5.QtWidgets import QDialog, QTextEdit, QVBoxLayout, QLabel
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QComboBox
from btchip.btchip import BTChipException

from electrumsv.gui.qt.password_dialog import PasswordLineEdit
from electrumsv.i18n import _
from electrumsv.logs import logs

from .ledger import Ledger_KeyStore


logger = logs.get_logger("plugin.ledger.auth2fa")


helpTxt = [
    _("Your Ledger Wallet wants to tell you a one-time PIN code.<br><br>"
      "For best security you should unplug your device, open a text editor on another computer, "
      "put your cursor into it, and plug your device into that computer. "
      "It will output a summary of the transaction being signed and a one-time PIN.<br><br>"
      "Verify the transaction summary and type the PIN code here.<br><br>"
      "Before pressing enter, plug the device back into this computer.<br>" ),
    _("Verify the address below.<br>Type the character from your security card corresponding "
      "to the <u><b>BOLD</b></u> character."),
]

class LedgerAuthDialog(QDialog):
    def __init__(self, handler, keystore: Ledger_KeyStore, data: Dict[str, Any]):
        '''Ask user for 2nd factor authentication. Support text and security card methods.
Пример #16
0
    def __init__(self, parent: QWidget, wallet: Abstract_Wallet) -> None:
        super().__init__(parent)

        self._parent = parent
        self._wallet = wallet
        self._logger = logs.get_logger(f"address-list[{wallet.name()}]")
        self._update_lock = threading.Lock()
        self._is_synchronizing = False

        self._headers = COLUMN_NAMES

        self.verticalHeader().setVisible(False)
        self.setAlternatingRowColors(True)

        self._pending_state: Dict[Address, EventFlags] = {}
        self._pending_actions = set([ListActions.RESET])
        self._parent.addresses_created_signal.connect(
            self._on_addresses_created)
        self._parent.addresses_updated_signal.connect(
            self._on_addresses_updated)

        model = _ItemModel(self, self._headers)
        model.set_data([])
        self._base_model = model

        # If the underlying model changes, observe it in the sort.
        proxy_model = _SortFilterProxyModel()
        proxy_model.setDynamicSortFilter(True)
        proxy_model.setSortRole(QT_SORT_ROLE)
        proxy_model.setSourceModel(model)
        self.setModel(proxy_model)

        fx = app_state.fx
        self._set_fiat_columns_enabled(fx and fx.get_fiat_address_config())

        # Sort by type then by index, by making sure the initial sort is our type column.
        self.sortByColumn(TYPE_COLUMN, Qt.AscendingOrder)
        self.setSortingEnabled(True)

        self.horizontalHeader().setSectionResizeMode(LABEL_COLUMN,
                                                     QHeaderView.Stretch)
        for i in range(FIAT_BALANCE_COLUMN):
            if i != LABEL_COLUMN:
                self.horizontalHeader().setSectionResizeMode(
                    i, QHeaderView.ResizeToContents)
        self.horizontalHeader().setMinimumSectionSize(20)
        self.verticalHeader().setMinimumSectionSize(20)
        # The initial spacing of rows is generous. This will draw in the spacing based on the
        # initial data we have put in the model, and give a more professional compact layout.
        # If there is no initial data, then this should be ineffectual, so we also call this on
        # explicit post-creation addition of rows as well to cover that case.
        self.resizeRowsToContents()

        self.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        # New selections clear existing selections, unless the user holds down control.
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)

        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self._event_create_menu)

        app_state.app.base_unit_changed.connect(
            self._on_balance_display_change)
        app_state.app.fiat_balance_changed.connect(
            self._on_fiat_balance_display_change)
        app_state.app.fiat_ccy_changed.connect(
            self._on_fiat_balance_display_change)
        app_state.app.labels_changed_signal.connect(self.update_labels)
        app_state.app.num_zeros_changed.connect(
            self._on_balance_display_change)

        self.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.doubleClicked.connect(self._event_double_clicked)

        self._last_not_synced = 0
        self._timer = QTimer(self)
        self._timer.setSingleShot(False)
        self._timer.setInterval(1000)
        self._timer.timeout.connect(self._on_update_check)
        self._timer.start()
Пример #17
0
 def __init__(self):
     super().__init__()
     self.logger = logs.get_logger("restapi-dapp")
     self.app_state = app_state  # easier to monkeypatch for testing
     self.add_routes()
Пример #18
0
    def __init__(self, main_window: ElectrumWindow) -> None:
        super().__init__(main_window)
        self._logger = logs.get_logger("key-view")

        self._main_window = main_window
        self._account: AbstractAccount = None
        self._account_id: Optional[int] = None

        self._update_lock = threading.Lock()

        self._headers = COLUMN_NAMES

        self.verticalHeader().setVisible(False)
        self.setAlternatingRowColors(True)

        self._pending_state: Dict[int, Tuple[KeyInstanceRow, EventFlags]] = {}
        self._pending_actions = set([ListActions.RESET])
        self._main_window.keys_created_signal.connect(self._on_keys_created)
        self._main_window.keys_updated_signal.connect(self._on_keys_updated)
        self._main_window.account_change_signal.connect(
            self._on_account_change)

        model = _ItemModel(self, self._headers)
        model.set_data([])
        self._base_model = model

        # If the underlying model changes, observe it in the sort.
        self._proxy_model = proxy_model = _SortFilterProxyModel()
        proxy_model.setDynamicSortFilter(True)
        proxy_model.setSortRole(QT_SORT_ROLE)
        proxy_model.setSourceModel(model)
        self.setModel(proxy_model)

        fx = app_state.fx
        self._set_fiat_columns_enabled(fx and fx.get_fiat_address_config())

        # Sort by type then by index, by making sure the initial sort is our type column.
        self.sortByColumn(TYPE_COLUMN, Qt.AscendingOrder)
        self.setSortingEnabled(True)

        self.horizontalHeader().setSectionResizeMode(LABEL_COLUMN,
                                                     QHeaderView.Stretch)
        for i in range(FIAT_BALANCE_COLUMN):
            if i != LABEL_COLUMN:
                self.horizontalHeader().setSectionResizeMode(
                    i, QHeaderView.ResizeToContents)
        self.horizontalHeader().setMinimumSectionSize(20)
        self.verticalHeader().setMinimumSectionSize(20)

        self.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        # New selections clear existing selections, unless the user holds down control.
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)

        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self._event_create_menu)

        app_state.app.base_unit_changed.connect(
            self._on_balance_display_change)
        app_state.app.fiat_balance_changed.connect(
            self._on_fiat_balance_display_change)
        app_state.app.fiat_ccy_changed.connect(
            self._on_fiat_balance_display_change)
        app_state.app.labels_changed_signal.connect(self.update_labels)
        app_state.app.num_zeros_changed.connect(
            self._on_balance_display_change)

        self.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.doubleClicked.connect(self._event_double_clicked)

        self._last_not_synced = 0
        self._timer = QTimer(self)
        self._timer.setSingleShot(False)
        self._timer.setInterval(1000)
        self._timer.timeout.connect(self._on_update_check)
Пример #19
0
    BIP32Derivation,
    bip32_decompose_chain_string,
    Address,
)

from electrumsv.app_state import app_state
from electrumsv.device import Device
from electrumsv.exceptions import UserCancelled
from electrumsv.i18n import _
from electrumsv.keystore import Hardware_KeyStore
from electrumsv.logs import logs
from electrumsv.networks import Net
from electrumsv.transaction import classify_tx_output, Transaction, TransactionContext
from electrumsv.wallet import AbstractAccount

logger = logs.get_logger("plugin.keepkey")

try:
    from .client import KeepKeyClient
    import keepkeylib
    import keepkeylib.ckd_public
    from keepkeylib.client import types
    from usb1 import USBContext
    KEEPKEYLIB = True
except Exception:
    logger.exception("Failed to import keepkeylib")
    KEEPKEYLIB = False

from ..hw_wallet import HW_PluginBase

# TREZOR initialization methods
Пример #20
0
 def __init__(self) -> None:
     self._logger = logs.get_logger("local-rpc")
Пример #21
0
from bitcoinx import PublicKey, bip32_key_from_string

from electrumsv import util, keystore
from electrumsv.app_state import app_state
from electrumsv.crypto import sha256d
from electrumsv.extensions import cosigner_pool
from electrumsv.i18n import _
from electrumsv.logs import logs
from electrumsv.transaction import Transaction
from electrumsv.util import bh2u, bfh
from electrumsv.wallet import Multisig_Wallet

from electrumsv.gui.qt.util import WaitingDialog

logger = logs.get_logger("cosignerpool")

server = ServerProxy('https://cosigner.electrum.org/', allow_none=True)

CosignerItem = namedtuple("CosignerItem", "window xpub K hash watching_only")


class Listener(util.DaemonThread):
    def __init__(self, parent):
        super().__init__('cosigner')
        self.daemon = True
        self.parent = parent
        self.received = set()

    def clear(self, keyhash):
        server.delete(keyhash)
Пример #22
0
import traceback

import requests
from PyQt5.QtCore import QObject, pyqtSignal, Qt
from PyQt5.QtWidgets import (
    QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QTextEdit, QMessageBox,
)

from electrumsv.i18n import _
from electrumsv.logs import logs
from electrumsv.version import PACKAGE_VERSION
from .main_window import ElectrumWindow
from .util import read_QIcon


logger = logs.get_logger("exc-handler")


issue_template = """<h2>Traceback</h2>
<pre>
{traceback}
</pre>

<h2>Additional information</h2>
<ul>
  <li>ElectrumSV version: {app_version}</li>
  <li>Python version: {python_version}</li>
  <li>Operating system: {os}</li>
  <li>Wallet type: {wallet_type}</li>
  <li>Locale: {locale}</li>
</ul>
Пример #23
0
import requests
import threading

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QHBoxLayout, QLabel, QVBoxLayout, QMessageBox, QPushButton

from electrumsv.app_state import app_state
from electrumsv.crypto import aes_decrypt_with_iv, aes_encrypt_with_iv
from electrumsv.exceptions import UserCancelled
from electrumsv.extensions import label_sync
from electrumsv.i18n import _
from electrumsv.logs import logs

from electrumsv.gui.qt.util import Buttons, EnterButton, WindowModalDialog, OkButton

logger = logs.get_logger("labels")


class LabelSync(object):
    def __init__(self):
        self.target_host = 'labels.electrum.org'
        self.wallets = {}
        app_state.app.window_opened_signal.connect(self.window_opened)
        app_state.app.window_closed_signal.connect(self.window_closed)

    def encode(self, wallet, msg):
        password, iv, wallet_id = self.wallets[wallet]
        encrypted = aes_encrypt_with_iv(password, iv, msg.encode('utf8'))
        return base64.b64encode(encrypted).decode()

    def decode(self, wallet, message):
Пример #24
0
from electrumsv.transaction import Transaction
from electrumsv.util import to_string

from ..hw_wallet import HW_PluginBase

try:
    import hid
    DIGIBOX = True
except ImportError as e:
    DIGIBOX = False

if TYPE_CHECKING:
    from electrumsv.wallet_database.tables import MasterKeyRow
    from electrumsv.gui.qt.account_wizard import AccountWizard

logger = logs.get_logger("plugin.bitbox")

# ----------------------------------------------------------------------------------
# USB HID interface
#


def derive_keys(x):
    h = sha256d(x)
    h = hashlib.sha512(h).digest()
    return (h[:32], h[32:])


MIN_MAJOR_VERSION = 5

Пример #25
0
from electrumsv.i18n import _, set_language
from electrumsv.logs import logs
from electrumsv.wallet import Abstract_Wallet

from . import dialogs
from .cosigner_pool import CosignerPool
from .main_window import ElectrumWindow
from .exception_window import Exception_Hook
from .installwizard import InstallWizard, GoBack
from .label_sync import LabelSync
from .log_window import SVLogWindow, SVLogHandler
from .network_dialog import NetworkDialog
from .util import ColorScheme, read_QIcon, MessageBox


logger = logs.get_logger('app')


class OpenFileEventFilter(QObject):
    def __init__(self, windows):
        super().__init__()
        self.windows = windows

    def eventFilter(self, obj, event):
        if event.type() == QtCore.QEvent.FileOpen:
            if len(self.windows) >= 1:
                self.windows[0].pay_to_URI(event.url().toString())
                return True
        return False

Пример #26
0
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from struct import pack
import time

from keepkeylib.client import proto, BaseClient, ProtocolMixin

from electrumsv.bip32 import serialize_xpub
from electrumsv.exceptions import UserCancelled
from electrumsv.i18n import _
from electrumsv.keystore import bip39_normalize_passphrase
from electrumsv.logs import logs

logger = logs.get_logger("keepkey.client")


class KeepKeyClient(ProtocolMixin, BaseClient):
    def __init__(self, transport, handler, plugin):
        BaseClient.__init__(self, transport)
        ProtocolMixin.__init__(self, transport)
        assert hasattr(self, 'tx_api')  # ProtocolMixin already constructed?
        self.proto = proto
        self.device = plugin.device
        self.handler = handler
        self.tx_api = plugin
        self.types = plugin.types
        self.msg = None
        self.creating_wallet = False
        self.used()
Пример #27
0
    def __init__(self, main_window: ElectrumWindow) -> None:
        super().__init__(main_window)
        self._logger = logs.get_logger("key-view")

        self._main_window = weakref.proxy(main_window)
        self._account: AbstractAccount = None
        self._account_id: Optional[int] = None

        self._update_lock = threading.Lock()

        self._headers = COLUMN_NAMES

        self.verticalHeader().setVisible(False)
        self.setAlternatingRowColors(True)

        self._pending_state: Dict[int, EventFlags] = {}
        self._pending_actions = set([ListActions.RESET])
        self._main_window.keys_created_signal.connect(self._on_keys_created)
        self._main_window.keys_updated_signal.connect(self._on_keys_updated)
        self._main_window.account_change_signal.connect(
            self._on_account_change)

        model = _ItemModel(self, self._headers)
        model.set_data(self._account_id, [])
        self._base_model = model

        # If the underlying model changes, observe it in the sort.
        self._proxy_model = proxy_model = _SortFilterProxyModel()
        proxy_model.setDynamicSortFilter(True)
        proxy_model.setSortRole(QT_SORT_ROLE)
        proxy_model.setSourceModel(model)
        self.setModel(proxy_model)

        fx = app_state.fx
        self._set_fiat_columns_enabled(fx and fx.get_fiat_address_config())

        # Sort by type then by index, by making sure the initial sort is our type column.
        self.sortByColumn(BALANCE_COLUMN, Qt.DescendingOrder)
        self.setSortingEnabled(True)

        defaultFontMetrics = QFontMetrics(app_state.app.font())

        def fw(s: str) -> int:
            return defaultFontMetrics.boundingRect(s).width() + 10

        self._monospace_font = QFont(platform.monospace_font)
        monospaceFontMetrics = QFontMetrics(self._monospace_font)

        def mw(s: str) -> int:
            return monospaceFontMetrics.boundingRect(s).width() + 10

        # We set the columm widths so that rendering is instant rather than taking a second or two
        # because ResizeToContents does not scale for thousands of rows.
        horizontalHeader = self.horizontalHeader()
        horizontalHeader.setMinimumSectionSize(20)
        horizontalHeader.resizeSection(TYPE_COLUMN,
                                       fw(COLUMN_NAMES[TYPE_COLUMN]))
        horizontalHeader.resizeSection(STATE_COLUMN,
                                       fw(COLUMN_NAMES[STATE_COLUMN]))
        horizontalHeader.resizeSection(KEY_COLUMN, fw("1442:01:m/000/1392"))
        horizontalHeader.resizeSection(SCRIPT_COLUMN,
                                       fw("MULTISIG_ACCUMULATOR"))
        horizontalHeader.setSectionResizeMode(LABEL_COLUMN,
                                              QHeaderView.Stretch)
        horizontalHeader.resizeSection(USAGES_COLUMN,
                                       fw(COLUMN_NAMES[USAGES_COLUMN]))
        balance_width = mw(app_state.format_amount(1.2, whitespaces=True))
        horizontalHeader.resizeSection(BALANCE_COLUMN, balance_width)

        verticalHeader = self.verticalHeader()
        verticalHeader.setSectionResizeMode(QHeaderView.Fixed)
        # This value will get pushed out if the contents are larger, so it does not have to be
        # correct, it just has to be minimal.
        lineHeight = defaultFontMetrics.height()
        verticalHeader.setDefaultSectionSize(lineHeight)

        self.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        # New selections clear existing selections, unless the user holds down control.
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)

        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self._event_create_menu)

        app_state.app.base_unit_changed.connect(
            self._on_balance_display_change)
        app_state.app.fiat_balance_changed.connect(
            self._on_fiat_balance_display_change)
        app_state.app.fiat_ccy_changed.connect(
            self._on_fiat_balance_display_change)
        app_state.app.labels_changed_signal.connect(self.update_labels)
        app_state.app.num_zeros_changed.connect(
            self._on_balance_display_change)

        self.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.doubleClicked.connect(self._event_double_clicked)

        self._last_not_synced = 0
        self._timer = QTimer(self)
        self._timer.setSingleShot(False)
        self._timer.setInterval(1000)
        self._timer.timeout.connect(self._on_update_check)
Пример #28
0
                             QToolTip, QTreeWidget, QTreeWidgetItem,
                             QVBoxLayout, QWidget, QWizard)
from PyQt5.uic import loadUi

from electrumsv.app_state import app_state
from electrumsv.constants import DATABASE_EXT
from electrumsv.exceptions import WaitingTaskCancelled
from electrumsv.i18n import _, languages
from electrumsv.logs import logs
from electrumsv.types import WaitingUpdateCallback
from electrumsv.util import resource_path

if TYPE_CHECKING:
    from .main_window import ElectrumWindow

logger = logs.get_logger("qt-util")

dialogs = []


class EnterButton(QPushButton):
    def __init__(self, text, func, parent: Optional[QWidget] = None):
        super().__init__(text, parent)
        self.func = func
        self.clicked.connect(func)

    def keyPressEvent(self, e: QKeyEvent):
        if e.key() in (Qt.Key_Return, Qt.Key_Enter):
            self.func()

Пример #29
0
from electrumsv.i18n import _
from electrumsv.logs import logs
from electrumsv.storage import WalletStorage
from electrumsv.util import get_electron_cash_user_dir
from electrumsv.wallet import ParentWallet

from .network_dialog import NetworkChoiceLayout
from .password_dialog import PasswordLayout, PW_NEW, PasswordLineEdit
from .seed_dialog import SeedLayout, KeysLayout
from .util import (
    MessageBoxMixin, Buttons, WWLabel, ChoicesLayout, icon_path, WindowModalDialog, HelpLabel,
    MessageBox
)


logger = logs.get_logger('wizard')


class GoBack(Exception):
    pass

MSG_GENERATING_WAIT = _("ElectrumSV is generating your addresses, please wait...")
MSG_ENTER_ANYTHING = _("Please enter a seed phrase, a master key, a list of "
                       "Bitcoin addresses, or a list of private keys")
MSG_ENTER_SEED_OR_MPK = _("Please enter a seed phrase or a master key (xpub or xprv):")
MSG_COSIGNER = _("Please enter the master public key of cosigner #{}:")
MSG_ENTER_PASSWORD = _("Choose a password to encrypt your wallet keys.") + '\n'\
                     + _("Leave this field empty if you want to disable encryption.")
MSG_RESTORE_PASSPHRASE = \
    _("Please enter your seed derivation passphrase. "
      "Note: this is NOT your encryption password. "
Пример #30
0
                             QWizardPage, QGridLayout, QListWidget,
                             QListWidgetItem, QSlider, QTextEdit, QWidget)

from electrumsv.app_state import app_state
from electrumsv.exceptions import InvalidPassword
from electrumsv.device import DeviceInfo
from electrumsv.i18n import _
from electrumsv import keystore
from electrumsv.logs import logs
from electrumsv import wallet_support

from .main_window import ElectrumWindow
from .password_dialog import PasswordLineEdit
from .util import ChoicesLayout, icon_path, MessageBoxMixin, read_QIcon, WWLabel

logger = logs.get_logger('wizard-account')

DeviceList = List[Tuple[str, DeviceInfo]]

PASSWORD_EXISTING_TEXT = _(
    "Your wallet has a password, and you will need to provide that "
    "password in order to add this account.")

NO_DEVICES_FOUND_TEXT = _(
    "A scan has been unable to locate any connected hardware wallets. "
    "Once you have connected your hardware wallet, and if necessary turned it on, please "
    "press the 'Rescan' button to try again."
) + "\n\n" + _(
    "If any problems were encountered "
    "during the scan, they will be displayed below. If there are no indications why your "
    "hardware wallet is not being found, press the 'Help' button for further direction."