sync_apply always updates local password if encrypt-on-disk is enabled

This commit is contained in:
Lex Berezhny 2019-10-16 10:06:17 -04:00
parent 722419dffc
commit d1a123997d
3 changed files with 21 additions and 9 deletions

View file

@ -16,7 +16,7 @@ from traceback import format_exc
from aiohttp import web from aiohttp import web
from functools import wraps, partial from functools import wraps, partial
from google.protobuf.message import DecodeError from google.protobuf.message import DecodeError
from torba.client.wallet import Wallet from torba.client.wallet import Wallet, ENCRYPT_ON_DISK
from torba.client.baseaccount import SingleKey, HierarchicalDeterministic from torba.client.baseaccount import SingleKey, HierarchicalDeterministic
from lbry import utils from lbry import utils
@ -1642,6 +1642,7 @@ class Daemon(metaclass=JSONRPCServerType):
""" """
wallet = self.wallet_manager.get_wallet_or_default(wallet_id) wallet = self.wallet_manager.get_wallet_or_default(wallet_id)
wallet_changed = False
if data is not None: if data is not None:
added_accounts = wallet.merge(self.wallet_manager, password, data) added_accounts = wallet.merge(self.wallet_manager, password, data)
if added_accounts and self.ledger.network.is_connected: if added_accounts and self.ledger.network.is_connected:
@ -1652,6 +1653,11 @@ class Daemon(metaclass=JSONRPCServerType):
else: else:
for new_account in added_accounts: for new_account in added_accounts:
asyncio.create_task(self.ledger.subscribe_account(new_account)) asyncio.create_task(self.ledger.subscribe_account(new_account))
wallet_changed = True
if wallet.preferences.get(ENCRYPT_ON_DISK, False) and password != wallet.encryption_password:
wallet.encryption_password = password
wallet_changed = True
if wallet_changed:
wallet.save() wallet.save()
encrypted = wallet.pack(password) encrypted = wallet.pack(password)
return { return {

View file

@ -117,15 +117,20 @@ class WalletEncryptionAndSynchronization(CommandTestCase):
daemon, daemon2 = self.daemon, self.daemon2 daemon, daemon2 = self.daemon, self.daemon2
wallet, wallet2 = daemon.wallet_manager.default_wallet, daemon2.wallet_manager.default_wallet wallet, wallet2 = daemon.wallet_manager.default_wallet, daemon2.wallet_manager.default_wallet
self.assertEqual(wallet2.encryption_password, None)
self.assertEqual(wallet2.encryption_password, None)
daemon.jsonrpc_wallet_encrypt('password') daemon.jsonrpc_wallet_encrypt('password')
self.assertEqual(wallet.encryption_password, 'password') self.assertEqual(wallet.encryption_password, 'password')
data = await daemon2.jsonrpc_sync_apply('password2') data = await daemon2.jsonrpc_sync_apply('password2')
# sync_apply doesn't save password if encrypt-on-disk is False
self.assertEqual(wallet2.encryption_password, None)
# need to use new password2 in sync_apply
with self.assertRaises(ValueError): # wrong password with self.assertRaises(ValueError): # wrong password
await daemon.jsonrpc_sync_apply('password', data=data['data'], blocking=True) await daemon.jsonrpc_sync_apply('password', data=data['data'], blocking=True)
await daemon.jsonrpc_sync_apply('password2', data=data['data'], blocking=True) await daemon.jsonrpc_sync_apply('password2', data=data['data'], blocking=True)
# sync_apply with new password2 also sets it as new local password
# password changed
self.assertEqual(wallet.encryption_password, 'password2') self.assertEqual(wallet.encryption_password, 'password2')
self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True}) self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True})
self.assertEqual(daemon.jsonrpc_preference_get(ENCRYPT_ON_DISK), {'encrypt-on-disk': True}) self.assertEqual(daemon.jsonrpc_preference_get(ENCRYPT_ON_DISK), {'encrypt-on-disk': True})
@ -137,13 +142,16 @@ class WalletEncryptionAndSynchronization(CommandTestCase):
self.assertTrue(daemon.jsonrpc_wallet_unlock('password2')) self.assertTrue(daemon.jsonrpc_wallet_unlock('password2'))
# propagate disk encryption to daemon2 # propagate disk encryption to daemon2
data = await daemon.jsonrpc_sync_apply('password2') data = await daemon.jsonrpc_sync_apply('password3')
# sync_apply (even with no data) on wallet with encrypt-on-disk updates local password
self.assertEqual(wallet.encryption_password, 'password3')
self.assertEqual(wallet2.encryption_password, None) self.assertEqual(wallet2.encryption_password, None)
await daemon2.jsonrpc_sync_apply('password2', data=data['data'], blocking=True) await daemon2.jsonrpc_sync_apply('password3', data=data['data'], blocking=True)
self.assertEqual(wallet.encryption_password, 'password2') # the other device got new password and on disk encryption
self.assertEqual(wallet2.encryption_password, 'password3')
self.assertEqual(daemon2.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True}) self.assertEqual(daemon2.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True})
self.assertEqual(daemon2.jsonrpc_preference_get(ENCRYPT_ON_DISK), {'encrypt-on-disk': True}) self.assertEqual(daemon2.jsonrpc_preference_get(ENCRYPT_ON_DISK), {'encrypt-on-disk': True})
self.assertWalletEncrypted(wallet2.storage.path, True) self.assertWalletEncrypted(wallet2.storage.path, True)
daemon2.jsonrpc_wallet_lock() daemon2.jsonrpc_wallet_lock()
self.assertTrue(daemon2.jsonrpc_wallet_unlock('password2')) self.assertTrue(daemon2.jsonrpc_wallet_unlock('password3'))

View file

@ -178,8 +178,6 @@ class Wallet:
added_accounts = [] added_accounts = []
decrypted_data = self.unpack(password, data) decrypted_data = self.unpack(password, data)
self.preferences.merge(decrypted_data.get('preferences', {})) self.preferences.merge(decrypted_data.get('preferences', {}))
if self.preferences.get(ENCRYPT_ON_DISK, False):
self.encryption_password = password
for account_dict in decrypted_data['accounts']: for account_dict in decrypted_data['accounts']:
ledger = manager.get_or_create_ledger(account_dict['ledger']) ledger = manager.get_or_create_ledger(account_dict['ledger'])
_, _, pubkey = ledger.account_class.keys_from_dict(ledger, account_dict) _, _, pubkey = ledger.account_class.keys_from_dict(ledger, account_dict)