From f82185d877bc8094bd43183c7028a0cfe1f99d60 Mon Sep 17 00:00:00 2001 From: Moul <moul@moul.re> Date: Fri, 14 Oct 2022 18:36:47 +0200 Subject: [PATCH] Move diffi in blockchain.difficulty (#330) --- silkaj/blockchain/difficulty.py | 93 +++++++++++++++++++++++++++++++++ silkaj/cli.py | 3 +- silkaj/commands.py | 69 +----------------------- 3 files changed, 96 insertions(+), 69 deletions(-) create mode 100644 silkaj/blockchain/difficulty.py diff --git a/silkaj/blockchain/difficulty.py b/silkaj/blockchain/difficulty.py new file mode 100644 index 00000000..e6bccdb3 --- /dev/null +++ b/silkaj/blockchain/difficulty.py @@ -0,0 +1,93 @@ +# Copyright 2016-2022 Maël Azimi <m.a@moul.re> +# +# Silkaj is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Silkaj is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Silkaj. If not, see <https://www.gnu.org/licenses/>. + +from collections import OrderedDict +from operator import itemgetter +from os import system +from typing import Dict, Tuple + +import click +import jsonschema +from duniterpy.api import bma +from duniterpy.api.client import WSConnection +from pendulum import from_timestamp +from websocket._exceptions import WebSocketConnectionClosedException + +from silkaj import tui +from silkaj.constants import ALL +from silkaj.network_tools import client_instance + + +@click.command( + "diffi", + help="Display the current Proof of Work difficulty level to generate the next block", +) +def difficulties() -> None: + client = client_instance() + try: + ws = client(bma.ws.block) + while True: + current = ws.receive_json() + jsonschema.validate(current, bma.ws.WS_BLOCK_SCHEMA) + diffi = client(bma.blockchain.difficulties) + display_diffi(current, diffi) + except (jsonschema.ValidationError, WebSocketConnectionClosedException) as e: + print(f"{str(e.__class__.__name__)}: {str(e)}") + + +def display_diffi(current: WSConnection, diffi: Dict) -> None: + levels = [OrderedDict((i, d[i]) for i in ("uid", "level")) for d in diffi["levels"]] + diffi["levels"] = levels + issuers = 0 + sorted_diffi = sorted(diffi["levels"], key=itemgetter("level"), reverse=True) + for d in diffi["levels"]: + if d["level"] / 2 < current["powMin"]: + issuers += 1 + d["match"] = match_pattern(d["level"])[0][:20] + d["Πdiffi"] = compute_power(match_pattern(d["level"])[1]) + d["Σ diffi"] = d.pop("level") + system("cls||clear") + block_gen = from_timestamp(current["time"], tz="local").format(ALL) + match = match_pattern(int(current["powMin"]))[0] + + table = tui.Table(style="columns").set_cols_dtype(["t", "t", "t", "i"]) + table.fill_from_dict_list(sorted_diffi) + + content = f'Current block: n°{current["number"]}, generated on {block_gen}\n\ +Generation of next block n°{diffi["block"]} \ +possible by at least {issuers}/{len(diffi["levels"])} members\n\ +Common Proof-of-Work difficulty level: {current["powMin"]}, hash starting with `{match}`\n\ +{table.draw()}' + print(content) + + +def match_pattern(_pow: int, match: str = "", p: int = 1) -> Tuple[str, int]: + while _pow > 0: + if _pow >= 16: + match += "0" + _pow -= 16 + p *= 16 + else: + match += f"[0-{hex(15 - _pow)[2:].upper()}]" + p *= _pow + _pow = 0 + return f"{match}*", p + + +def compute_power(nbr: float, power: int = 0) -> str: + while nbr >= 10: + nbr /= 10 + power += 1 + return f"{nbr:.1f} × 10^{power}" diff --git a/silkaj/cli.py b/silkaj/cli.py index 54c83cb6..df68a307 100644 --- a/silkaj/cli.py +++ b/silkaj/cli.py @@ -20,11 +20,12 @@ from duniterpy.api.endpoint import endpoint as du_endpoint from silkaj import revocation from silkaj.auth import generate_auth_file +from silkaj.blockchain.difficulty import difficulties from silkaj.blockchain.information import argos_info, currency_info from silkaj.blocks import verify_blocks_signatures from silkaj.cert import send_certification from silkaj.checksum import checksum_command -from silkaj.commands import difficulties, list_blocks +from silkaj.commands import list_blocks from silkaj.constants import ( G1_DEFAULT_ENDPOINT, G1_TEST_DEFAULT_ENDPOINT, diff --git a/silkaj/commands.py b/silkaj/commands.py index f0ba6c62..07092dd8 100644 --- a/silkaj/commands.py +++ b/silkaj/commands.py @@ -15,16 +15,12 @@ from collections import OrderedDict from operator import itemgetter -from os import system -from typing import Dict, List, Tuple +from typing import List from urllib.error import HTTPError -import jsonschema from click import IntRange, argument, command, option from duniterpy.api import bma -from duniterpy.api.client import WSConnection from pendulum import from_timestamp -from websocket._exceptions import WebSocketConnectionClosedException from silkaj import tui from silkaj.blockchain_tools import get_head_block @@ -33,69 +29,6 @@ from silkaj.network_tools import client_instance from silkaj.wot_tools import identity_of -def match_pattern(_pow: int, match: str = "", p: int = 1) -> Tuple[str, int]: - while _pow > 0: - if _pow >= 16: - match += "0" - _pow -= 16 - p *= 16 - else: - match += f"[0-{hex(15 - _pow)[2:].upper()}]" - p *= _pow - _pow = 0 - return f"{match}*", p - - -def compute_power(nbr: float, power: int = 0) -> str: - while nbr >= 10: - nbr /= 10 - power += 1 - return f"{nbr:.1f} × 10^{power}" - - -@command( - "diffi", - help="Display the current Proof of Work difficulty level to generate the next block", -) -def difficulties() -> None: - client = client_instance() - try: - ws = client(bma.ws.block) - while True: - current = ws.receive_json() - jsonschema.validate(current, bma.ws.WS_BLOCK_SCHEMA) - diffi = client(bma.blockchain.difficulties) - display_diffi(current, diffi) - except (jsonschema.ValidationError, WebSocketConnectionClosedException) as e: - print(f"{str(e.__class__.__name__)}: {str(e)}") - - -def display_diffi(current: WSConnection, diffi: Dict) -> None: - levels = [OrderedDict((i, d[i]) for i in ("uid", "level")) for d in diffi["levels"]] - diffi["levels"] = levels - issuers = 0 - sorted_diffi = sorted(diffi["levels"], key=itemgetter("level"), reverse=True) - for d in diffi["levels"]: - if d["level"] / 2 < current["powMin"]: - issuers += 1 - d["match"] = match_pattern(d["level"])[0][:20] - d["Πdiffi"] = compute_power(match_pattern(d["level"])[1]) - d["Σ diffi"] = d.pop("level") - system("cls||clear") - block_gen = from_timestamp(current["time"], tz="local").format(ALL) - match = match_pattern(int(current["powMin"]))[0] - - table = tui.Table(style="columns").set_cols_dtype(["t", "t", "t", "i"]) - table.fill_from_dict_list(sorted_diffi) - - content = f'Current block: n°{current["number"]}, generated on {block_gen}\n\ -Generation of next block n°{diffi["block"]} \ -possible by at least {issuers}/{len(diffi["levels"])} members\n\ -Common Proof-of-Work difficulty level: {current["powMin"]}, hash starting with `{match}`\n\ -{table.draw()}' - print(content) - - @command("blocks", help="Display blocks: default: 0 for current window size") @argument("number", default=0, type=IntRange(0, 5000)) @option( -- GitLab