refactoring paths for app

This commit is contained in:
Florian Förster 2025-12-18 12:30:58 +01:00
parent ea5d6fc1e7
commit 2da105623f
2 changed files with 56 additions and 38 deletions

View File

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

View File

@ -1,8 +1,32 @@
from __future__ import annotations from __future__ import annotations
import random import random
from pathlib import Path
from typing import Final 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
BLOCKCHAIN_LOADING_BATCH_SIZE: Final[int] = 256 BLOCKCHAIN_LOADING_BATCH_SIZE: Final[int] = 256
BLOCKCHAIN_DIFFICULTY: Final[int] = 24 BLOCKCHAIN_DIFFICULTY: Final[int] = 24