From 56df145052ba25253abe27d3ba2f9c046a0abb86 Mon Sep 17 00:00:00 2001 From: Lex Berezhny Date: Thu, 3 Oct 2019 23:14:09 -0400 Subject: [PATCH] updating/abanding streams/channels works across all accounts --- lbry/lbry/extras/daemon/Daemon.py | 64 ++++++++++++++----- lbry/tests/integration/test_claim_commands.py | 32 ++++++++++ 2 files changed, 80 insertions(+), 16 deletions(-) diff --git a/lbry/lbry/extras/daemon/Daemon.py b/lbry/lbry/extras/daemon/Daemon.py index 6557e468d..1399683e0 100644 --- a/lbry/lbry/extras/daemon/Daemon.py +++ b/lbry/lbry/extras/daemon/Daemon.py @@ -2248,7 +2248,7 @@ class Daemon(metaclass=JSONRPCServerType): --clear_locations : (bool) clear existing locations (prior to adding new ones) --thumbnail_url=: (str) thumbnail url --cover_url= : (str) url of cover image - --account_id= : (str) account to use for holding the transaction + --account_id= : (str) account in which to look for channel (default: all) --wallet_id= : (str) restrict operation to specific wallet --funding_account_ids=: (list) ids of accounts to fund this transaction --claim_address=: (str) address where the channel is sent @@ -2263,15 +2263,21 @@ class Daemon(metaclass=JSONRPCServerType): Returns: {Transaction} """ wallet = self.wallet_manager.get_wallet_or_default(wallet_id) - account = wallet.get_account_or_default(account_id) funding_accounts = wallet.get_accounts_or_all(funding_account_ids) + if account_id: + account = wallet.get_account_or_error(account_id) + accounts = [account] + else: + account = wallet.default_account + accounts = wallet.accounts existing_channels = await self.ledger.get_claims( - wallet=wallet, accounts=[account] if account_id else wallet.accounts, claim_id=claim_id + wallet=wallet, accounts=accounts, claim_id=claim_id ) if len(existing_channels) != 1: + account_ids = ', '.join(f"'{account.id}'" for account in accounts) raise Exception( - f"Can't find the channel '{claim_id}' in account '{account.id}'." + f"Can't find the channel '{claim_id}' in account(s) {account_ids}." ) old_txo = existing_channels[0] if not old_txo.claim.is_channel: @@ -2346,12 +2352,21 @@ class Daemon(metaclass=JSONRPCServerType): Returns: {Transaction} """ wallet = self.wallet_manager.get_wallet_or_default(wallet_id) - account = wallet.get_account_or_default(account_id) + if account_id: + account = wallet.get_account_or_error(account_id) + accounts = [account] + else: + account = wallet.default_account + accounts = wallet.accounts if txid is not None and nout is not None: - claims = await account.get_claims(**{'txo.txid': txid, 'txo.position': nout}) + claims = await self.ledger.get_claims( + wallet=wallet, accounts=accounts, **{'txo.txid': txid, 'txo.position': nout} + ) elif claim_id is not None: - claims = await account.get_claims(claim_id=claim_id) + claims = await self.ledger.get_claims( + wallet=wallet, accounts=accounts, claim_id=claim_id + ) else: raise Exception('Must specify claim_id, or txid and nout') @@ -2854,7 +2869,7 @@ class Daemon(metaclass=JSONRPCServerType): --clear_channel : (bool) remove channel signature --channel_account_id=: (str) one or more account ids for accounts to look in for channel certificates, defaults to all accounts. - --account_id= : (str) account to use for holding the transaction + --account_id= : (str) account in which to look for stream (default: all) --wallet_id= : (str) restrict operation to specific wallet --funding_account_ids=: (list) ids of accounts to fund this transaction --claim_address=: (str) address where the claim is sent to, if not specified @@ -2869,13 +2884,21 @@ class Daemon(metaclass=JSONRPCServerType): Returns: {Transaction} """ wallet = self.wallet_manager.get_wallet_or_default(wallet_id) - account = wallet.get_account_or_default(account_id) funding_accounts = wallet.get_accounts_or_all(funding_account_ids) + if account_id: + account = wallet.get_account_or_error(account_id) + accounts = [account] + else: + account = wallet.default_account + accounts = wallet.accounts - existing_claims = await account.get_claims(claim_id=claim_id) + existing_claims = await self.ledger.get_claims( + wallet=wallet, accounts=accounts, claim_id=claim_id + ) if len(existing_claims) != 1: + account_ids = ', '.join(f"'{account.id}'" for account in accounts) raise Exception( - f"Can't find the claim '{claim_id}' in account '{account.id}'." + f"Can't find the stream '{claim_id}' in account(s) {account_ids}." ) old_txo = existing_claims[0] if not old_txo.claim.is_stream: @@ -2979,12 +3002,21 @@ class Daemon(metaclass=JSONRPCServerType): Returns: {Transaction} """ wallet = self.wallet_manager.get_wallet_or_default(wallet_id) - account = wallet.get_account_or_default(account_id) + if account_id: + account = wallet.get_account_or_error(account_id) + accounts = [account] + else: + account = wallet.default_account + accounts = wallet.accounts if txid is not None and nout is not None: - claims = await account.get_claims(**{'txo.txid': txid, 'txo.position': nout}) + claims = await self.ledger.get_claims( + wallet=wallet, accounts=accounts, **{'txo.txid': txid, 'txo.position': nout} + ) elif claim_id is not None: - claims = await account.get_claims(claim_id=claim_id) + claims = await self.ledger.get_claims( + wallet=wallet, accounts=accounts, claim_id=claim_id + ) else: raise Exception('Must specify claim_id, or txid and nout') @@ -2992,14 +3024,14 @@ class Daemon(metaclass=JSONRPCServerType): raise Exception('No claim found for the specified claim_id or txid:nout') tx = await Transaction.create( - [Input.spend(txo) for txo in claims], [], [account], account + [Input.spend(txo) for txo in claims], [], accounts, account ) if not preview: await self.broadcast_or_release(tx, blocking) await self.analytics_manager.send_claim_action('abandon') else: - await account.ledger.release_tx(tx) + await self.ledger.release_tx(tx) return tx diff --git a/lbry/tests/integration/test_claim_commands.py b/lbry/tests/integration/test_claim_commands.py index 6f961e3ad..04e12b196 100644 --- a/lbry/tests/integration/test_claim_commands.py +++ b/lbry/tests/integration/test_claim_commands.py @@ -507,6 +507,22 @@ class ChannelCommands(CommandTestCase): # second wallet should be able to update now await daemon2.jsonrpc_channel_update(claim_id, bid='0.5') + async def test_channel_update_across_accounts(self): + account2 = await self.daemon.jsonrpc_account_create('second account') + channel = await self.out(self.channel_create('@spam', '1.0', account_id=account2.id)) + # channel not in account1 + with self.assertRaisesRegex(Exception, "Can't find the channel"): + await self.channel_update(self.get_claim_id(channel), bid='2.0', account_id=self.account.id) + # channel is in account2 + await self.channel_update(self.get_claim_id(channel), bid='2.0', account_id=account2.id) + result = await self.out(self.daemon.jsonrpc_channel_list()) + self.assertEqual(result[0]['amount'], '2.0') + # check all accounts for channel + await self.channel_update(self.get_claim_id(channel), bid='3.0') + result = await self.out(self.daemon.jsonrpc_channel_list()) + self.assertEqual(result[0]['amount'], '3.0') + await self.channel_abandon(self.get_claim_id(channel)) + class StreamCommands(ClaimTestCase): @@ -564,6 +580,22 @@ class StreamCommands(ClaimTestCase): self.assertEqual(len(tx['outputs']), 1) # no change self.assertEqual(len(await self.daemon.jsonrpc_claim_list()), 2) + async def test_stream_update_and_abandon_across_accounts(self): + account2 = await self.daemon.jsonrpc_account_create('second account') + stream = await self.out(self.stream_create('spam', '1.0', account_id=account2.id)) + # stream not in account1 + with self.assertRaisesRegex(Exception, "Can't find the stream"): + await self.stream_update(self.get_claim_id(stream), bid='2.0', account_id=self.account.id) + # stream is in account2 + await self.stream_update(self.get_claim_id(stream), bid='2.0', account_id=account2.id) + result = await self.out(self.daemon.jsonrpc_stream_list()) + self.assertEqual(result[0]['amount'], '2.0') + # check all accounts for stream + await self.stream_update(self.get_claim_id(stream), bid='3.0') + result = await self.out(self.daemon.jsonrpc_stream_list()) + self.assertEqual(result[0]['amount'], '3.0') + await self.stream_abandon(self.get_claim_id(stream)) + async def test_publishing_checks_all_accounts_for_channel(self): account1_id, account1 = self.account.id, self.account new_account = await self.out(self.daemon.jsonrpc_account_create('second account'))