From ff45f6a54dae43f1947716f4d8b45648436990a8 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Wed, 21 Dec 2022 16:57:40 -0400 Subject: [PATCH 1/3] Updates for Oxen 11 dev branch compatibility --- observer.py | 53 +++++++++++++++++---------- templates/block.html | 8 ++-- templates/include/mempool.html | 6 +-- templates/include/sn_awaiting.html | 3 +- templates/include/tx_fee.html | 2 +- templates/include/tx_type_symbol.html | 8 ++-- templates/index.html | 4 +- templates/sn.html | 40 ++++---------------- templates/tx.html | 34 ++++++++--------- 9 files changed, 75 insertions(+), 83 deletions(-) diff --git a/observer.py b/observer.py index 6734272..c3cc19a 100644 --- a/observer.py +++ b/observer.py @@ -194,7 +194,7 @@ def get_sns(sns_future, info_future): sn_states = sns_future.get() sn_states = sn_states['service_node_states'] if 'service_node_states' in sn_states else [] for sn in sn_states: - sn['contribution_open'] = sn['staking_requirement'] - sn['total_reserved'] + sn['contribution_open'] = sn['staking_requirement'] - sn.get('total_reserved', sn['total_contributed']) sn['contribution_required'] = sn['staking_requirement'] - sn['total_contributed'] sn['num_contributions'] = sum(len(x['locked_contributions']) for x in sn['contributors'] if 'locked_contributions' in x) @@ -242,7 +242,13 @@ def parse_mempool(mempool_future): mp['_sorted'] = True for tx in mp['transactions']: - tx['info'] = json.loads(tx["tx_json"]) + if 'type' not in tx and 'tx_json' in tx: + # Legacy code for Oxen 10 and earlier + info = json.loads(tx["tx_json"]) + # FIXME -- do we have parsed extra stuff already? + info['tx_extra_raw'] = bytes_to_hex(info['extra']) + del info['extra'] + tx.update(info) else: mp['transactions'] = [] return mp @@ -327,17 +333,16 @@ def main(refresh=None, page=0, per_page=None, first=None, last=None, style=None) if 'tx_hashes' in b: txids += b['tx_hashes'] if txids: - txs = parse_txs(tx_req(omq, oxend, txids, cache_key='mempool').get()) + txs = parse_txs(tx_req(omq, oxend, txids, cache_key='recent').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]: + if 'vin' in tx and len(tx['vin']) == 1 and 'gen' in tx['vin'][0]: tx['coinbase'] = True # TXs should come back in the same order so we can just skip ahead one when the block # height changes rather than needing to search for the block if blocks[i]['height'] != tx['block_height']: i += 1 while i < len(blocks) and blocks[i]['height'] != tx['block_height']: - print("Something getting wrong: missing txes?", file=sys.stderr) i += 1 if i >= len(blocks): print("Something getting wrong: have leftover txes") @@ -347,12 +352,17 @@ def main(refresh=None, page=0, per_page=None, first=None, last=None, style=None) # Clean up the SN data a bit to make things easier for the templates awaiting_sns, active_sns, inactive_sns = get_sns(sns, inforeq) + accrued = accrued.get() + accrued_total = ( + sum(amt for wallet, amt in accrued['balances'].items()) if 'balances' in accrued else + sum(accrued['amounts'])) + return flask.render_template('index.html', info=info, stake=stake.get(), fees=base_fee.get(), emission=coinbase.get(), - accrued_total=sum(accrued.get()['amounts']), + accrued_total=accrued_total, hf=hfinfo.get(), active_sns=active_sns, active_swarms=len(set(x['swarm_id'] for x in active_sns)), @@ -398,8 +408,9 @@ 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, + "decode_as_json": True, # Can drop once we no longer need Oxen 10 support "tx_extra": True, + "tx_extra_raw": True, "prune": True, "stake_info": True, }, @@ -586,9 +597,9 @@ def show_sn(pubkey, more_details=False): # Number of staked contributions sn['num_contributions'] = sum(len(x["locked_contributions"]) for x in sn["contributors"] if "locked_contributions" in x) # Number of unfilled, reserved contribution spots: - sn['num_reserved_spots'] = sum(x["amount"] < x["reserved"] for x in sn["contributors"]) + sn['num_reserved_spots'] = sum('reserved' in x and x["amount"] < x["reserved"] for x in sn["contributors"]) # Available open contribution spots: - sn['num_open_spots'] = 0 if sn['total_reserved'] >= sn['staking_requirement'] else max(0, 4 - sn['num_contributions'] - sn['num_reserved_spots']) + sn['num_open_spots'] = 0 if sn.get('total_reserved', sn['total_contributed']) >= sn['staking_requirement'] else max(0, 4 - sn['num_contributions'] - sn['num_reserved_spots']) if more_details: formatter = HtmlFormatter(cssclass="syntax-highlight", style="paraiso-dark") @@ -635,14 +646,18 @@ def parse_txs(txs_rpc): return [] for tx in txs_rpc['txs']: - if 'info' not in tx: + if 'type' not in tx and 'as_json' in tx: + # Pre Oxen 11 crammed the details into "as_json" that we have to parse again # We have serialized JSON data inside a field in the JSON, because of oxend's # multiple incompatible JSON generators 🤮: - tx['info'] = json.loads(tx["as_json"]) + info = json.loads(tx["as_json"]) del tx['as_json'] # The "extra" field inside as_json is retardedly in per-byte integer values, # convert it to a hex string 🤮: - tx['info']['extra'] = bytes_to_hex(tx['info']['extra']) + info['tx_extra_raw'] = bytes_to_hex(info['extra']) + del info['extra'] + tx.update(info) + return txs_rpc['txs'] @@ -742,19 +757,19 @@ 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']: + if tx['version'] >= 4 and 'sn_state_change' in tx['extra']: 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} } } block_info_req = None - if 'vin' in tx['info']: - if len(tx['info']['vin']) == 1 and 'gen' in tx['info']['vin'][0]: + if 'vin' in tx: + if len(tx['vin']) == 1 and 'gen' in tx['vin'][0]: tx['coinbase'] = True - elif tx['info']['vin'] and config.enable_mixins_details: + elif tx['vin'] and config.enable_mixins_details: # Load output details for all outputs contained in the inputs outs_req = [] - for inp in tx['info']['vin']: + for inp in tx['vin']: # Key positions are stored as offsets from the previous index rather than indices, # so de-delta them back into indices: if 'key_offsets' in inp['key'] and 'key_indices' not in inp['key']: @@ -766,7 +781,7 @@ def show_tx(txid, more_details=False): kis.append(kbase) 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']] + outs_req = [{"amount":inp['key']['amount'], "index":ki} for inp in tx['vin'] for ki in inp['key']['key_indices']] outputs = FutureJSON(omq, oxend, 'rpc.get_outs', args={ 'get_txid': True, 'outputs': outs_req, @@ -778,7 +793,7 @@ def show_tx(txid, more_details=False): 'heights': [o["height"] for o in outputs] }) i = 0 - for inp in tx['info']['vin']: + for inp in tx['vin']: amount = inp['key']['amount'] if amount not in kindex_info: kindex_info[amount] = {} diff --git a/templates/block.html b/templates/block.html index d885fbb..f86adbe 100644 --- a/templates/block.html +++ b/templates/block.html @@ -50,7 +50,7 @@ Validator bits: {{"{:011b}".format(block.info.pulse.validator_bitset)}}"> - {%if sn.storage_server_last_reachable == 0 and sn.storage_server_last_unreachable == 0%} - Not yet tested - {%elif sn.storage_server_last_reachable >= sn.storage_server_last_unreachable%} - - Reachable (as of {{sn.storage_server_last_reachable | from_timestamp | ago}} ago - - {%else%} - - Not reachable (as of {{sn.storage_server_last_unreachable | from_timestamp | ago}} ago) - - {%endif%} - + {% import 'include/reachable.html' as reachable %} - - sn.lokinet_last_reachable%} class="omg warning"{%endif%}>Lokinet: - {%if sn.lokinet_last_reachable == 0 and sn.lokinet_last_unreachable == 0%} - Not yet tested - {%elif sn.lokinet_last_reachable >= sn.lokinet_last_unreachable%} - - Reachable (as of {{sn.lokinet_last_reachable | from_timestamp | ago}} ago - - {%else%} - - Not reachable (as of {{sn.lokinet_last_unreachable | from_timestamp | ago}} ago) - - {%endif%} - + {{reachable.display(sn)}} + {{reachable.display(sn, true)}} {%endif%} {%set pulse_voted = sn.pulse_participation | selectattr("voted") | list | length%} @@ -188,7 +163,8 @@

Awaiting registration. This service node has {{(sn.staking_requirement - sn.total_contributed) | oxen}} remaining to be contributed. {%if sn.num_open_spots > 0%} - The minimum required stake contribution is {{((sn.staking_requirement - sn.total_reserved) / sn.num_open_spots) | oxen}}. + {%set total_staked = sn.total_reserved if 'total_reserved' in sn else sn.total_contributed%} + The minimum required stake contribution is {{((sn.staking_requirement - total_staked) / sn.num_open_spots) | oxen}}. {%endif%}

{%endif%} @@ -224,7 +200,7 @@ ({{c.locked_contributions|length}} contributions) {%endif-%} - {{c.reserved | oxen}} + {{(c.reserved if 'reserved' in c else c.amount) | oxen}} {%endfor%} diff --git a/templates/tx.html b/templates/tx.html index 9a01d5b..b0e8af7 100644 --- a/templates/tx.html +++ b/templates/tx.html @@ -46,7 +46,7 @@ {{tx.received_timestamp | from_timestamp | format_datetime('short')}} UTC ({{tx.received_timestamp | from_timestamp | ago}} ago) {%endif%} - {{tx.info.version}}/{{sym.display(tx, text=true)}} + {{tx.version}}/{{sym.display(tx, text=true)}} {%if not have_raw_tx%} {%if 'block_timestamp' in tx%} {{tx.block_timestamp | from_timestamp | format_datetime('short')}} UTC @@ -56,17 +56,17 @@ {# FIXME - if in mempool then link to mempool page instead #} - {%if tx.coinbase or 'rct_signatures' not in tx.info%} + {%if tx.coinbase or 'rct_signatures' not in tx%} N/A {%else%} {{fee.display(tx)}} - ({{(tx.info.rct_signatures.txnFee * 1000 / tx.size) | oxen(tag=false, decimals=6)}}) + ({{(tx.rct_signatures.txnFee * 1000 / tx.size) | oxen(tag=false, decimals=6)}}) {%endif%} {{tx.size|si}}B {%if 'block_height' in tx%}{{info.height - tx.block_height}}{%else%}None (in mempool){%endif%} - {%if tx.info.version >= 2 and 'rct_signatures' in tx.info and not tx.coinbase%}Yes/{{tx.info.rct_signatures.type}}{%else%}No{%endif%} + {%if tx.version >= 2 and 'rct_signatures' in tx and not tx.coinbase%}Yes/{{tx.rct_signatures.type}}{%else%}No{%endif%} {%if tx.coinbase and tx.extra.sn_winner%} @@ -78,10 +78,10 @@ {%endif%} -
{{tx.info.extra}}
+
{{tx.tx_extra_raw}}
- {% if tx.info.version >= 4 -%} - {% if tx.info.type == 1 and 'sn_state_change' in tx.extra %} + {% if tx.version >= 4 -%} + {% if tx.type == 1 and 'sn_state_change' in tx.extra %}

{%- set show_reasons = false -%} {% if tx.extra.sn_state_change.type == 'decom' -%} @@ -159,12 +159,12 @@ This tx does not includes a vote from this testing service node (only 7 votes ar {%endif%} - {% elif tx.info.type == 2 %} + {% elif tx.type == 2 %}

🔓 Service Node Unlock

{{tx.extra.sn_pubkey}}

{{unlock_key_image}}

{# FIXME #}

{{unlock_signature}}

{# FIXME #} - {% elif tx.info.type == 4 and 'lns' in tx.extra %} + {% elif tx.type == 4 and 'lns' in tx.extra %} {% if 'buy' in tx.extra.lns %}

🎫 Oxen Name Service Registration

{% elif 'update' in tx.extra.lns %} @@ -216,10 +216,10 @@ This tx does not includes a vote from this testing service node (only 7 votes ar {% endif %} - {%if tx.info.vout%} + {%if tx.vout%}

Outputs

-

{{tx.info.vout|length}} output(s) for total of - {{tx.info.vout | sum(attribute='amount') | oxen(zero='???') | safe}}

+

{{tx.vout|length}} output(s) for total of + {{tx.vout | sum(attribute='amount') | oxen(zero='???') | safe}}

@@ -232,7 +232,7 @@ This tx does not includes a vote from this testing service node (only 7 votes ar - {%for out in tx.info.vout%} + {%for out in tx.vout%} @@ -549,12 +549,12 @@ This tx does not includes a vote from this testing service node (only 7 votes ar {%endif%} #} - {%if not tx.coinbase and tx.info.vin|length > 0 %} + {%if not tx.coinbase and tx.vin|length > 0 %}

Inputs

-

{{tx.info.vin|length}} input(s) for total of - {{tx.info.vin | sum(attribute='key.amount') | oxen(zero='???') | safe}}

+

{{tx.vin|length}} input(s) for total of + {{tx.vin | sum(attribute='key.amount') | oxen(zero='???') | safe}}

{#FIXME#} @@ -574,7 +574,7 @@ This tx does not includes a vote from this testing service node (only 7 votes ar
{{out.target.key}} {{out.amount | oxen(zero='?')}}
- {%for inp in tx.info.vin if 'key' in inp%} + {%for inp in tx.vin if 'key' in inp%}
{{inp.key.k_image}} From 3b68f65c238acdcf6a9f206ff1c8d40da07e9662 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Wed, 21 Dec 2022 16:59:34 -0400 Subject: [PATCH 2/3] Rebranding Better late than never. :) --- templates/tx.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/tx.html b/templates/tx.html index b0e8af7..351f05b 100644 --- a/templates/tx.html +++ b/templates/tx.html @@ -219,7 +219,7 @@ This tx does not includes a vote from this testing service node (only 7 votes ar {%if tx.vout%}

Outputs

{{tx.vout|length}} output(s) for total of - {{tx.vout | sum(attribute='amount') | oxen(zero='???') | safe}}

+ {{tx.vout | sum(attribute='amount') | oxen(zero='???') | safe}}
@@ -554,7 +554,7 @@ This tx does not includes a vote from this testing service node (only 7 votes ar

Inputs

{{tx.vin|length}} input(s) for total of - {{tx.vin | sum(attribute='key.amount') | oxen(zero='???') | safe}}

+ {{tx.vin | sum(attribute='key.amount') | oxen(zero='???') | safe}}
{#FIXME#} From d92abf692bdcfd9e906ae7e1ba234e9c61a57590 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Wed, 11 Jan 2023 19:39:10 -0400 Subject: [PATCH 3/3] Fix bug in reserved amount display --- templates/sn.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/sn.html b/templates/sn.html index 340d3c1..afc08dd 100644 --- a/templates/sn.html +++ b/templates/sn.html @@ -60,7 +60,7 @@ {%if 'total_reserved' in sn and sn.total_reserved != sn.total_contributed%} - {{sn.total_reserved - sn.total_contributed | oxen}} + {{(sn.total_reserved - sn.total_contributed) | oxen}} {%endif%}