Merge pull request #1894 from lbryio/fix-max-key-fee

fix max_key_fee not being followed
This commit is contained in:
Jack Robison 2019-02-11 16:27:29 -05:00 committed by GitHub
commit afdc44ca13
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 53 additions and 11 deletions

View file

@ -498,7 +498,7 @@ class Config(CLIConfig):
) )
max_key_fee = MaxKeyFee( max_key_fee = MaxKeyFee(
"Don't download streams with fees exceeding this amount", {'currency': 'USD', 'amount': 50.0} "Don't download streams with fees exceeding this amount", {'currency': 'USD', 'amount': 50.0}
) # TODO: use this )
# reflector settings # reflector settings
reflect_streams = Toggle( reflect_streams = Toggle(

View file

@ -219,7 +219,7 @@ class ExchangeRateManager:
def convert_currency(self, from_currency, to_currency, amount): def convert_currency(self, from_currency, to_currency, amount):
rates = [market.rate for market in self.market_feeds] rates = [market.rate for market in self.market_feeds]
log.info("Converting %f %s to %s, rates: %s" % (amount, from_currency, to_currency, rates)) log.debug("Converting %f %s to %s, rates: %s" % (amount, from_currency, to_currency, rates))
if from_currency == to_currency: if from_currency == to_currency:
return amount return amount

View file

@ -4,7 +4,7 @@ import typing
import binascii import binascii
import logging import logging
import random import random
from lbrynet.error import ResolveError, InvalidStreamDescriptorError from lbrynet.error import ResolveError, InvalidStreamDescriptorError, KeyFeeAboveMaxAllowed, InsufficientFundsError
from lbrynet.stream.downloader import StreamDownloader from lbrynet.stream.downloader import StreamDownloader
from lbrynet.stream.managed_stream import ManagedStream from lbrynet.stream.managed_stream import ManagedStream
from lbrynet.schema.claim import ClaimDict from lbrynet.schema.claim import ClaimDict
@ -287,9 +287,6 @@ class StreamManager:
already_started = tuple(filter(lambda s: s.descriptor.sd_hash == sd_hash, self.streams)) already_started = tuple(filter(lambda s: s.descriptor.sd_hash == sd_hash, self.streams))
if already_started: if already_started:
return already_started[0] return already_started[0]
if should_pay and fee_address and fee_amount and fee_amount > await self.wallet.default_account.get_balance():
raise Exception("not enough funds")
self.starting_streams[sd_hash] = asyncio.Future(loop=self.loop) self.starting_streams[sd_hash] = asyncio.Future(loop=self.loop)
stream_task = self.loop.create_task( stream_task = self.loop.create_task(
self._download_stream_from_claim(node, self.config.download_dir, claim_info, file_name) self._download_stream_from_claim(node, self.config.download_dir, claim_info, file_name)
@ -354,7 +351,7 @@ class StreamManager:
timeout = timeout or self.config.download_timeout timeout = timeout or self.config.download_timeout
parsed_uri = parse_lbry_uri(uri) parsed_uri = parse_lbry_uri(uri)
if parsed_uri.is_channel: if parsed_uri.is_channel:
raise Exception("cannot download a channel claim, specify a /path") raise ResolveError("cannot download a channel claim, specify a /path")
resolved = (await self.wallet.resolve(uri)).get(uri, {}) resolved = (await self.wallet.resolve(uri)).get(uri, {})
resolved = resolved if 'value' in resolved else resolved.get('claim') resolved = resolved if 'value' in resolved else resolved.get('claim')
@ -372,6 +369,19 @@ class StreamManager:
fee_amount = round(exchange_rate_manager.convert_currency( fee_amount = round(exchange_rate_manager.convert_currency(
claim.source_fee.currency, "LBC", claim.source_fee.amount claim.source_fee.currency, "LBC", claim.source_fee.amount
), 5) ), 5)
max_fee_amount = round(exchange_rate_manager.convert_currency(
self.config.max_key_fee['currency'], "LBC", self.config.max_key_fee['amount']
), 5)
if fee_amount > max_fee_amount:
msg = f"fee of {fee_amount} exceeds max configured to allow of {max_fee_amount}"
log.warning(msg)
raise KeyFeeAboveMaxAllowed(msg)
else:
balance = await self.wallet.default_account.get_balance()
if fee_amount > balance:
msg = f"fee of {fee_amount} exceeds max available balance"
log.warning(msg)
raise InsufficientFundsError(msg)
fee_address = claim.source_fee.address.decode() fee_address = claim.source_fee.address.decode()
outpoint = f"{resolved['txid']}:{resolved['nout']}" outpoint = f"{resolved['txid']}:{resolved['nout']}"
existing = self.get_filtered_streams(outpoint=outpoint) existing = self.get_filtered_streams(outpoint=outpoint)

View file

@ -40,7 +40,7 @@ def get_dummy_exchange_rate_manager(time):
'BTCLBC': {'spot': 3.0, 'ts': time.time() + 1}, 'BTCLBC': {'spot': 3.0, 'ts': time.time() + 1},
'USDBTC': {'spot': 2.0, 'ts': time.time() + 2} 'USDBTC': {'spot': 2.0, 'ts': time.time() + 2}
} }
return DummyExchangeRateManager([BTCLBCFeed()], rates) return DummyExchangeRateManager([BTCLBCFeed(), USDBTCFeed()], rates)
class FeeFormatTest(unittest.TestCase): class FeeFormatTest(unittest.TestCase):

View file

@ -5,7 +5,7 @@ import asyncio
import time import time
from tests.unit.blob_exchange.test_transfer_blob import BlobExchangeTestBase from tests.unit.blob_exchange.test_transfer_blob import BlobExchangeTestBase
from tests.unit.lbrynet_daemon.test_ExchangeRateManager import get_dummy_exchange_rate_manager from tests.unit.lbrynet_daemon.test_ExchangeRateManager import get_dummy_exchange_rate_manager
from lbrynet.error import InsufficientFundsError, KeyFeeAboveMaxAllowed
from lbrynet.extras.wallet.manager import LbryWalletManager from lbrynet.extras.wallet.manager import LbryWalletManager
from lbrynet.stream.stream_manager import StreamManager from lbrynet.stream.stream_manager import StreamManager
from lbrynet.stream.descriptor import StreamDescriptor from lbrynet.stream.descriptor import StreamDescriptor
@ -26,7 +26,7 @@ def get_mock_node(peer):
return mock_node return mock_node
def get_mock_wallet(sd_hash, storage): def get_mock_wallet(sd_hash, storage, balance=10.0, fee=None):
claim = { claim = {
"address": "bYFeMtSL7ARuG1iMpjFyrnTe4oJHSAVNXF", "address": "bYFeMtSL7ARuG1iMpjFyrnTe4oJHSAVNXF",
"amount": "0.1", "amount": "0.1",
@ -69,6 +69,8 @@ def get_mock_wallet(sd_hash, storage):
"version": "_0_0_1" "version": "_0_0_1"
} }
} }
if fee:
claim['value']['stream']['metadata']['fee'] = fee
claim_dict = ClaimDict.load_dict(claim['value']) claim_dict = ClaimDict.load_dict(claim['value'])
claim['hex'] = binascii.hexlify(claim_dict.serialized).decode() claim['hex'] = binascii.hexlify(claim_dict.serialized).decode()
@ -80,6 +82,11 @@ def get_mock_wallet(sd_hash, storage):
mock_wallet = mock.Mock(spec=LbryWalletManager) mock_wallet = mock.Mock(spec=LbryWalletManager)
mock_wallet.resolve = mock_resolve mock_wallet.resolve = mock_resolve
async def get_balance(*_):
return balance
mock_wallet.default_account.get_balance = get_balance
return mock_wallet, claim['permanent_url'] return mock_wallet, claim['permanent_url']
@ -91,12 +98,15 @@ class TestStreamManager(BlobExchangeTestBase):
f.write(os.urandom(20000000)) f.write(os.urandom(20000000))
descriptor = await StreamDescriptor.create_stream(self.loop, self.server_blob_manager.blob_dir, file_path) descriptor = await StreamDescriptor.create_stream(self.loop, self.server_blob_manager.blob_dir, file_path)
self.sd_hash = descriptor.calculate_sd_hash() self.sd_hash = descriptor.calculate_sd_hash()
self.mock_wallet, self.uri = get_mock_wallet(self.sd_hash, self.client_storage)
async def setup_stream_manager(self, balance=10.0, fee=None):
self.mock_wallet, self.uri = get_mock_wallet(self.sd_hash, self.client_storage, balance, fee)
self.stream_manager = StreamManager(self.loop, self.client_config, self.client_blob_manager, self.mock_wallet, self.stream_manager = StreamManager(self.loop, self.client_config, self.client_blob_manager, self.mock_wallet,
self.client_storage, get_mock_node(self.server_from_client)) self.client_storage, get_mock_node(self.server_from_client))
self.exchange_rate_manager = get_dummy_exchange_rate_manager(time) self.exchange_rate_manager = get_dummy_exchange_rate_manager(time)
async def test_download_stop_resume_delete(self): async def test_download_stop_resume_delete(self):
await self.setup_stream_manager()
self.assertSetEqual(self.stream_manager.streams, set()) self.assertSetEqual(self.stream_manager.streams, set())
stream = await self.stream_manager.download_stream_from_uri(self.uri, self.exchange_rate_manager) stream = await self.stream_manager.download_stream_from_uri(self.uri, self.exchange_rate_manager)
stream_hash = stream.stream_hash stream_hash = stream.stream_hash
@ -137,3 +147,25 @@ class TestStreamManager(BlobExchangeTestBase):
"select status from file where stream_hash=?", stream_hash "select status from file where stream_hash=?", stream_hash
) )
self.assertEqual(stored_status, None) self.assertEqual(stored_status, None)
async def test_insufficient_funds(self):
fee = {
'currency': 'LBC',
'amount': 11.0,
'address': 'bYFeMtSL7ARuG1iMpjFyrnTe4oJHSAVNXF',
'version': '_0_0_1'
}
await self.setup_stream_manager(10.0, fee)
with self.assertRaises(InsufficientFundsError):
await self.stream_manager.download_stream_from_uri(self.uri, self.exchange_rate_manager)
async def test_fee_above_max_allowed(self):
fee = {
'currency': 'USD',
'amount': 51.0,
'address': 'bYFeMtSL7ARuG1iMpjFyrnTe4oJHSAVNXF',
'version': '_0_0_1'
}
await self.setup_stream_manager(1000000.0, fee)
with self.assertRaises(KeyFeeAboveMaxAllowed):
await self.stream_manager.download_stream_from_uri(self.uri, self.exchange_rate_manager)