Skip to content

Commit

Permalink
command
Browse files Browse the repository at this point in the history
  • Loading branch information
Emojigit committed Dec 23, 2023
1 parent cf2b367 commit 2e03baf
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 30 deletions.
61 changes: 60 additions & 1 deletion bchosttrust/analysis/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,43 @@ def get_website_votes(
return result


@typechecked
def get_specific_website_votes(
backend: BCHTStorageBase,
bhash: bytes,
hostname: str) -> defaultdict[int, int]:
"""Get the number of votes with different attitudes on a specific website
Parameters
----------
backend : BCHTStorageBase
The storage backend to be used.
bhash : bytes
The hash of the starting block. See iter_from_block(...) for more details.
hostname : str
The hostname to be checked.
Returns
-------
defaultdict[int, int]
A dictionary with attitudes as keys and votes as values.
"""

result: defaultdict[int, int] = defaultdict(int)

for block in iter_from_block(backend, bhash):
for entry in block.entries:
if entry.domain_name == hostname:
result[entry.attitude] += 1

return result


@typechecked
def get_website_rating(
backend: BCHTStorageBase,
bhash: bytes) -> dict[str, int]:
"""Get the rating of a hostname by their votes.
"""Get the rating of hostnames by their votes.
Parameters
----------
Expand All @@ -104,3 +136,30 @@ def get_website_rating(
result[name] = sum((attitudes.WEIGHTS[att] * num)
for att, num in votes.items())
return result


@typechecked
def get_specific_website_rating(
backend: BCHTStorageBase,
bhash: bytes,
hostname: str) -> int:
"""Get the rating of hostnames by their votes.
Parameters
----------
backend : BCHTStorageBase
The storage backend to be used.
bhash : bytes
The hash of the starting block. See iter_from_block(...) for more details.
hostname : str
The hostname to be checked.
Returns
-------
int
The rating of the hostname.
"""

votes = get_specific_website_votes(backend, bhash, hostname)

return sum((attitudes.WEIGHTS[att] * num) for att, num in votes.items())
2 changes: 1 addition & 1 deletion bchosttrust/analysis/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def generate_tree(block_list: Iterable[BCHTBlock], from_block: bytes) -> Node:
Returns
-------
anytree.Node
Node
The Node object of the root. The name attibute of it is the hash.
See https://anytree.readthedocs.io/en/stable/api/anytree.node.html#anytree.node.node.Node
for more usages.
Expand Down
3 changes: 2 additions & 1 deletion bchosttrust/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"import_block", # Command: import
"create",
"get_rate",
"similar_domain"
"similar_domain",
"tree"
)

import lazy_loader as lazy
Expand Down
28 changes: 20 additions & 8 deletions bchosttrust/cli/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,17 @@
from ..storage import BCHTStorageBase, import_block
from ..consensus.powc import attempt
from .. import exceptions
from ..utils import HashParamType
from ..storage.import_block import get_curr_blocks


@click.command("create")
@click.argument("version", nargs=1, type=int)
@click.argument("prev_hash", nargs=1, type=HashParamType())
@click.argument("creation_time", nargs=1, type=int)
@click.argument("entries", nargs=-1, type=str)
@click.pass_context
def cli( # pylint: disable=too-many-arguments, too-many-locals
ctx: click.Context,
version: int,
prev_hash: bytes,
creation_time: int,
entries: tuple):
"""Create a BCHT block from data supplied.
Expand All @@ -30,6 +28,12 @@ def cli( # pylint: disable=too-many-arguments, too-many-locals
prev_hash: The hash of the previous block. For genesis block, use zeros only.
creation_time: Creation time in Unix epoch.
entries: Entry in the format of <hostname> <attitude>
Example:
$ bcht create 0 "$(date -u '+%s')" "example.com 0" "example.net 0"
Working on 000054870dde74253d34661700fe18adee3646cce0415832c0bc9391595ee176
Block found at nonce 120756
00007a6c5cbf2e3fd493938ef9b69e2350d2fcefaa448390f1d9fae1c1383cc2
"""

# `input` is a file opened in read mode.
Expand All @@ -46,7 +50,7 @@ def cli( # pylint: disable=too-many-arguments, too-many-locals
list_entries = []

for i, lines in enumerate(entries):
lines = lines.trim()
lines = lines.strip()
if lines == "":
continue
if lines[0] == "#":
Expand All @@ -71,15 +75,22 @@ def cli( # pylint: disable=too-many-arguments, too-many-locals

list_entries.append(new_entry)

curr_hashes = get_curr_blocks(storage)
if len(curr_hashes) == 0:
echo("Current block not found.", err=True)
ctx.exit(3)
echo(f"Working on {curr_hashes[0].hexdigest}", err=True)

try:
block, _ = attempt(version, prev_hash, creation_time, list_entries)
block, nonce = attempt(version, curr_hashes[0].hash,
creation_time, tuple(list_entries))
except exceptions.BCHTOutOfRangeError as e:
echo(f"Some value is out of range: {e}", err=True)
ctx.exit(3)
ctx.exit(4)

if block is None:
echo("No solution for this block.")
ctx.exit(4)
ctx.exit(5)

block_hash = block.hash

Expand All @@ -97,6 +108,7 @@ def cli( # pylint: disable=too-many-arguments, too-many-locals
except exceptions.BCHTConsensusFailedError as e:
echo(
f"Import failed: The block failed the consensus: {e}", err=True)
ctx.exit(3)
ctx.exit(4)
echo(f"Block found at nonce {nonce}")
echo(block.hexdigest)
ctx.exit(0)
5 changes: 3 additions & 2 deletions bchosttrust/cli/get.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# bchosttrust/bchosttrust/cli/get.py
"""Implements the retrieval of block from the database."""

from time import strftime
from datetime import datetime
import click
from click import echo

Expand Down Expand Up @@ -32,7 +32,8 @@ def cli(ctx, output_format, block_hash):
echo("Failed to obtain block (unknown error)", err=True)
raise

time_str = strftime("%a, %d %b %Y %H:%M:%S +0000", block.creation_time)
time_datetime = datetime.utcfromtimestamp(block.creation_time)
time_str = time_datetime.strftime('%Y-%m-%d %H:%M:%S UTC')

match output_format:
case "raw":
Expand Down
18 changes: 1 addition & 17 deletions bchosttrust/cli/get_rate.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,6 @@
def cli(ctx: click.Context, safe: bool, hostname: str):
"""Get the rating of a domain"""

# Get the rating of the domain name with the search.get_website_rating function.

storage: BCHTStorageBase = ctx.obj["storage"]

try:
last_block_hash = get_last_block_hash(storage, safe)
except RuntimeError:
echo("Cannot find last block hash", err=True)
ctx.exit(1)

ratings = search.get_website_rating(storage, last_block_hash)

if hostname in ratings:
echo(ratings[hostname])
ctx.exit(0)

echo("WARNING: rating not found", err=True)
echo(0)
ctx.exit(2)
# use search.get_specific_website_rating
52 changes: 52 additions & 0 deletions bchosttrust/cli/tree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# bchosttrust/bchosttrust/cli/tree.py
"""Generate a tree view of blocks"""

import click
from click import echo

from anytree import RenderTree
import anytree.render

from ..storage.import_block import get_curr_blocks
from ..storage.meta import BCHTStorageBase
from ..analysis.search import iter_from_block
from ..analysis.tree import generate_tree


@click.command("tree")
@click.option('-s', '--style',
type=click.Choice(
["ascii", "cont", "round", "double"], case_sensitive=False),
help="The display style to be used.", default="cont")
@click.pass_context
def cli(ctx: click.Context, style: str):
"""Display the tree of blocks."""

storage: BCHTStorageBase = ctx.obj["storage"]

match style:
case "ascii":
style = anytree.render.AsciiStyle
case "cont":
style = anytree.render.ContStyle
case "round":
style = anytree.render.ContRoundStyle
case "double":
style = anytree.render.DoubleStyle

curr_blocks = get_curr_blocks(storage)
if len(curr_blocks) == 0:
echo("Create some blocks first.", err=True)
ctx.exit(1)

_iter = iter_from_block(storage, curr_blocks[0].hash)
try:
while True:
gen_block = next(_iter)
except StopIteration:
pass

tree = generate_tree(tuple(storage.iter_blocks()), gen_block.hash)

for pre, _, node in RenderTree(tree, style=style):
print(f"{pre}{node.name.hex()}")

0 comments on commit 2e03baf

Please sign in to comment.