Esempio n. 1
0
    def run(self):
        network = Network.get_instance()
        if not network:
            self.notify_offline()
            return

        for i, p in enumerate(self.DERIVATION_PATHS):
            if self.aborting:
                return
            k = keystore.from_seed(self.seed, '', derivation=p, seed_type=self.seed_type)
            p_safe = p.replace('/', '_').replace("'", 'h')
            storage_path = os.path.join(
                tempfile.gettempdir(),
                p_safe + '_' + random.getrandbits(32).to_bytes(4, 'big').hex()[:8] + "_not_saved_"
            )
            tmp_storage = WalletStorage(storage_path, in_memory_only=True)
            tmp_storage.put('seed_type', self.seed_type)
            tmp_storage.put('keystore', k.dump())
            wallet = Standard_Wallet(tmp_storage)
            try:
                wallet.start_threads(network)
                wallet.synchronize()
                wallet.print_error("Scanning", p)
                synched = False
                for ctr in range(25):
                    try:
                        wallet.wait_until_synchronized(timeout=1.0)
                        synched = True
                    except TimeoutException:
                        wallet.print_error(f'timeout try {ctr+1}/25')
                    if self.aborting:
                        return
                if not synched:
                    wallet.print_error("Timeout on", p)
                    self.notify_timedout(i)
                    continue
                while network.is_connecting():
                    time.sleep(0.1)
                    if self.aborting:
                        return
                num_tx = len(wallet.get_history())
                self.update_table_cb(i, str(num_tx))
            finally:
                wallet.clear_history()
                wallet.stop_threads()
Esempio n. 2
0
class NewBatchDialog(QDialog, MessageBoxMixin, PrintError):
    settings_updated_signal = pyqtSignal()

    def __init__(self, parent, plugin, wallet_name, password=None):
        QDialog.__init__(self, parent)
        self.main_window = parent
        self.password = password
        self.wallet = parent.wallet
        self.plugin = plugin
        self.network = parent.network
        self.wallet_name = wallet_name
        self.batch_label = "BitcoinBiletoj1"
        self.template_file = ''
        self.working_directory = self.wallet.storage.get("bileto_path")
        if self.working_directory:
            if not os.path.exists(self.working_directory):
                self.working_directory = None
        self.number = 0
        self.times = 1
        self.public_key = ''
        for x in range(10):
            name = 'tmp_wo_wallet' + ''.join(
                random.choices(string.ascii_letters + string.digits, k=10))
            self.file = os.path.join(tempfile.gettempdir(), name)
            if not os.path.exists(self.file):
                break
        else:
            raise RuntimeError(
                'Could not find a unique temp file in tmp directory',
                tempfile.gettempdir())
        self.tmp_pass = ''.join(
            random.choices(string.ascii_uppercase + string.digits, k=10))

        from electroncash import mnemonic
        seed = mnemonic.Mnemonic('en').make_seed('standard')
        self.keystore = keystore.from_seed(seed, self.tmp_pass, False)
        self.storage = WalletStorage(self.file)
        self.storage.set_password(self.tmp_pass, encrypt=True)
        self.storage.put('keystore', self.keystore.dump())
        self.recipient_wallet = Standard_Wallet(self.storage)
        self.recipient_wallet.start_threads(self.network)
        Weak.finalize(self.recipient_wallet, self.delete_temp_wallet_file,
                      self.file)
        vbox = QVBoxLayout()
        self.setLayout(vbox)
        hbox = QHBoxLayout()
        vbox.addLayout(hbox)
        l = QLabel("<b>%s</b>" % (_("Bitcoin Bileto")))
        hbox.addStretch(1)
        hbox.addWidget(l)
        hbox.addStretch(1)
        vbox.addWidget(QLabel("Working directory:"))
        hbox = QHBoxLayout()
        vbox.addLayout(hbox)
        self.wd_label = QLabel(self.working_directory)
        hbox.addWidget(self.wd_label)
        b = QPushButton("Set")
        b.clicked.connect(lambda: self.plugin.settings_dialog(
            self, self.settings_updated_signal))
        self.settings_updated_signal.connect(self.on_settings_updated)
        hbox.addWidget(b)
        data = "prywatny klucz do portfela"
        self.qrw_priv = QRCodeWidget(data)
        self.qrw_add = QRCodeWidget(data)

        self.batch_label_wid = QLineEdit()
        self.batch_label_wid.setPlaceholderText(
            _("Bitcoin biletoj batch label"))
        self.batch_label_wid.textEdited.connect(self.batch_info_changed)
        vbox.addWidget(self.batch_label_wid)

        grid = QGridLayout()
        vbox.addLayout(grid)
        self.number_wid = QLineEdit()
        self.number_wid.setPlaceholderText(_("Number of biletoj"))
        self.number_wid.textEdited.connect(self.batch_info_changed)
        self.times_wid = QLineEdit()
        self.times_wid.textEdited.connect(self.batch_info_changed)
        self.times_wid.setText("1")
        hbox = QHBoxLayout()
        vbox.addLayout(hbox)
        hbox.addWidget(self.number_wid)
        #hbox.addWidget(QLabel("x"))
        #hbox.addWidget(self.times_wid)
        hbox.addStretch(1)
        self.times_wid.setMaximumWidth(120)
        self.number_wid.setMaximumWidth(140)
        self.only_qrcodes_checkbox = QCheckBox("Only make QR codes.")
        self.only_qrcodes_checkbox.stateChanged.connect(
            self.batch_info_changed)
        self.encrypt_checkbox = QCheckBox("Encrypt Batch.")
        vbox.addWidget(self.encrypt_checkbox)
        vbox.addWidget(self.only_qrcodes_checkbox)
        #b = QPushButton(_("Load .tex template"))
        #b.clicked.connect(self.load_template)
        #b.setMaximumWidth(130)
        #grid.addWidget(b, 0, 0)
        #self.template_path_label_wid = QLabel('set path')
        #grid.addWidget(self.template_path_label_wid, 0, 1)
        self.public_key_wid = QLineEdit()
        self.public_key_wid.setPlaceholderText(
            _("Public Key") + _(" for encryption"))
        self.public_key_wid.textEdited.connect(self.batch_info_changed)
        #vbox.addWidget(self.public_key_wid)
        self.b = QPushButton(_("Generate biletoj"))
        self.b.clicked.connect(self.generate_biletoj)
        self.prog_bar = QProgressBar()
        self.prog_bar.setVisible(False)
        vbox.addWidget(self.b)
        vbox.addWidget(self.prog_bar)
        self.b.setDisabled(True)
        vbox.addStretch(1)

    def on_settings_updated(self):
        self.working_directory = self.wallet.storage.get("bileto_path")
        self.wd_label.setText(self.working_directory)

    def save_qrcode(self, qrw, name):
        p = qrw and qrw.grab()
        filename = os.path.join(self.working_directory, name)
        if p and not p.isNull():
            if filename:
                print_error("saving")
                p.save(filename, 'png')

    def batch_info_changed(self):
        # string = self.recipient_wallet.get_unused_address().to_ui_string()
        try:
            self.batch_label = str(self.batch_label_wid.text())
            self.number = int(self.number_wid.text())
            self.times = int(self.times_wid.text())
            assert self.times > 0
            # self.public_key = str(self.public_key_wid.text())
            self.public_key = self.wallet.get_pubkey(False, 0)
            assert os.path.exists(self.working_directory)
            #if not self.only_qrcodes_checkbox.isChecked():
            #assert os.path.isfile(self.template_file)
        except AssertionError:
            self.times_wid.setText("1")
            self.b.setDisabled(True)
        except:
            self.b.setDisabled(True)
        else:
            self.b.setDisabled(False)

    def load_template(self):
        self.template_file = self.main_window.getOpenFileName(
            "Load Latex template", "*.tex")
        self.template_path_label_wid.setText(self.template_file)
        self.batch_info_changed()

    def generate_biletoj(self):
        self.b.setDisabled(True)
        self.b.setText("In progress...")
        self.prog_bar.setRange(0, self.number)
        self.prog_bar.setVisible(True)
        QCoreApplication.processEvents()
        try:
            path_to_latex = check_output(["which", "pdflatex"],
                                         shell=False).strip()
        except:
            path_to_latex = '/Library/Tex/texbin/pdflatex'
        batch_privs = self.batch_label + '\n'
        os.mkdir(
            os.path.join(self.working_directory,
                         self.batch_label + "_qrcodes"))
        for i in range(self.number):
            add = self.recipient_wallet.create_new_address()
            privkey = self.recipient_wallet.export_private_key(add, None)
            batch_privs += privkey + '\n'
            self.qrw_priv.number_label.setText('  ' + str(i + 1))
            self.qrw_priv.setData(privkey)
            self.save_qrcode(
                self.qrw_priv,
                self.batch_label + "_qrcodes/priv_key_" + str(i + 1) + ".png")
            self.qrw_add.number_label.setText('  ' + str(i + 1))
            self.qrw_priv.setData("bitcoincash:" + add.to_ui_string())
            self.save_qrcode(
                self.qrw_add,
                self.batch_label + "_qrcodes/address_" + str(i + 1) + ".png")
            self.prog_bar.setValue(i + 1)
        if not self.only_qrcodes_checkbox.isChecked():
            self.scripts()
            call(['chmod', 'u+x', "compile.sh"],
                 cwd=self.working_directory,
                 shell=False)
            call([
                "./compile.sh", '-l', self.batch_label, '-n',
                str(self.number)
            ],
                 cwd=self.working_directory,
                 shell=False)
        filename = os.path.join(self.working_directory,
                                self.batch_label + '_encrypted_private_keys')

        save_private_keys(batch_privs, self.public_key, filename,
                          self.encrypt_checkbox.isChecked())
        self.prog_bar.setVisible(False)
        self.main_window.show_message("Done!")
        self.b.setDisabled(False)
        self.b.setText(_("Generate biletoj"))

    def filter(self, *args):
        ''' This is here because searchable_list must define a filter method '''

    def scripts(self):
        for name, scr in script_dict.items():
            path = os.path.join(self.working_directory, name)
            if not os.path.isfile(path):
                with open(path, 'w') as file:
                    file.write(scr)

    @staticmethod
    def delete_temp_wallet_file(file):
        ''' deletes the wallet file '''
        if file and os.path.exists(file):
            try:
                os.remove(file)
                print_error("[BitcoinBileto] Removed temp file", file)
            except Exception as e:
                print_error("[BitcoinBileto] Failed to remove temp file", file,
                            "error: ", repr(e))

    def closeEvent(self, event):
        #self.plugin.on_create_dialog_closed(self.wallet_name)
        event.accept()
Esempio n. 3
0
class LoadRWallet(MessageBoxMixin, PrintError, QWidget):
    def __init__(self,
                 parent: ElectrumWindow,
                 plugin,
                 wallet_name,
                 recipient_wallet=None,
                 time=None,
                 password=None):
        QWidget.__init__(self, parent)
        assert isinstance(parent, ElectrumWindow)
        self.password = password
        self.wallet = parent.wallet
        self.utxos = []  # populated by self.refresh_utxos() below
        self.weakWindow = Weak.ref(
            parent)  # grab a weak reference to the ElectrumWindow
        self.refresh_utxos()  # sets self.utxos
        for x in range(10):
            name = 'tmp_wo_wallet' + ''.join(
                random.choices(string.ascii_letters + string.digits, k=10))
            self.file = os.path.join(tempfile.gettempdir(), name)
            if not os.path.exists(self.file):
                break
        else:
            raise RuntimeError(
                'Could not find a unique temp file in tmp directory',
                tempfile.gettempdir())
        self.tmp_pass = ''.join(
            random.choices(string.ascii_uppercase + string.digits, k=10))
        self.storage = None
        self.recipient_wallet = None
        self.keystore = None
        self.plugin = plugin
        self.network = parent.network
        self.wallet_name = wallet_name
        self.keystore = None
        vbox = QVBoxLayout()
        self.setLayout(vbox)
        self.local_xpub = self.wallet.get_master_public_keys()
        l = QLabel(
            _("Master Public Key") +
            _(" of this wallet (used to generate all of your addresses): "))
        l2 = QLabel((self.local_xpub and self.local_xpub[0]) or _(
            "This wallet is <b>non-deterministic</b> and cannot be used as a transfer destination."
        ))
        vbox.addWidget(l)
        vbox.addWidget(l2)
        l2.setTextInteractionFlags(Qt.TextSelectableByMouse)
        l = QLabel(
            _("Master Public Key") +
            " of the wallet you want to transfer your funds to:")
        disabled = False
        if self.wallet.is_watching_only():
            l.setText(
                _("This wallet is <b>watching-only</b> and cannot be used as a transfer source."
                  ))
            disabled = True
        elif any([
                isinstance(k, Hardware_KeyStore)
                for k in self.wallet.get_keystores()
        ]):
            l.setText(
                _("This wallet is a <b>hardware wallet</b> and cannot be used as a transfer source."
                  ))
            disabled = True
        elif (
            (hasattr(self.wallet, 'is_multisig') and self.wallet.is_multisig())
                or isinstance(self.wallet, Multisig_Wallet)):
            l.setText(
                _("This wallet is a <b>multisig wallet</b> and cannot be used as a transfer source."
                  ))
            # MultiSig wallet xpub keys are not useful and don't work. Hide the key.
            l2.setText(
                _("This wallet is a <b>multisig wallet</b> and cannot be used as a transfer destination."
                  ))
            disabled = True
        vbox.addWidget(l)
        self.xpubkey = None
        self.xpubkey_wid = QLineEdit()
        self.xpubkey_wid.textEdited.connect(self.transfer_changed)
        self.xpubkey_wid.setDisabled(disabled)
        vbox.addWidget(self.xpubkey_wid)
        l = QLabel(_("How long the transfer should take (in whole hours): "))
        vbox.addWidget(l)
        l.setDisabled(disabled)
        self.time_e = QLineEdit()
        self.time_e.setMaximumWidth(70)
        self.time_e.textEdited.connect(self.transfer_changed)
        self.time_e.setDisabled(disabled)
        hbox = QHBoxLayout()
        vbox.addLayout(hbox)
        hbox.addWidget(self.time_e)
        self.speed = QLabel()
        hbox.addWidget(self.speed)
        hbox.addStretch(1)
        hbox2 = QHBoxLayout()
        hbox2.addStretch(1)
        self.transfer_button = QPushButton(_("Transfer"))
        self.transfer_button.clicked.connect(self.transfer)
        self.transfer_button.setMinimumWidth(200)
        hbox2.addWidget(self.transfer_button)
        hbox2.addStretch(1)
        vbox.addLayout(hbox2)
        self.transfer_button.setDisabled(True)

        vbox.addStretch(1)

        if hasattr(parent, 'history_updated_signal'):
            # So that we get told about when new coins come in, and the UI updates itself
            parent.history_updated_signal.connect(self.refresh_utxos)
            parent.history_updated_signal.connect(self.transfer_changed)

    def refresh_utxos(self):
        parent = self.weakWindow()
        if parent:
            self.utxos = self.wallet.get_spendable_coins(None, parent.config)
            random.shuffle(self.utxos)  # randomize the coins' order

    def filter(self, *args):
        """This is here because searchable_list must define a filter method"""

    def showEvent(self, e):
        super().showEvent(e)
        if not self.network and self.isEnabled():
            self.show_warning(
                _("The Inter-Wallet Transfer plugin cannot function in offline mode. "
                  "Restart Electron Cash in online mode to proceed."))
            self.setDisabled(True)

    @staticmethod
    def delete_temp_wallet_file(file):
        """deletes the wallet file"""
        if file and os.path.exists(file):
            try:
                os.remove(file)
                print_error("[InterWalletTransfer] Removed temp file", file)
            except Exception as e:
                print_error("[InterWalletTransfer] Failed to remove temp file",
                            file, "error: ", repr(e))

    def transfer(self):
        self.show_message(
            _("You should not use either wallet during the transfer. Leave Electron Cash active. "
              "The plugin ceases operation and will have to be re-activated if Electron Cash "
              "is stopped during the operation."))
        self.storage = WalletStorage(self.file)
        self.storage.set_password(self.tmp_pass, encrypt=True)
        self.storage.put('keystore', self.keystore.dump())
        self.recipient_wallet = Standard_Wallet(self.storage)
        self.recipient_wallet.start_threads(self.network)
        # comment the below out if you want to disable auto-clean of temp file
        # otherwise the temp file will be auto-cleaned on app exit or
        # on the recepient_wallet object's destruction (when refct drops to 0)
        Weak.finalize(self.recipient_wallet, self.delete_temp_wallet_file,
                      self.file)
        self.plugin.switch_to(Transfer,
                              self.wallet_name, self.recipient_wallet,
                              float(self.time_e.text()), self.password)

    def transfer_changed(self):
        try:
            assert float(self.time_e.text()) > 0
            self.xpubkey = self.xpubkey_wid.text()
            self.keystore = keystore.from_master_key(self.xpubkey)
        except:
            self.speed.setText('')
            self.transfer_button.setDisabled(True)
        else:
            self.transfer_button.setDisabled(False)
            v = len(self.utxos) / float(self.time_e.text())
            self.speed.setText('{0:.2f}'.format(v) + ' tx/h on average')