From cd214df1b22c85743b979a0af79c1c6728da56ac Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Sat, 30 Oct 2021 00:11:09 -0300 Subject: [PATCH] Switch to using new python3-oxenmq --- .gitmodules | 3 - README.md | 36 +++-------- devnet.py | 3 +- lmq.py | 30 ++++----- mainnet.py | 3 +- observer.py | 173 ++++++++++++++++++++++++++-------------------------- pylokimq | 1 - testnet.py | 3 +- 8 files changed, 118 insertions(+), 134 deletions(-) delete mode 100644 .gitmodules delete mode 160000 pylokimq diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index b287c4e..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "pylokimq"] - path = pylokimq - url = https://github.com/majestrate/pylokimq.git diff --git a/README.md b/README.md index a071ec4..d9f5176 100644 --- a/README.md +++ b/README.md @@ -5,25 +5,9 @@ awesome, safe. ## Prerequisite packages -sudo apt install build-essential pkg-config libsodium-dev libzmq3-dev python3-dev python3-flask python3-babel python3-pygments + sudo apt install build-essential pkg-config libsodium-dev libzmq3-dev python3-dev python3-flask python3-babel python3-pygments python3-oxenmq -## Building and running - -Quick and dirty setup instructions for now: - - git submodule update --init --recursive - cd pylokimq - mkdir build - cd build - cmake .. - make -j6 - cd ../.. - ln -s pylokimq/build/pylokimq/pylokimq.cpython-*.so . - -(Note that we require a very recent python3-jinja package (2.11+), which may not be installed by the -above.) - -You'll also need to run oxend with `--lmq-local-control ipc:///path/to/loki-observer/mainnet.sock`. +Note that the last requirement (python3-oxenmq) comes from the Oxen repository (https://deb.oxen.io). ## Running in debug mode @@ -32,11 +16,11 @@ To run it in debug mode (production requires setting up a WSGI server, see below FLASK_APP=observer flask run --reload --debugger This mode seems to be a bit flakey, though -- reloading, in particular, seems to break things and -make it just silently exit after a while. +make it just silently exit after a while, so only do this for quick and dirty testing. ## Setting up for production with uwsgi-emperor: -Do all of the above, but instead of running it with flask, set up uwsgi-emperor as follows: +Do the above, but instead of running it with flask directly, set up uwsgi-emperor as follows: apt install uwsgi-emperor uwsgi-plugin-python3 @@ -47,24 +31,24 @@ in `/etc/uwsgi-emperor/emperor.ini` add configuration of: cap = setgid,setuid emperor-tyrant = true -Create a "vassal" config for loki-observer, `/etc/uwsgi-emperor/vassals/loki-observer.ini`, containing: +Create a "vassal" config for oxen-observer, `/etc/uwsgi-emperor/vassals/oxen-observer.ini`, containing: [uwsgi] - chdir = /path/to/loki-observer + chdir = /path/to/oxen-observer socket = mainnet.wsgi plugins = python3,logfile processes = 4 manage-script-name = true mount = /=mainnet:app - logger = file:logfile=/path/to/loki-observer/mainnet.log + logger = file:logfile=/path/to/oxen-observer/mainnet.log -Set ownership of this user to whatever use you want it to run as, and set the group to `_loki` (so +Set ownership of this user to whatever user you want it to run as, and set the group to `_loki` (so that it can open the oxend unix socket): chown MYUSERNAME:_loki /etc/uwsgi-emperor/vassals/loki-observer.ini -In the loki-observer/mainnet.py, set: +In the oxen-observer/mainnet.py, set: config.oxend_rpc = 'ipc:///var/lib/loki/oxend.sock' @@ -88,4 +72,4 @@ make uwsgi restart (for example because you are changing things) then it is suff apache2/uwsgi-emperor layers). If you want to set up a testnet or devnet observer the procedure is essentially the same, but -using testnet.py or devnet.py pointing to a oxend.sock from a testnet or devnet oxend. +using testnet.py or devnet.py pointing to the oxend.sock from a testnet or devnet oxend. diff --git a/devnet.py b/devnet.py index c5f617c..a66cab3 100644 --- a/devnet.py +++ b/devnet.py @@ -1,3 +1,4 @@ from observer import app, config +import oxenmq -config.oxend_rpc = 'ipc://oxend/devnet.sock' +config.oxend_rpc = oxenmq.Address('ipc://oxend/devnet.sock') diff --git a/lmq.py b/lmq.py index 066a9a1..ae5327b 100644 --- a/lmq.py +++ b/lmq.py @@ -1,19 +1,19 @@ -import pylokimq +import oxenmq import config import json import sys from datetime import datetime, timedelta -lmq, oxend = None, None -def lmq_connection(): - global lmq, oxend - if lmq is None: - lmq = pylokimq.LokiMQ(pylokimq.LogLevel.warn) - lmq.max_message_size = 200*1024*1024 - lmq.start() +omq, oxend = None, None +def omq_connection(): + global omq, oxend + if omq is None: + omq = oxenmq.OxenMQ(log_level=oxenmq.LogLevel.warn) + omq.max_message_size = 200*1024*1024 + omq.start() if oxend is None: - oxend = lmq.connect_remote(config.oxend_rpc) - return (lmq, oxend) + oxend = omq.connect_remote(config.oxend_rpc) + return (omq, oxend) cached = {} cached_args = {} @@ -30,9 +30,9 @@ class FutureJSON(): Cache entries are *not* purged, they are only replaced, so using dynamic data in the key would result in unbounded memory growth. - lmq - the lmq object - oxend - the oxend lmq connection id object - endpoint - the lmq endpoint, e.g. 'rpc.get_info' + omq - the omq object + oxend - the oxend omq connection id object + endpoint - the omq endpoint, e.g. 'rpc.get_info' cache_seconds - how long to cache the response; can be None to not cache it at all cache_key - fixed string to enable different caches of the same endpoint args - if not None, a value to pass (after converting to JSON) as the request parameter. Typically a dict. @@ -40,7 +40,7 @@ class FutureJSON(): timeout - maximum time to spend waiting for a reply """ - def __init__(self, lmq, oxend, endpoint, cache_seconds=3, *, cache_key='', args=None, fail_okay=False, timeout=10): + def __init__(self, omq, oxend, endpoint, cache_seconds=3, *, cache_key='', args=None, fail_okay=False, timeout=10): self.endpoint = endpoint self.cache_key = self.endpoint + cache_key self.fail_okay = fail_okay @@ -53,7 +53,7 @@ class FutureJSON(): else: self.json = None self.args = args - self.future = lmq.request_future(oxend, self.endpoint, [] if self.args is None else [self.args], timeout=timeout) + self.future = omq.request_future(oxend, self.endpoint, [] if self.args is None else [self.args], timeout=timeout) self.cache_seconds = cache_seconds def get(self): diff --git a/mainnet.py b/mainnet.py index 7303b79..f201c6f 100644 --- a/mainnet.py +++ b/mainnet.py @@ -1,3 +1,4 @@ from observer import app, config +import oxenmq -config.oxend_rpc = 'ipc://oxend/mainnet.sock' +config.oxend_rpc = oxenmq.Address('ipc://oxend/mainnet.sock') diff --git a/observer.py b/observer.py index e75af5f..da49f8c 100644 --- a/observer.py +++ b/observer.py @@ -25,7 +25,7 @@ import base58 import sha3 import config import local_config -from lmq import FutureJSON, lmq_connection +from lmq import FutureJSON, omq_connection # Make a dict of config.* to pass to templating conf = {x: getattr(config, x) for x in dir(config) if not x.startswith('__')} @@ -178,8 +178,8 @@ def css(): return flask.send_from_directory('static', 'style.css') -def get_sns_future(lmq, oxend): - return FutureJSON(lmq, oxend, 'rpc.get_service_nodes', 5, +def get_sns_future(omq, oxend): + return FutureJSON(omq, oxend, 'rpc.get_service_nodes', 5, args={ 'all': False, 'fields': { x: True for x in ('service_node_pubkey', 'requested_unlock_height', 'last_reward_block_height', @@ -209,8 +209,8 @@ def get_sns(sns_future, info_future): return awaiting_sns, active_sns, inactive_sns -def get_quorums_future(lmq, oxend, height): - return FutureJSON(lmq, oxend, 'rpc.get_quorum_state', 30, +def get_quorums_future(omq, oxend, height): + return FutureJSON(omq, oxend, 'rpc.get_quorum_state', 30, args={ 'start_height': height-55, 'end_height': height }) @@ -227,8 +227,8 @@ def get_quorums(quorums_future): print("Something getting wrong in quorums: found unknown quorum_type={}".format(q['quorum_type']), file=sys.stderr) return quo -def get_mempool_future(lmq, oxend): - return FutureJSON(lmq, oxend, 'rpc.get_transaction_pool', 5, args={"tx_extra":True, "stake_info":True}) +def get_mempool_future(omq, oxend): + return FutureJSON(omq, oxend, 'rpc.get_transaction_pool', 5, args={"tx_extra":True, "stake_info":True}) def parse_mempool(mempool_future): # mempool RPC return values are about as nasty as can be. For each mempool tx, we get back @@ -264,21 +264,22 @@ def template_globals(): @app.route('/page//') @app.route('/range//') @app.route('/autorefresh/') +@app.route('/v') # debug while mucking with stylesheets @app.route('/') -def main(refresh=None, page=0, per_page=None, first=None, last=None): - lmq, oxend = lmq_connection() - inforeq = FutureJSON(lmq, oxend, 'rpc.get_info', 1) - stake = FutureJSON(lmq, oxend, 'rpc.get_staking_requirement', 10) - base_fee = FutureJSON(lmq, oxend, 'rpc.get_fee_estimate', 10) - hfinfo = FutureJSON(lmq, oxend, 'rpc.hard_fork_info', 10) - mempool = get_mempool_future(lmq, oxend) - sns = get_sns_future(lmq, oxend) - checkpoints = FutureJSON(lmq, oxend, 'rpc.get_checkpoints', args={"count": 3}) +def main(refresh=None, page=0, per_page=None, first=None, last=None, style=None): + omq, oxend = omq_connection() + inforeq = FutureJSON(omq, oxend, 'rpc.get_info', 1) + stake = FutureJSON(omq, oxend, 'rpc.get_staking_requirement', 10) + base_fee = FutureJSON(omq, oxend, 'rpc.get_fee_estimate', 10) + hfinfo = FutureJSON(omq, oxend, 'rpc.hard_fork_info', 10) + mempool = get_mempool_future(omq, oxend) + sns = get_sns_future(omq, oxend) + checkpoints = FutureJSON(omq, oxend, 'rpc.get_checkpoints', args={"count": 3}) # This call is slow the first time it gets called in oxend but will be fast after that, so call # it with a very short timeout. It's also an admin-only command, so will always fail if we're # using a restricted RPC interface. - coinbase = FutureJSON(lmq, oxend, 'admin.get_coinbase_tx_sum', 10, timeout=1, fail_okay=True, + coinbase = FutureJSON(omq, oxend, 'admin.get_coinbase_tx_sum', 10, timeout=1, fail_okay=True, args={"height":0, "count":2**31-1}) custom_per_page = '' @@ -307,7 +308,7 @@ def main(refresh=None, page=0, per_page=None, first=None, last=None): end_height = max(0, height - per_page*page - 1) start_height = max(0, end_height - per_page + 1) - blocks = FutureJSON(lmq, oxend, 'rpc.get_block_headers_range', cache_key='main', args={ + blocks = FutureJSON(omq, oxend, 'rpc.get_block_headers_range', cache_key='main', args={ 'start_height': start_height, 'end_height': end_height, 'get_tx_hashes': True, @@ -324,7 +325,7 @@ def main(refresh=None, page=0, per_page=None, first=None, last=None): if 'tx_hashes' in b: txids += b['tx_hashes'] if txids: - txs = parse_txs(tx_req(lmq, oxend, txids, cache_key='mempool').get()) + txs = parse_txs(tx_req(omq, oxend, txids, cache_key='mempool').get()) i = 0 for tx in txs: if 'vin' in tx['info'] and len(tx['info']['vin']) == 1 and 'gen' in tx['info']['vin'][0]: @@ -366,9 +367,9 @@ def main(refresh=None, page=0, per_page=None, first=None, last=None): @app.route('/txpool') def mempool(): - lmq, oxend = lmq_connection() - info = FutureJSON(lmq, oxend, 'rpc.get_info', 1) - mempool = get_mempool_future(lmq, oxend) + omq, oxend = omq_connection() + info = FutureJSON(omq, oxend, 'rpc.get_info', 1) + mempool = get_mempool_future(omq, oxend) return flask.render_template('mempool.html', info=info.get(), @@ -377,9 +378,9 @@ def mempool(): @app.route('/service_nodes') def sns(): - lmq, oxend = lmq_connection() - info = FutureJSON(lmq, oxend, 'rpc.get_info', 1) - awaiting, active, inactive = get_sns(get_sns_future(lmq, oxend), info) + omq, oxend = omq_connection() + info = FutureJSON(omq, oxend, 'rpc.get_info', 1) + awaiting, active, inactive = get_sns(get_sns_future(omq, oxend), info) return flask.render_template('service_nodes.html', info=info.get(), @@ -388,8 +389,8 @@ def sns(): inactive_sns=inactive, ) -def tx_req(lmq, oxend, txids, cache_key='single', **kwargs): - return FutureJSON(lmq, oxend, 'rpc.get_transactions', cache_seconds=10, cache_key=cache_key, +def tx_req(omq, oxend, txids, cache_key='single', **kwargs): + return FutureJSON(omq, oxend, 'rpc.get_transactions', cache_seconds=10, cache_key=cache_key, args={ "txs_hashes": txids, "decode_as_json": True, @@ -399,36 +400,36 @@ def tx_req(lmq, oxend, txids, cache_key='single', **kwargs): }, **kwargs) -def sn_req(lmq, oxend, pubkey, **kwargs): - return FutureJSON(lmq, oxend, 'rpc.get_service_nodes', 5, cache_key='single', +def sn_req(omq, oxend, pubkey, **kwargs): + return FutureJSON(omq, oxend, 'rpc.get_service_nodes', 5, cache_key='single', args={"service_node_pubkeys": [pubkey]}, **kwargs ) -def block_header_req(lmq, oxend, hash_or_height, **kwargs): +def block_header_req(omq, oxend, hash_or_height, **kwargs): if isinstance(hash_or_height, int) or (len(hash_or_height) <= 10 and hash_or_height.isdigit()): - return FutureJSON(lmq, oxend, 'rpc.get_block_header_by_height', cache_key='single', + return FutureJSON(omq, oxend, 'rpc.get_block_header_by_height', cache_key='single', args={ "height": int(hash_or_height) }, **kwargs) else: - return FutureJSON(lmq, oxend, 'rpc.get_block_header_by_hash', cache_key='single', + return FutureJSON(omq, oxend, 'rpc.get_block_header_by_hash', cache_key='single', args={ 'hash': hash_or_height }, **kwargs) -def block_with_txs_req(lmq, oxend, hash_or_height, **kwargs): +def block_with_txs_req(omq, oxend, hash_or_height, **kwargs): args = { 'get_tx_hashes': True } if isinstance(hash_or_height, int) or (len(hash_or_height) <= 10 and hash_or_height.isdigit()): args['height'] = int(hash_or_height) else: args['hash'] = hash_or_height - return FutureJSON(lmq, oxend, 'rpc.get_block', cache_key='single', args=args, **kwargs) + return FutureJSON(omq, oxend, 'rpc.get_block', cache_key='single', args=args, **kwargs) -def ons_info(lmq, oxend, name,ons_type,**kwargs): +def ons_info(omq, oxend, name,ons_type,**kwargs): if ons_type == 2: name=name+'.loki' name_hash = nacl.hash.blake2b(name.encode(), encoder = nacl.encoding.Base64Encoder) - return FutureJSON(lmq, oxend, 'rpc.ons_names_to_owners', args={ + return FutureJSON(omq, oxend, 'rpc.ons_names_to_owners', args={ "entries": [{'name_hash':name_hash.decode('ascii'),'types':[ons_type]}]}) @@ -436,8 +437,8 @@ def ons_info(lmq, oxend, name,ons_type,**kwargs): @app.route('/ons//') def show_ons(name, more_details=False): name = name.lower() - lmq, oxend = lmq_connection() - info = FutureJSON(lmq, oxend, 'rpc.get_info', 1) + omq, oxend = omq_connection() + info = FutureJSON(omq, oxend, 'rpc.get_info', 1) if len(name) > 64 or not all(c.isalnum() or c in '_-' for c in name): return flask.render_template('not_found.html', @@ -453,7 +454,7 @@ def show_ons(name, more_details=False): LOKINET_ENCRYPTED_LENGTH = 144 # The user must update their session mapping. for ons_type in ons_types: - onsinfo = ons_info(lmq, oxend, name, ons_types[ons_type]).get() + onsinfo = ons_info(omq, oxend, name, ons_types[ons_type]).get() if 'entries' not in onsinfo: # If returned with no data from the RPC @@ -469,7 +470,7 @@ def show_ons(name, more_details=False): if len(onsinfo['encrypted_value']) not in [SESSION_ENCRYPTED_LENGTH, WALLET_ENCRYPTED_LENGTH, LOKINET_ENCRYPTED_LENGTH]: # Encryption involves a much more expensive argon2-based calculation for HF15 registrations. # Owners should be notified they should update to the new encryption format. - ons_data[ons_type] = ons_info(lmq, oxend, name,ons_types[ons_type]).get()['entries'][0] + ons_data[ons_type] = ons_info(omq, oxend, name,ons_types[ons_type]).get()['entries'][0] ons_data[ons_type]['mapping'] = 'Owner needs to update their ID for mapping info.' else: @@ -560,11 +561,11 @@ def show_ons(name, more_details=False): @app.route('/sn/') @app.route('/sn//') def show_sn(pubkey, more_details=False): - lmq, oxend = lmq_connection() - info = FutureJSON(lmq, oxend, 'rpc.get_info', 1) - hfinfo = FutureJSON(lmq, oxend, 'rpc.hard_fork_info', 10) - sn = sn_req(lmq, oxend, pubkey).get() - quos = get_quorums_future(lmq, oxend, info.get()['height']) + omq, oxend = omq_connection() + info = FutureJSON(omq, oxend, 'rpc.get_info', 1) + hfinfo = FutureJSON(omq, oxend, 'rpc.hard_fork_info', 10) + sn = sn_req(omq, oxend, pubkey).get() + quos = get_quorums_future(omq, oxend, info.get()['height']) if 'service_node_states' not in sn or not sn['service_node_states']: @@ -640,7 +641,7 @@ def parse_txs(txs_rpc): return txs_rpc['txs'] -def get_block_txs_future(lmq, oxend, block): +def get_block_txs_future(omq, oxend, block): hashes = [] if 'tx_hashes' in block: hashes += block['tx_hashes'] @@ -653,7 +654,7 @@ def get_block_txs_future(lmq, oxend, block): except Exception as e: print("Something getting wrong: cannot parse block json for block {}: {}".format(block_height, e), file=sys.stderr) - return tx_req(lmq, oxend, hashes, cache_key='block') + return tx_req(omq, oxend, hashes, cache_key='block') @app.route('/block/') @@ -661,15 +662,15 @@ def get_block_txs_future(lmq, oxend, block): @app.route('/block/') @app.route('/block//') def show_block(height=None, hash=None, more_details=False): - lmq, oxend = lmq_connection() - info = FutureJSON(lmq, oxend, 'rpc.get_info', 1) - hfinfo = FutureJSON(lmq, oxend, 'rpc.hard_fork_info', 10) + omq, oxend = omq_connection() + info = FutureJSON(omq, oxend, 'rpc.get_info', 1) + hfinfo = FutureJSON(omq, oxend, 'rpc.hard_fork_info', 10) if height is not None: val = height elif hash is not None: val = hash - block = None if val is None else block_with_txs_req(lmq, oxend, val).get() + block = None if val is None else block_with_txs_req(omq, oxend, val).get() if block is None: return flask.render_template("not_found.html", info=info.get(), @@ -681,10 +682,10 @@ def show_block(height=None, hash=None, more_details=False): next_block = None block_height = block['block_header']['height'] - txs = get_block_txs_future(lmq, oxend, block) + txs = get_block_txs_future(omq, oxend, block) if info.get()['height'] > 1 + block_height: - next_block = block_header_req(lmq, oxend, '{}'.format(block_height + 1)) + next_block = block_header_req(omq, oxend, '{}'.format(block_height + 1)) if more_details: formatter = HtmlFormatter(cssclass="syntax-highlight", style="native") @@ -712,17 +713,17 @@ def show_block(height=None, hash=None, more_details=False): @app.route('/block/latest') def show_block_latest(): - lmq, oxend = lmq_connection() - height = FutureJSON(lmq, oxend, 'rpc.get_info', 1).get()['height'] - 1 + omq, oxend = omq_connection() + height = FutureJSON(omq, oxend, 'rpc.get_info', 1).get()['height'] - 1 return flask.redirect(flask.url_for('show_block', height=height), code=302) @app.route('/tx/') @app.route('/tx//') def show_tx(txid, more_details=False): - lmq, oxend = lmq_connection() - info = FutureJSON(lmq, oxend, 'rpc.get_info', 1) - txs = tx_req(lmq, oxend, [txid]).get() + omq, oxend = omq_connection() + info = FutureJSON(omq, oxend, 'rpc.get_info', 1) + txs = tx_req(omq, oxend, [txid]).get() if 'txs' not in txs or not txs['txs']: return flask.render_template('not_found.html', @@ -735,7 +736,7 @@ def show_tx(txid, more_details=False): # If this is a state change, see if we have the quorum stored to provide context testing_quorum = None if tx['info']['version'] >= 4 and 'sn_state_change' in tx['extra']: - testing_quorum = FutureJSON(lmq, oxend, 'rpc.get_quorum_state', 60, cache_key='tx_state_change', + testing_quorum = FutureJSON(omq, oxend, 'rpc.get_quorum_state', 60, cache_key='tx_state_change', args={ 'quorum_type': 0, 'start_height': tx['extra']['sn_state_change']['height'] }) kindex_info = {} # { amount => { keyindex => {output-info} } } @@ -759,14 +760,14 @@ def show_tx(txid, more_details=False): del inp['key']['key_offsets'] outs_req = [{"amount":inp['key']['amount'], "index":ki} for inp in tx['info']['vin'] for ki in inp['key']['key_indices']] - outputs = FutureJSON(lmq, oxend, 'rpc.get_outs', args={ + outputs = FutureJSON(omq, oxend, 'rpc.get_outs', args={ 'get_txid': True, 'outputs': outs_req, }).get() if outputs and 'outs' in outputs and len(outputs['outs']) == len(outs_req): outputs = outputs['outs'] # Also load block details for all of those outputs: - block_info_req = FutureJSON(lmq, oxend, 'rpc.get_block_header_by_height', args={ + block_info_req = FutureJSON(omq, oxend, 'rpc.get_block_header_by_height', args={ 'heights': [o["height"] for o in outputs] }) i = 0 @@ -816,9 +817,9 @@ def show_tx(txid, more_details=False): @app.route('/quorums') def show_quorums(): - lmq, oxend = lmq_connection() - info = FutureJSON(lmq, oxend, 'rpc.get_info', 1) - quos = get_quorums_future(lmq, oxend, info.get()['height']) + omq, oxend = omq_connection() + info = FutureJSON(omq, oxend, 'rpc.get_info', 1) + quos = get_quorums_future(omq, oxend, info.get()['height']) return flask.render_template('quorums.html', info=info.get(), @@ -832,8 +833,8 @@ base32z_map = {base32z_dict[i]: i for i in range(len(base32z_dict))} @app.route('/search') def search(): - lmq, oxend = lmq_connection() - info = FutureJSON(lmq, oxend, 'rpc.get_info', 1) + omq, oxend = omq_connection() + info = FutureJSON(omq, oxend, 'rpc.get_info', 1) val = (flask.request.args.get('value') or '').strip() if val and len(val) < 10 and val.isdigit(): # Block height return flask.redirect(flask.url_for('show_block', height=val), code=301) @@ -848,9 +849,9 @@ def search(): if len(val) == 64: # Initiate all the lookups at once, then redirect to whichever one responds affirmatively - snreq = sn_req(lmq, oxend, val) - blreq = block_header_req(lmq, oxend, val, fail_okay=True) - txreq = tx_req(lmq, oxend, [val]) + snreq = sn_req(omq, oxend, val) + blreq = block_header_req(omq, oxend, val, fail_okay=True) + txreq = tx_req(omq, oxend, [val]) sn = snreq.get() if sn and 'service_node_states' in sn and sn['service_node_states']: @@ -881,9 +882,9 @@ def search(): @app.route('/api/networkinfo') def api_networkinfo(): - lmq, oxend = lmq_connection() - info = FutureJSON(lmq, oxend, 'rpc.get_info', 1) - hfinfo = FutureJSON(lmq, oxend, 'rpc.hard_fork_info', 10) + omq, oxend = omq_connection() + info = FutureJSON(omq, oxend, 'rpc.get_info', 1) + hfinfo = FutureJSON(omq, oxend, 'rpc.hard_fork_info', 10) info = info.get() data = {**info} @@ -895,9 +896,9 @@ def api_networkinfo(): @app.route('/api/emission') def api_emission(): - lmq, oxend = lmq_connection() - info = FutureJSON(lmq, oxend, 'rpc.get_info', 1) - coinbase = FutureJSON(lmq, oxend, 'admin.get_coinbase_tx_sum', 10, timeout=1, fail_okay=True, + omq, oxend = omq_connection() + info = FutureJSON(omq, oxend, 'rpc.get_info', 1) + coinbase = FutureJSON(omq, oxend, 'admin.get_coinbase_tx_sum', 10, timeout=1, fail_okay=True, args={"height":0, "count":2**31-1}).get() if not coinbase: return flask.jsonify(None) @@ -917,10 +918,10 @@ def api_emission(): @app.route('/api/service_node_stats') def api_service_node_stats(): - lmq, oxend = lmq_connection() - info = FutureJSON(lmq, oxend, 'rpc.get_info', 1) - stakinginfo = FutureJSON(lmq, oxend, 'rpc.get_staking_requirement', 30) - sns = get_sns_future(lmq, oxend) + omq, oxend = omq_connection() + info = FutureJSON(omq, oxend, 'rpc.get_info', 1) + stakinginfo = FutureJSON(omq, oxend, 'rpc.get_staking_requirement', 30) + sns = get_sns_future(omq, oxend) sns = sns.get() if 'service_node_states' not in sns: return flask.jsonify({"status": "Error retrieving SN stats"}), 500 @@ -952,8 +953,8 @@ def api_service_node_stats(): @app.route('/api/circulating_supply') def api_circulating_supply(): - lmq, oxend = lmq_connection() - coinbase = FutureJSON(lmq, oxend, 'admin.get_coinbase_tx_sum', 10, timeout=1, fail_okay=True, + omq, oxend = omq_connection() + coinbase = FutureJSON(omq, oxend, 'admin.get_coinbase_tx_sum', 10, timeout=1, fail_okay=True, args={"height":0, "count":2**31-1}).get() return flask.jsonify((coinbase["emission_amount"] - coinbase["burn_amount"]) // 1_000_000_000 if coinbase else None) @@ -961,8 +962,8 @@ def api_circulating_supply(): # FIXME: need better error handling here @app.route('/api/transaction/') def api_tx(txid): - lmq, oxend = lmq_connection() - tx = tx_req(lmq, oxend, [txid]).get() + omq, oxend = omq_connection() + tx = tx_req(omq, oxend, [txid]).get() txs = parse_txs(tx) return flask.jsonify({ "status": tx['status'], @@ -972,9 +973,9 @@ def api_tx(txid): @app.route('/api/block/') @app.route('/api/block/') def api_block(blkid=None, height=None): - lmq, oxend = lmq_connection() - block = block_with_txs_req(lmq, oxend, blkid if blkid is not None else height).get() - txs = get_block_txs_future(lmq, oxend, block) + omq, oxend = omq_connection() + block = block_with_txs_req(omq, oxend, blkid if blkid is not None else height).get() + txs = get_block_txs_future(omq, oxend, block) if 'block_header' in block: data = block['block_header'].copy() diff --git a/pylokimq b/pylokimq deleted file mode 160000 index 558c679..0000000 --- a/pylokimq +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 558c679c55c5a366b57110a55b6cbc68c447925d diff --git a/testnet.py b/testnet.py index 3f9e972..44d88e9 100644 --- a/testnet.py +++ b/testnet.py @@ -1,3 +1,4 @@ from observer import app, config +import oxenmq -config.oxend_rpc = 'ipc://oxend/testnet.sock' +config.oxend_rpc = oxenmq.Address('ipc://oxend/testnet.sock')