2019-06-26 16:28:13 -04:00
|
|
|
import asyncio
|
|
|
|
|
2019-12-31 14:52:57 -05:00
|
|
|
import lbry
|
2019-07-23 13:45:10 -03:00
|
|
|
import lbry.wallet
|
2020-02-21 10:05:46 -05:00
|
|
|
from lbry.error import ServerPaymentFeeAboveMaxAllowedError
|
2020-01-03 02:40:37 -05:00
|
|
|
from lbry.wallet.network import ClientSession
|
2021-08-05 15:58:41 -03:00
|
|
|
from lbry.wallet.rpc import RPCError
|
2021-06-17 21:22:23 -04:00
|
|
|
from lbry.wallet.server.db.elasticsearch.sync import run_sync, make_es_index
|
2021-01-16 16:27:42 -05:00
|
|
|
from lbry.wallet.server.session import LBRYElectrumX
|
2020-02-21 00:04:37 -03:00
|
|
|
from lbry.testcase import IntegrationTestCase, CommandTestCase
|
2020-01-06 01:29:48 -03:00
|
|
|
from lbry.wallet.orchstr8.node import SPVNode
|
2019-06-26 16:28:13 -04:00
|
|
|
|
|
|
|
|
2019-11-08 12:52:39 -03:00
|
|
|
class TestSessions(IntegrationTestCase):
|
2019-06-26 16:28:13 -04:00
|
|
|
"""
|
2019-07-16 06:23:44 -03:00
|
|
|
Tests that server cleans up stale connections after session timeout and client times out too.
|
2019-06-26 16:28:13 -04:00
|
|
|
"""
|
|
|
|
async def test_session_bloat_from_socket_timeout(self):
|
2019-07-16 06:23:44 -03:00
|
|
|
await self.conductor.stop_spv()
|
2019-07-21 23:26:49 -03:00
|
|
|
await self.ledger.stop()
|
2019-07-16 06:23:44 -03:00
|
|
|
self.conductor.spv_node.session_timeout = 1
|
|
|
|
await self.conductor.start_spv()
|
2019-09-03 11:28:30 -03:00
|
|
|
session = ClientSession(
|
|
|
|
network=None, server=(self.conductor.spv_node.hostname, self.conductor.spv_node.port), timeout=0.2
|
|
|
|
)
|
2019-07-16 06:23:44 -03:00
|
|
|
await session.create_connection()
|
|
|
|
await session.send_request('server.banner', ())
|
|
|
|
self.assertEqual(len(self.conductor.spv_node.server.session_mgr.sessions), 1)
|
|
|
|
self.assertFalse(session.is_closing())
|
|
|
|
await asyncio.sleep(1.1)
|
|
|
|
with self.assertRaises(asyncio.TimeoutError):
|
|
|
|
await session.send_request('server.banner', ())
|
|
|
|
self.assertTrue(session.is_closing())
|
|
|
|
self.assertEqual(len(self.conductor.spv_node.server.session_mgr.sessions), 0)
|
2019-07-23 13:45:10 -03:00
|
|
|
|
2019-11-08 12:52:39 -03:00
|
|
|
async def test_proper_version(self):
|
|
|
|
info = await self.ledger.network.get_server_features()
|
2019-12-31 14:52:57 -05:00
|
|
|
self.assertEqual(lbry.__version__, info['server_version'])
|
2019-11-08 12:52:39 -03:00
|
|
|
|
2019-11-18 12:19:16 -03:00
|
|
|
async def test_client_errors(self):
|
|
|
|
# Goal is ensuring thsoe are raised and not trapped accidentally
|
|
|
|
with self.assertRaisesRegex(Exception, 'not a valid address'):
|
|
|
|
await self.ledger.network.get_history('of the world')
|
|
|
|
with self.assertRaisesRegex(Exception, 'rejected by network rules.*TX decode failed'):
|
|
|
|
await self.ledger.network.broadcast('13370042004200')
|
|
|
|
|
2019-07-23 13:45:10 -03:00
|
|
|
|
2020-01-06 01:29:48 -03:00
|
|
|
class TestUsagePayment(CommandTestCase):
|
2021-01-21 19:29:59 -05:00
|
|
|
async def _test_single_server_payment(self):
|
2020-02-18 13:50:41 -03:00
|
|
|
wallet_pay_service = self.daemon.component_manager.get_component('wallet_server_payments')
|
|
|
|
wallet_pay_service.payment_period = 1
|
2020-02-21 14:15:17 -03:00
|
|
|
# only starts with a positive max key fee
|
|
|
|
wallet_pay_service.max_fee = "0.0"
|
|
|
|
await wallet_pay_service.start(ledger=self.ledger, wallet=self.wallet)
|
|
|
|
self.assertFalse(wallet_pay_service.running)
|
|
|
|
wallet_pay_service.max_fee = "1.0"
|
|
|
|
await wallet_pay_service.start(ledger=self.ledger, wallet=self.wallet)
|
|
|
|
self.assertTrue(wallet_pay_service.running)
|
2020-02-18 13:50:41 -03:00
|
|
|
await wallet_pay_service.stop()
|
|
|
|
await wallet_pay_service.start(ledger=self.ledger, wallet=self.wallet)
|
2020-02-11 22:05:49 -03:00
|
|
|
|
2020-02-21 17:25:12 -03:00
|
|
|
address = await self.blockchain.get_raw_change_address()
|
2020-01-06 05:07:37 -03:00
|
|
|
_, history = await self.ledger.get_local_status_and_history(address)
|
|
|
|
self.assertEqual(history, [])
|
2020-01-06 01:29:48 -03:00
|
|
|
|
|
|
|
node = SPVNode(self.conductor.spv_module, node_number=2)
|
2020-01-06 05:07:37 -03:00
|
|
|
await node.start(self.blockchain, extraconf={"PAYMENT_ADDRESS": address, "DAILY_FEE": "1.1"})
|
2020-02-21 12:18:44 -05:00
|
|
|
self.addCleanup(node.stop)
|
2020-02-17 13:35:46 -03:00
|
|
|
self.daemon.jsonrpc_settings_set('lbryum_servers', [f"{node.hostname}:{node.port}"])
|
2021-01-21 17:52:57 -05:00
|
|
|
await self.daemon.jsonrpc_wallet_reconnect()
|
2021-01-16 16:27:42 -05:00
|
|
|
LBRYElectrumX.set_server_features(node.server.env)
|
2020-02-21 00:04:37 -03:00
|
|
|
features = await self.ledger.network.get_server_features()
|
|
|
|
self.assertEqual(features["payment_address"], address)
|
|
|
|
self.assertEqual(features["daily_fee"], "1.1")
|
2020-02-21 10:05:46 -05:00
|
|
|
with self.assertRaises(ServerPaymentFeeAboveMaxAllowedError):
|
2021-01-21 17:52:57 -05:00
|
|
|
await asyncio.wait_for(wallet_pay_service.on_payment.first, timeout=30)
|
2021-01-16 16:27:42 -05:00
|
|
|
node.server.env.daily_fee = "1.0"
|
|
|
|
node.server.env.payment_address = address
|
|
|
|
LBRYElectrumX.set_server_features(node.server.env)
|
|
|
|
# self.daemon.jsonrpc_settings_set('lbryum_servers', [f"{node.hostname}:{node.port}"])
|
2020-01-06 05:07:37 -03:00
|
|
|
await self.daemon.jsonrpc_wallet_reconnect()
|
2020-01-06 01:29:48 -03:00
|
|
|
features = await self.ledger.network.get_server_features()
|
2020-01-06 05:07:37 -03:00
|
|
|
self.assertEqual(features["payment_address"], address)
|
2020-02-17 13:35:46 -03:00
|
|
|
self.assertEqual(features["daily_fee"], "1.0")
|
2021-01-16 16:27:42 -05:00
|
|
|
tx = await asyncio.wait_for(wallet_pay_service.on_payment.first, timeout=30)
|
2020-02-21 17:25:12 -03:00
|
|
|
self.assertIsNotNone(await self.blockchain.get_raw_transaction(tx.id)) # verify its broadcasted
|
2020-02-21 16:41:23 -03:00
|
|
|
self.assertEqual(tx.outputs[0].amount, 100000000)
|
|
|
|
self.assertEqual(tx.outputs[0].get_address(self.ledger), address)
|
2021-05-11 21:38:05 -03:00
|
|
|
|
|
|
|
|
|
|
|
class TestESSync(CommandTestCase):
|
|
|
|
async def test_es_sync_utility(self):
|
|
|
|
for i in range(10):
|
|
|
|
await self.stream_create(f"stream{i}", bid='0.001')
|
|
|
|
await self.generate(1)
|
|
|
|
self.assertEqual(10, len(await self.claim_search(order_by=['height'])))
|
|
|
|
db = self.conductor.spv_node.server.db
|
|
|
|
await db.search_index.delete_index()
|
|
|
|
db.search_index.clear_caches()
|
|
|
|
self.assertEqual(0, len(await self.claim_search(order_by=['height'])))
|
|
|
|
await db.search_index.stop()
|
|
|
|
self.assertTrue(await make_es_index(db.search_index))
|
2021-05-12 00:21:03 -03:00
|
|
|
|
|
|
|
async def resync():
|
|
|
|
await db.search_index.start()
|
|
|
|
db.search_index.clear_caches()
|
2021-06-17 21:22:23 -04:00
|
|
|
await run_sync(index_name=db.search_index.index, db=db)
|
2021-05-12 00:21:03 -03:00
|
|
|
self.assertEqual(10, len(await self.claim_search(order_by=['height'])))
|
2021-06-17 21:22:23 -04:00
|
|
|
|
|
|
|
self.assertEqual(0, len(await self.claim_search(order_by=['height'])))
|
|
|
|
|
2021-05-12 00:21:03 -03:00
|
|
|
await resync()
|
|
|
|
|
|
|
|
# this time we will test a migration from unversioned to v1
|
|
|
|
await db.search_index.sync_client.indices.delete_template(db.search_index.index)
|
|
|
|
await db.search_index.stop()
|
|
|
|
self.assertTrue(await make_es_index(db.search_index))
|
2021-05-11 21:38:05 -03:00
|
|
|
await db.search_index.start()
|
2021-05-12 00:21:03 -03:00
|
|
|
await resync()
|
2021-05-10 15:50:16 -04:00
|
|
|
|
|
|
|
|
|
|
|
class TestHubDiscovery(CommandTestCase):
|
|
|
|
|
|
|
|
async def test_hub_discovery(self):
|
2021-06-14 13:06:31 -04:00
|
|
|
us_final_node = SPVNode(self.conductor.spv_module, node_number=2)
|
|
|
|
await us_final_node.start(self.blockchain, extraconf={"COUNTRY": "US"})
|
|
|
|
self.addCleanup(us_final_node.stop)
|
|
|
|
final_node_host = f"{us_final_node.hostname}:{us_final_node.port}"
|
|
|
|
|
|
|
|
kp_final_node = SPVNode(self.conductor.spv_module, node_number=3)
|
|
|
|
await kp_final_node.start(self.blockchain, extraconf={"COUNTRY": "KP"})
|
|
|
|
self.addCleanup(kp_final_node.stop)
|
|
|
|
kp_final_node_host = f"{kp_final_node.hostname}:{kp_final_node.port}"
|
|
|
|
|
|
|
|
relay_node = SPVNode(self.conductor.spv_module, node_number=4)
|
|
|
|
await relay_node.start(self.blockchain, extraconf={
|
|
|
|
"COUNTRY": "FR",
|
|
|
|
"PEER_HUBS": ",".join([kp_final_node_host, final_node_host])
|
|
|
|
})
|
2021-05-10 15:50:16 -04:00
|
|
|
relay_node_host = f"{relay_node.hostname}:{relay_node.port}"
|
|
|
|
self.addCleanup(relay_node.stop)
|
|
|
|
|
|
|
|
self.assertEqual(list(self.daemon.conf.known_hubs), [])
|
|
|
|
self.assertEqual(
|
|
|
|
self.daemon.ledger.network.client.server_address_and_port,
|
|
|
|
('127.0.0.1', 50002)
|
|
|
|
)
|
|
|
|
|
2021-06-14 13:06:31 -04:00
|
|
|
# connect to relay hub which will tell us about the final hubs
|
2021-05-19 10:56:22 -04:00
|
|
|
self.daemon.jsonrpc_settings_set('lbryum_servers', [relay_node_host])
|
2021-05-10 15:50:16 -04:00
|
|
|
await self.daemon.jsonrpc_wallet_reconnect()
|
2021-06-14 13:06:31 -04:00
|
|
|
self.assertEqual(
|
|
|
|
self.daemon.conf.known_hubs.filter(), {
|
|
|
|
(relay_node.hostname, relay_node.port): {"country": "FR"},
|
|
|
|
(us_final_node.hostname, us_final_node.port): {}, # discovered from relay but not contacted yet
|
|
|
|
(kp_final_node.hostname, kp_final_node.port): {}, # discovered from relay but not contacted yet
|
|
|
|
}
|
|
|
|
)
|
2021-05-19 10:56:22 -04:00
|
|
|
self.assertEqual(
|
|
|
|
self.daemon.ledger.network.client.server_address_and_port, ('127.0.0.1', relay_node.port)
|
|
|
|
)
|
2021-05-10 15:50:16 -04:00
|
|
|
|
2021-06-14 13:06:31 -04:00
|
|
|
# use known_hubs to connect to final US hub
|
|
|
|
self.daemon.jsonrpc_settings_clear('lbryum_servers')
|
|
|
|
self.daemon.conf.jurisdiction = "US"
|
2021-05-19 10:56:22 -04:00
|
|
|
await self.daemon.jsonrpc_wallet_reconnect()
|
2021-05-10 15:50:16 -04:00
|
|
|
self.assertEqual(
|
2021-06-14 13:06:31 -04:00
|
|
|
self.daemon.conf.known_hubs.filter(), {
|
|
|
|
(relay_node.hostname, relay_node.port): {"country": "FR"},
|
|
|
|
(us_final_node.hostname, us_final_node.port): {"country": "US"},
|
|
|
|
(kp_final_node.hostname, kp_final_node.port): {"country": "KP"},
|
|
|
|
}
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
self.daemon.ledger.network.client.server_address_and_port, ('127.0.0.1', us_final_node.port)
|
2021-05-10 15:50:16 -04:00
|
|
|
)
|
2021-05-21 09:50:47 -04:00
|
|
|
|
2021-06-14 13:06:31 -04:00
|
|
|
# connection to KP jurisdiction
|
|
|
|
self.daemon.conf.jurisdiction = "KP"
|
|
|
|
await self.daemon.jsonrpc_wallet_reconnect()
|
|
|
|
self.assertEqual(
|
|
|
|
self.daemon.ledger.network.client.server_address_and_port, ('127.0.0.1', kp_final_node.port)
|
|
|
|
)
|
|
|
|
|
|
|
|
kp_final_node.server.session_mgr._notify_peer('127.0.0.1:9988')
|
2021-05-21 09:50:47 -04:00
|
|
|
await self.daemon.ledger.network.on_hub.first
|
2021-06-14 13:06:31 -04:00
|
|
|
await asyncio.sleep(0.5) # wait for above event to be processed by other listeners
|
|
|
|
self.assertEqual(
|
|
|
|
self.daemon.conf.known_hubs.filter(), {
|
|
|
|
(relay_node.hostname, relay_node.port): {"country": "FR"},
|
|
|
|
(us_final_node.hostname, us_final_node.port): {"country": "US"},
|
|
|
|
(kp_final_node.hostname, kp_final_node.port): {"country": "KP"},
|
|
|
|
('127.0.0.1', 9988): {}
|
|
|
|
}
|
|
|
|
)
|
2021-06-25 11:33:17 -03:00
|
|
|
|
|
|
|
|
2021-07-16 15:43:17 -04:00
|
|
|
class TestStressFlush(CommandTestCase):
|
2021-08-09 21:04:42 -04:00
|
|
|
# async def test_flush_over_66_thousand(self):
|
|
|
|
# history = self.conductor.spv_node.server.db.history
|
|
|
|
# history.flush_count = 66_000
|
|
|
|
# history.flush()
|
|
|
|
# self.assertEqual(history.flush_count, 66_001)
|
|
|
|
# await self.generate(1)
|
|
|
|
# self.assertEqual(history.flush_count, 66_002)
|
2021-08-05 15:58:41 -03:00
|
|
|
|
|
|
|
async def test_thousands_claim_ids_on_search(self):
|
|
|
|
await self.stream_create()
|
|
|
|
with self.assertRaises(RPCError) as err:
|
|
|
|
await self.claim_search(not_channel_ids=[("%040x" % i) for i in range(8196)])
|
2021-09-15 13:17:26 -04:00
|
|
|
# in the go hub this doesnt have a `.` at the end, in python it does
|
|
|
|
self.assertTrue(err.exception.message.startswith('not_channel_ids cant have more than 2048 items'))
|