forked from LBRYCommunity/lbry-sdk
Merge pull request #1792 from lbryio/delete-unused-scripts
delete unused scripts
This commit is contained in:
commit
68d7a7014c
9 changed files with 0 additions and 1027 deletions
|
@ -1,57 +0,0 @@
|
||||||
"""Decrypt a single blob"""
|
|
||||||
import argparse
|
|
||||||
import binascii
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from twisted.internet import defer
|
|
||||||
from twisted.internet import reactor
|
|
||||||
|
|
||||||
from lbrynet import conf
|
|
||||||
from lbrynet.cryptstream import CryptBlob
|
|
||||||
from lbrynet.blob import BlobFile
|
|
||||||
from lbrynet.core import log_support
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger('decrypt_blob')
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
conf.initialize_settings()
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument('blob_file')
|
|
||||||
parser.add_argument('hex_key')
|
|
||||||
parser.add_argument('hex_iv')
|
|
||||||
parser.add_argument('output')
|
|
||||||
args = parser.parse_args()
|
|
||||||
log_support.configure_console()
|
|
||||||
|
|
||||||
d = run(args)
|
|
||||||
reactor.run()
|
|
||||||
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def run(args):
|
|
||||||
try:
|
|
||||||
yield decrypt_blob(args.blob_file, args.hex_key, args.hex_iv, args.output)
|
|
||||||
except Exception:
|
|
||||||
log.exception('Failed to decrypt blob')
|
|
||||||
finally:
|
|
||||||
reactor.callLater(0, reactor.stop)
|
|
||||||
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def decrypt_blob(blob_file, key, iv, output):
|
|
||||||
filename = os.path.abspath(blob_file)
|
|
||||||
length = os.path.getsize(filename)
|
|
||||||
directory, blob_hash = os.path.split(filename)
|
|
||||||
blob = BlobFile(directory, blob_hash, length)
|
|
||||||
decryptor = CryptBlob.StreamBlobDecryptor(
|
|
||||||
blob, binascii.unhexlify(key), binascii.unhexlify(iv), length)
|
|
||||||
with open(output, 'w') as f:
|
|
||||||
yield decryptor.decrypt(f.write)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
|
@ -1,85 +0,0 @@
|
||||||
import curses
|
|
||||||
import time
|
|
||||||
import datetime
|
|
||||||
from jsonrpc.proxy import JSONRPCProxy
|
|
||||||
|
|
||||||
stdscr = curses.initscr()
|
|
||||||
|
|
||||||
api = JSONRPCProxy.from_url("http://localhost:5280")
|
|
||||||
|
|
||||||
|
|
||||||
def init_curses():
|
|
||||||
curses.noecho()
|
|
||||||
curses.cbreak()
|
|
||||||
stdscr.nodelay(1)
|
|
||||||
stdscr.keypad(1)
|
|
||||||
|
|
||||||
|
|
||||||
def teardown_curses():
|
|
||||||
curses.nocbreak()
|
|
||||||
stdscr.keypad(0)
|
|
||||||
curses.echo()
|
|
||||||
curses.endwin()
|
|
||||||
|
|
||||||
|
|
||||||
def refresh(node_index):
|
|
||||||
height, width = stdscr.getmaxyx()
|
|
||||||
node_ids = api.get_node_ids()
|
|
||||||
node_id = node_ids[node_index]
|
|
||||||
node_statuses = api.node_status()
|
|
||||||
running = node_statuses[node_id]
|
|
||||||
buckets = api.node_routing_table(node_id=node_id)
|
|
||||||
|
|
||||||
for y in range(height):
|
|
||||||
stdscr.addstr(y, 0, " " * (width - 1))
|
|
||||||
|
|
||||||
stdscr.addstr(0, 0, "node id: %s, running: %s (%i/%i running)" % (node_id, running, sum(node_statuses.values()), len(node_ids)))
|
|
||||||
stdscr.addstr(1, 0, "%i buckets, %i contacts" %
|
|
||||||
(len(buckets), sum([len(buckets[b]['contacts']) for b in buckets])))
|
|
||||||
|
|
||||||
y = 3
|
|
||||||
for i in sorted(buckets.keys()):
|
|
||||||
stdscr.addstr(y, 0, "bucket %s" % i)
|
|
||||||
y += 1
|
|
||||||
for h in sorted(buckets[i]['contacts'], key=lambda x: x['node_id'].decode('hex')):
|
|
||||||
stdscr.addstr(y, 0, '%s (%s:%i) failures: %i, last replied to us: %s, last requested from us: %s' %
|
|
||||||
(h['node_id'], h['address'], h['port'], h['failedRPCs'],
|
|
||||||
datetime.datetime.fromtimestamp(float(h['lastReplied'] or 0)),
|
|
||||||
datetime.datetime.fromtimestamp(float(h['lastRequested'] or 0))))
|
|
||||||
y += 1
|
|
||||||
y += 1
|
|
||||||
|
|
||||||
stdscr.addstr(y + 1, 0, str(time.time()))
|
|
||||||
stdscr.refresh()
|
|
||||||
return len(node_ids)
|
|
||||||
|
|
||||||
|
|
||||||
def do_main():
|
|
||||||
c = None
|
|
||||||
nodes = 1
|
|
||||||
node_index = 0
|
|
||||||
while c not in [ord('q'), ord('Q')]:
|
|
||||||
try:
|
|
||||||
nodes = refresh(node_index)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
c = stdscr.getch()
|
|
||||||
if c == curses.KEY_LEFT:
|
|
||||||
node_index -= 1
|
|
||||||
node_index = max(node_index, 0)
|
|
||||||
elif c == curses.KEY_RIGHT:
|
|
||||||
node_index += 1
|
|
||||||
node_index = min(node_index, nodes - 1)
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
try:
|
|
||||||
init_curses()
|
|
||||||
do_main()
|
|
||||||
finally:
|
|
||||||
teardown_curses()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
|
@ -1,104 +0,0 @@
|
||||||
"""A simple script that attempts to directly download a single blob or stream from a given peer"""
|
|
||||||
import argparse
|
|
||||||
import logging
|
|
||||||
import sys
|
|
||||||
import tempfile
|
|
||||||
import time
|
|
||||||
import shutil
|
|
||||||
from pprint import pprint
|
|
||||||
|
|
||||||
from twisted.internet import asyncioreactor
|
|
||||||
asyncioreactor.install()
|
|
||||||
from twisted.internet import defer, threads, reactor
|
|
||||||
|
|
||||||
from lbrynet import conf, log_support
|
|
||||||
from lbrynet.p2p import Peer
|
|
||||||
from lbrynet.p2p.SinglePeerDownloader import SinglePeerDownloader
|
|
||||||
from lbrynet.p2p.StreamDescriptor import BlobStreamDescriptorReader
|
|
||||||
from lbrynet.p2p.BlobManager import DiskBlobManager
|
|
||||||
from lbrynet.extras.daemon.Components import f2d
|
|
||||||
from lbrynet.extras.daemon.storage import SQLiteStorage
|
|
||||||
from lbrynet.extras.wallet import LbryWalletManager
|
|
||||||
|
|
||||||
log = logging.getLogger()
|
|
||||||
|
|
||||||
|
|
||||||
def main(args=None):
|
|
||||||
conf.initialize_settings()
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument('peer')
|
|
||||||
parser.add_argument('blob_hash')
|
|
||||||
parser.add_argument('--timeout', type=int, default=30)
|
|
||||||
args = parser.parse_args(args)
|
|
||||||
|
|
||||||
log_support.configure_console(level='DEBUG')
|
|
||||||
log_support.configure_twisted()
|
|
||||||
|
|
||||||
if ":" in str(args.peer):
|
|
||||||
host, port = str(args.peer).strip().split(":")
|
|
||||||
else:
|
|
||||||
host = args.peer
|
|
||||||
port = 3333
|
|
||||||
|
|
||||||
d = download_it(Peer.Peer(host, int(port)), args.timeout, args.blob_hash)
|
|
||||||
d.addErrback(log.exception)
|
|
||||||
d.addBoth(lambda _: reactor.callLater(0, reactor.stop))
|
|
||||||
reactor.run()
|
|
||||||
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def download_it(peer, timeout, blob_hash):
|
|
||||||
tmp_dir = yield threads.deferToThread(tempfile.mkdtemp)
|
|
||||||
storage = SQLiteStorage(tmp_dir, reactor)
|
|
||||||
yield storage.setup()
|
|
||||||
tmp_blob_manager = DiskBlobManager(tmp_dir, storage)
|
|
||||||
|
|
||||||
config = {'auto_connect': True}
|
|
||||||
config['wallet_dir'] = tempfile.mkdtemp()
|
|
||||||
config['use_keyring'] = False
|
|
||||||
config['blockchain_name'] = conf.settings['blockchain_name']
|
|
||||||
config['lbryum_servers'] = []
|
|
||||||
wallet = yield f2d(LbryWalletManager.from_lbrynet_config(config, storage))
|
|
||||||
|
|
||||||
downloader = SinglePeerDownloader()
|
|
||||||
downloader.setup(wallet)
|
|
||||||
|
|
||||||
try:
|
|
||||||
blob_downloaded = yield downloader.download_blob_from_peer(peer, timeout, blob_hash,
|
|
||||||
tmp_blob_manager)
|
|
||||||
if blob_downloaded:
|
|
||||||
log.info("SUCCESS!")
|
|
||||||
blob = yield tmp_blob_manager.get_blob(blob_hash)
|
|
||||||
pprint(blob)
|
|
||||||
if not blob.verified:
|
|
||||||
log.error("except that its not verified....")
|
|
||||||
else:
|
|
||||||
reader = BlobStreamDescriptorReader(blob)
|
|
||||||
info = None
|
|
||||||
for x in range(0, 3):
|
|
||||||
try:
|
|
||||||
info = yield reader.get_info()
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
if info:
|
|
||||||
break
|
|
||||||
|
|
||||||
# there's some kind of race condition where it sometimes doesn't write the blob to disk in time
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
if info is not None:
|
|
||||||
pprint(info)
|
|
||||||
for content_blob in info['blobs']:
|
|
||||||
if 'blob_hash' in content_blob:
|
|
||||||
yield download_it(peer, timeout, content_blob['blob_hash'])
|
|
||||||
else:
|
|
||||||
log.error("Download failed")
|
|
||||||
finally:
|
|
||||||
yield tmp_blob_manager.stop()
|
|
||||||
yield threads.deferToThread(shutil.rmtree, tmp_dir)
|
|
||||||
|
|
||||||
defer.returnValue(True)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
|
@ -1,80 +0,0 @@
|
||||||
"""A test script that downloads blobs from a reflector server"""
|
|
||||||
import argparse
|
|
||||||
import itertools
|
|
||||||
import json
|
|
||||||
import random
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument('reflector_ip')
|
|
||||||
parser.add_argument('--ssh-key')
|
|
||||||
parser.add_argument('--size', type=int, default=100)
|
|
||||||
parser.add_argument('--batch', type=int, default=10)
|
|
||||||
parser.add_argument('--timeout', type=int, default=30)
|
|
||||||
parser.add_argument('--hashes', help='file listing hashes in json')
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
if args.hashes:
|
|
||||||
hashes = readHashes(args.hashes)
|
|
||||||
else:
|
|
||||||
hashes = getHashes(args.reflector_ip, args.ssh_key)
|
|
||||||
if len(hashes) > args.size:
|
|
||||||
selected_hashes = random.sample(hashes, args.size)
|
|
||||||
else:
|
|
||||||
print 'Only {} hashes are available'.format(hashes)
|
|
||||||
selected_hashes = hashes
|
|
||||||
|
|
||||||
successes = 0
|
|
||||||
for hashes in grouper(selected_hashes, args.batch):
|
|
||||||
hashes = filter(None, hashes)
|
|
||||||
successes += downloadHashes(args.reflector_ip, hashes, args.timeout)
|
|
||||||
print 'Downloaded {} / {}'.format(successes, len(selected_hashes))
|
|
||||||
|
|
||||||
|
|
||||||
def grouper(iterable, n, fillvalue=None):
|
|
||||||
"Collect data into fixed-length chunks or blocks"
|
|
||||||
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
|
|
||||||
args = [iter(iterable)] * n
|
|
||||||
return itertools.izip_longest(fillvalue=fillvalue, *args)
|
|
||||||
|
|
||||||
|
|
||||||
def readHashes(hash_file):
|
|
||||||
with open(hash_file) as f:
|
|
||||||
return json.load(f)
|
|
||||||
|
|
||||||
|
|
||||||
def getHashes(ip, key=None):
|
|
||||||
key = ['-i', key] if key else []
|
|
||||||
hashes = subprocess.check_output(['ssh'] + key +
|
|
||||||
['lbry@{}'.format(ip), '/opt/venvs/lbrynet/bin/lbrynet-cli', 'get_blob_hashes'])
|
|
||||||
return json.loads(hashes)
|
|
||||||
|
|
||||||
|
|
||||||
def downloadHashes(ip, blob_hashes, timeout=30):
|
|
||||||
processes = [
|
|
||||||
subprocess.Popen(
|
|
||||||
[
|
|
||||||
'python',
|
|
||||||
'download_blob_from_peer.py',
|
|
||||||
'--timeout', str(timeout), '{}:3333'.format(ip), blob_hash,
|
|
||||||
],
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.PIPE,
|
|
||||||
)
|
|
||||||
for blob_hash in blob_hashes
|
|
||||||
]
|
|
||||||
for p, h in zip(processes, blob_hashes):
|
|
||||||
stdout, stderr = p.communicate()
|
|
||||||
print p.returncode, h
|
|
||||||
if p.returncode != 0:
|
|
||||||
print 'Failed to download', h
|
|
||||||
print stdout
|
|
||||||
print stderr
|
|
||||||
return sum(1 for p in processes if p.returncode == 0)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
|
@ -1,63 +0,0 @@
|
||||||
"""Encrypt a single file using the given key and iv"""
|
|
||||||
import argparse
|
|
||||||
import logging
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from twisted.internet import defer
|
|
||||||
from twisted.internet import reactor
|
|
||||||
from twisted.web.client import FileBodyProducer
|
|
||||||
|
|
||||||
from lbrynet import conf
|
|
||||||
from lbrynet.core import log_support
|
|
||||||
from lbrynet.extras.daemon.HashAnnouncer import DHTHashAnnouncer
|
|
||||||
from lbrynet.core.BlobManager import DiskBlobManager
|
|
||||||
from lbrynet.cryptstream.CryptStreamCreator import CryptStreamCreator
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger('decrypt_blob')
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
conf.initialize_settings()
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument('filename')
|
|
||||||
parser.add_argument('hex_key')
|
|
||||||
parser.add_argument('hex_iv')
|
|
||||||
args = parser.parse_args()
|
|
||||||
log_support.configure_console(level='DEBUG')
|
|
||||||
|
|
||||||
run(args)
|
|
||||||
reactor.run()
|
|
||||||
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def run(args):
|
|
||||||
try:
|
|
||||||
yield encrypt_blob(args.filename, args.hex_key, args.hex_iv)
|
|
||||||
except Exception:
|
|
||||||
log.exception('Failed to encrypt blob')
|
|
||||||
finally:
|
|
||||||
reactor.callLater(0, reactor.stop)
|
|
||||||
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def encrypt_blob(filename, key, iv):
|
|
||||||
dummy_announcer = DummyHashAnnouncer()
|
|
||||||
manager = DiskBlobManager(dummy_announcer, '.', '.')
|
|
||||||
yield manager.setup()
|
|
||||||
creator = CryptStreamCreator(manager, filename, key, iv_generator(iv))
|
|
||||||
with open(filename, 'r') as infile:
|
|
||||||
producer = FileBodyProducer(infile, readSize=2**22)
|
|
||||||
yield producer.startProducing(creator)
|
|
||||||
yield creator.stop()
|
|
||||||
|
|
||||||
|
|
||||||
def iv_generator(iv):
|
|
||||||
iv = int(iv, 16)
|
|
||||||
while 1:
|
|
||||||
iv += 1
|
|
||||||
yield ("%016d" % iv)[-16:]
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
|
@ -1,206 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Generate docs: python gen_api_docs.py
|
|
||||||
# See docs: pip install mkdocs; mkdocs serve
|
|
||||||
# Push docs: mkdocs build
|
|
||||||
|
|
||||||
import re
|
|
||||||
import inspect
|
|
||||||
import subprocess
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from lbrynet.daemon.Daemon import Daemon
|
|
||||||
|
|
||||||
import pip
|
|
||||||
installed_packages = [package.project_name for package in pip.get_installed_distributions()]
|
|
||||||
|
|
||||||
for package in ["mkdocs", "mkdocs-material"]:
|
|
||||||
if package not in installed_packages:
|
|
||||||
print "'" + package + "' is not installed"
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
try:
|
|
||||||
from tabulate import tabulate
|
|
||||||
except ImportError:
|
|
||||||
raise ImportError("tabulate is not installed")
|
|
||||||
|
|
||||||
INDENT = " "
|
|
||||||
REQD_CMD_REGEX = r"\(.*?=<(?P<reqd>.*?)>\)"
|
|
||||||
OPT_CMD_REGEX = r"\[.*?=<(?P<opt>.*?)>\]"
|
|
||||||
CMD_REGEX = r"--.*?(?P<cmd>.*?)[=,\s,<]"
|
|
||||||
DOCS_BUILD_DIR = "docs_build" # must match mkdocs.yml
|
|
||||||
|
|
||||||
|
|
||||||
def _cli_tabulate_options(_options_docstr, method):
|
|
||||||
_option_list = []
|
|
||||||
for line in _options_docstr.splitlines():
|
|
||||||
if (line.strip().startswith("--")):
|
|
||||||
# separates command name and description
|
|
||||||
parts = line.split(":", 1)
|
|
||||||
# separates command type(in brackets) and description
|
|
||||||
new_parts = parts[1].lstrip().split(" ", 1)
|
|
||||||
else:
|
|
||||||
parts = [line]
|
|
||||||
|
|
||||||
# len will be 2 when there's cmd name and description
|
|
||||||
if len(parts) == 2:
|
|
||||||
_option_list.append([parts[0], ":", new_parts[0], new_parts[1]])
|
|
||||||
# len will be 1 when there's continuation of multiline description in the next line
|
|
||||||
# check `blob_announce`'s `stream_hash` command
|
|
||||||
elif len(parts) == 1:
|
|
||||||
_option_list.append([None, None, None, parts[0]])
|
|
||||||
else:
|
|
||||||
print "Error: Ill formatted doc string for {}".format(method)
|
|
||||||
print "Error causing line: {}".format(line)
|
|
||||||
|
|
||||||
# tabulate to make the options look pretty
|
|
||||||
_options_docstr_no_indent = tabulate(_option_list, missingval="", tablefmt="plain")
|
|
||||||
|
|
||||||
# Indent the options properly
|
|
||||||
_options_docstr = ""
|
|
||||||
for line in _options_docstr_no_indent.splitlines():
|
|
||||||
_options_docstr += INDENT + line + '\n'
|
|
||||||
|
|
||||||
return _options_docstr
|
|
||||||
|
|
||||||
|
|
||||||
def _api_tabulate_options(_options_docstr, method, reqd_matches, opt_matches):
|
|
||||||
_option_list = []
|
|
||||||
for line in _options_docstr.splitlines():
|
|
||||||
if (line.strip().startswith("--")):
|
|
||||||
# separates command name and description
|
|
||||||
parts = line.split(":", 1)
|
|
||||||
|
|
||||||
# checks whether the command is optional or required
|
|
||||||
# and remove the cli type formatting and convert to
|
|
||||||
# api style formatitng
|
|
||||||
match = re.findall(CMD_REGEX, parts[0])
|
|
||||||
|
|
||||||
if match[0] not in reqd_matches:
|
|
||||||
parts[0] = "'" + match[0] + "'"
|
|
||||||
else:
|
|
||||||
parts[0] = "'" + match[0] + "' (required)"
|
|
||||||
|
|
||||||
# separates command type(in brackets) and description
|
|
||||||
new_parts = parts[1].lstrip().split(" ", 1)
|
|
||||||
else:
|
|
||||||
parts = [line]
|
|
||||||
|
|
||||||
# len will be 2 when there's cmd name and description
|
|
||||||
if len(parts) == 2:
|
|
||||||
_option_list.append([parts[0], ":", new_parts[0], new_parts[1]])
|
|
||||||
# len will be 1 when there's continuation of multiline description in the next line
|
|
||||||
# check `blob_announce`'s `stream_hash` command
|
|
||||||
elif len(parts) == 1:
|
|
||||||
_option_list.append([None, None, None, parts[0]])
|
|
||||||
else:
|
|
||||||
print "Error: Ill formatted doc string for {}".format(method)
|
|
||||||
print "Error causing line: {}".format(line)
|
|
||||||
|
|
||||||
# tabulate to make the options look pretty
|
|
||||||
_options_docstr_no_indent = tabulate(_option_list, missingval="", tablefmt="plain")
|
|
||||||
|
|
||||||
# tabulate to make the options look pretty
|
|
||||||
_options_docstr = ""
|
|
||||||
for line in _options_docstr_no_indent.splitlines():
|
|
||||||
_options_docstr += INDENT + line + '\n'
|
|
||||||
|
|
||||||
return _options_docstr
|
|
||||||
|
|
||||||
|
|
||||||
def _cli_doc(obj):
|
|
||||||
docstr = (inspect.getdoc(obj) or '').strip()
|
|
||||||
|
|
||||||
try:
|
|
||||||
_usage_docstr, _docstr_after_options = docstr.split("Options:", 1)
|
|
||||||
_options_docstr, _returns_docstr = _docstr_after_options.split("Returns:", 1)
|
|
||||||
except(ValueError):
|
|
||||||
print "Error: Ill formatted doc string for {}".format(obj)
|
|
||||||
print "Please ensure that the docstring has all the three headings i.e. \"Usage:\""
|
|
||||||
print "\"Options:\" and \"Returns:\" exactly as specified, including the colon"
|
|
||||||
return "Error!"
|
|
||||||
|
|
||||||
try:
|
|
||||||
_options_docstr = _cli_tabulate_options(_options_docstr.strip(), obj)
|
|
||||||
except Exception as e:
|
|
||||||
print "Please make sure that the individual options are properly formatted"
|
|
||||||
print "It should be strictly of the format:"
|
|
||||||
print "--command_name=<command_name> : (type) desc"
|
|
||||||
print e.message
|
|
||||||
|
|
||||||
docstr = _usage_docstr + \
|
|
||||||
"\nOptions:\n" + \
|
|
||||||
_options_docstr + \
|
|
||||||
"\nReturns:" + \
|
|
||||||
_returns_docstr
|
|
||||||
|
|
||||||
return docstr
|
|
||||||
|
|
||||||
|
|
||||||
def _api_doc(obj):
|
|
||||||
docstr = (inspect.getdoc(obj) or '').strip()
|
|
||||||
|
|
||||||
try:
|
|
||||||
_desc, _docstr_after_desc = docstr.split("Usage:", 1)
|
|
||||||
_usage_docstr, _docstr_after_options = _docstr_after_desc.split("Options:", 1)
|
|
||||||
_options_docstr, _returns_docstr = _docstr_after_options.split("Returns:", 1)
|
|
||||||
except(ValueError):
|
|
||||||
print "Error: Ill formatted doc string for {}".format(obj)
|
|
||||||
print "Please ensure that the docstring has all the three headings i.e. \"Usage:\""
|
|
||||||
print "\"Options:\" and \"Returns:\" exactly as specified, including the colon"
|
|
||||||
return "Error!"
|
|
||||||
|
|
||||||
opt_matches = re.findall(OPT_CMD_REGEX, _usage_docstr)
|
|
||||||
reqd_matches = re.findall(REQD_CMD_REGEX, _usage_docstr)
|
|
||||||
|
|
||||||
try:
|
|
||||||
_options_docstr = _api_tabulate_options(_options_docstr.strip(), obj, reqd_matches, opt_matches)
|
|
||||||
except Exception as e:
|
|
||||||
print "Please make sure that the individual options are properly formatted"
|
|
||||||
print "It should be strictly of the format:"
|
|
||||||
print "--command_name=<command_name> : (type) desc"
|
|
||||||
print e.message
|
|
||||||
|
|
||||||
docstr = _desc + \
|
|
||||||
"Args:\n" + \
|
|
||||||
_options_docstr + \
|
|
||||||
"\nReturns:" + \
|
|
||||||
_returns_docstr
|
|
||||||
|
|
||||||
return docstr
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
||||||
build_dir = os.path.realpath(os.path.join(root_dir, DOCS_BUILD_DIR))
|
|
||||||
if not os.path.exists(build_dir):
|
|
||||||
os.makedirs(build_dir)
|
|
||||||
api_doc_path = os.path.join(build_dir, 'index.md')
|
|
||||||
cli_doc_path = os.path.join(build_dir, 'cli.md')
|
|
||||||
|
|
||||||
_api_docs = ''
|
|
||||||
_cli_docs = ''
|
|
||||||
for method_name in sorted(Daemon.callable_methods.keys()):
|
|
||||||
method = Daemon.callable_methods[method_name]
|
|
||||||
_api_docs += '## ' + method_name + "\n\n```text\n" + _api_doc(method) + "\n```\n\n"
|
|
||||||
_cli_docs += '## ' + method_name + "\n\n```text\n" + _cli_doc(method) + "\n```\n\n"
|
|
||||||
|
|
||||||
_api_docs = "# LBRY JSON-RPC API Documentation\n\n" + _api_docs
|
|
||||||
with open(api_doc_path, 'w+') as f:
|
|
||||||
f.write(_api_docs)
|
|
||||||
|
|
||||||
_cli_docs = "# LBRY JSON-RPC API Documentation\n\n" + _cli_docs
|
|
||||||
with open(cli_doc_path, 'w+') as f:
|
|
||||||
f.write(_cli_docs)
|
|
||||||
|
|
||||||
try:
|
|
||||||
subprocess.check_output("exec mkdocs build", cwd=root_dir, shell=True)
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
print e.output
|
|
||||||
return 1
|
|
||||||
|
|
||||||
return 0
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
|
@ -1,110 +0,0 @@
|
||||||
import argparse
|
|
||||||
import hashlib
|
|
||||||
import json
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import base58
|
|
||||||
|
|
||||||
from lbryum import SimpleConfig, Network
|
|
||||||
from lbryum.wallet import WalletStorage, Wallet
|
|
||||||
from lbryum.commands import known_commands, Commands
|
|
||||||
from lbryum import lbrycrd
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument('--wallet', help='path to lbryum wallet')
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
ensureCliIsOnPathAndServerIsRunning()
|
|
||||||
|
|
||||||
wallet = getWallet(args.wallet)
|
|
||||||
addresses = wallet.addresses(True)
|
|
||||||
for addr in addresses[:-1]:
|
|
||||||
printBalance(wallet, addr)
|
|
||||||
saveAddr(wallet, addr)
|
|
||||||
# on the last one, rescan. Don't rescan early for sake of efficiency
|
|
||||||
addr = addresses[-1]
|
|
||||||
printBalance(wallet, addr)
|
|
||||||
saveAddr(wallet, addr, "true")
|
|
||||||
|
|
||||||
|
|
||||||
def ensureCliIsOnPathAndServerIsRunning():
|
|
||||||
try:
|
|
||||||
output = subprocess.check_output(['lbrycrd-cli', 'getinfo'])
|
|
||||||
except OSError:
|
|
||||||
print 'Failed to run: lbrycrd-cli needs to be on the PATH'
|
|
||||||
sys.exit(1)
|
|
||||||
except subprocess.CalledProcessError:
|
|
||||||
print 'Failed to run: could not connect to the lbrycrd server.'
|
|
||||||
print 'Make sure it is running and able to be connected to.'
|
|
||||||
print 'One way to do this is to run:'
|
|
||||||
print ' lbrycrdd -server -printtoconsole'
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
def validateAddress(addr):
|
|
||||||
raw_output = subprocess.check_output(
|
|
||||||
['lbrycrd-cli', 'validateaddress', addr])
|
|
||||||
output = json.loads(raw_output)
|
|
||||||
if not output['isvalid']:
|
|
||||||
raise Exception('Address {} is not valid'.format(addr))
|
|
||||||
if not output['ismine']:
|
|
||||||
raise Exception('Address {} is not yours'.format(addr))
|
|
||||||
|
|
||||||
|
|
||||||
def printBalance(wallet, addr):
|
|
||||||
balance = getBalance(wallet, addr)
|
|
||||||
print 'Importing private key for %s with balance %s' % (addr, balance)
|
|
||||||
|
|
||||||
|
|
||||||
def getBalance(wallet, addr):
|
|
||||||
return sum(wallet.get_addr_balance(addr))
|
|
||||||
|
|
||||||
|
|
||||||
def getWallet(path=None):
|
|
||||||
if not path:
|
|
||||||
config = SimpleConfig()
|
|
||||||
path = config.get_wallet_path()
|
|
||||||
storage = WalletStorage(path)
|
|
||||||
if not storage.file_exists:
|
|
||||||
print "Failed to run: No wallet to migrate"
|
|
||||||
sys.exit(1)
|
|
||||||
return Wallet(storage)
|
|
||||||
|
|
||||||
|
|
||||||
def saveAddr(wallet, addr, rescan="false"):
|
|
||||||
keys = wallet.get_private_key(addr, None)
|
|
||||||
assert len(keys) == 1, 'Address {} has {} keys. Expected 1'.format(addr, len(keys))
|
|
||||||
key = keys[0]
|
|
||||||
# copied from lbrycrd.regenerate_key
|
|
||||||
b = lbrycrd.ASecretToSecret(key)
|
|
||||||
pkey = b[0:32]
|
|
||||||
is_compressed = lbrycrd.is_compressed(key)
|
|
||||||
wif = pkeyToWif(pkey, is_compressed)
|
|
||||||
subprocess.check_call(
|
|
||||||
['lbrycrd-cli', 'importprivkey', wif, "", rescan])
|
|
||||||
validateAddress(addr)
|
|
||||||
|
|
||||||
|
|
||||||
def pkeyToWif(pkey, compressed):
|
|
||||||
# Follow https://en.bitcoin.it/wiki/Wallet_import_format
|
|
||||||
# to convert from a private key to the wallet import format
|
|
||||||
prefix = '\x1c'
|
|
||||||
wif = prefix + pkey
|
|
||||||
if compressed:
|
|
||||||
wif += '\x01'
|
|
||||||
intermediate_checksum = hashlib.sha256(wif).digest()
|
|
||||||
checksum = hashlib.sha256(intermediate_checksum).digest()
|
|
||||||
wif = wif + checksum[:4]
|
|
||||||
return base58.b58encode(wif)
|
|
||||||
|
|
||||||
|
|
||||||
def wifToPkey(wif):
|
|
||||||
pkey = base58.b58decode(wif)
|
|
||||||
return pkey[1:-4]
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
|
@ -1,94 +0,0 @@
|
||||||
"""Reseed a file.
|
|
||||||
|
|
||||||
Given a file and a matching sd_blob,
|
|
||||||
re-chunk and encrypt the file, adding
|
|
||||||
the new blobs to the manager.
|
|
||||||
"""
|
|
||||||
import argparse
|
|
||||||
import binascii
|
|
||||||
import logging
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from twisted.internet import defer
|
|
||||||
from twisted.internet import reactor
|
|
||||||
from twisted.protocols import basic
|
|
||||||
|
|
||||||
from lbrynet import conf
|
|
||||||
from lbrynet.core import BlobManager
|
|
||||||
from lbrynet.dht import hashannouncer
|
|
||||||
from lbrynet.core import log_support
|
|
||||||
from lbrynet.cryptstream import CryptStreamCreator
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger('reseed_file')
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
conf.initialize_settings()
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument('input_file')
|
|
||||||
parser.add_argument('sd_blob', help='a json file containing a key and the IVs')
|
|
||||||
args = parser.parse_args()
|
|
||||||
log_support.configure_console()
|
|
||||||
|
|
||||||
run(args)
|
|
||||||
reactor.run()
|
|
||||||
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def run(args):
|
|
||||||
try:
|
|
||||||
yield reseed_file(args.input_file, args.sd_blob)
|
|
||||||
except Exception as e:
|
|
||||||
log.exception('Failed to reseed')
|
|
||||||
finally:
|
|
||||||
reactor.stop()
|
|
||||||
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def reseed_file(input_file, sd_blob):
|
|
||||||
sd_blob = SdBlob.new_instance(sd_blob)
|
|
||||||
db_dir = conf.settings['data_dir']
|
|
||||||
blobfile_dir = os.path.join(db_dir, "blobfiles")
|
|
||||||
announcer = hashannouncer.DummyHashAnnouncer()
|
|
||||||
blob_manager = BlobManager.DiskBlobManager(announcer, blobfile_dir, db_dir)
|
|
||||||
yield blob_manager.setup()
|
|
||||||
creator = CryptStreamCreator.CryptStreamCreator(
|
|
||||||
blob_manager, None, sd_blob.key(), sd_blob.iv_generator())
|
|
||||||
file_sender = basic.FileSender()
|
|
||||||
with open(input_file) as f:
|
|
||||||
yield file_sender.beginFileTransfer(f, creator)
|
|
||||||
yield creator.stop()
|
|
||||||
for blob_info in sd_blob.blob_infos():
|
|
||||||
if 'blob_hash' not in blob_info:
|
|
||||||
# the last blob is always empty and without a hash
|
|
||||||
continue
|
|
||||||
blob = yield blob_manager.get_blob(blob_info['blob_hash'], True)
|
|
||||||
if not blob.verified:
|
|
||||||
print "Blob {} is not verified".format(blob)
|
|
||||||
|
|
||||||
|
|
||||||
class SdBlob(object):
|
|
||||||
def __init__(self, contents):
|
|
||||||
self.contents = contents
|
|
||||||
|
|
||||||
def key(self):
|
|
||||||
return binascii.unhexlify(self.contents['key'])
|
|
||||||
|
|
||||||
def iv_generator(self):
|
|
||||||
for blob_info in self.blob_infos():
|
|
||||||
yield binascii.unhexlify(blob_info['iv'])
|
|
||||||
|
|
||||||
def blob_infos(self):
|
|
||||||
return self.contents['blobs']
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def new_instance(cls, filename):
|
|
||||||
with open(filename) as f:
|
|
||||||
return cls(json.load(f))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
|
@ -1,228 +0,0 @@
|
||||||
import struct
|
|
||||||
import json
|
|
||||||
import logging
|
|
||||||
import argparse
|
|
||||||
import hashlib
|
|
||||||
from copy import deepcopy
|
|
||||||
from urllib import urlopen
|
|
||||||
from twisted.internet.epollreactor import install as install_epoll
|
|
||||||
install_epoll()
|
|
||||||
from twisted.internet import reactor, defer
|
|
||||||
from twisted.web import resource
|
|
||||||
from twisted.web.server import Site
|
|
||||||
from lbrynet import conf
|
|
||||||
from lbrynet.dht import constants
|
|
||||||
from lbrynet.dht.node import Node
|
|
||||||
from lbrynet.dht.error import TransportNotConnected
|
|
||||||
from lbrynet.core.log_support import configure_console, configure_twisted
|
|
||||||
from lbrynet.daemon.auth.server import AuthJSONRPCServer
|
|
||||||
|
|
||||||
# configure_twisted()
|
|
||||||
conf.initialize_settings()
|
|
||||||
configure_console()
|
|
||||||
lbrynet_handler = logging.getLogger("lbrynet").handlers[0]
|
|
||||||
log = logging.getLogger("dht router")
|
|
||||||
log.addHandler(lbrynet_handler)
|
|
||||||
log.setLevel(logging.INFO)
|
|
||||||
|
|
||||||
|
|
||||||
def node_id_supplier(seed="jack.lbry.tech"): # simple deterministic node id generator
|
|
||||||
h = hashlib.sha384()
|
|
||||||
h.update(seed)
|
|
||||||
while True:
|
|
||||||
next_id = h.digest()
|
|
||||||
yield next_id
|
|
||||||
h = hashlib.sha384()
|
|
||||||
h.update(seed)
|
|
||||||
h.update(next_id)
|
|
||||||
|
|
||||||
|
|
||||||
def get_external_ip():
|
|
||||||
response = json.loads(urlopen("https://api.lbry.io/ip").read())
|
|
||||||
if not response['success']:
|
|
||||||
raise ValueError("failed to get external ip")
|
|
||||||
return response['data']['ip']
|
|
||||||
|
|
||||||
|
|
||||||
def format_contact(contact):
|
|
||||||
return {
|
|
||||||
"node_id": contact.id.encode('hex'),
|
|
||||||
"address": contact.address,
|
|
||||||
"nodePort": contact.port,
|
|
||||||
"lastReplied": contact.lastReplied,
|
|
||||||
"lastRequested": contact.lastRequested,
|
|
||||||
"failedRPCs": contact.failedRPCs,
|
|
||||||
"lastFailed": None if not contact.failures else contact.failures[-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def format_datastore(node):
|
|
||||||
datastore = deepcopy(node._dataStore._dict)
|
|
||||||
result = {}
|
|
||||||
for key, values in datastore.items():
|
|
||||||
contacts = []
|
|
||||||
for (contact, value, last_published, originally_published, original_publisher_id) in values:
|
|
||||||
contact_dict = format_contact(contact)
|
|
||||||
contact_dict['peerPort'] = struct.unpack('>H', value[4:6])[0]
|
|
||||||
contact_dict['lastPublished'] = last_published
|
|
||||||
contact_dict['originallyPublished'] = originally_published
|
|
||||||
contact_dict['originalPublisherID'] = original_publisher_id.encode('hex')
|
|
||||||
contacts.append(contact_dict)
|
|
||||||
result[key.encode('hex')] = contacts
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
class MultiSeedRPCServer(AuthJSONRPCServer):
|
|
||||||
def __init__(self, starting_node_port, nodes, rpc_port):
|
|
||||||
AuthJSONRPCServer.__init__(self, False)
|
|
||||||
self.port = None
|
|
||||||
self.rpc_port = rpc_port
|
|
||||||
self.external_ip = get_external_ip()
|
|
||||||
node_id_gen = node_id_supplier()
|
|
||||||
self._nodes = [Node(node_id=next(node_id_gen), udpPort=starting_node_port+i, externalIP=self.external_ip)
|
|
||||||
for i in range(nodes)]
|
|
||||||
self._own_addresses = [(self.external_ip, starting_node_port+i) for i in range(nodes)]
|
|
||||||
reactor.addSystemEventTrigger('after', 'startup', self.start)
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def start(self):
|
|
||||||
self.announced_startup = True
|
|
||||||
root = resource.Resource()
|
|
||||||
root.putChild('', self)
|
|
||||||
self.port = reactor.listenTCP(self.rpc_port, Site(root), interface='localhost')
|
|
||||||
log.info("starting %i nodes on %s, rpc available on localhost:%i", len(self._nodes), self.external_ip, self.rpc_port)
|
|
||||||
|
|
||||||
for node in self._nodes:
|
|
||||||
node.start_listening()
|
|
||||||
yield node._protocol._listening
|
|
||||||
|
|
||||||
for node1 in self._nodes:
|
|
||||||
for node2 in self._nodes:
|
|
||||||
if node1 is node2:
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
yield node1.addContact(node1.contact_manager.make_contact(node2.node_id, node2.externalIP,
|
|
||||||
node2.port, node1._protocol))
|
|
||||||
except TransportNotConnected:
|
|
||||||
pass
|
|
||||||
node1.safe_start_looping_call(node1._change_token_lc, constants.tokenSecretChangeInterval)
|
|
||||||
node1.safe_start_looping_call(node1._refresh_node_lc, constants.checkRefreshInterval)
|
|
||||||
node1._join_deferred = defer.succeed(True)
|
|
||||||
reactor.addSystemEventTrigger('before', 'shutdown', self.stop)
|
|
||||||
log.info("finished bootstrapping the network, running %i nodes", len(self._nodes))
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def stop(self):
|
|
||||||
yield self.port.stopListening()
|
|
||||||
yield defer.DeferredList([node.stop() for node in self._nodes])
|
|
||||||
|
|
||||||
def jsonrpc_get_node_ids(self):
|
|
||||||
return defer.succeed([node.node_id.encode('hex') for node in self._nodes])
|
|
||||||
|
|
||||||
def jsonrpc_node_datastore(self, node_id):
|
|
||||||
for node in self._nodes:
|
|
||||||
if node.node_id == node_id.decode('hex'):
|
|
||||||
return defer.succeed(format_datastore(node))
|
|
||||||
|
|
||||||
def jsonrpc_get_nodes_who_stored(self, blob_hash):
|
|
||||||
storing_nodes = {}
|
|
||||||
for node in self._nodes:
|
|
||||||
datastore = format_datastore(node)
|
|
||||||
if blob_hash in datastore:
|
|
||||||
storing_nodes[node.node_id.encode('hex')] = datastore[blob_hash]
|
|
||||||
return defer.succeed(storing_nodes)
|
|
||||||
|
|
||||||
def jsonrpc_node_routing_table(self, node_id):
|
|
||||||
def format_bucket(bucket):
|
|
||||||
return {
|
|
||||||
"contacts": [format_contact(contact) for contact in bucket._contacts],
|
|
||||||
"lastAccessed": bucket.lastAccessed
|
|
||||||
}
|
|
||||||
|
|
||||||
def format_routing(node):
|
|
||||||
return {
|
|
||||||
i: format_bucket(bucket) for i, bucket in enumerate(node._routingTable._buckets)
|
|
||||||
}
|
|
||||||
|
|
||||||
for node in self._nodes:
|
|
||||||
if node.node_id == node_id.decode('hex'):
|
|
||||||
return defer.succeed(format_routing(node))
|
|
||||||
|
|
||||||
def jsonrpc_restart_node(self, node_id):
|
|
||||||
for node in self._nodes:
|
|
||||||
if node.node_id == node_id.decode('hex'):
|
|
||||||
d = node.stop()
|
|
||||||
d.addCallback(lambda _: node.start(self._own_addresses))
|
|
||||||
return d
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def jsonrpc_local_node_rpc(self, from_node, query, args=()):
|
|
||||||
def format_result(response):
|
|
||||||
if isinstance(response, list):
|
|
||||||
return [[node_id.encode('hex'), address, port] for (node_id, address, port) in response]
|
|
||||||
if isinstance(response, dict):
|
|
||||||
return {'token': response['token'].encode('hex'), 'contacts': format_result(response['contacts'])}
|
|
||||||
return response
|
|
||||||
|
|
||||||
for node in self._nodes:
|
|
||||||
if node.node_id == from_node.decode('hex'):
|
|
||||||
fn = getattr(node, query)
|
|
||||||
self_contact = node.contact_manager.make_contact(node.node_id, node.externalIP, node.port, node._protocol)
|
|
||||||
if args:
|
|
||||||
args = (str(arg) if isinstance(arg, (str, unicode)) else int(arg) for arg in args)
|
|
||||||
result = yield fn(self_contact, *args)
|
|
||||||
else:
|
|
||||||
result = yield fn()
|
|
||||||
# print "result: %s" % result
|
|
||||||
defer.returnValue(format_result(result))
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def jsonrpc_node_rpc(self, from_node, to_node, query, args=()):
|
|
||||||
def format_result(response):
|
|
||||||
if isinstance(response, list):
|
|
||||||
return [[node_id.encode('hex'), address, port] for (node_id, address, port) in response]
|
|
||||||
if isinstance(response, dict):
|
|
||||||
return {'token': response['token'].encode('hex'), 'contacts': format_result(response['contacts'])}
|
|
||||||
return response
|
|
||||||
|
|
||||||
for node in self._nodes:
|
|
||||||
if node.node_id == from_node.decode('hex'):
|
|
||||||
remote = node._routingTable.getContact(to_node.decode('hex'))
|
|
||||||
fn = getattr(remote, query)
|
|
||||||
if args:
|
|
||||||
args = (str(arg).decode('hex') for arg in args)
|
|
||||||
result = yield fn(*args)
|
|
||||||
else:
|
|
||||||
result = yield fn()
|
|
||||||
defer.returnValue(format_result(result))
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def jsonrpc_get_nodes_who_know(self, ip_address):
|
|
||||||
nodes = []
|
|
||||||
for node_id in [n.node_id.encode('hex') for n in self._nodes]:
|
|
||||||
routing_info = yield self.jsonrpc_node_routing_table(node_id=node_id)
|
|
||||||
for index, bucket in routing_info.items():
|
|
||||||
if ip_address in map(lambda c: c['address'], bucket['contacts']):
|
|
||||||
nodes.append(node_id)
|
|
||||||
break
|
|
||||||
defer.returnValue(nodes)
|
|
||||||
|
|
||||||
def jsonrpc_node_status(self):
|
|
||||||
return defer.succeed({
|
|
||||||
node.node_id.encode('hex'): node._join_deferred is not None and node._join_deferred.called
|
|
||||||
for node in self._nodes
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument('--rpc_port', default=5280)
|
|
||||||
parser.add_argument('--starting_port', default=4455)
|
|
||||||
parser.add_argument('--nodes', default=32)
|
|
||||||
args = parser.parse_args()
|
|
||||||
MultiSeedRPCServer(int(args.starting_port), int(args.nodes), int(args.rpc_port))
|
|
||||||
reactor.run()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
Loading…
Reference in a new issue