43 lines
1.2 KiB
Python
43 lines
1.2 KiB
Python
"""Tamper-evident ledger for test attestations (MVP).
|
|
|
|
Implements a simple hash-chain ledger suitable for signing and auditing
|
|
test results.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import json
|
|
from dataclasses import dataclass, asdict, field
|
|
from typing import List, Dict, Any
|
|
|
|
|
|
@dataclass
|
|
class LedgerEntry:
|
|
index: int
|
|
payload: Dict[str, Any]
|
|
prev_hash: str
|
|
hash: str = field(init=False)
|
|
|
|
def __post_init__(self):
|
|
self.hash = self.compute_hash()
|
|
|
|
def compute_hash(self) -> str:
|
|
data = json.dumps({"index": self.index, "payload": self.payload, "prev_hash": self.prev_hash}, sort_keys=True)
|
|
return hashlib.sha256(data.encode("utf-8")).hexdigest()
|
|
|
|
|
|
class Ledger:
|
|
def __init__(self):
|
|
self.entries: List[LedgerEntry] = []
|
|
self._genesis_hash = "0" * 64
|
|
|
|
def add_entry(self, payload: Dict[str, Any]) -> LedgerEntry:
|
|
index = len(self.entries)
|
|
prev_hash = self.entries[-1].hash if self.entries else self._genesis_hash
|
|
entry = LedgerEntry(index=index, payload=payload, prev_hash=prev_hash)
|
|
self.entries.append(entry)
|
|
return entry
|
|
|
|
def get_chain(self) -> List[Dict[str, Any]]:
|
|
return [asdict(e) for e in self.entries]
|