From c44de4848129be54052fa5c42626faf31d043526 Mon Sep 17 00:00:00 2001 From: Lex Berezhny Date: Tue, 12 Mar 2019 13:19:17 -0400 Subject: [PATCH] + account.apply and addressmanager.apply --- tests/client_tests/unit/test_account.py | 48 +++++++++++++++++++++++++ torba/client/baseaccount.py | 17 +++++++++ 2 files changed, 65 insertions(+) diff --git a/tests/client_tests/unit/test_account.py b/tests/client_tests/unit/test_account.py index 8c451d2a6..7ca2cf33a 100644 --- a/tests/client_tests/unit/test_account.py +++ b/tests/client_tests/unit/test_account.py @@ -174,6 +174,54 @@ class TestHierarchicalDeterministicAccount(AsyncioTestCase): account_data['ledger'] = 'btc_mainnet' self.assertDictEqual(account_data, account.to_dict()) + def test_apply_diff(self): + account_data = { + 'name': 'My Account', + 'modified_on': 123.456, + 'seed': + "carbon smart garage balance margin twelve chest sword toast envelope bottom stomac" + "h absent", + 'encrypted': False, + 'private_key': + 'xprv9s21ZrQH143K3TsAz5efNV8K93g3Ms3FXcjaWB9fVUsMwAoE3ZT4vYymkp' + '5BxKKfnpz8J6sHDFriX1SnpvjNkzcks8XBnxjGLS83BTyfpna', + 'public_key': + 'xpub661MyMwAqRbcFwwe67Bfjd53h5WXmKm6tqfBJZZH3pQLoy8Nb6mKUMJFc7' + 'UbpVNzmwFPN2evn3YHnig1pkKVYcvCV8owTd2yAcEkJfCX53g', + 'address_generator': { + 'name': 'deterministic-chain', + 'receiving': {'gap': 5, 'maximum_uses_per_address': 2}, + 'change': {'gap': 5, 'maximum_uses_per_address': 2} + } + } + account = self.ledger.account_class.from_dict(self.ledger, Wallet(), account_data) + + self.assertEqual(account.name, 'My Account') + self.assertEqual(account.modified_on, 123.456) + self.assertEqual(account.change.gap, 5) + self.assertEqual(account.change.maximum_uses_per_address, 2) + self.assertEqual(account.receiving.gap, 5) + self.assertEqual(account.receiving.maximum_uses_per_address, 2) + + account_data['name'] = 'Changed Name' + account_data['address_generator']['change']['gap'] = 6 + account_data['address_generator']['change']['maximum_uses_per_address'] = 7 + account_data['address_generator']['receiving']['gap'] = 8 + account_data['address_generator']['receiving']['maximum_uses_per_address'] = 9 + + account.apply(account_data) + # no change because modified_on is not newer + self.assertEqual(account.name, 'My Account') + + account_data['modified_on'] = 200.00 + + account.apply(account_data) + self.assertEqual(account.name, 'Changed Name') + self.assertEqual(account.change.gap, 6) + self.assertEqual(account.change.maximum_uses_per_address, 7) + self.assertEqual(account.receiving.gap, 8) + self.assertEqual(account.receiving.maximum_uses_per_address, 9) + class TestSingleKeyAccount(AsyncioTestCase): diff --git a/torba/client/baseaccount.py b/torba/client/baseaccount.py index fac1276b3..896bc3840 100644 --- a/torba/client/baseaccount.py +++ b/torba/client/baseaccount.py @@ -42,6 +42,9 @@ class AddressManager: d['change'] = change_dict return d + def apply(self, d: dict): + raise NotImplementedError + def to_dict_instance(self) -> Optional[dict]: raise NotImplementedError @@ -95,6 +98,10 @@ class HierarchicalDeterministic(AddressManager): cls(account, 1, **d.get('change', {'gap': 6, 'maximum_uses_per_address': 1})) ) + def apply(self, d: dict): + self.gap = d.get('gap', self.gap) + self.maximum_uses_per_address = d.get('maximum_uses_per_address', self.maximum_uses_per_address) + def to_dict_instance(self): return {'gap': self.gap, 'maximum_uses_per_address': self.maximum_uses_per_address} @@ -296,6 +303,16 @@ class BaseAccount: 'modified_on': self.modified_on } + def apply(self, d: dict): + if d.get('modified_on', 0) > self.modified_on: + self.name = d['name'] + self.modified_on = d.get('modified_on', time.time()) + assert self.address_generator.name == d['address_generator']['name'] + for chain_name in ('change', 'receiving'): + if chain_name in d['address_generator']: + chain_object = getattr(self, chain_name) + chain_object.apply(d['address_generator'][chain_name]) + @property def hash(self) -> bytes: return sha256(json.dumps(self.to_dict()).encode())