wallet.restore_wallet_from_text: support creating wallet in-memory
This commit is contained in:
@@ -102,7 +102,7 @@ class WalletStorage(Logger):
|
|||||||
def file_exists(self) -> bool:
|
def file_exists(self) -> bool:
|
||||||
return self._file_exists
|
return self._file_exists
|
||||||
|
|
||||||
def is_past_initial_decryption(self):
|
def is_past_initial_decryption(self) -> bool:
|
||||||
"""Return if storage is in a usable state for normal operations.
|
"""Return if storage is in a usable state for normal operations.
|
||||||
|
|
||||||
The value is True exactly
|
The value is True exactly
|
||||||
@@ -111,14 +111,14 @@ class WalletStorage(Logger):
|
|||||||
"""
|
"""
|
||||||
return not self.is_encrypted() or bool(self.pubkey)
|
return not self.is_encrypted() or bool(self.pubkey)
|
||||||
|
|
||||||
def is_encrypted(self):
|
def is_encrypted(self) -> bool:
|
||||||
"""Return if storage encryption is currently enabled."""
|
"""Return if storage encryption is currently enabled."""
|
||||||
return self.get_encryption_version() != StorageEncryptionVersion.PLAINTEXT
|
return self.get_encryption_version() != StorageEncryptionVersion.PLAINTEXT
|
||||||
|
|
||||||
def is_encrypted_with_user_pw(self):
|
def is_encrypted_with_user_pw(self) -> bool:
|
||||||
return self.get_encryption_version() == StorageEncryptionVersion.USER_PASSWORD
|
return self.get_encryption_version() == StorageEncryptionVersion.USER_PASSWORD
|
||||||
|
|
||||||
def is_encrypted_with_hw_device(self):
|
def is_encrypted_with_hw_device(self) -> bool:
|
||||||
return self.get_encryption_version() == StorageEncryptionVersion.XPUB_PASSWORD
|
return self.get_encryption_version() == StorageEncryptionVersion.XPUB_PASSWORD
|
||||||
|
|
||||||
def get_encryption_version(self):
|
def get_encryption_version(self):
|
||||||
|
|||||||
@@ -195,6 +195,19 @@ class TestCreateRestoreWallet(WalletTestCase):
|
|||||||
self.assertEqual(encrypt_file, wallet.storage.is_encrypted())
|
self.assertEqual(encrypt_file, wallet.storage.is_encrypted())
|
||||||
self.assertEqual('bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', wallet.get_receiving_addresses()[0])
|
self.assertEqual('bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', wallet.get_receiving_addresses()[0])
|
||||||
|
|
||||||
|
def test_restore_wallet_from_text_no_storage(self):
|
||||||
|
text = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver'
|
||||||
|
d = restore_wallet_from_text(
|
||||||
|
text,
|
||||||
|
path=None,
|
||||||
|
gap_limit=1,
|
||||||
|
config=self.config,
|
||||||
|
)
|
||||||
|
wallet = d['wallet'] # type: Standard_Wallet
|
||||||
|
self.assertEqual(None, wallet.storage)
|
||||||
|
self.assertEqual(text, wallet.keystore.get_seed(None))
|
||||||
|
self.assertEqual('bc1q3g5tmkmlvxryhh843v4dz026avatc0zzr6h3af', wallet.get_receiving_addresses()[0])
|
||||||
|
|
||||||
def test_restore_wallet_from_text_xpub(self):
|
def test_restore_wallet_from_text_xpub(self):
|
||||||
text = 'zpub6nydoME6CFdJtMpzHW5BNoPz6i6XbeT9qfz72wsRqGdgGEYeivso6xjfw8cGcCyHwF7BNW4LDuHF35XrZsovBLWMF4qXSjmhTXYiHbWqGLt'
|
text = 'zpub6nydoME6CFdJtMpzHW5BNoPz6i6XbeT9qfz72wsRqGdgGEYeivso6xjfw8cGcCyHwF7BNW4LDuHF35XrZsovBLWMF4qXSjmhTXYiHbWqGLt'
|
||||||
d = restore_wallet_from_text(text, path=self.wallet_path, gap_limit=1, config=self.config)
|
d = restore_wallet_from_text(text, path=self.wallet_path, gap_limit=1, config=self.config)
|
||||||
|
|||||||
@@ -2561,7 +2561,7 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
|||||||
def can_delete_address(self):
|
def can_delete_address(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def has_password(self):
|
def has_password(self) -> bool:
|
||||||
return self.has_keystore_encryption() or self.has_storage_encryption()
|
return self.has_keystore_encryption() or self.has_storage_encryption()
|
||||||
|
|
||||||
def can_have_keystore_encryption(self):
|
def can_have_keystore_encryption(self):
|
||||||
@@ -2578,18 +2578,18 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
|||||||
else:
|
else:
|
||||||
return StorageEncryptionVersion.USER_PASSWORD
|
return StorageEncryptionVersion.USER_PASSWORD
|
||||||
|
|
||||||
def has_keystore_encryption(self):
|
def has_keystore_encryption(self) -> bool:
|
||||||
"""Returns whether encryption is enabled for the keystore.
|
"""Returns whether encryption is enabled for the keystore.
|
||||||
|
|
||||||
If True, e.g. signing a transaction will require a password.
|
If True, e.g. signing a transaction will require a password.
|
||||||
"""
|
"""
|
||||||
if self.can_have_keystore_encryption():
|
if self.can_have_keystore_encryption():
|
||||||
return self.db.get('use_encryption', False)
|
return bool(self.db.get('use_encryption', False))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def has_storage_encryption(self):
|
def has_storage_encryption(self) -> bool:
|
||||||
"""Returns whether encryption is enabled for the wallet file on disk."""
|
"""Returns whether encryption is enabled for the wallet file on disk."""
|
||||||
return self.storage and self.storage.is_encrypted()
|
return bool(self.storage) and self.storage.is_encrypted()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def may_have_password(cls):
|
def may_have_password(cls):
|
||||||
@@ -3484,15 +3484,18 @@ def create_new_wallet(*, path, config: SimpleConfig, passphrase=None, password=N
|
|||||||
return {'seed': seed, 'wallet': wallet, 'msg': msg}
|
return {'seed': seed, 'wallet': wallet, 'msg': msg}
|
||||||
|
|
||||||
|
|
||||||
def restore_wallet_from_text(text, *, path, config: SimpleConfig,
|
def restore_wallet_from_text(text, *, path: Optional[str], config: SimpleConfig,
|
||||||
passphrase=None, password=None, encrypt_file=True,
|
passphrase=None, password=None, encrypt_file=True,
|
||||||
gap_limit=None) -> dict:
|
gap_limit=None) -> dict:
|
||||||
"""Restore a wallet from text. Text can be a seed phrase, a master
|
"""Restore a wallet from text. Text can be a seed phrase, a master
|
||||||
public key, a master private key, a list of bitcoin addresses
|
public key, a master private key, a list of bitcoin addresses
|
||||||
or bitcoin private keys."""
|
or bitcoin private keys."""
|
||||||
storage = WalletStorage(path)
|
if path is None: # create wallet in-memory
|
||||||
if storage.file_exists():
|
storage = None
|
||||||
raise Exception("Remove the existing wallet first!")
|
else:
|
||||||
|
storage = WalletStorage(path)
|
||||||
|
if storage.file_exists():
|
||||||
|
raise Exception("Remove the existing wallet first!")
|
||||||
db = WalletDB('', manual_upgrades=False)
|
db = WalletDB('', manual_upgrades=False)
|
||||||
text = text.strip()
|
text = text.strip()
|
||||||
if keystore.is_address_list(text):
|
if keystore.is_address_list(text):
|
||||||
@@ -3525,7 +3528,8 @@ def restore_wallet_from_text(text, *, path, config: SimpleConfig,
|
|||||||
if gap_limit is not None:
|
if gap_limit is not None:
|
||||||
db.put('gap_limit', gap_limit)
|
db.put('gap_limit', gap_limit)
|
||||||
wallet = Wallet(db, storage, config=config)
|
wallet = Wallet(db, storage, config=config)
|
||||||
assert not storage.file_exists(), "file was created too soon! plaintext keys might have been written to disk"
|
if storage:
|
||||||
|
assert not storage.file_exists(), "file was created too soon! plaintext keys might have been written to disk"
|
||||||
wallet.update_password(old_pw=None, new_pw=password, encrypt_storage=encrypt_file)
|
wallet.update_password(old_pw=None, new_pw=password, encrypt_storage=encrypt_file)
|
||||||
wallet.synchronize()
|
wallet.synchronize()
|
||||||
msg = ("This wallet was restored offline. It may contain more addresses than displayed. "
|
msg = ("This wallet was restored offline. It may contain more addresses than displayed. "
|
||||||
|
|||||||
Reference in New Issue
Block a user