idea164-bexproof-verifiable.../bexproof/ledger.py

54 lines
1.7 KiB
Python

"""Tamper-evident ledger scaffold for BeXProof.
This ledger appends entries with a simple hash-chain to provide an auditable trail.
It's a lightweight MVP; a production system would use a proper append-only store.
"""
from __future__ import annotations
import json
import time
import hashlib
from pathlib import Path
from typing import Dict, Any
class TamperProofLedger:
def __init__(self, path: str = "bexproof_ledger.log"):
self.path = Path(path)
self.path.parent.mkdir(parents=True, exist_ok=True)
self._last_hash = self._load_last_hash()
def _load_last_hash(self) -> str:
if not self.path.exists():
return "" # no previous hash
# read last line to pull last hash if present
last = None
with self.path.open("r", encoding="utf-8") as f:
for line in f:
last = line
if not last:
return ""
try:
obj = json.loads(last)
return obj.get("hash", "")
except Exception:
return ""
def _hash_entry(self, entry: Dict[str, Any], prev_hash: str) -> str:
payload = json.dumps(entry, sort_keys=True).encode("utf-8")
data = payload + prev_hash.encode("utf-8")
return hashlib.sha256(data).hexdigest()
def append(self, entry: Dict[str, Any]) -> Dict[str, Any]:
prev_hash = self._last_hash or ""
h = self._hash_entry(entry, prev_hash)
record = {
"entry": entry,
"timestamp": int(time.time() * 1000),
"prev_hash": prev_hash,
"hash": h,
}
with self.path.open("a", encoding="utf-8") as f:
f.write(json.dumps(record, sort_keys=True) + "\n")
self._last_hash = h
return record