Exemplo n.º 1
0
    def settings_dialog(self, window):
        d = WindowModalDialog(window, _("Email settings"))
        d.setMinimumSize(500, 200)

        vbox = QVBoxLayout(d)
        vbox.addWidget(QLabel(_('Server hosting your email acount')))
        grid = QGridLayout()
        vbox.addLayout(grid)
        grid.addWidget(QLabel('Server (IMAP)'), 0, 0)
        server_e = QLineEdit()
        server_e.setText(self.imap_server)
        grid.addWidget(server_e, 0, 1)

        grid.addWidget(QLabel('Username'), 1, 0)
        username_e = QLineEdit()
        username_e.setText(self.username)
        grid.addWidget(username_e, 1, 1)

        grid.addWidget(QLabel('Password'), 2, 0)
        password_e = QLineEdit()
        password_e.setText(self.password)
        grid.addWidget(password_e, 2, 1)

        vbox.addStretch()
        vbox.addLayout(Buttons(CloseButton(d), OkButton(d)))

        if not d.exec_():
            return

        server = str(server_e.text())
        self.config.set_key('email_server', server)

        username = str(username_e.text())
        self.config.set_key('email_username', username)

        password = str(password_e.text())
        self.config.set_key('email_password', password)
Exemplo n.º 2
0
 def multisig_dialog(self, run_next):
     cw = CosignWidget(2, 2)
     m_edit = QSlider(Qt.Horizontal, self)
     n_edit = QSlider(Qt.Horizontal, self)
     n_edit.setMinimum(2)
     n_edit.setMaximum(15)
     m_edit.setMinimum(1)
     m_edit.setMaximum(2)
     n_edit.setValue(2)
     m_edit.setValue(2)
     n_label = QLabel()
     m_label = QLabel()
     grid = QGridLayout()
     grid.addWidget(n_label, 0, 0)
     grid.addWidget(n_edit, 0, 1)
     grid.addWidget(m_label, 1, 0)
     grid.addWidget(m_edit, 1, 1)
     def on_m(m):
         m_label.setText(_('Require %d signatures')%m)
         cw.set_m(m)
     def on_n(n):
         n_label.setText(_('From %d cosigners')%n)
         cw.set_n(n)
         m_edit.setMaximum(n)
     n_edit.valueChanged.connect(on_n)
     m_edit.valueChanged.connect(on_m)
     on_n(2)
     on_m(2)
     vbox = QVBoxLayout()
     vbox.addWidget(cw)
     vbox.addWidget(WWLabel(_("Choose the number of signatures needed to unlock funds in your wallet:")))
     vbox.addLayout(grid)
     self.exec_layout(vbox, _("Multi-Signature Wallet"))
     m = int(m_edit.value())
     n = int(n_edit.value())
     return (m, n)
Exemplo n.º 3
0
    def create_masternode_conf_tab(self):
        """Create the tab used to import masternode.conf files."""

        desc = ' '.join(['You can use this form to import your masternode.conf file.',
            'This file is usually located in the same directory that your wallet file is in.',
            'If you just need to import your masternode\'s private key, use the regular process for importing a key.'])
        desc = QLabel(_(desc))
        desc.setWordWrap(True)

        import_filename_edit = QLineEdit()
        import_filename_edit.setPlaceholderText(_('Enter the path to your masternode.conf'))
        import_select_file = QPushButton(_('Select File...'))
        hbox = QHBoxLayout()
        hbox.addWidget(import_filename_edit, stretch=1)
        hbox.addWidget(import_select_file)
        import_conf_button = QPushButton(_('Import'))
        vbox = QVBoxLayout()
        vbox.addWidget(desc)
        vbox.addLayout(hbox)
        vbox.addLayout(util.Buttons(import_conf_button))
        vbox.addStretch(1)

        def select_import_file():
            text = QFileDialog.getOpenFileName(None, _('Select a file to import'), '', '*.conf')
            if text:
                import_filename_edit.setText(text)
        import_select_file.clicked.connect(select_import_file)

        def do_import_file():
            path = str(import_filename_edit.text())
            self.import_masternode_conf(path)
        import_conf_button.clicked.connect(do_import_file)

        w = QWidget()
        w.setLayout(vbox)
        return w
Exemplo n.º 4
0
    def scan_for_outputs(self, include_frozen):
        """Scan for 1000 PAC outputs.

        If one or more is found, populate the list and enable the sign button.
        """
        self.valid_outputs_list.clear()
        exclude_frozen = not include_frozen

        coins = self.manager.get_masternode_outputs(exclude_frozen=exclude_frozen)

        if len(coins) > 0:
            self.valid_outputs_list.add_outputs(coins)
        else:
            self.status_edit.setText(_('No 1000 PAC outputs were found.'))
            self.status_edit.setStyleSheet(util.RED_FG)
Exemplo n.º 5
0
 def dbb_load_backup(self, show_msg=True):
     backups = self.hid_send_encrypt('{"backup":"list"}')
     if 'error' in backups:
         raise Exception(backups['error']['message'])
     try:
         f = self.handler.win.query_choice(_("Choose a backup file:"),
                                           backups['backup'])
     except Exception:
         return False  # Back button pushed
     key = self.backup_password_dialog()
     if key is None:
         raise Exception('Canceled by user')
     key = self.stretch_key(key)
     if show_msg:
         self.handler.show_message(_("Loading backup...\r\n\r\n" \
                                     "To continue, touch the Digital Bitbox's light for 3 seconds.\r\n\r\n" \
                                     "To cancel, briefly touch the light or wait for the timeout."))
     msg = '{"seed":{"source": "backup", "key": "%s", "filename": "%s"}}' % (
         key, backups['backup'][f])
     hid_reply = self.hid_send_encrypt(msg)
     self.handler.clear_dialog()
     if 'error' in hid_reply:
         raise Exception(hid_reply['error']['message'])
     return True
Exemplo n.º 6
0
 def pw_changed(self):
     password = self.new_pw.text()
     if password:
         colors = {
             "Weak": "Red",
             "Medium": "Blue",
             "Strong": "Green",
             "Very Strong": "Green"
         }
         strength = check_password_strength(password)
         label = (_("Password Strength") + ": " + "<font color=" +
                  colors[strength] + ">" + strength + "</font>")
     else:
         label = ""
     self.pw_strength.setText(label)
Exemplo n.º 7
0
def seed_warning_msg(seed):
    return ''.join([
        "<p>",
        _("Please save these %d words on paper (order is important). "),
        _("This seed will allow you to recover your wallet in case "
          "of computer failure."), "</p>", "<b>" + _("WARNING") + ":</b>",
        "<ul>", "<li>" + _("Never disclose your seed.") + "</li>",
        "<li>" + _("Never type it on a website.") + "</li>",
        "<li>" + _("Do not store it electronically.") + "</li>", "</ul>"
    ]) % len(seed.split())
Exemplo n.º 8
0
def address_field(addresses):
    hbox = QHBoxLayout()
    address_e = QLineEdit()
    if addresses:
        address_e.setText(addresses[0])

    def func():
        i = addresses.index(str(address_e.text())) + 1
        i = i % len(addresses)
        address_e.setText(addresses[i])

    button = QPushButton(_('Address'))
    button.clicked.connect(func)
    hbox.addWidget(button)
    hbox.addWidget(address_e)
    return hbox, address_e
Exemplo n.º 9
0
 def change_homescreen():
     from PIL import Image  # FIXME
     dialog = QFileDialog(self, _("Choose Homescreen"))
     filename = dialog.getOpenFileName()
     if filename:
         im = Image.open(str(filename))
         if im.size != (hs_cols, hs_rows):
             raise Exception('Image must be 64 x 128 pixels')
         im = im.convert('1')
         pix = im.load()
         img = ''
         for j in range(hs_rows):
             for i in range(hs_cols):
                 img += '1' if pix[i, j] else '0'
         img = ''.join(chr(int(img[i:i + 8], 2))
                       for i in range(0, len(img), 8))
         invoke_client('change_homescreen', img)
Exemplo n.º 10
0
    def set_mapper_index(self, row):
        """Set the row that the data widget mapper should use."""
        self.status_edit.clear()
        self.status_edit.setStyleSheet(util.BLACK_FG)
        self.mapper.setCurrentIndex(row)
        mn = self.dialog.masternodes_widget.masternode_for_row(row)

        # Disable the sign button if the masternode can't be signed (for whatever reason).
        status_text = '%s can be activated' % mn.alias
        can_sign = True
        try:
            self.manager.check_can_sign_masternode(mn.alias)
        except Exception as e:
            status_text = str(e)
            can_sign = False

        self.status_edit.setText(_(status_text))
        self.sign_button.setEnabled(can_sign)
Exemplo n.º 11
0
    def create_sign_announce_tab(self):
        desc = ' '.join(['You can sign a Masternode Announce message to activate your masternode.',
            'First, ensure that all the required data has been entered for this masternode.',
            'Then, click "Activate Masternode" to activate your masternode.',
        ])
        desc = QLabel(_(desc))
        desc.setWordWrap(True)

        self.sign_announce_widget = SignAnnounceWidget(self)

        vbox = QVBoxLayout()
        vbox.addWidget(desc)
        vbox.addWidget(self.sign_announce_widget)
        vbox.addStretch(1)

        w = QWidget()
        w.setLayout(vbox)
        return w
Exemplo n.º 12
0
 def item_changed(self, item):
     if item is None:
         return
     if not self.isItemSelected(item):
         return
     addr = str(item.text(1))
     req = self.wallet.receive_requests[addr]
     expires = age(req['time'] +
                   req['exp']) if req.get('exp') else _('Never')
     amount = req['amount']
     message = self.wallet.labels.get(addr, '')
     self.parent.receive_address_e.setText(addr)
     self.parent.receive_message_e.setText(message)
     self.parent.receive_amount_e.setAmount(amount)
     self.parent.expires_combo.hide()
     self.parent.expires_label.show()
     self.parent.expires_label.setText(expires)
     self.parent.new_request_button.setEnabled(True)
Exemplo n.º 13
0
 def passphrase_dialog(self, msg, confirm):
     # If confirm is true, require the user to enter the passphrase twice
     parent = self.top_level_window()
     if confirm:
         d = PasswordDialog(parent, None, msg, PW_PASSPHRASE)
         confirmed, p, passphrase = d.run()
     else:
         d = WindowModalDialog(parent, _("Enter Passphrase"))
         pw = QLineEdit()
         pw.setEchoMode(2)
         pw.setMinimumWidth(200)
         vbox = QVBoxLayout()
         vbox.addWidget(WWLabel(msg))
         vbox.addWidget(pw)
         vbox.addLayout(Buttons(CancelButton(d), OkButton(d)))
         d.setLayout(vbox)
         passphrase = unicode(pw.text()) if d.exec_() else None
     self.passphrase = passphrase
     self.done.set()
    def create_proposal_tx(self, proposal, pw, callback):
        """Create and sign the proposal fee transaction."""
        result = [False]

        def tx_thread():
            return self.parent.masternode_manager.create_proposal_tx(
                proposal.proposal_name, pw, save=False)

        def on_tx_made(tx):
            result[0] = tx

        def on_done():
            callback(proposal, result[0])

        self.waiting_dialog = util.WaitingDialog(self,
                                                 _('Creating Transaction...'),
                                                 tx_thread, on_tx_made,
                                                 on_done)
        self.waiting_dialog.start()
Exemplo n.º 15
0
 def refresh_headers(self):
     headers = [
         '', '',
         _('Date'),
         _('Description'),
         _('Amount'),
         _('Balance')
     ]
     fx = self.parent.fx
     if fx and fx.show_history():
         headers.extend(
             ['%s ' % fx.ccy + _('Amount'),
              '%s ' % fx.ccy + _('Balance')])
     self.update_headers(headers)
Exemplo n.º 16
0
 def sign_message(self, sequence, message, password):
     self.signing = True
     # prompt for the PIN before displaying the dialog if necessary
     client = self.get_client()
     address_path = self.get_derivation()[2:] + "/%d/%d"%sequence
     self.handler.show_message("Signing message ...")
     try:
         info = self.get_client().signMessagePrepare(address_path, message)
         pin = ""
         if info['confirmationNeeded']:
             pin = self.handler.get_auth( info ) # does the authenticate dialog and returns pin
             if not pin:
                 raise UserWarning(_('Cancelled by user'))
             pin = str(pin).encode()
         signature = self.get_client().signMessageSign(pin)
     except BTChipException, e:
         if e.sw == 0x6a80:
             self.give_error("Unfortunately, this message cannot be signed by the Ledger wallet. Only alphanumerical messages shorter than 140 characters are supported. Please remove any extra characters (tab, carriage return) and retry.")
         else:
             self.give_error(e, True)
Exemplo n.º 17
0
    def __init__(self, parent, address):
        WindowModalDialog.__init__(self, parent, _("Address"))
        self.address = address
        self.parent = parent
        self.config = parent.config
        self.wallet = parent.wallet
        self.app = parent.app
        self.saved = True

        self.setMinimumWidth(700)
        vbox = QVBoxLayout()
        self.setLayout(vbox)

        vbox.addWidget(QLabel(_("Address:")))
        self.addr_e = ButtonsLineEdit(self.address)
        self.addr_e.addCopyButton(self.app)
        self.addr_e.addButton(":icons/qrcode.png", self.show_qr, _("Show QR Code"))
        self.addr_e.setReadOnly(True)
        vbox.addWidget(self.addr_e)

        try:
            pubkeys = self.wallet.get_public_keys(address)
        except BaseException as e:
            pubkeys = None
        if pubkeys:
            vbox.addWidget(QLabel(_("Public keys") + ':'))
            for pubkey in pubkeys:
                pubkey_e = ButtonsLineEdit(pubkey)
                pubkey_e.addCopyButton(self.app)
                vbox.addWidget(pubkey_e)

        try:
            redeem_script = self.wallet.pubkeys_to_redeem_script(pubkeys)
        except BaseException as e:
            redeem_script = None
        if redeem_script:
            vbox.addWidget(QLabel(_("Redeem Script") + ':'))
            redeem_e = ShowQRTextEdit(text=redeem_script)
            redeem_e.addCopyButton(self.app)
            vbox.addWidget(redeem_e)

        vbox.addWidget(QLabel(_("History")))
        self.hw = HistoryList(self.parent)
        self.hw.get_domain = self.get_domain
        vbox.addWidget(self.hw)

        vbox.addLayout(Buttons(CloseButton(self)))
        self.format_amount = self.parent.format_amount
        self.hw.update()
Exemplo n.º 18
0
 def settings_dialog(self, window):
     wallet = window.parent().wallet
     d = WindowModalDialog(window, _("Label Settings"))
     hbox = QHBoxLayout()
     hbox.addWidget(QLabel("Label sync options:"))
     upload = ThreadedButton("Force upload",
                             partial(self.push_thread, wallet),
                             partial(self.done_processing, d))
     download = ThreadedButton("Force download",
                               partial(self.pull_thread, wallet, True),
                               partial(self.done_processing, d))
     vbox = QVBoxLayout()
     vbox.addWidget(upload)
     vbox.addWidget(download)
     hbox.addLayout(vbox)
     vbox = QVBoxLayout(d)
     vbox.addLayout(hbox)
     vbox.addSpacing(20)
     vbox.addLayout(Buttons(OkButton(d)))
     return bool(d.exec_())
Exemplo n.º 19
0
 def show_restore(self, wallet, network):
     # FIXME: these messages are shown after the install wizard is
     # finished and the window closed.  On MacOSX they appear parented
     # with a re-appeared ghost install wizard window...
     if network:
         def task():
             wallet.wait_until_synchronized()
             if wallet.is_found():
                 msg = _("Recovery successful")
             else:
                 msg = _("No transactions found for this seed")
             self.emit(QtCore.SIGNAL('synchronized'), msg)
         self.connect(self, QtCore.SIGNAL('synchronized'), self.show_message)
         t = threading.Thread(target = task)
         t.daemon = True
         t.start()
     else:
         msg = _("This wallet was restored offline. It may "
                 "contain more addresses than displayed.")
         self.show_message(msg)
Exemplo n.º 20
0
 def __init__(self, config, app, plugins, storage):
     BaseWizard.__init__(self, config, storage)
     QDialog.__init__(self, None)
     self.setWindowTitle('Electrum-PAC  -  ' + _('Install Wizard'))
     self.app = app
     self.config = config
     # Set for base base class
     self.plugins = plugins
     self.language_for_seed = config.get('language')
     self.setMinimumSize(600, 400)
     self.connect(self, QtCore.SIGNAL('accept'), self.accept)
     self.title = QLabel()
     self.main_widget = QWidget()
     self.back_button = QPushButton(_("Back"), self)
     self.back_button.setText(
         _('Back') if self.can_go_back() else _('Cancel'))
     self.next_button = QPushButton(_("Next"), self)
     self.next_button.setDefault(True)
     self.logo = QLabel()
     self.please_wait = QLabel(_("Please wait..."))
     self.please_wait.setAlignment(Qt.AlignCenter)
     self.icon_filename = None
     self.loop = QEventLoop()
     self.rejected.connect(lambda: self.loop.exit(0))
     self.back_button.clicked.connect(lambda: self.loop.exit(1))
     self.next_button.clicked.connect(lambda: self.loop.exit(2))
     outer_vbox = QVBoxLayout(self)
     inner_vbox = QVBoxLayout()
     inner_vbox = QVBoxLayout()
     inner_vbox.addWidget(self.title)
     inner_vbox.addWidget(self.main_widget)
     inner_vbox.addStretch(1)
     inner_vbox.addWidget(self.please_wait)
     inner_vbox.addStretch(1)
     icon_vbox = QVBoxLayout()
     icon_vbox.addWidget(self.logo)
     icon_vbox.addStretch(1)
     hbox = QHBoxLayout()
     hbox.addLayout(icon_vbox)
     hbox.addSpacing(5)
     hbox.addLayout(inner_vbox)
     hbox.setStretchFactor(inner_vbox, 1)
     outer_vbox.addLayout(hbox)
     outer_vbox.addLayout(Buttons(self.back_button, self.next_button))
     self.set_icon(':icons/electrum-PAC.png')
     self.show()
     self.raise_()
     self.refresh_gui()  # Need for QT on MacOSX.  Lame.
    def submit_waiting_proposals(self):
        """Submit the proposals that are ready to the network."""
        # Submit the proposals that are ready.
        results = [('', '', False)] * len(self.unsubmitted_proposals)

        def submit_thread():
            for i, (proposal_name,
                    txid) in enumerate(self.unsubmitted_proposals):
                errmsg, success = self.parent.masternode_manager.submit_proposal(
                    proposal_name, save=False)
                results[i] = (proposal_name, errmsg, success)
                if success:
                    print_error('Sucessfully submitted proposal "%s"' %
                                proposal_name)
                else:
                    print_error('Failed to submit proposal "%s": %s' %
                                (proposal_name, errmsg))
            return results

        def on_done():
            msg = ''
            for proposal_name, errmsg, success in results:
                if success:
                    msg += '<b>' + proposal_name + '</b>' + _(
                        ': submitted successfully.')
                else:
                    msg += '<b>' + proposal_name + '</b>' + _(
                        ': failed! "%s"' % errmsg)

                msg += '\n'
            QMessageBox.information(self, _('Results'), msg)
            self.update_unsubmitted_proposals()
            self.parent.masternode_manager.save()

        self.waiting_dialog = util.WaitingDialog(self,
                                                 _('Submitting Proposals...'),
                                                 submit_thread,
                                                 on_complete=on_done)
        self.waiting_dialog.start()
Exemplo n.º 22
0
 def on_update(self):
     inv_list = self.parent.invoices.unpaid_invoices()
     self.clear()
     for pr in inv_list:
         key = pr.get_id()
         status = self.parent.invoices.get_status(key)
         requestor = pr.get_requestor()
         exp = pr.get_expiration_date()
         date_str = format_time(exp) if exp else _('Never')
         item = QTreeWidgetItem([
             date_str, requestor, pr.memo,
             self.parent.format_amount(pr.get_amount(), whitespaces=True),
             pr_tooltips.get(status, '')
         ])
         item.setIcon(4, QIcon(pr_icons.get(status)))
         item.setData(0, Qt.UserRole, key)
         item.setFont(1, QFont(MONOSPACE_FONT))
         item.setFont(3, QFont(MONOSPACE_FONT))
         self.addTopLevelItem(item)
     self.setCurrentItem(self.topLevelItem(0))
     self.setVisible(len(inv_list))
     self.parent.invoices_label.setVisible(len(inv_list))
Exemplo n.º 23
0
    def on_receive(self, keyhash, message):
        self.print_error("signal arrived for", keyhash)
        for key, _hash, window in self.keys:
            if _hash == keyhash:
                break
        else:
            self.print_error("keyhash not found")
            return

        wallet = window.wallet
        if wallet.has_password():
            password = window.password_dialog(
                'An encrypted transaction was retrieved from cosigning pool.\nPlease enter your password to decrypt it.'
            )
            if not password:
                return
        else:
            password = None
            if not window.question(
                    _("An encrypted transaction was retrieved from cosigning pool.\nDo you want to open it now?"
                      )):
                return

        xprv = wallet.keystore.get_master_private_key(password)
        if not xprv:
            return
        try:
            k = bitcoin.deserialize_xprv(xprv)[-1].encode('hex')
            EC = bitcoin.EC_KEY(k.decode('hex'))
            message = EC.decrypt_message(message)
        except Exception as e:
            traceback.print_exc(file=sys.stdout)
            window.show_message(str(e))
            return

        self.listener.clear(keyhash)
        tx = transaction.Transaction(message)
        show_transaction(tx, window, prompt_if_unsaved=True)
Exemplo n.º 24
0
    def _initialize_device(self, settings, method, device_id, wizard, handler):
        item, label, pin_protection, passphrase_protection = settings

        if method == TIM_RECOVER and self.device == 'TREZOR':
            # Warn user about firmware lameness
            handler.show_error(
                _("You will be asked to enter 24 words regardless of your "
                  "seed's actual length.  If you enter a word incorrectly or "
                  "misspell it, you cannot change it or go back - you will need "
                  "to start again from the beginning.\n\nSo please enter "
                  "the words carefully!"))

        language = 'english'
        devmgr = self.device_manager()
        client = devmgr.client_by_id(device_id)

        if method == TIM_NEW:
            strength = 64 * (item + 2)  # 128, 192 or 256
            u2f_counter = 0
            skip_backup = False
            client.reset_device(True, strength, passphrase_protection,
                                pin_protection, label, language, u2f_counter,
                                skip_backup)
        elif method == TIM_RECOVER:
            word_count = 6 * (item + 2)  # 12, 18 or 24
            client.step = 0
            client.recovery_device(word_count, passphrase_protection,
                                   pin_protection, label, language)
        elif method == TIM_MNEMONIC:
            pin = pin_protection  # It's the pin, not a boolean
            client.load_device_by_mnemonic(str(item), pin,
                                           passphrase_protection, label,
                                           language)
        else:
            pin = pin_protection  # It's the pin, not a boolean
            client.load_device_by_xprv(item, pin, passphrase_protection, label,
                                       language)
        wizard.loop.exit(0)
    def update_unsubmitted_proposals(self):
        """Update the list of unsubmitted proposals."""
        self.unsubmitted_proposals = []
        for p in self.parent.masternode_manager.proposals:
            if p.fee_txid and not p.submitted and not p.rejected:
                confirmations, timestamp = self.parent.wallet.get_confirmations(
                    p.fee_txid)
                if confirmations < BUDGET_FEE_CONFIRMATIONS:
                    continue

                item = (p.proposal_name, p.fee_txid)
                if item not in self.unsubmitted_proposals:
                    self.unsubmitted_proposals.append(item)

        can_submit = len(self.unsubmitted_proposals) > 0
        self.submit_ready_proposals_button.setEnabled(can_submit)

        num = len(self.unsubmitted_proposals)
        noun = 'proposal%s' % ('' if num == 1 else 's')
        article = 'is' if num == 1 else 'are'
        self.ready_proposals.setText(
            str(num) + _(' %s %s ready to be submitted.' % (noun, article)))
        self.ready_proposals.setVisible(can_submit)
Exemplo n.º 26
0
 def f(b):
     if b:
         msg = ' '.join([
             '<b>' + _('Warning') + '</b>' + ': ',
             _('BIP39 seeds may not be supported in the future.'),
             '<br/><br/>',
             _('As technology matures, PAC address generation may change.'
               ),
             _('However, BIP39 seeds do not include a version number.'
               ),
             _('As a result, it is not possible to infer your wallet type from a BIP39 seed.'
               ),
             '<br/><br/>',
             _('We do not guarantee that BIP39 seeds will be supported in future versions of Electrum-PAC.'
               ),
             _('We recommend to use seeds generated by Electrum-PAC or compatible wallets.'
               ),
         ])
         #self.parent.show_warning(msg)
     self.seed_type_label.setVisible(not b)
     self.is_seed = (lambda x: bool(x)) if b else self.saved_is_seed
     self.on_edit()
Exemplo n.º 27
0
    def send(self, window, addr):
        from electrum_PAC import paymentrequest
        r = window.wallet.receive_requests.get(addr)
        message = r.get('memo', '')
        if r.get('signature'):
            pr = paymentrequest.serialize_request(r)
        else:
            pr = paymentrequest.make_request(self.config, r)
        if not pr:
            return
        recipient, ok = QtGui.QInputDialog.getText(window, 'Send request',
                                                   'Email invoice to:')
        if not ok:
            return
        recipient = str(recipient)
        payload = pr.SerializeToString()
        self.print_error('sending mail to', recipient)
        try:
            self.processor.send(recipient, message, payload)
        except BaseException as e:
            window.show_message(str(e))
            return

        window.show_message(_('Request sent.'))
Exemplo n.º 28
0
    def create_menu(self, position):
        menu = QMenu()
        selected = self.selectedItems()
        if not selected:
            menu.addAction(_("New contact"), lambda: self.parent.new_contact_dialog())
            menu.addAction(_("Import file"), lambda: self.parent.import_contacts())
        else:
            names = [unicode(item.text(0)) for item in selected]
            keys = [unicode(item.text(1)) for item in selected]
            column = self.currentColumn()
            column_title = self.headerItem().text(column)
            column_data = '\n'.join([unicode(item.text(column)) for item in selected])
            menu.addAction(_("Copy %s")%column_title, lambda: self.parent.app.clipboard().setText(column_data))
            if column in self.editable_columns:
                menu.addAction(_("Edit %s")%column_title, lambda: self.editItem(item, column))
            menu.addAction(_("Pay to"), lambda: self.parent.payto_contacts(keys))
            menu.addAction(_("Delete"), lambda: self.parent.delete_contacts(keys))
            URLs = [block_explorer_URL(self.config, 'addr', key) for key in filter(is_address, keys)]
            if URLs:
                menu.addAction(_("View on block explorer"), lambda: map(webbrowser.open, URLs))

        run_hook('create_contact_menu', menu, selected)
        menu.exec_(self.viewport().mapToGlobal(position))
Exemplo n.º 29
0
    def __init__(self, parent=None):
        super(PrevOutWidget, self).__init__(parent)
        self.vin = {}
        self.hash_edit = QLineEdit()
        self.hash_edit.setPlaceholderText(_('The TxID of your 1000 PAC output'))
        self.index_edit = QLineEdit()
        self.index_edit.setPlaceholderText(_('The output number of your 1000 PAC output'))
        self.address_edit = QLineEdit()
        self.address_edit.setPlaceholderText(_('The address that 1000 PAC was sent to'))

        # Collection of fields so that it's easier to act on them all at once.
        self.fields = (self.hash_edit, self.index_edit, self.address_edit)
        for i in self.fields:
            i.setFont(QFont(util.MONOSPACE_FONT))

        form = QFormLayout()
        form.setContentsMargins(0, 0, 0, 0)
        form.addRow(_('TxID:'), self.hash_edit)
        form.addRow(_('Output Index:'), self.index_edit)
        form.addRow(_('Address:'), self.address_edit)
        self.setLayout(form)
Exemplo n.º 30
0
    def sign_transaction(self, tx, password):
        if tx.is_complete():
            return

        try:
            p2shTransaction = False
            derivations = self.get_tx_derivations(tx)
            inputhasharray = []
            hasharray = []
            pubkeyarray = []

            # Build hasharray from inputs
            for i, txin in enumerate(tx.inputs()):
                if txin['type'] == 'coinbase':
                    self.give_error(
                        "Coinbase not supported")  # should never happen

                if txin['type'] in ['p2sh']:
                    p2shTransaction = True

                for x_pubkey in txin['x_pubkeys']:
                    if x_pubkey in derivations:
                        index = derivations.get(x_pubkey)
                        inputPath = "%s/%d/%d" % (self.get_derivation(),
                                                  index[0], index[1])
                        inputHash = Hash(
                            tx.serialize_preimage(i).decode('hex'))
                        hasharray_i = {
                            'hash': inputHash.encode('hex'),
                            'keypath': inputPath
                        }
                        hasharray.append(hasharray_i)
                        inputhasharray.append(inputHash)
                        break
                else:
                    self.give_error("No matching x_key for sign_transaction"
                                    )  # should never happen

            # Sanity check
            if p2shTransaction:
                for txinput in tx.inputs():
                    if txinput['type'] != 'p2sh':
                        self.give_error(
                            "P2SH / regular input mixed in same transaction not supported"
                        )  # should never happen

            # Build pubkeyarray from outputs (unused because echo for smart verification not implemented)
            if not p2shTransaction:
                for _type, address, amount in tx.outputs():
                    assert _type == TYPE_ADDRESS
                    info = tx.output_info.get(address)
                    if info is not None:
                        index, xpubs, m = info
                        changePath = self.get_derivation() + "/%d/%d" % index
                        changePubkey = self.derive_pubkey(index[0], index[1])
                        pubkeyarray_i = {
                            'pubkey': changePubkey,
                            'keypath': changePath
                        }
                        pubkeyarray.append(pubkeyarray_i)

            # Build sign command
            dbb_signatures = []
            steps = math.ceil(1.0 * len(hasharray) / self.maxInputs)
            for step in range(int(steps)):
                hashes = hasharray[step * self.maxInputs:(step + 1) *
                                   self.maxInputs]

                msg = '{"sign": {"meta":"%s", "data":%s, "checkpub":%s} }' % \
                       (Hash(tx.serialize()).encode('hex'), json.dumps(hashes), json.dumps(pubkeyarray))

                dbb_client = self.plugin.get_client(self)

                if not dbb_client.is_paired():
                    raise Exception("Could not sign transaction.")

                reply = dbb_client.hid_send_encrypt(msg)

                if 'error' in reply:
                    raise Exception(reply['error']['message'])

                if 'echo' not in reply:
                    raise Exception("Could not sign transaction.")

                if steps > 1:
                    self.handler.show_message(_("Signing large transaction. Please be patient ...\r\n\r\n" \
                                                "To continue, touch the Digital Bitbox's blinking light for 3 seconds. " \
                                                "(Touch " + str(step + 1) + " of " + str(int(steps)) + ")\r\n\r\n" \
                                                "To cancel, briefly touch the blinking light or wait for the timeout.\r\n\r\n"))
                else:
                    self.handler.show_message(_("Signing transaction ...\r\n\r\n" \
                                                "To continue, touch the Digital Bitbox's blinking light for 3 seconds.\r\n\r\n" \
                                                "To cancel, briefly touch the blinking light or wait for the timeout."))

                reply = dbb_client.hid_send_encrypt(
                    msg
                )  # Send twice, first returns an echo for smart verification (not implemented)
                self.handler.clear_dialog()

                if 'error' in reply:
                    raise Exception(reply['error']['message'])

                if 'sign' not in reply:
                    raise Exception("Could not sign transaction.")

                dbb_signatures.extend(reply['sign'])

            # Fill signatures
            if len(dbb_signatures) <> len(tx.inputs()):
                raise Exception("Incorrect number of transactions signed."
                                )  # Should never occur
            for i, txin in enumerate(tx.inputs()):
                num = txin['num_sig']
                for pubkey in txin['pubkeys']:
                    signatures = filter(None, txin['signatures'])
                    if len(signatures) == num:
                        break  # txin is complete
                    ii = txin['pubkeys'].index(pubkey)
                    signed = dbb_signatures[i]
                    if 'recid' in signed:
                        # firmware > v2.1.1
                        recid = int(signed['recid'], 16)
                        s = signed['sig'].decode('hex')
                        h = inputhasharray[i]
                        pk = MyVerifyingKey.from_signature(s,
                                                           recid,
                                                           h,
                                                           curve=SECP256k1)
                        pk = point_to_ser(pk.pubkey.point, True).encode('hex')
                    elif 'pubkey' in signed:
                        # firmware <= v2.1.1
                        pk = signed['pubkey']
                    if pk != pubkey:
                        continue
                    sig_r = int(signed['sig'][:64], 16)
                    sig_s = int(signed['sig'][64:], 16)
                    sig = sigencode_der(sig_r, sig_s,
                                        generator_secp256k1.order())
                    txin['signatures'][ii] = sig.encode('hex') + '01'
                    tx._inputs[i] = txin

        except BaseException as e:
            self.give_error(e, True)
        else:
            print_error("Transaction is_complete", tx.is_complete())
            tx.raw = tx.serialize()