Пример #1
0
def init_daemon(config_options):
    config = SimpleConfig(config_options)
    wallet_path = config.get_wallet_path()
    if not WalletStorage.files_are_matched_by_path(wallet_path):
        print("Error: Wallet file not found.")
        print("Type 'electrum-sv create' to create a new wallet, "
              "or provide a path to a wallet with the -w option")
        sys.exit(0)
    storage = WalletStorage(wallet_path)
    if storage.is_encrypted():
        if 'wallet_password' in config_options:
            print(
                'Warning: unlocking wallet with commandline argument \"--walletpassword\"'
            )
            password = config_options['wallet_password']
        elif config.get('password'):
            password = config.get('password')
        else:
            password = prompt_password('Password:'******'password'] = password
Пример #2
0
 def _on_filename(filename):
     # A relative path will be relative to the folder we offered in the choose dialog.
     # An absolute path will not get joined to the dialog folder (no-op).
     path = os.path.join(wallet_folder, filename)
     try:
         self.storage = WalletStorage(path, manual_upgrades=True)
         self.next_button.setEnabled(True)
     except IOError:
         self.storage = None
         self.next_button.setEnabled(False)
     if self.storage:
         if not self.storage.file_exists():
             msg =_("This file does not exist.") + '\n' \
                   + _("Press 'Next' to create this wallet, or choose another file.")
             pw = False
         elif self.storage.file_exists() and self.storage.is_encrypted():
             msg = '\n'.join([
                 _("This file is encrypted."),
                 _('Enter your password or choose another file.'),
             ])
             pw = True
         else:
             msg = _("Press 'Next' to open this wallet.")
             pw = False
     else:
         msg = _('Cannot read file')
         pw = False
     self.msg_label.setText(msg)
     if pw:
         self.pw_label.show()
         self.pw_e.show()
         self.pw_e.setFocus()
     else:
         self.pw_label.hide()
         self.pw_e.hide()
Пример #3
0
 def attempt_open(
         klass,
         wallet_path: str) -> Tuple[bool, bool, Optional['WalletWizard']]:
     """
     Returns a tuple containing:
     `is_valid` - indicates the open action should proceed.
     `was_aborted` - indicates the user performed an action to abort the process.
     `wizard` - optionally present for valid cases where the wallet cannot be opened directly
         (migration is required).
     """
     entry = create_file_state(wallet_path)
     was_aborted = False
     if entry is not None:
         storage = WalletStorage(wallet_path)
         try:
             password = request_password(None, storage, entry)
             if password is not None:
                 if entry.requires_upgrade:
                     migration_context = MigrationContext(
                         entry, storage, password)
                     # We hand off the storage reference to the wallet wizard to close.
                     storage = None
                     return True, False, klass(
                         migration_data=migration_context)
                 return True, False, None
             was_aborted = True
         finally:
             if storage is not None:
                 storage.close()
     return False, was_aborted, None
Пример #4
0
def run_non_RPC(config):
    """Most commands should go through the daemon or RPC, especially commands that operate on
    wallets."""
    cmdname = config.get('cmd')

    def get_wallet_path() -> str:
        wallet_path = config.get_cmdline_wallet_filepath()
        if wallet_path is None:
            sys.exit("error: no wallet path provided")

        final_path = WalletStorage.canonical_path(wallet_path)
        if WalletStorage.files_are_matched_by_path(wallet_path):
            sys.exit(f"error: wallet already exists: {final_path}")

        return final_path

    if cmdname in {'create_wallet', 'create_account'}:
        if not config.cmdline_options.get('nopasswordcheck'):
            password = prompt_password("Password:"******"error: wallet creation requires a password")

        if cmdname == 'create_wallet':
            wallet_path = get_wallet_path()
            storage = WalletStorage.create(wallet_path, password)
            storage.close()
            print(f"Wallet saved in '{wallet_path}'")
            sys.exit(0)

        elif cmdname == 'create_account':
            wallet_path = config.get_cmdline_wallet_filepath()
            storage = WalletStorage.create(wallet_path, password)
            parent_wallet = Wallet(storage)

            # create an account for the Wallet (only random new seeds supported - no importing)
            text_type = KeystoreTextType.EXTENDED_PRIVATE_KEY

            text_match = os.getenv("ELECTRUMSV_ACCOUNT_XPRV")
            if not text_match:  # generate a random account seed
                data = urandom(64)
                coin = bitcoinx.BitcoinRegtest
                xprv = bitcoinx.BIP32PrivateKey._from_parts(
                    data[:32], data[32:], coin)
                text_match = xprv.to_extended_key_string()

            keystore = instantiate_keystore_from_text(text_type,
                                                      text_match,
                                                      password,
                                                      derivation_text=None,
                                                      passphrase=None,
                                                      watch_only=False)
            parent_wallet.create_account_from_keystore(keystore)
            print(f"New standard (bip32) account created for: '{wallet_path}'")
            sys.exit(0)

    else:
        sys.exit("error: unrecognised command")
Пример #5
0
def test_wallet_storage_database_nonexistent_creates(tmp_path) -> None:
    wallet_filepath = os.path.join(tmp_path, "walletfile")
    storage = WalletStorage(wallet_filepath)
    try:
        assert type(storage._store) is DatabaseStore
        assert storage.get("migration") == DatabaseStore.CURRENT_MIGRATION
    finally:
        storage.close()
Пример #6
0
def validate_password(storage: WalletStorage, password: str) -> bool:
    try:
        storage.check_password(password)
    except InvalidPassword:
        pass
    else:
        return True
    return False
Пример #7
0
def test_wallet_storage_new() -> None:
    base_storage_path = tempfile.mkdtemp()
    wallet_filepath = os.path.join(base_storage_path, "walletfile")
    storage = WalletStorage(wallet_filepath)
    assert type(storage._store) is DatabaseStore
    assert storage.get("wallet_author") == "ESV"
    assert storage.get("seed_version") == DatabaseStore.INITIAL_SEED_VERSION
    key = storage.get("tx_store_aeskey")
    assert type(key) is str
Пример #8
0
def init_cmdline(config_options, server):
    config = SimpleConfig(config_options)
    cmdname = config.get('cmd')
    cmd = known_commands[cmdname]

    if cmdname == 'signtransaction' and config.get('privkey'):
        cmd.requires_wallet = False
        cmd.requires_password = False

    if cmdname in ['payto', 'paytomany'] and config.get('unsigned'):
        cmd.requires_password = False

    if cmdname in ['payto', 'paytomany'] and config.get('broadcast'):
        cmd.requires_network = True

    wallet_path = config.get_wallet_path()
    if cmd.requires_wallet and not WalletStorage.files_are_matched_by_path(
            wallet_path):
        print("Error: Wallet file not found.")
        print("Type 'electrum-sv create' to create a new wallet, "
              "or provide a path to a wallet with the -w option")
        sys.exit(0)

    # instantiate wallet for command-line
    storage = WalletStorage(wallet_path)

    # important warning
    if cmd.name in ['getprivatekeys']:
        print("WARNING: ALL your private keys are secret.", file=sys.stderr)
        print(
            "Exposing a single private key can compromise your entire wallet!",
            file=sys.stderr)
        print(
            "In particular, DO NOT use 'redeem private key' services "
            "proposed by third parties.",
            file=sys.stderr)

    # commands needing password
    if cmd.requires_wallet and server is None or cmd.requires_password:
        if config.get('password'):
            password = config.get('password')
        else:
            password = prompt_password('Password:'******'password'] = password

    if cmd.name == 'password':
        new_password = prompt_password('New password:'******'new_password'] = new_password

    return cmd, password
Пример #9
0
    def get_wallet_path() -> str:
        wallet_path = config.get_cmdline_wallet_filepath()
        if wallet_path is None:
            sys.exit("error: no wallet path provided")

        final_path = WalletStorage.canonical_path(wallet_path)
        if WalletStorage.files_are_matched_by_path(wallet_path):
            sys.exit(f"error: wallet already exists: {final_path}")

        return final_path
Пример #10
0
    def test_read_dictionary_from_file(self):

        some_dict = {"a": "b", "c": "d"}
        contents = json.dumps(some_dict)
        with open(self.wallet_path, "w") as f:
            contents = f.write(contents)

        storage = WalletStorage(self.wallet_path, manual_upgrades=True)
        self.assertEqual("b", storage.get("a"))
        self.assertEqual("d", storage.get("c"))
Пример #11
0
def test_legacy_wallet_loading(storage_info: WalletStorageInfo) -> None:
    # When a wallet is composed of multiple files, we need to know which to load.
    wallet_filenames = []
    if storage_info.kind != StorageKind.DATABASE:
        wallet_filenames.append(storage_info.filename)
    if storage_info.kind in (StorageKind.DATABASE, StorageKind.HYBRID):
        wallet_filenames.append(storage_info.filename + DATABASE_EXT)

    temp_dir = tempfile.mkdtemp()
    for _wallet_filename in wallet_filenames:
        source_wallet_path = os.path.join(TEST_WALLET_PATH, _wallet_filename)
        wallet_path = os.path.join(temp_dir, _wallet_filename)
        shutil.copyfile(source_wallet_path, wallet_path)

    # net = None
    # if "testnet" in wallet_filename:
    #     net = SVTestnet
    # elif "mainnet" in wallet_filename:
    #     net = SVMainnet
    # else:
    #     raise Exception(f"unable to identify wallet network for {wallet_filename}")

    wallet_filename = storage_info.filename
    wallet_path = os.path.join(temp_dir, wallet_filename)

    password = "******"
    storage = WalletStorage(wallet_path)
    if "passworded" in wallet_filename:
        storage.decrypt(password)

    try:
        parent_wallet = ParentWallet(storage)
    except OSError as e:
        if "is not a valid Win32 application" not in e.args[1]:
            raise e
        pytest.xfail("Missing libusb for this architecture")
        return

    if "standard" in wallet_filename:
        is_bip39 = "bip39" in wallet_filename
        check_legacy_parent_of_standard_wallet(parent_wallet,
                                               is_bip39=is_bip39,
                                               password=password)
    elif "imported_privkey" in wallet_filename:
        check_legacy_parent_of_imported_privkey_wallet(parent_wallet)
    elif "imported_address" in wallet_filename:
        check_legacy_parent_of_imported_address_wallet(parent_wallet)
    elif "multisig" in wallet_filename:
        check_legacy_parent_of_multisig_wallet(parent_wallet)
    elif "hardware" in wallet_filename:
        check_legacy_parent_of_hardware_wallet(parent_wallet)
    else:
        raise Exception(f"unrecognised wallet file {wallet_filename}")
Пример #12
0
    def _attempt_open_wallet(self,
                             wallet_path: str,
                             change_page: bool = False) -> bool:
        if not os.path.exists(wallet_path):
            MessageBox.show_error(_("Unable to open a deleted wallet."))
            return False

        entry: Optional[FileState] = None
        for entry in self._recent_wallet_entries.values():
            if entry.path == wallet_path:
                break
        else:
            entry = create_file_state(wallet_path)
            if entry is None:
                MessageBox.show_error(
                    _("Unrecognised or unsupported wallet file."))
                return False

        if entry.is_too_modern:
            MessageBox.show_error(
                _("The selected wallet cannot be opened as it is from a later "
                  "version of ElectrumSV."))
            return False

        password: str = None
        wizard: WalletWizard = self.wizard()
        storage = WalletStorage(entry.path)
        try:
            password = request_password(self, storage, entry)
            if password is None:
                return False

            if change_page:
                self._force_completed = True

                if entry.requires_upgrade:
                    self._next_page_id = WalletPage.MIGRATE_OLDER_WALLET
                    migration_page = wizard.page(
                        WalletPage.MIGRATE_OLDER_WALLET)
                    migration_page.set_migration_data(entry, storage, password)
                    # Give the storage object to the migration page, which we are going to.
                    storage = None
                    wizard.next()
                else:
                    assert entry.storage_kind == StorageKind.DATABASE, \
                        f"not a database {entry.storage_kind}"
                    wizard.set_wallet_path(entry.path)
                    wizard.accept()
        finally:
            # We may have handed off the storage and are no longer responsible for closing it.
            if storage is not None:
                storage.close()
        return True
Пример #13
0
def create_file_state(wallet_path: str) -> Optional[FileState]:
    if not os.path.exists(wallet_path):
        return None

    try:
        storage = WalletStorage(wallet_path)
    except Exception:
        logger.exception("problem looking at selected wallet '%s'",
                         wallet_path)
        return None

    is_too_modern = False
    try:
        storage_info = categorise_file(wallet_path)
        if storage_info.kind == StorageKind.HYBRID:
            return None

        wallet_action = WalletAction.OPEN
        password_state = PasswordState.UNKNOWN

        if storage_info.kind == StorageKind.FILE:
            text_store = storage.get_text_store()
            try:
                text_store.attempt_load_data()
            except IOError:
                # IOError: storage.py:load_data() raises when selected file cannot be parsed.
                return None
            if storage.get("use_encryption"):
                # If there is a password and the wallet is not encrypted, then the private data
                # is encrypted.
                password_state = PasswordState.PASSWORDED
            elif text_store.is_encrypted():
                # If there is a password and the wallet is encrypted, then the private data is
                # encrypted and the file is encrypted.
                password_state = PasswordState.PASSWORDED | PasswordState.ENCRYPTED
            else:
                # Neither the private data is encrypted or the file itself.
                password_state = PasswordState.NONE
        else:
            assert storage_info.kind == StorageKind.DATABASE
            password_state = PasswordState.PASSWORDED
            database_store = storage.get_database_store()
            is_too_modern = database_store.get("migration") > MIGRATION_CURRENT

        requires_upgrade = storage.requires_split(
        ) or storage.requires_upgrade()
    finally:
        storage.close()

    name = get_wallet_name_from_path(wallet_path)
    modification_time = os.path.getmtime(wallet_path)
    return FileState(name, wallet_path, wallet_action, storage_info.kind,
                     password_state, requires_upgrade, modification_time,
                     is_too_modern)
Пример #14
0
    async def create_new_wallet(self, request):
        """only for regtest for the moment..."""
        try:
            vars = await self.argparser(
                request,
                required_vars=[VNAME.PASSWORD, VNAME.WALLET_NAME],
                check_wallet_availability=False)

            create_filepath = str(
                Path(self.wallets_path).joinpath(vars[VNAME.WALLET_NAME]))
            self.check_if_wallet_exists(create_filepath)

            storage = WalletStorage.create(create_filepath,
                                           vars[VNAME.PASSWORD])
            storage.close()

            parent_wallet = self.app_state.daemon.load_wallet(create_filepath)

            # create an account for the Wallet with the same password via an imported seed
            text_type = KeystoreTextType.EXTENDED_PRIVATE_KEY
            text_match = 'tprv8ZgxMBicQKsPd4wsdaJ11eH84eq4hHLX1K6Mx8EQQhJzq8jr25WH1m8hgGkCqnks' \
                         'JDCZPZbDoMbQ6QtroyCyn5ZckCmsLeiHDb1MAxhNUHN'

            keystore = instantiate_keystore_from_text(text_type,
                                                      text_match,
                                                      vars[VNAME.PASSWORD],
                                                      derivation_text=None,
                                                      passphrase=None)
            parent_wallet.create_account_from_keystore(keystore)
            await self._load_wallet(vars[VNAME.WALLET_NAME])
            response = {"new_wallet": create_filepath}
            return good_response(response)
        except Fault as e:
            return fault_to_http_response(e)
Пример #15
0
def test_wallet_storage_json_path_nonexistent_errors() -> None:
    base_storage_path = tempfile.mkdtemp()
    nonexistent_storage_path = os.path.join(base_storage_path, "nonexistent",
                                            "walletfile")

    with pytest.raises(OSError):
        storage = WalletStorage(nonexistent_storage_path)
Пример #16
0
def run_non_RPC(config):
    """Most commands should go through the daemon or RPC, especially commands that operate on
    wallets."""
    cmdname = config.get('cmd')

    def get_wallet_path() -> str:
        wallet_path = config.get_cmdline_wallet_filepath()
        if wallet_path is None:
            sys.exit("error: no wallet path provided")

        final_path = WalletStorage.canonical_path(wallet_path)
        if WalletStorage.files_are_matched_by_path(wallet_path):
            sys.exit(f"error: wallet already exists: {final_path}")

        return final_path

    if cmdname == 'create_wallet':
        wallet_path = get_wallet_path()
        password = prompt_password("Password:"******"error: wallet creation requires a password")

        storage = WalletStorage.create(wallet_path, password)
        storage.close()

        print(f"Wallet saved in '{wallet_path}'")
        sys.exit(0)
    else:
        sys.exit("error: unrecognised command")
Пример #17
0
        def _on_filename(filename: str) -> None:
            pw = False
            self._storage_existing = None

            # A relative path will be relative to the folder we offered in the choose dialog.
            # An absolute path will not get joined to the dialog folder (no-op).
            path = os.path.join(wallet_folder, filename)
            if WalletStorage.files_are_matched_by_path(path):
                try:
                    self._storage_existing = WalletStorage(
                        path, manual_upgrades=True)
                except IOError:
                    self.next_button.setEnabled(False)
                    msg = _('Cannot read file')
                else:
                    self.next_button.setEnabled(True)
                    if self._storage_existing.is_encrypted():
                        msg = '\n'.join([
                            _("This file is encrypted."),
                            _('Enter your password or choose another file.'),
                        ])
                        pw = True
                    else:
                        msg = _("Press 'Next' to open this wallet.")
            else:
                msg = _("This file does not exist.")
                if os.access(wallet_folder, os.W_OK):
                    self.next_button.setEnabled(True)
                    msg += "\n" + _(
                        "Press 'Next' to create this wallet, or choose another file."
                    )
                    self._path_new = path
                else:
                    self.next_button.setEnabled(False)
                    msg += "\n" + _("You do not have write access " +
                                    "to this folder to create a new wallet.")

            self.msg_label.setText(msg)
            if pw:
                self.pw_label.show()
                self.pw_e.show()
                self.pw_e.setFocus()
            else:
                self.pw_label.hide()
                self.pw_e.hide()
Пример #18
0
 def test_encrypt_message(self):
     key = WalletStorage.get_eckey_from_password('secret_password77')
     public_key = key.public_key
     msgs = [bytes([0] * 555), b'cannot think of anything funny']
     for plaintext in msgs:
         ciphertext1 = public_key.encrypt_message(plaintext)
         ciphertext2 = public_key.encrypt_message(plaintext)
         self.assertEqual(plaintext, key.decrypt_message(ciphertext1))
         self.assertEqual(plaintext, key.decrypt_message(ciphertext2))
         self.assertNotEqual(ciphertext1, ciphertext2)
Пример #19
0
 def _get_recently_opened_wallets(self):
     return [{
         'name':
         os.path.basename(file_path),
         'path':
         file_path,
         'is_encrypted':
         WalletStorage(file_path, manual_upgrades=True).is_encrypted,
     } for file_path in app_state.config.get('recently_open', [])
             if os.path.exists(file_path)]
Пример #20
0
def test_legacy_wallet_backup_hybrid() -> None:
    # We only need to test for one hybrid wallet, and test permutations of backup cases against it.
    wallet_filename = "19_testnet_standard_electrum"
    source_wallet_path = os.path.join(TEST_WALLET_PATH, wallet_filename)
    temp_dir = tempfile.mkdtemp()
    wallet_path = os.path.join(temp_dir, wallet_filename)
    shutil.copyfile(source_wallet_path, wallet_path)
    shutil.copyfile(source_wallet_path + DATABASE_EXT, wallet_path)

    # We do not care about loading the data, this is purely a test of the renaming.
    storage = WalletStorage(source_wallet_path, manual_upgrades=True)
Пример #21
0
def create_new_wallet(parent: QWidget, initial_dirpath: str) -> Optional[str]:
    create_filepath, __ = QFileDialog.getSaveFileName(parent, _("Enter a new wallet file name"),
        initial_dirpath)

    assert not os.path.exists(create_filepath)

    dirpath, filename = os.path.split(create_filepath)
    if not dirpath or not os.path.isdir(dirpath) or not os.access(dirpath, os.R_OK | os.W_OK):
        MessageBox.show_error(_("The selected directory is not accessible."))
        return None

    name_edit = QLabel(filename)
    fields = [
        (QLabel(_("Wallet") +":"), name_edit),
    ]
    from .password_dialog import ChangePasswordDialog, PasswordAction
    from .wallet_wizard import PASSWORD_NEW_TEXT
    d = ChangePasswordDialog(parent, PASSWORD_NEW_TEXT, _("Create New Wallet"), fields,
        kind=PasswordAction.NEW)
    success, _old_password, new_password = d.run()
    if not success or not new_password.strip():
        return None

    from electrumsv.storage import WalletStorage
    storage = WalletStorage(create_filepath)
    storage.put("password-token", pw_encode(os.urandom(32).hex(), new_password))
    storage.close()

    return create_filepath
Пример #22
0
def run_offline_command(config, config_options):
    cmdname = config.get('cmd')
    cmd = known_commands[cmdname]
    password = config_options.get('password')
    if cmd.requires_wallet:
        wallet_path = config.get_wallet_path()
        if not WalletStorage.files_are_matched_by_path(wallet_path):
            print("Error: wallet does not exist at given path")
            sys.exit(1)
        storage = WalletStorage(wallet_path)
        wallet = Wallet(storage)
    else:
        wallet = None
    if cmd.requires_password:
        try:
            wallet.check_password(password)
        except InvalidPassword:
            print(
                "Error: This password cannot access the wallet's private data."
            )
            sys.exit(1)
    if cmd.requires_network:
        print("Warning: running command offline")
    # arguments passed to function
    args = [config.get(x) for x in cmd.params]
    # decode json arguments
    if cmdname not in ('setconfig', ):
        args = [json_decode(arg) for arg in args]
    # options
    kwargs = {}
    for x in cmd.options:
        kwargs[x] = (config_options.get(x)
                     if x in ['password', 'new_password'] else config.get(x))
    cmd_runner = Commands(config, wallet, None)
    func = getattr(cmd_runner, cmd.name)
    result = func(*args, **kwargs)
    # save wallet
    if wallet:
        wallet.save_storage()
    return result
Пример #23
0
    def __init__(self, config, daemon, plugins):
        self.config = config
        self.network = daemon.network
        storage = WalletStorage(config.get_wallet_path())
        if not storage.file_exists:
            print("Wallet not found. try 'electrum-sv create'")
            exit()
        if storage.is_encrypted():
            password = getpass.getpass('Password:'******'updated', 'banner'])
        self.commands = [
            _("[h] - displays this help text"),
            _("[i] - display transaction history"),
            _("[o] - enter payment order"),
            _("[p] - print stored payment order"),
            _("[s] - send stored payment order"),
            _("[r] - show own receipt addresses"),
            _("[c] - display contacts"),
            _("[b] - print server banner"),
            _("[q] - quit"),
        ]
        self.num_commands = len(self.commands)
Пример #24
0
    def start_new_window(self, path, uri, is_startup=False):
        '''Raises the window for the wallet if it is open.  Otherwise
        opens the wallet and creates a new window for it.'''
        for w in self.windows:
            if w.wallet.storage.path == path:
                w.bring_to_top()
                break
        else:
            try:
                wallet = app_state.daemon.load_wallet(path, None)
                if not wallet:
                    storage = WalletStorage(path, manual_upgrades=True)
                    wizard = InstallWizard(storage)
                    try:
                        wallet = wizard.start_gui(is_startup=is_startup)
                    except UserQuit:
                        pass
                    except UserCancelled:
                        pass
                    except GoBack as e:
                        logger.error(
                            '[start_new_window] Exception caught (GoBack) %s',
                            e)
                    finally:
                        wizard.terminate()
                    if not wallet:
                        return
                    wallet.start_threads(app_state.daemon.network)
                    app_state.daemon.add_wallet(wallet)
            except Exception as e:
                logger.exception("")
                if '2fa' in str(e):
                    d = QMessageBox(QMessageBox.Warning, _('Error'),
                                    '2FA wallets are not unsupported.')
                    d.exec_()
                else:
                    d = QMessageBox(QMessageBox.Warning, _('Error'),
                                    'Cannot load wallet:\n' + str(e))
                    d.exec_()
                return
            w = self._create_window_for_wallet(wallet)
        if uri:
            w.pay_to_URI(uri)
        w.bring_to_top()
        w.setWindowState(w.windowState() & ~QtCore.Qt.WindowMinimized
                         | QtCore.Qt.WindowActive)

        # this will activate the window
        w.activateWindow()
        return w
Пример #25
0
def run_offline_command(config, config_options):
    cmdname = config.get('cmd')
    cmd = known_commands[cmdname]
    password = config_options.get('password')
    if cmd.requires_wallet:
        storage = WalletStorage(config.get_wallet_path())
        if storage.is_encrypted():
            storage.decrypt(password)
        parent_wallet = ParentWallet(storage)
    else:
        parent_wallet = None
    # check password
    if cmd.requires_password and parent_wallet.has_password():
        try:
            parent_wallet.check_password(password)
        except InvalidPassword:
            print("Error: This password does not decode this wallet.")
            sys.exit(1)
    if cmd.requires_network:
        print("Warning: running command offline")
    # arguments passed to function
    args = [config.get(x) for x in cmd.params]
    # decode json arguments
    if cmdname not in ('setconfig', ):
        args = [json_decode(arg) for arg in args]
    # options
    kwargs = {}
    for x in cmd.options:
        kwargs[x] = (config_options.get(x)
                     if x in ['password', 'new_password'] else config.get(x))
    cmd_runner = Commands(config, parent_wallet, None)
    func = getattr(cmd_runner, cmd.name)
    result = func(*args, **kwargs)
    # save wallet
    if parent_wallet:
        parent_wallet.save_storage()
    return result
Пример #26
0
    def __init__(self, config, daemon, plugins):

        self.config = config
        self.network = daemon.network
        storage = WalletStorage(config.get_wallet_path())
        if not storage.file_exists():
            print("Wallet not found. try 'electrum-sv create'")
            exit()
        if storage.is_encrypted():
            password = getpass.getpass('Password:'******'')
        self.encoding = locale.getpreferredencoding()

        self.stdscr = curses.initscr()
        curses.noecho()
        curses.cbreak()
        curses.start_color()
        curses.use_default_colors()
        curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE)
        curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_CYAN)
        curses.init_pair(3, curses.COLOR_BLACK, curses.COLOR_WHITE)
        self.stdscr.keypad(1)
        self.stdscr.border(0)
        self.maxy, self.maxx = self.stdscr.getmaxyx()
        self.set_cursor(0)
        self.w = curses.newwin(10, 50, 5, 5)

        disable_verbose_logging()
        self.tab = 0
        self.pos = 0
        self.popup_pos = 0

        self.str_recipient = ""
        self.str_description = ""
        self.str_amount = ""
        self.str_fee = ""
        self.history = None

        if self.network:
            self.network.register_callback(self.update, ['updated'])

        self.tab_names = [
            _("History"),
            _("Send"),
            _("Receive"),
            _("Addresses"),
            _("Contacts"),
            _("Banner")
        ]
        self.num_tabs = len(self.tab_names)
Пример #27
0
def create_new_wallet(parent: QWidget, initial_dirpath: str) -> Optional[str]:
    create_filepath, __ = QFileDialog.getSaveFileName(
        parent, _("Enter a new wallet file name"), initial_dirpath)
    if not create_filepath:
        return None

    # QFileDialog.getSaveFileName uses forward slashes for "easier pathing".. correct this.
    create_filepath = os.path.normpath(create_filepath)

    if os.path.exists(create_filepath):
        MessageBox.show_error(
            _("Overwriting existing files not supported at this time."))
        return None

    dirpath, filename = os.path.split(create_filepath)

    if not create_filepath.endswith(DATABASE_EXT):
        if os.path.exists(create_filepath + DATABASE_EXT):
            MessageBox.show_error(
                _("The file name '{}' is already in use.").format(filename))
            return None

    if not dirpath or not os.path.isdir(dirpath) or not os.access(
            dirpath, os.R_OK | os.W_OK):
        MessageBox.show_error(_("The selected directory is not accessible."))
        return None

    name_edit = QLabel(filename)
    fields = [
        (QLabel(_("Wallet") + ":"), name_edit),
    ]
    from .password_dialog import ChangePasswordDialog, PasswordAction
    from .wallet_wizard import PASSWORD_NEW_TEXT
    d = ChangePasswordDialog(parent,
                             PASSWORD_NEW_TEXT,
                             _("Create New Wallet"),
                             fields,
                             kind=PasswordAction.NEW)
    success, _old_password, new_password = d.run()
    if not success or not new_password.strip():
        return None

    from electrumsv.storage import WalletStorage
    storage = WalletStorage.create(create_filepath, new_password)
    storage.close()
    return create_filepath
Пример #28
0
 def test_decrypt_message(self):
     key = WalletStorage.get_eckey_from_password('pw123')
     self.assertEqual(
         b'me<(s_s)>age',
         key.decrypt_message(
             'QklFMQMDFtgT3zWSQsa+Uie8H/WvfUjlu9UN9OJtTt3KlgKeSTi6SQfuhcg1uIz9hp3WIUOFGTLr4RNQBdjPNqzXwhkcPi2Xsbiw6UCNJncVPJ6QBg=='
         ))
     self.assertEqual(
         b'me<(s_s)>age',
         key.decrypt_message(
             'QklFMQKXOXbylOQTSMGfo4MFRwivAxeEEkewWQrpdYTzjPhqjHcGBJwdIhB7DyRfRQihuXx1y0ZLLv7XxLzrILzkl/H4YUtZB4uWjuOAcmxQH4i/Og=='
         ))
     self.assertEqual(
         b'hey_there' * 100,
         key.decrypt_message(
             'QklFMQLOOsabsXtGQH8edAa6VOUa5wX8/DXmxX9NyHoAx1a5bWgllayGRVPeI2bf0ZdWK0tfal0ap0ZIVKbd2eOJybqQkILqT6E1/Syzq0Zicyb/AA1eZNkcX5y4gzloxinw00ubCA8M7gcUjJpOqbnksATcJ5y2YYXcHMGGfGurWu6uJ/UyrNobRidWppRMW5yR9/6utyNvT6OHIolCMEf7qLcmtneoXEiz51hkRdZS7weNf9mGqSbz9a2NL3sdh1A0feHIjAZgcCKcAvksNUSauf0/FnIjzTyPRpjRDMeDC8Ci3sGiuO3cvpWJwhZfbjcS26KmBv2CHWXfRRNFYOInHZNIXWNAoBB47Il5bGSMd+uXiGr+SQ9tNvcu+BiJNmFbxYqg+oQ8dGAl1DtvY2wJVY8k7vO9BIWSpyIxfGw7EDifhc5vnOmGe016p6a01C3eVGxgl23UYMrP7+fpjOcPmTSF4rk5U5ljEN3MSYqlf1QEv0OqlI9q1TwTK02VBCjMTYxDHsnt04OjNBkNO8v5uJ4NR+UUDBEp433z53I59uawZ+dbk4v4ZExcl8EGmKm3Gzbal/iJ/F7KQuX2b/ySEhLOFVYFWxK73X1nBvCSK2mC2/8fCw8oI5pmvzJwQhcCKTdEIrz3MMvAHqtPScDUOjzhXxInQOCb3+UBj1PPIdqkYLvZss1TEaBwYZjLkVnK2MBj7BaqT6Rp6+5A/fippUKHsnB6eYMEPR2YgDmCHL+4twxHJG6UWdP3ybaKiiAPy2OHNP6PTZ0HrqHOSJzBSDD+Z8YpaRg29QX3UEWlqnSKaan0VYAsV1VeaN0XFX46/TWO0L5tjhYVXJJYGqo6tIQJymxATLFRF6AZaD1Mwd27IAL04WkmoQoXfO6OFfwdp/shudY/1gBkDBvGPICBPtnqkvhGF+ZF3IRkuPwiFWeXmwBxKHsRx/3+aJu32Ml9+za41zVk2viaxcGqwTc5KMexQFLAUwqhv+aIik7U+5qk/gEVSuRoVkihoweFzKolNF+BknH2oB4rZdPixag5Zje3DvgjsSFlOl69W/67t/Gs8htfSAaHlsB8vWRQr9+v/lxTbrAw+O0E+sYGoObQ4qQMyQshNZEHbpPg63eWiHtJJnrVBvOeIbIHzoLDnMDsWVWZSMzAQ1vhX1H5QLgSEbRlKSliVY03kDkh/Nk/KOn+B2q37Ialq4JcRoIYFGJ8AoYEAD0tRuTqFddIclE75HzwaNG7NyKW1plsa72ciOPwsPJsdd5F0qdSQ3OSKtooTn7uf6dXOc4lDkfrVYRlZ0PX'
         ))
Пример #29
0
    def _attempt_open_wallet(self,
                             wallet_path: str,
                             change_page: bool = False) -> bool:
        try:
            storage = WalletStorage(wallet_path)
        except Exception:
            logger.exception("problem looking at selected wallet '%s'",
                             wallet_path)
            MessageBox.show_error(
                _("Unrecognised or unsupported wallet file."))
            return False

        try:
            storage_info = categorise_file(wallet_path)
            if storage_info.kind == StorageKind.HYBRID:
                MessageBox.show_error(
                    _("Unrecognised or unsupported wallet file."))
                return False

            wallet_type = StorageKind.FILE if storage.is_legacy_format(
            ) else StorageKind.DATABASE
            if wallet_type == StorageKind.FILE:
                text_store = storage.get_text_store()
                text_store.attempt_load_data()
                if storage.get("use_encryption") or text_store.is_encrypted():
                    # If there is a password and the wallet is not encrypted, then the private data
                    # is encrypted. If there is a password and the wallet is encrypted, then the
                    # private data is encrypted and the file is encrypted.
                    self._next_page_id = WalletPage.PREMIGRATION_PASSWORD_REQUEST
                else:
                    # Neither the private data is encrypted or the file itself.
                    self._next_page_id = WalletPage.PREMIGRATION_PASSWORD_ADDITION
            else:
                self._next_page_id = WalletPage.PREMIGRATION_PASSWORD_REQUEST
        finally:
            storage.close()

        self._force_completed = True

        wizard: WalletWizard = self.wizard()
        wizard.set_wallet_action(WalletAction.OPEN)
        wizard.set_wallet_type(wallet_type)
        wizard.set_wallet_path(wallet_path)

        if change_page:
            wizard.next()

        return True
Пример #30
0
    def validatePage(self) -> bool:
        # Called when 'Next' or 'Finish' is clicked for last-minute validation.
        result = self.isComplete()
        if result:
            new_password = self._password_layout.new_pw.text().strip()

            # If we are going to exit then create the empty wallet.
            wizard: WalletWizard = self.wizard()
            wallet_filepath = wizard.get_wallet_path()
            storage = WalletStorage(wallet_filepath)
            storage.put("password-token",
                        pw_encode(os.urandom(32).hex(), new_password))
            storage.close()
        return result