diff --git a/lbry/conf.py b/lbry/conf.py index da2f45f85..c204a49f5 100644 --- a/lbry/conf.py +++ b/lbry/conf.py @@ -558,6 +558,7 @@ class Config(CLIConfig): "Don't download streams with fees exceeding this amount. When set to " "null, the amount is unbounded.", {'currency': 'USD', 'amount': 50.0} ) + max_wallet_server_fee = String("Maximum daily LBC amount allowed as payment for wallet servers.", "1.0") # reflector settings reflect_streams = Toggle( diff --git a/lbry/wallet/manager.py b/lbry/wallet/manager.py index 5005f3732..5e374051c 100644 --- a/lbry/wallet/manager.py +++ b/lbry/wallet/manager.py @@ -81,7 +81,9 @@ class WalletManager: await asyncio.gather(*( l.start() for l in self.ledgers.values() )) - await self.usage_payment_service.start(self.ledger, self.default_wallet) + await self.usage_payment_service.start( + self.ledger, self.default_wallet, self.config.max_wallet_server_fee if self.config else None + ) async def stop(self): await asyncio.gather(*( diff --git a/lbry/wallet/usage_payment.py b/lbry/wallet/usage_payment.py index d480fd566..b5f7130bf 100644 --- a/lbry/wallet/usage_payment.py +++ b/lbry/wallet/usage_payment.py @@ -8,13 +8,14 @@ log = logging.getLogger(__name__) class WalletServerPayer: - def __init__(self, payment_period=24 * 60 * 60): + def __init__(self, payment_period=24 * 60 * 60, max_fee='1.0'): self.ledger = None self.wallet = None self.running = False self.task = None self.payment_period = payment_period self.analytics_manager = None + self.max_fee = max_fee async def pay(self): while self.running: @@ -33,7 +34,13 @@ class WalletServerPayer: continue amount = lbc_to_dewies(features['daily_fee']) # check that this is in lbc and not dewies - # todo: check that amount is less than our max + limit = lbc_to_dewies(self.max_fee) + if amount > limit: + log.warning( + "Server asked %s LBC as daily fee, but maximum allowed is %s LBC. Skipping payment round.", + features['daily_fee'], self.max_fee + ) + continue tx = await Transaction.create( [], @@ -46,7 +53,8 @@ class WalletServerPayer: if self.analytics_manager: await self.analytics_manager.send_credits_sent() - async def start(self, ledger, default_wallet): + async def start(self, ledger, default_wallet, max_fee=None): + self.max_fee = max_fee or self.max_fee self.ledger = ledger self.wallet = default_wallet self.running = True diff --git a/tests/integration/blockchain/test_wallet_server_sessions.py b/tests/integration/blockchain/test_wallet_server_sessions.py index 460fac052..233cbd2b5 100644 --- a/tests/integration/blockchain/test_wallet_server_sessions.py +++ b/tests/integration/blockchain/test_wallet_server_sessions.py @@ -65,18 +65,35 @@ class TestUsagePayment(CommandTestCase): node = SPVNode(self.conductor.spv_module, node_number=2) await node.start(self.blockchain, extraconf={"PAYMENT_ADDRESS": address, "DAILY_FEE": "1.1"}) + self.daemon.jsonrpc_settings_set('lbryum_servers', [f"{node.hostname}:{node.port}"]) + with self.assertLogs(level='WARNING') as cm: + await self.daemon.jsonrpc_wallet_reconnect() + + features = await self.ledger.network.get_server_features() + self.assertEqual(features["payment_address"], address) + self.assertEqual(features["daily_fee"], "1.1") + elapsed = 0 + while not cm.output: + await asyncio.sleep(0.1) + elapsed += 1 + if elapsed > 30: + raise TimeoutError('Nothing logged for 3 seconds.') + self.assertEqual( + cm.output, + ['WARNING:lbry.wallet.usage_payment:Server asked 1.1 LBC as daily fee, but ' + 'maximum allowed is 1.0 LBC. Skipping payment round.'] + ) + await node.stop(False) + await node.start(self.blockchain, extraconf={"PAYMENT_ADDRESS": address, "DAILY_FEE": "1.0"}) self.addCleanup(node.stop) self.daemon.jsonrpc_settings_set('lbryum_servers', [f"{node.hostname}:{node.port}"]) await self.daemon.jsonrpc_wallet_reconnect() - features = await self.ledger.network.get_server_features() self.assertEqual(features["payment_address"], address) - self.assertEqual(features["daily_fee"], "1.1") - - if len(history) == 0: - await asyncio.wait_for(self.on_address_update(address), timeout=1) - _, history = await self.ledger.get_local_status_and_history(address) + self.assertEqual(features["daily_fee"], "1.0") + await asyncio.wait_for(self.on_address_update(address), timeout=1) + _, history = await self.ledger.get_local_status_and_history(address) txid, nout = history[0] tx_details = await self.daemon.jsonrpc_transaction_show(txid) - self.assertEqual(tx_details.outputs[nout].amount, 110000000) + self.assertEqual(tx_details.outputs[nout].amount, 100000000) self.assertEqual(tx_details.outputs[nout].get_address(self.ledger), address)