wallet encryption

This commit is contained in:
Lex Berezhny 2019-10-13 23:43:06 -04:00
parent dc580b9eff
commit 270f77df24
4 changed files with 55 additions and 133 deletions

View file

@ -252,8 +252,6 @@ class WalletComponent(Component):
'blocks': max(local_height, 0),
'blocks_behind': max(remote_height - local_height, 0),
'best_blockhash': best_hash,
'is_encrypted': self.wallet_manager.use_encryption,
'is_locked': not self.wallet_manager.is_wallet_unlocked,
}
async def start(self):

View file

@ -1166,6 +1166,22 @@ class Daemon(metaclass=JSONRPCServerType):
)
return dict_values_to_lbc(balance)
def jsonrpc_wallet_status(self, wallet_id=None):
"""
Status of wallet including encryption/lock state.
Usage:
wallet_status [<wallet_id> | --wallet_id=<wallet_id>]
Options:
--wallet_id=<wallet_id> : (str) status of specific wallet
Returns:
Dictionary of wallet status information.
"""
wallet = self.wallet_manager.get_wallet_or_default(wallet_id)
return {'is_encrypted': wallet.is_encrypted, 'is_locked': wallet.is_locked}
@requires(WALLET_COMPONENT)
def jsonrpc_wallet_unlock(self, password, wallet_id=None):
"""
@ -1501,98 +1517,6 @@ class Daemon(metaclass=JSONRPCServerType):
return account
@deprecated('wallet_unlock')
@requires(WALLET_COMPONENT)
def jsonrpc_account_unlock(self, password, account_id=None, wallet_id=None):
"""
Unlock an encrypted account
Usage:
account_unlock (<password> | --password=<password>)
[<account_id> | --account_id=<account_id>]
[--wallet_id=<wallet_id>]
Options:
--password=<password> : (str) password to use for unlocking
--account_id=<account_id> : (str) id for the account to unlock, unlocks default account
if not provided
--wallet_id=<wallet_id> : (str) restrict operation to specific wallet
Returns:
(bool) true if account is unlocked, otherwise false
"""
wallet = self.wallet_manager.get_wallet_or_default(wallet_id)
return self.wallet_manager.unlock_account(
password, wallet.get_account_or_default(account_id)
)
@deprecated('wallet_lock')
@requires(WALLET_COMPONENT)
def jsonrpc_account_lock(self, account_id=None, wallet_id=None):
"""
Lock an unlocked account
Usage:
account_lock [<account_id> | --account_id=<account_id>] [--wallet_id=<wallet_id>]
Options:
--account_id=<account_id> : (str) id for the account to lock
--wallet_id=<wallet_id> : (str) restrict operation to specific wallet
Returns:
(bool) true if account is locked, otherwise false
"""
wallet = self.wallet_manager.get_wallet_or_default(wallet_id)
return self.wallet_manager.lock_account(
wallet.get_account_or_default(account_id)
)
@deprecated('wallet_decrypt')
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
def jsonrpc_account_decrypt(self, account_id=None, wallet_id=None):
"""
Decrypt an encrypted account, this will remove the wallet password. The account must be unlocked to decrypt it
Usage:
account_decrypt [<account_id> | --account_id=<account_id>] [--wallet_id=<wallet_id>]
Options:
--account_id=<account_id> : (str) id for the account to decrypt
--wallet_id=<wallet_id> : (str) restrict operation to specific wallet
Returns:
(bool) true if wallet is decrypted, otherwise false
"""
wallet = self.wallet_manager.get_wallet_or_default(wallet_id)
return self.wallet_manager.decrypt_account(
wallet.get_account_or_default(account_id)
)
@deprecated('wallet_encrypt')
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
def jsonrpc_account_encrypt(self, new_password, account_id=None, wallet_id=None):
"""
Encrypt an unencrypted account with a password
Usage:
account_encrypt (<new_password> | --new_password=<new_password>)
[<account_id> | --account_id=<account_id>]
[--wallet_id=<wallet_id>]
Options:
--new_password=<new_password> : (str) password to encrypt account
--account_id=<account_id> : (str) id for the account to encrypt, encrypts
default account if not provided
--wallet_id=<wallet_id> : (str) restrict operation to specific wallet
Returns:
(bool) true if wallet is decrypted, otherwise false
"""
wallet = self.wallet_manager.get_wallet_or_default(wallet_id)
return self.wallet_manager.encrypt_account(
new_password, wallet.get_account_or_default(account_id)
)
@requires("wallet")
def jsonrpc_account_max_address_gap(self, account_id, wallet_id=None):
"""
@ -1720,6 +1644,7 @@ class Daemon(metaclass=JSONRPCServerType):
"""
wallet = self.wallet_manager.get_wallet_or_default(wallet_id)
assert not wallet.is_locked, "Cannot sync apply on a locked wallet."
if data is not None:
added_accounts = wallet.merge(self.wallet_manager, password, data)
if added_accounts and self.ledger.network.is_connected:

View file

@ -26,42 +26,8 @@ class LbryWalletManager(BaseWalletManager):
def db(self) -> WalletDatabase:
return self.ledger.db
@property
def use_encryption(self):
return self.default_account.serialize_encrypted
@property
def is_wallet_unlocked(self):
return not self.default_account.encrypted
def check_locked(self):
return self.default_account.encrypted
def decrypt_account(self, account):
assert account.password is not None, "account is not unlocked"
assert not account.encrypted, "account is not unlocked"
account.serialize_encrypted = False
self.save()
return not account.encrypted and not account.serialize_encrypted
def encrypt_account(self, password, account):
assert not account.encrypted, "account is already encrypted"
account.encrypt(password)
account.serialize_encrypted = True
self.save()
self.unlock_account(password, account)
return account.serialize_encrypted
def unlock_account(self, password, account):
assert account.encrypted, "account is not locked"
account.decrypt(password)
return not account.encrypted
def lock_account(self, account):
assert account.password is not None, "account is already locked"
assert not account.encrypted and account.serialize_encrypted, "account is not encrypted"
account.encrypt(account.password)
return account.encrypted
return self.default_wallet.is_locked
@staticmethod
def migrate_lbryum_to_torba(path):
@ -210,7 +176,3 @@ class LbryWalletManager(BaseWalletManager):
tx = self.ledger.transaction_class(unhexlify(raw))
await self.ledger.maybe_verify_transaction(tx, height)
return tx
def save(self):
for wallet in self.wallets:
wallet.save()

View file

@ -170,6 +170,43 @@ class Wallet:
added_accounts.append(new_account)
return added_accounts
@property
def is_locked(self) -> bool:
for account in self.accounts:
if account.encrypted:
return True
return False
def unlock(self, password):
for account in self.accounts:
if account.encrypted:
account.decrypt(password)
def lock(self):
for account in self.accounts:
if not account.encrypted:
account.encrypt(account.password)
@property
def is_encrypted(self) -> bool:
for account in self.accounts:
if account.serialize_encrypted:
return True
return False
def decrypt(self):
for account in self.accounts:
account.serialize_encrypted = False
self.save()
def encrypt(self, password):
for account in self.accounts:
if not self.encrypted:
account.encrypt(password)
account.serialize_encrypted = True
self.save()
self.unlock(password)
class WalletStorage: