Example #1
0
 def receive_list_menu(self, menu, addr):
     window = menu.parentWidget()
     menu.addAction(_("Send via e-mail"), lambda: self.send(window, addr))
Example #2
0
    def create_menu(self, position):
        from fermatum.wallet import Multisig_Wallet
        is_multisig = isinstance(self.wallet, Multisig_Wallet)
        can_delete = self.wallet.can_delete_address()
        selected = self.selectedItems()
        multi_select = len(selected) > 1
        addrs = [unicode(item.text(0)) for item in selected]
        if not addrs:
            return
        if not multi_select:
            item = self.itemAt(position)
            col = self.currentColumn()
            if not item:
                return
            addr = addrs[0]
            if not is_address(addr):
                item.setExpanded(not item.isExpanded())
                return

        menu = QMenu()
        if not multi_select:
            column_title = self.headerItem().text(col)
            menu.addAction(
                _("Copy %s") % column_title,
                lambda: self.parent.app.clipboard().setText(item.text(col)))
            if col in self.editable_columns:
                menu.addAction(
                    _("Edit %s") % column_title,
                    lambda: self.editItem(item, col))
            menu.addAction(_("Request payment"),
                           lambda: self.parent.receive_at(addr))
            menu.addAction(_('History'),
                           lambda: self.parent.show_address(addr))
            menu.addAction(_('Public Keys'),
                           lambda: self.parent.show_public_keys(addr))
            if self.wallet.can_export():
                menu.addAction(_("Private key"),
                               lambda: self.parent.show_private_key(addr))
            if not is_multisig and not self.wallet.is_watching_only():
                menu.addAction(_("Sign/verify message"),
                               lambda: self.parent.sign_verify_message(addr))
                menu.addAction(_("Encrypt/decrypt message"),
                               lambda: self.parent.encrypt_message(addr))
            if can_delete:
                menu.addAction(_("Remove from wallet"),
                               lambda: self.parent.remove_address(addr))
            addr_URL = block_explorer_URL(self.config, 'addr', addr)
            if addr_URL:
                menu.addAction(_("View on block explorer"),
                               lambda: webbrowser.open(addr_URL))

            if not self.wallet.is_frozen(addr):
                menu.addAction(
                    _("Freeze"),
                    lambda: self.parent.set_frozen_state([addr], True))
            else:
                menu.addAction(
                    _("Unfreeze"),
                    lambda: self.parent.set_frozen_state([addr], False))

        coins = self.wallet.get_utxos(addrs)
        if coins:
            menu.addAction(_("Spend from"),
                           lambda: self.parent.spend_coins(coins))

        run_hook('receive_menu', menu, addrs, self.wallet)
        menu.exec_(self.viewport().mapToGlobal(position))
Example #3
0
 def description(self):
     return _("Send and receive payment requests via email")
Example #4
0
 def copy_to_clipboard():
     p = QPixmap.grabWindow(qrw.winId())
     p.save(filename, 'png')
     QApplication.clipboard().setImage(QImage(filename))
     self.show_message(_("QR code copied to clipboard"))
Example #5
0
 def __init__(self, parent=None):
     MyTreeWidget.__init__(
         self, parent, self.create_menu,
         [_('Address'), _('Label'),
          _('Balance'), _('Tx')], 1)
     self.setSelectionMode(QAbstractItemView.ExtendedSelection)
Example #6
0
from fermatum.i18n import _
fullname = _('Cosigner Pool')
description = ' '.join([
    _("This plugin facilitates the use of multi-signatures wallets."),
    _("It sends and receives partially signed transactions from/to your cosigner wallet."
      ),
    _("Transactions are encrypted and stored on a remote server.")
])
#requires_wallet_type = ['2of2', '2of3']
available_for = ['qt']
Example #7
0
 def __init__(self, text=""):
     ButtonsTextEdit.__init__(self, text)
     self.setReadOnly(0)
     self.addButton(":icons/file.png", self.file_input, _("Read file"))
     self.addButton(":icons/qrcode.png", self.qr_input, _("Read QR code"))
     run_hook('scan_text_edit', self)
Example #8
0
 def change_label(self, label):
     self.msg = _("Confirm the new label on your %s device")
     self.apply_settings(label=label)
Example #9
0
 def change_homescreen(self, homescreen):
     self.msg = _("Confirm on your %s device to change your home screen")
     self.apply_settings(homescreen=homescreen)
Example #10
0
 def decrypt_message(self, pubkey, message, password):
     raise RuntimeError(
         _('Encryption and decryption are currently not supported for %s') %
         self.device)
Example #11
0
    def sign_transaction(self, tx, password):
        if tx.is_complete():
            return
        client = self.get_client()
        self.signing = True
        inputs = []
        inputsPaths = []
        pubKeys = []
        chipInputs = []
        redeemScripts = []
        signatures = []
        preparedTrustedInputs = []
        changePath = ""
        changeAmount = None
        output = None
        outputAmount = None
        p2shTransaction = False
        reorganize = False
        pin = ""
        self.get_client(
        )  # prompt for the PIN before displaying the dialog if necessary

        # Fetch inputs of the transaction to sign
        derivations = self.get_tx_derivations(tx)
        for txin in tx.inputs():
            if txin['type'] == 'coinbase':
                self.give_error(
                    "Coinbase not supported")  # should never happen

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

            pubkeys, x_pubkeys = tx.get_sorted_pubkeys(txin)
            for i, x_pubkey in enumerate(x_pubkeys):
                if x_pubkey in derivations:
                    signingPos = i
                    s = derivations.get(x_pubkey)
                    hwAddress = "%s/%d/%d" % (self.get_derivation()[2:], s[0],
                                              s[1])
                    break
            else:
                self.give_error("No matching x_key for sign_transaction"
                                )  # should never happen

            inputs.append([
                txin['prev_tx'].raw, txin['prevout_n'],
                txin.get('redeemScript'), txin['prevout_hash'], signingPos
            ])
            inputsPaths.append(hwAddress)
            pubKeys.append(pubkeys)

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

        txOutput = var_int(len(tx.outputs()))
        for txout in tx.outputs():
            output_type, addr, amount = txout
            txOutput += int_to_hex(amount, 8)
            script = tx.pay_script(output_type, addr)
            txOutput += var_int(len(script) / 2)
            txOutput += script
        txOutput = txOutput.decode('hex')

        # Recognize outputs - only one output and one change is authorized
        if not p2shTransaction:
            if not self.get_client_fermatum().supports_multi_output():
                if len(tx.outputs()) > 2:
                    self.give_error(
                        "Transaction with more than 2 outputs not supported")
            for _type, address, amount in tx.outputs():
                assert _type == TYPE_ADDRESS
                info = tx.output_info.get(address)
                if (info is not None) and (len(tx.outputs()) != 1):
                    index, xpubs, m = info
                    changePath = self.get_derivation()[2:] + "/%d/%d" % index
                    changeAmount = amount
                else:
                    output = address
                    outputAmount = amount

        self.handler.show_message(
            _("Confirm Transaction on your Ledger device..."))
        try:
            # Get trusted inputs from the original transactions
            for utxo in inputs:
                if not p2shTransaction:
                    txtmp = iopTransaction(bytearray(utxo[0].decode('hex')))
                    chipInputs.append(self.get_client().getTrustedInput(
                        txtmp, utxo[1]))
                    redeemScripts.append(txtmp.outputs[utxo[1]].script)
                else:
                    tmp = utxo[3].decode('hex')[::-1].encode('hex')
                    tmp += int_to_hex(utxo[1], 4)
                    chipInputs.append({'value': tmp.decode('hex')})
                    redeemScripts.append(bytearray(utxo[2].decode('hex')))

            # Sign all inputs
            firstTransaction = True
            inputIndex = 0
            rawTx = tx.serialize()
            self.get_client().enableAlternate2fa(False)
            while inputIndex < len(inputs):
                self.get_client().startUntrustedTransaction(
                    firstTransaction, inputIndex, chipInputs,
                    redeemScripts[inputIndex])
                if not p2shTransaction:
                    outputData = self.get_client().finalizeInput(
                        output, format_satoshis_plain(outputAmount),
                        format_satoshis_plain(tx.get_fee()), changePath,
                        bytearray(rawTx.decode('hex')))
                    reorganize = True
                else:
                    outputData = self.get_client().finalizeInputFull(txOutput)
                    outputData['outputData'] = txOutput

                if firstTransaction:
                    transactionOutput = outputData['outputData']
                if outputData['confirmationNeeded']:
                    outputData['address'] = output
                    self.handler.clear_dialog()
                    pin = self.handler.get_auth(
                        outputData
                    )  # does the authenticate dialog and returns pin
                    if not pin:
                        raise UserWarning()
                    if pin != 'paired':
                        self.handler.show_message(
                            _("Confirmed. Signing Transaction..."))
                else:
                    # Sign input with the provided PIN
                    inputSignature = self.get_client().untrustedHashSign(
                        inputsPaths[inputIndex], pin)
                    inputSignature[0] = 0x30  # force for 1.4.9+
                    signatures.append(inputSignature)
                    inputIndex = inputIndex + 1
                if pin != 'paired':
                    firstTransaction = False
        except UserWarning:
            self.handler.show_error(_('Cancelled by user'))
            return
        except BaseException as e:
            traceback.print_exc(file=sys.stdout)
            self.give_error(e, True)
        finally:
            self.handler.clear_dialog()

        # Reformat transaction
        inputIndex = 0
        while inputIndex < len(inputs):
            if p2shTransaction:
                signaturesPack = [signatures[inputIndex]] * len(
                    pubKeys[inputIndex])
                inputScript = get_p2sh_input_script(redeemScripts[inputIndex],
                                                    signaturesPack)
                preparedTrustedInputs.append([
                    ("\x00" * 4) + chipInputs[inputIndex]['value'], inputScript
                ])
            else:
                inputScript = get_regular_input_script(
                    signatures[inputIndex],
                    pubKeys[inputIndex][0].decode('hex'))
                preparedTrustedInputs.append(
                    [chipInputs[inputIndex]['value'], inputScript])
            inputIndex = inputIndex + 1
        updatedTransaction = format_transaction(transactionOutput,
                                                preparedTrustedInputs)
        updatedTransaction = hexlify(updatedTransaction)

        if reorganize:
            tx.update(updatedTransaction)
        else:
            tx.update_signatures(updatedTransaction)
        self.signing = False
Example #12
0
class Ledger_KeyStore(Hardware_KeyStore):
    hw_type = 'ledger'
    device = 'Ledger'

    def __init__(self, d):
        Hardware_KeyStore.__init__(self, d)
        # Errors and other user interaction is done through the wallet's
        # handler.  The handler is per-window and preserved across
        # device reconnects
        self.force_watching_only = False
        self.signing = False
        self.cfg = d.get('cfg', {'mode': 0, 'pair': ''})

    def dump(self):
        obj = Hardware_KeyStore.dump(self)
        obj['cfg'] = self.cfg
        return obj

    def get_derivation(self):
        return self.derivation

    def get_client(self):
        return self.plugin.get_client(self).dongleObject

    def get_client_fermatum(self):
        return self.plugin.get_client(self)

    def give_error(self, message, clear_client=False):
        print_error(message)
        if not self.signing:
            self.handler.show_error(message)
        else:
            self.signing = False
        if clear_client:
            self.client = None
        raise Exception(message)

    def address_id_stripped(self, address):
        # Strip the leading "m/"
        change, index = self.get_address_index(address)
        derivation = self.derivation
        address_path = "%s/%d/%d" % (derivation, change, index)
        return address_path[2:]

    def decrypt_message(self, pubkey, message, password):
        raise RuntimeError(
            _('Encryption and decryption are currently not supported for %s') %
            self.device)

    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)
        except UserWarning:
            self.handler.show_error(_('Cancelled by user'))
            return ''
Example #13
0
    def sign_transaction(self, tx, password):
        if tx.is_complete():
            return

        try:
            p2shTransaction = False
            derivations = self.get_tx_derivations(tx)
            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')).encode('hex')
                        hasharray_i = {'hash': inputHash, 'keypath': inputPath}
                        hasharray.append(hasharray_i)
                        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 signed['pubkey'] != 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')
                    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()
Example #14
0
    def show_settings_dialog(self, window, success):
        if not success:
            window.show_message(_('Server not reachable.'))
            return

        wallet = window.wallet
        d = WindowModalDialog(window, _("TrustedCoin Information"))
        d.setMinimumSize(500, 200)
        vbox = QVBoxLayout(d)
        hbox = QHBoxLayout()

        logo = QLabel()
        logo.setPixmap(QPixmap(":icons/trustedcoin-status.png"))
        msg = _('This wallet is protected by TrustedCoin\'s two-factor authentication.') + '<br/>'\
              + _("For more information, visit") + " <a href=\"https://api.trustedcoin.com/#/fermatum-help\">https://api.trustedcoin.com/#/fermatum-help</a>"
        label = QLabel(msg)
        label.setOpenExternalLinks(1)

        hbox.addStretch(10)
        hbox.addWidget(logo)
        hbox.addStretch(10)
        hbox.addWidget(label)
        hbox.addStretch(10)

        vbox.addLayout(hbox)
        vbox.addStretch(10)

        msg = _(
            'TrustedCoin charges a fee per co-signed transaction. You may pay on each transaction (an extra output will be added to your transaction), or you may purchase prepaid transaction using this dialog.'
        ) + '<br/>'
        label = QLabel(msg)
        label.setWordWrap(1)
        vbox.addWidget(label)

        vbox.addStretch(10)
        grid = QGridLayout()
        vbox.addLayout(grid)

        price_per_tx = wallet.price_per_tx
        v = price_per_tx.get(1)
        grid.addWidget(QLabel(_("Price per transaction (not prepaid):")), 0, 0)
        grid.addWidget(
            QLabel(window.format_amount(v) + ' ' + window.base_unit()), 0, 1)

        i = 1

        for k, v in sorted(price_per_tx.items()):
            if k == 1:
                continue
            grid.addWidget(QLabel("Price for %d prepaid transactions:" % k), i,
                           0)
            grid.addWidget(
                QLabel("%d x " % k + window.format_amount(v / k) + ' ' +
                       window.base_unit()), i, 1)
            b = QPushButton(_("Buy"))
            b.clicked.connect(lambda b, k=k, v=v: self.on_buy(window, k, v, d))
            grid.addWidget(b, i, 2)
            i += 1

        n = wallet.billing_info.get('tx_remaining', 0)
        grid.addWidget(
            QLabel(_("Your wallet has %d prepaid transactions.") % n), i, 0)

        # tranfer button
        #def on_transfer():
        #    server.transfer_credit(self.user_id, recipient, otp, signature_callback)
        #    pass
        #b = QPushButton(_("Transfer"))
        #b.clicked.connect(on_transfer)
        #grid.addWidget(b, 1, 2)

        #grid.addWidget(QLabel(_("Next Billing Address:")), i, 0)
        #grid.addWidget(QLabel(self.billing_info['billing_address']), i, 1)
        vbox.addLayout(Buttons(CloseButton(d)))
        d.exec_()
Example #15
0
 def settings_widget(self, window):
     return EnterButton(_('Settings'), partial(self.settings_dialog,
                                               window))
Example #16
0
class GuiMixin(object):
    # Requires: self.proto, self.device

    messages = {
        3:
        _("Confirm the transaction output on your %s device"),
        4:
        _("Confirm internal entropy on your %s device to begin"),
        5:
        _("Write down the seed word shown on your %s"),
        6:
        _("Confirm on your %s that you want to wipe it clean"),
        7:
        _("Confirm on your %s device the message to sign"),
        8:
        _("Confirm the total amount spent and the transaction fee on your "
          "%s device"),
        10:
        _("Confirm wallet address on your %s device"),
        'default':
        _("Check your %s device to continue"),
    }

    def callback_Failure(self, msg):
        # BaseClient's unfortunate call() implementation forces us to
        # raise exceptions on failure in order to unwind the stack.
        # However, making the user acknowledge they cancelled
        # gets old very quickly, so we suppress those.  The NotInitialized
        # one is misnamed and indicates a passphrase request was cancelled.
        if msg.code in (self.types.Failure_PinCancelled,
                        self.types.Failure_ActionCancelled,
                        self.types.Failure_NotInitialized):
            raise UserCancelled()
        raise RuntimeError(msg.message)

    def callback_ButtonRequest(self, msg):
        message = self.msg
        if not message:
            message = self.messages.get(msg.code, self.messages['default'])
        self.handler.show_message(message % self.device, self.cancel)
        return self.proto.ButtonAck()

    def callback_PinMatrixRequest(self, msg):
        if msg.type == 2:
            msg = _("Enter a new PIN for your %s:")
        elif msg.type == 3:
            msg = (_("Re-enter the new PIN for your %s.\n\n"
                     "NOTE: the positions of the numbers have changed!"))
        else:
            msg = _("Enter your current %s PIN:")
        pin = self.handler.get_pin(msg % self.device)
        if not pin:
            return self.proto.Cancel()
        return self.proto.PinMatrixAck(pin=pin)

    def callback_PassphraseRequest(self, req):
        if self.creating_wallet:
            msg = _("Enter a passphrase to generate this wallet.  Each time "
                    "you use this wallet your %s will prompt you for the "
                    "passphrase.  If you forget the passphrase you cannot "
                    "access the IoPs in the wallet.") % self.device
        else:
            msg = _("Enter the passphrase to unlock this wallet:")
        passphrase = self.handler.get_passphrase(msg, self.creating_wallet)
        if passphrase is None:
            return self.proto.Cancel()
        passphrase = bip39_normalize_passphrase(passphrase)
        return self.proto.PassphraseAck(passphrase=passphrase)

    def callback_WordRequest(self, msg):
        self.step += 1
        msg = _("Step %d/24.  Enter seed word as explained on "
                "your %s:") % (self.step, self.device)
        word = self.handler.get_word(msg)
        # Unfortunately the device can't handle self.proto.Cancel()
        return self.proto.WordAck(word=word)

    def callback_CharacterRequest(self, msg):
        char_info = self.handler.get_char(msg)
        if not char_info:
            return self.proto.Cancel()
        return self.proto.CharacterAck(**char_info)
Example #17
0
    def __init__(self, network, config, wizard=False):
        self.network = network
        self.config = config
        self.protocol = None
        self.tor_proxy = None

        self.servers = network.get_servers()
        host, port, protocol, proxy_config, auto_connect = network.get_parameters(
        )
        if not proxy_config:
            proxy_config = {
                "mode": "none",
                "host": "localhost",
                "port": "9050"
            }

        if not wizard:
            n = len(network.get_interfaces())
            if n:
                status = _("Blockchain") + ": " + "%d " % (
                    network.get_local_height()) + _("blocks") + ".\n" + _(
                        "Getting block headers from %d nodes.") % n
            else:
                status = _("Not connected")
            if network.is_connected():
                status += "\n" + _("Server") + ": %s" % (host)
            else:
                status += "\n" + _("Disconnected from server")
        else:
            status = _("Please choose a server.") + "\n" + _(
                "Press 'Next' if you are offline.")

        vbox = QVBoxLayout()
        hbox = QHBoxLayout()
        l = QLabel()
        l.setPixmap(QPixmap(":icons/network.png"))
        hbox.addStretch(10)
        hbox.addWidget(l)
        hbox.addWidget(QLabel(status))
        hbox.addStretch(50)
        msg = _("Fermatum sends your wallet addresses to a single server, in order to receive your transaction history.") + "\n\n" \
            + _("In addition, Fermatum connects to several nodes in order to download block headers and find out the longest blockchain.") + " " \
            + _("This blockchain is used to verify the transactions sent by the address server.")
        hbox.addWidget(HelpButton(msg))
        vbox.addLayout(hbox)
        vbox.addSpacing(15)

        # grid layout
        grid = QGridLayout()
        grid.setSpacing(8)
        vbox.addLayout(grid)

        # server
        self.server_host = QLineEdit()
        self.server_host.setFixedWidth(200)
        self.server_port = QLineEdit()
        self.server_port.setFixedWidth(60)

        grid.addWidget(QLabel(_('Server') + ':'), 0, 0)
        grid.addWidget(self.server_host, 0, 1, 1, 2)
        grid.addWidget(self.server_port, 0, 3)

        # use SSL
        self.ssl_cb = QCheckBox(_('Use SSL'))
        self.ssl_cb.setChecked(auto_connect)
        grid.addWidget(self.ssl_cb, 0, 2, 1, 1, Qt.AlignRight)
        self.ssl_cb.stateChanged.connect(self.change_protocol)

        # auto connect
        self.autoconnect_cb = QCheckBox(_('Select server automatically'))
        self.autoconnect_cb.setChecked(auto_connect)
        grid.addWidget(self.autoconnect_cb, 1, 1, 1, 3)
        self.autoconnect_cb.setEnabled(
            self.config.is_modifiable('auto_connect'))
        msg = _("If auto-connect is enabled, Fermatum will always use a server that is on the longest blockchain.") + "\n" \
            + _("If it is disabled, Fermatum will warn you if your server is lagging.")
        self.autoconnect_cb.setToolTip(msg)

        label = _('Active Servers') if network.is_connected() else _(
            'Default Servers')
        self.servers_list_widget = QTreeWidget()
        self.servers_list_widget.setHeaderLabels([label, _('Limit')])
        self.servers_list_widget.setMaximumHeight(150)
        self.servers_list_widget.setColumnWidth(0, 240)

        self.change_server(host, protocol)
        self.set_protocol(protocol)
        self.servers_list_widget.connect(
            self.servers_list_widget,
            SIGNAL('currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)'),
            lambda x, y: self.server_changed(x))
        grid.addWidget(self.servers_list_widget, 2, 1, 1, 3)

        def enable_set_server():
            if config.is_modifiable('server'):
                enabled = not self.autoconnect_cb.isChecked()
                self.server_host.setEnabled(enabled)
                self.server_port.setEnabled(enabled)
                self.servers_list_widget.setEnabled(enabled)
            else:
                for w in [
                        self.autoconnect_cb, self.server_host,
                        self.server_port, self.ssl_cb, self.servers_list_widget
                ]:
                    w.setEnabled(False)

        self.autoconnect_cb.clicked.connect(enable_set_server)
        enable_set_server()

        # proxy setting
        self.proxy_mode = QComboBox()
        self.proxy_host = QLineEdit()
        self.proxy_host.setFixedWidth(200)
        self.proxy_port = QLineEdit()
        self.proxy_port.setFixedWidth(60)
        self.proxy_mode.addItems(['NONE', 'SOCKS4', 'SOCKS5', 'HTTP'])
        self.proxy_user = QLineEdit()
        self.proxy_user.setPlaceholderText(_("Proxy user"))
        self.proxy_password = QLineEdit()
        self.proxy_password.setPlaceholderText(_("Password"))
        self.proxy_password.setEchoMode(QLineEdit.Password)
        self.proxy_password.setFixedWidth(60)

        def check_for_disable(index=False):
            if self.config.is_modifiable('proxy'):
                for w in [
                        self.proxy_host, self.proxy_port, self.proxy_user,
                        self.proxy_password
                ]:
                    w.setEnabled(self.proxy_mode.currentText() != 'NONE')
            else:
                for w in [self.proxy_host, self.proxy_port, self.proxy_mode]:
                    w.setEnabled(False)

        check_for_disable()
        self.proxy_mode.connect(self.proxy_mode,
                                SIGNAL('currentIndexChanged(int)'),
                                check_for_disable)

        self.proxy_mode.setCurrentIndex(
            self.proxy_mode.findText(str(proxy_config.get("mode").upper())))
        self.proxy_host.setText(proxy_config.get("host"))
        self.proxy_port.setText(proxy_config.get("port"))
        self.proxy_user.setText(proxy_config.get("user", ""))
        self.proxy_password.setText(proxy_config.get("password", ""))

        self.proxy_mode.connect(self.proxy_mode,
                                SIGNAL('currentIndexChanged(int)'),
                                self.proxy_settings_changed)
        self.proxy_host.connect(self.proxy_host, SIGNAL('textEdited(QString)'),
                                self.proxy_settings_changed)
        self.proxy_port.connect(self.proxy_port, SIGNAL('textEdited(QString)'),
                                self.proxy_settings_changed)
        self.proxy_user.connect(self.proxy_user, SIGNAL('textEdited(QString)'),
                                self.proxy_settings_changed)
        self.proxy_password.connect(self.proxy_password,
                                    SIGNAL('textEdited(QString)'),
                                    self.proxy_settings_changed)

        grid.addWidget(QLabel(_('Proxy') + ':'), 4, 0)
        grid.addWidget(self.proxy_mode, 4, 1)
        grid.addWidget(self.proxy_host, 4, 2)
        grid.addWidget(self.proxy_port, 4, 3)
        grid.addWidget(self.proxy_user, 5, 2)
        grid.addWidget(self.proxy_password, 5, 3)
        self.tor_button = QCheckBox(_("Use Tor Proxy"))
        self.tor_button.setIcon(QIcon(":icons/tor_logo.png"))
        self.tor_button.hide()
        self.tor_button.clicked.connect(self.use_tor_proxy)
        grid.addWidget(self.tor_button, 6, 2, 1, 2)
        self.layout_ = vbox
        self.td = td = TorDetector()
        td.found_proxy.connect(self.suggest_proxy)
        td.start()
Example #18
0
class Plugin(BasePlugin):

    button_label = _("Verify GA instant")

    @hook
    def transaction_dialog(self, d):
        d.verify_button = QPushButton(self.button_label)
        d.verify_button.clicked.connect(lambda: self.do_verify(d))
        d.buttons.insert(0, d.verify_button)
        self.transaction_dialog_update(d)

    def get_my_addr(self, d):
        """Returns the address for given tx which can be used to request
        instant confirmation verification from GreenAddress"""
        for addr, _ in d.tx.get_outputs():
            if d.wallet.is_mine(addr):
                return addr
        return None

    @hook
    def transaction_dialog_update(self, d):
        if d.tx.is_complete() and self.get_my_addr(d):
            d.verify_button.show()
        else:
            d.verify_button.hide()

    def do_verify(self, d):
        tx = d.tx
        wallet = d.wallet
        window = d.parent
        # 1. get the password and sign the verification request
        password = None
        if wallet.use_encryption:
            msg = _('GreenAddress requires your signature \n'
                    'to verify that transaction is instant.\n'
                    'Please enter your password to sign a\n'
                    'verification request.')
            password = window.password_dialog(msg, parent=d)
            if not password:
                return
        try:
            d.verify_button.setText(_('Verifying...'))
            QApplication.processEvents()  # update the button label

            addr = self.get_my_addr(d)
            message = "Please verify if %s is GreenAddress instant confirmed" % tx.hash(
            )
            sig = wallet.sign_message(addr, message, password)
            sig = base64.b64encode(sig)

            # 2. send the request
            response = requests.request(
                "GET",
                ("https://greenaddress.it/verify/?signature=%s&txhash=%s" %
                 (urllib.quote(sig), tx.hash())),
                headers={'User-Agent': 'Fermatum'})
            response = response.json()

            # 3. display the result
            if response.get('verified'):
                d.show_message(
                    _('%s is covered by GreenAddress instant confirmation') %
                    (tx.hash()),
                    title=_('Verification successful!'))
            else:
                d.show_critical(
                    _('%s is not covered by GreenAddress instant confirmation')
                    % (tx.hash()),
                    title=_('Verification failed!'))
        except BaseException as e:
            import traceback
            traceback.print_exc(file=sys.stdout)
            d.show_error(str(e))
        finally:
            d.verify_button.setText(self.button_label)
Example #19
0
 def contextMenuEvent(self, e):
     m = self.createStandardContextMenu()
     m.addAction(_("Show as QR code"), self.qr_show)
     m.exec_(e.globalPos())
Example #20
0
 def done_processing(self, dialog, result):
     dialog.show_message(_("Your labels have been synchronised."))
Example #21
0
 def contextMenuEvent(self, e):
     m = self.createStandardContextMenu()
     m.addAction(_("Read QR code"), self.qr_input)
     m.exec_(e.globalPos())
Example #22
0
 def print_qr():
     p = QPixmap.grabWindow(qrw.winId())
     p.save(filename, 'png')
     self.show_message(_("QR code saved to file") + " " + filename)