diff --git a/src/dopt_pollublock_blockchain/app.py b/src/dopt_pollublock_blockchain/app.py index d2adb3a..3fdec65 100644 --- a/src/dopt_pollublock_blockchain/app.py +++ b/src/dopt_pollublock_blockchain/app.py @@ -1,10 +1,10 @@ -# %% +from __future__ import annotations + import dataclasses as dc import hashlib import json import random import sys -from pathlib import Path from typing import cast import click @@ -13,7 +13,6 @@ import polars as pl import rich.box import rich.table import sqlalchemy as sql -from dopt_basics import io from rich.console import Console from dopt_pollublock_blockchain import blockchain, db, types @@ -22,13 +21,7 @@ from dopt_pollublock_blockchain import constants as const user_seed: int | None = const.RNG_DEFAULT_SEED console = Console() -p_base = io.search_folder_path(Path(__file__), "src", return_inclusive=False) -assert p_base is not None -p_bc_db = p_base / "prototypes/blockchain.db" -assert p_bc_db.exists(), "blockchain data path not found" -p_sensor_data = p_base / "prototypes/pollublock_data.db" -assert p_sensor_data.exists(), "sensor data path not found" -engine = sql.create_engine(f"sqlite:///{str(p_sensor_data)}") +db_engine = sql.create_engine(f"sqlite:///{str(const.P_SENSOR_DATA)}") # // common helper functions @@ -137,7 +130,7 @@ def sample_entry( def blockchain_init() -> blockchain.Blockchain: console.print("Einlesen der Blockchain...") try: - chain = blockchain.Blockchain(p_bc_db) + chain = blockchain.Blockchain(const.P_BLOCKCHAIN_DATA) chain.difficulty = const.BLOCKCHAIN_DIFFICULTY chain.load(const.BLOCKCHAIN_LOADING_BATCH_SIZE) if not chain.genesis_done: @@ -221,7 +214,7 @@ def scenario_1(chain: blockchain.Blockchain) -> bool: max_idx: int = 0 try: - with engine.connect() as con: + with db_engine.connect() as con: res = con.execute(sql.select(sql.func.max(db.sensor_data.c.Index))) max_idx = cast(int, res.scalar()) except Exception: @@ -236,7 +229,7 @@ def scenario_1(chain: blockchain.Blockchain) -> bool: try: stmt = sql.select(db.sensor_data).where(db.sensor_data.c.Index == chosen_idx) db_entry = pl.read_database( - stmt, engine, schema_overrides=db.sensor_data_query_schema + stmt, db_engine, schema_overrides=db.sensor_data_query_schema ) table = rich_table_from_db_entry( db_entry, title=f"Sensordaten zu Eintrag {chosen_idx}" @@ -268,8 +261,8 @@ def scenario_1(chain: blockchain.Blockchain) -> bool: highlight=False, ) console.print( - f"Wir nutzen SHA256 als Hash-Algorithmus. Dies gibt uns den folgenden Hashwert zurück: " - f"[bold]{hashed_data_hex}[/bold]", + f"Wir nutzen SHA256 als Hash-Algorithmus. Dies gibt uns den folgenden Hashwert " + f"zurück: [bold]{hashed_data_hex}[/bold]", ) if not click.confirm("Fortfahren?", default=True): return True @@ -314,8 +307,9 @@ def scenario_1(chain: blockchain.Blockchain) -> bool: console.print(f"Ermittelter Hashwert der Einträge:\t[bold]{hashed_data_hex}[/bold]") console.print(f"Hashwert der Blockchain:\t\t[bold]{py_block_data_hash}[/bold]") console.print( - "[green3]Wir sehen, dass beide Werte übereinstimmen. Das bedeutet, dass der Datensatz " - "integer ist und seit der Referenzierung in der Blockchain nicht verändert wurde." + "[green3]Wir sehen, dass beide Werte übereinstimmen. Das bedeutet, dass " + "der Datensatz integer ist und seit der Referenzierung in der " + "Blockchain nicht verändert wurde." ) return False @@ -325,7 +319,7 @@ def scenario_2(chain: blockchain.Blockchain) -> bool: max_idx: int = 0 try: - with engine.connect() as con: + with db_engine.connect() as con: res = con.execute(sql.select(sql.func.max(db.sensor_data.c.Index))) max_idx = cast(int, res.scalar()) except Exception: @@ -344,14 +338,14 @@ def scenario_2(chain: blockchain.Blockchain) -> bool: stmt_insert = sql.insert(db.sensor_data).values(sampled_entry) stmt_sel = sql.select(db.sensor_data).order_by(db.sensor_data.c.Index.desc()).limit(1) - with engine.begin() as con: + with db_engine.begin() as con: res = con.execute(stmt_insert, sampled_entry) if res.rowcount <= 0: raise RuntimeError("Database query not successful") db_entry = pl.read_database( - stmt_sel, engine, schema_overrides=db.sensor_data_query_schema + stmt_sel, db_engine, schema_overrides=db.sensor_data_query_schema ) table = rich_table_from_db_entry(db_entry, title="Zufällig generierte Sensordaten") except Exception: @@ -360,7 +354,7 @@ def scenario_2(chain: blockchain.Blockchain) -> bool: max_idx: int = 0 try: - with engine.connect() as con: + with db_engine.connect() as con: res = con.execute(sql.select(sql.func.max(db.sensor_data.c.Index))) max_idx = cast(int, res.scalar()) except Exception: @@ -389,8 +383,8 @@ def scenario_2(chain: blockchain.Blockchain) -> bool: highlight=False, ) console.print( - f"Wir nutzen SHA256 als Hash-Algorithmus. Dies gibt uns den folgenden Hashwert zurück: " - f"[bold]{hashed_data_hex}[/bold]", + f"Wir nutzen SHA256 als Hash-Algorithmus. Dies gibt uns den folgenden Hashwert " + f"zurück: [bold]{hashed_data_hex}[/bold]", ) if not click.confirm("Fortfahren?", default=True): return True @@ -427,7 +421,7 @@ def scenario_2(chain: blockchain.Blockchain) -> bool: .where(db.sensor_data.c.Index == sql.bindparam("idx")) .values(Blockchain_Block_Number=sql.bindparam("bc_num")) ) - with engine.begin() as con: + with db_engine.begin() as con: res = con.execute(stmt, {"idx": max_idx, "bc_num": block_number}) if res.rowcount <= 0: @@ -435,7 +429,7 @@ def scenario_2(chain: blockchain.Blockchain) -> bool: stmt_sel = sql.select(db.sensor_data).where(db.sensor_data.c.Index == max_idx) db_entry = pl.read_database( - stmt_sel, engine, schema_overrides=db.sensor_data_query_schema + stmt_sel, db_engine, schema_overrides=db.sensor_data_query_schema ) table = rich_table_from_db_entry(db_entry, title=f"Sensordaten zu Eintrag {max_idx}") @@ -487,14 +481,14 @@ def scenario_2(chain: blockchain.Blockchain) -> bool: console.print(f"Ermittelter Hashwert der Einträge:\t[bold]{hashed_data_hex}[/bold]") console.print(f"Hashwert der Blockchain:\t\t[bold]{py_block_data_hash}[/bold]") console.print( - "[green3]Wir sehen, dass beide Werte übereinstimmen. Das bedeutet, dass der Datensatz " - "erfolgreich abgespeichert wurde und für eine zukünftige Prüfung zur Verfügung steht." + "[green3]Wir sehen, dass beide Werte übereinstimmen. Das bedeutet, dass der " + "Datensatz erfolgreich abgespeichert wurde und für eine zukünftige Prüfung zur " + "Verfügung steht." ) return False -# %% # // app start def app() -> bool: console.rule("[bold]Willkommen beim POLLU-BLOCK-Demonstrator!", style="yellow3") @@ -522,17 +516,20 @@ def app() -> bool: console.rule("\n[bold]Szenario-Auswahl", style="yellow3") console.print("Dieser Demonstrator erlaubt die Wahl zwischen zwei Anwendungsszenarien:") console.print( - " • [bold]Szenario 1: Integritätsprüfung einer bereits verfügbaren Datenreihe[/bold]\n" - " Es wird ein Datenbankeintrag ausgewählt und die Integritätsprüfung\n" + " • [bold]Szenario 1: Integritätsprüfung einer bereits verfügbaren " + "Datenreihe[/bold]\n" + " Es wird ein Datenbankeintrag ausgewählt und die " + "Integritätsprüfung\n" " in einem geführten Prozess veranschaulicht." ) console.print( " • [bold]Szenario 2: Generierung einer neuen Datenreihe[/bold]\n" - " Es wird ein neuer zufälliger Datenbankeintrag generiert und in der\n" - " Blockchain hinzugefügt. Dabei wird live ein neuer Block generiert.\n" - " Anschließend wird anhand des Hashwerts der Datenreihe gezeigt, dass die\n" - " Daten erfolgreich in der Blockchain hinterlegt wurden und für eine\n" - " Integritätsprüfung wie in Szenario 1 zur Verfügung stehen." + " Es wird ein neuer zufälliger Datenbankeintrag generiert und in\n" + " der Blockchain hinzugefügt. Dabei wird live ein neuer Block\n" + " generiert. Anschließend wird anhand des Hashwerts der Datenreihe\n" + " gezeigt, dass die Daten erfolgreich in der Blockchain hinterlegt\n" + " wurden und für eine Integritätsprüfung wie in Szenario 1 zur\n" + " Verfügung stehen." ) console.print( "\nBitte wählen Sie das gewünschte Anwendungsszenario, indem Sie [bold]'1'[/bold] " @@ -622,6 +619,3 @@ def main() -> None: if __name__ == "__main__": main() - - -# %% diff --git a/src/dopt_pollublock_blockchain/constants.py b/src/dopt_pollublock_blockchain/constants.py index 4a5a430..2e2658a 100644 --- a/src/dopt_pollublock_blockchain/constants.py +++ b/src/dopt_pollublock_blockchain/constants.py @@ -1,8 +1,32 @@ from __future__ import annotations import random +from pathlib import Path from typing import Final +from dopt_basics import io as io_ + +# ** paths +p_sensor_data = io_.search_file_iterative( + Path(__file__), + "pollublock*.db", + "dopt_pollublock_blockchain", +) +if p_sensor_data is None: + raise FileNotFoundError("Sensor database not found") +P_SENSOR_DATA: Final[Path] = p_sensor_data + +p_blockchain_data = io_.search_file_iterative( + Path(__file__), + "blockchain.db", + "dopt_pollublock_blockchain", +) +if p_blockchain_data is None: + raise FileNotFoundError("Blockchain database not found") +P_BLOCKCHAIN_DATA: Final[Path] = p_blockchain_data + +P_LIB: Final[Path] = P_SENSOR_DATA.parent + # ** blockchain BLOCKCHAIN_LOADING_BATCH_SIZE: Final[int] = 256 BLOCKCHAIN_DIFFICULTY: Final[int] = 24