forked from LBRYCommunity/lbry-sdk
Merge branch 'master' into improve-install-md
This commit is contained in:
commit
3c89ecafdd
9 changed files with 118 additions and 6 deletions
|
@ -13,6 +13,7 @@ RUN apt-get update && \
|
||||||
wget \
|
wget \
|
||||||
tar unzip \
|
tar unzip \
|
||||||
build-essential \
|
build-essential \
|
||||||
|
automake libtool \
|
||||||
pkg-config \
|
pkg-config \
|
||||||
libleveldb-dev \
|
libleveldb-dev \
|
||||||
python3.7 \
|
python3.7 \
|
||||||
|
|
|
@ -11,6 +11,7 @@ ENV DOCKER_TAG=$DOCKER_TAG DOCKER_COMMIT=$DOCKER_COMMIT
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get -y --no-install-recommends install \
|
apt-get -y --no-install-recommends install \
|
||||||
wget \
|
wget \
|
||||||
|
automake libtool \
|
||||||
tar unzip \
|
tar unzip \
|
||||||
build-essential \
|
build-essential \
|
||||||
pkg-config \
|
pkg-config \
|
||||||
|
|
|
@ -481,6 +481,10 @@ class UPnPComponent(Component):
|
||||||
log.info("external ip changed from %s to %s", self.external_ip, external_ip)
|
log.info("external ip changed from %s to %s", self.external_ip, external_ip)
|
||||||
if external_ip:
|
if external_ip:
|
||||||
self.external_ip = external_ip
|
self.external_ip = external_ip
|
||||||
|
dht_component = self.component_manager.get_component(DHT_COMPONENT)
|
||||||
|
if dht_component:
|
||||||
|
dht_node = dht_component.component
|
||||||
|
dht_node.protocol.external_ip = external_ip
|
||||||
# assert self.external_ip is not None # TODO: handle going/starting offline
|
# assert self.external_ip is not None # TODO: handle going/starting offline
|
||||||
|
|
||||||
if not self.upnp_redirects and self.upnp: # setup missing redirects
|
if not self.upnp_redirects and self.upnp: # setup missing redirects
|
||||||
|
|
|
@ -186,7 +186,7 @@ class UPbitBTCFeed(MarketFeed):
|
||||||
params = {"markets": "BTC-LBC"}
|
params = {"markets": "BTC-LBC"}
|
||||||
|
|
||||||
def get_rate_from_response(self, json_response):
|
def get_rate_from_response(self, json_response):
|
||||||
if len(json_response) != 1 or 'trade_price' not in json_response[0]:
|
if "error" in json_response or len(json_response) != 1 or 'trade_price' not in json_response[0]:
|
||||||
raise InvalidExchangeRateResponseError(self.name, 'result not found')
|
raise InvalidExchangeRateResponseError(self.name, 'result not found')
|
||||||
return 1.0 / float(json_response[0]['trade_price'])
|
return 1.0 / float(json_response[0]['trade_price'])
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,7 @@ class AddressManager:
|
||||||
return [r['address'] for r in records]
|
return [r['address'] for r in records]
|
||||||
|
|
||||||
async def get_or_create_usable_address(self) -> str:
|
async def get_or_create_usable_address(self) -> str:
|
||||||
|
async with self.address_generator_lock:
|
||||||
addresses = await self.get_addresses(only_usable=True, limit=10)
|
addresses = await self.get_addresses(only_usable=True, limit=10)
|
||||||
if addresses:
|
if addresses:
|
||||||
return random.choice(addresses)
|
return random.choice(addresses)
|
||||||
|
|
|
@ -1,3 +1,19 @@
|
||||||
|
"""A simple script that attempts to directly download a single blob.
|
||||||
|
|
||||||
|
To Do:
|
||||||
|
------
|
||||||
|
Currently `lbrynet blob get <hash>` does not work to download single blobs
|
||||||
|
which are not already present in the system. The function locks up and
|
||||||
|
never returns.
|
||||||
|
It only works for blobs that are in the `blobfiles` directory already.
|
||||||
|
|
||||||
|
This bug is reported in lbryio/lbry-sdk, issue #2070.
|
||||||
|
|
||||||
|
Maybe this script can be investigated, and certain parts can be added to
|
||||||
|
`lbry.extras.daemon.daemon.jsonrpc_blob_get`
|
||||||
|
in order to solve the previous issue, and finally download single blobs
|
||||||
|
from the network (peers or reflector servers).
|
||||||
|
"""
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import asyncio
|
import asyncio
|
||||||
|
@ -47,7 +63,11 @@ async def main(blob_hash: str, url: str):
|
||||||
print(f"deleted {blob_hash}")
|
print(f"deleted {blob_hash}")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__": # usage: python download_blob_from_peer.py <blob_hash> [host url:port]
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("usage: download_blob_from_peer.py <blob_hash> [host_url:port]")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
url = 'reflector.lbry.com:5567'
|
url = 'reflector.lbry.com:5567'
|
||||||
if len(sys.argv) > 2:
|
if len(sys.argv) > 2:
|
||||||
url = sys.argv[2]
|
url = sys.argv[2]
|
||||||
|
|
71
scripts/troubleshoot_p2p_and_dht_webservice.py
Normal file
71
scripts/troubleshoot_p2p_and_dht_webservice.py
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
import asyncio
|
||||||
|
from aiohttp import web
|
||||||
|
|
||||||
|
from lbry.blob_exchange.serialization import BlobRequest, BlobResponse
|
||||||
|
from lbry.dht.constants import generate_id
|
||||||
|
from lbry.dht.node import Node
|
||||||
|
from lbry.dht.peer import make_kademlia_peer, PeerManager
|
||||||
|
from lbry.extras.daemon.storage import SQLiteStorage
|
||||||
|
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
NODE = Node(
|
||||||
|
loop, PeerManager(loop), generate_id(), 60600, 60600, 3333, None,
|
||||||
|
storage=SQLiteStorage(None, ":memory:", loop, loop.time)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def check_p2p(ip, port):
|
||||||
|
writer = None
|
||||||
|
try:
|
||||||
|
reader, writer = await asyncio.open_connection(ip, port)
|
||||||
|
writer.write(BlobRequest.make_request_for_blob_hash('0'*96).serialize())
|
||||||
|
return BlobResponse.deserialize(await reader.readuntil(b'}')).get_address_response().lbrycrd_address
|
||||||
|
except OSError:
|
||||||
|
return None
|
||||||
|
finally:
|
||||||
|
if writer:
|
||||||
|
writer.close()
|
||||||
|
await writer.wait_closed()
|
||||||
|
|
||||||
|
|
||||||
|
async def check_dht(ip, port):
|
||||||
|
peer = make_kademlia_peer(None, ip, udp_port=int(port))
|
||||||
|
return await NODE.protocol.get_rpc_peer(peer).ping()
|
||||||
|
|
||||||
|
|
||||||
|
async def endpoint_p2p(request):
|
||||||
|
p2p_port = request.match_info.get('p2p_port', "3333")
|
||||||
|
try:
|
||||||
|
address = await asyncio.wait_for(check_p2p(request.remote, p2p_port), 3)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
address = None
|
||||||
|
return {"status": address is not None, "port": p2p_port, "payment_address": address}
|
||||||
|
|
||||||
|
|
||||||
|
async def endpoint_dht(request):
|
||||||
|
dht_port = request.match_info.get('dht_port', "3333")
|
||||||
|
try:
|
||||||
|
response = await check_dht(request.remote, dht_port)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
response = None
|
||||||
|
return {"status": response == b'pong', "port": dht_port}
|
||||||
|
|
||||||
|
|
||||||
|
async def endpoint_default(request):
|
||||||
|
return {"dht_status": await endpoint_dht(request), "p2p_status": await endpoint_p2p(request)}
|
||||||
|
|
||||||
|
|
||||||
|
def as_json_response_wrapper(endpoint):
|
||||||
|
async def json_endpoint(*args, **kwargs):
|
||||||
|
return web.json_response(await endpoint(*args, **kwargs))
|
||||||
|
return json_endpoint
|
||||||
|
|
||||||
|
|
||||||
|
app = web.Application()
|
||||||
|
app.add_routes([web.get('/', as_json_response_wrapper(endpoint_default)),
|
||||||
|
web.get('/dht/{dht_port}', as_json_response_wrapper(endpoint_dht)),
|
||||||
|
web.get('/p2p/{p2p_port}', as_json_response_wrapper(endpoint_p2p))])
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
loop.create_task(NODE.start_listening("0.0.0.0"))
|
||||||
|
web.run_app(app, port=60666)
|
|
@ -1,4 +1,5 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
import typing
|
import typing
|
||||||
from lbry.testcase import AsyncioTestCase
|
from lbry.testcase import AsyncioTestCase
|
||||||
|
@ -92,11 +93,11 @@ class TestNodePingQueueDiscover(AsyncioTestCase):
|
||||||
|
|
||||||
|
|
||||||
class TestTemporarilyLosingConnection(AsyncioTestCase):
|
class TestTemporarilyLosingConnection(AsyncioTestCase):
|
||||||
@unittest.SkipTest
|
TIMEOUT = None # not supported as it advances time
|
||||||
async def test_losing_connection(self):
|
async def test_losing_connection(self):
|
||||||
async def wait_for(check_ok, insist, timeout=20):
|
async def wait_for(check_ok, insist, timeout=20):
|
||||||
start = loop.time()
|
start = time.time()
|
||||||
while loop.time() - start < timeout:
|
while time.time() - start < timeout:
|
||||||
if check_ok():
|
if check_ok():
|
||||||
break
|
break
|
||||||
await asyncio.sleep(0)
|
await asyncio.sleep(0)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import asyncio
|
||||||
from binascii import hexlify
|
from binascii import hexlify
|
||||||
from lbry.testcase import AsyncioTestCase
|
from lbry.testcase import AsyncioTestCase
|
||||||
from lbry.wallet import Wallet, Ledger, Database, Headers, Account, SingleKey, HierarchicalDeterministic
|
from lbry.wallet import Wallet, Ledger, Database, Headers, Account, SingleKey, HierarchicalDeterministic
|
||||||
|
@ -37,6 +38,18 @@ class TestAccount(AsyncioTestCase):
|
||||||
addresses = await account.change.get_addresses()
|
addresses = await account.change.get_addresses()
|
||||||
self.assertEqual(len(addresses), 6)
|
self.assertEqual(len(addresses), 6)
|
||||||
|
|
||||||
|
async def test_unused_address_on_account_creation_does_not_cause_a_race(self):
|
||||||
|
account = Account.generate(self.ledger, Wallet(), 'lbryum')
|
||||||
|
await account.ledger.db.db.executescript("update pubkey_address set used_times=10")
|
||||||
|
await account.receiving.address_generator_lock.acquire()
|
||||||
|
delayed1 = asyncio.ensure_future(account.receiving.ensure_address_gap())
|
||||||
|
delayed = asyncio.ensure_future(account.receiving.get_or_create_usable_address())
|
||||||
|
await asyncio.sleep(0)
|
||||||
|
# wallet being created and queried at the same time
|
||||||
|
account.receiving.address_generator_lock.release()
|
||||||
|
await delayed1
|
||||||
|
await delayed
|
||||||
|
|
||||||
async def test_generate_keys_over_batch_threshold_saves_it_properly(self):
|
async def test_generate_keys_over_batch_threshold_saves_it_properly(self):
|
||||||
account = Account.generate(self.ledger, Wallet(), 'lbryum')
|
account = Account.generate(self.ledger, Wallet(), 'lbryum')
|
||||||
async with account.receiving.address_generator_lock:
|
async with account.receiving.address_generator_lock:
|
||||||
|
|
Loading…
Reference in a new issue