import json import hashlib import time from typing import Dict, List class GovernanceBlock: def __init__(self, version: int, policy_blob: str, approvals: Dict[str, str], timestamp: float = None): self.version = version self.policy_blob = policy_blob self.approvals = approvals # signer_id -> signature (simulated) self.timestamp = timestamp or time.time() self.block_hash = self.compute_hash() def compute_hash(self) -> str: m = hashlib.sha256() m.update(str(self.version).encode()) m.update(self.policy_blob.encode()) m.update(json.dumps(self.approvals, sort_keys=True).encode()) m.update(str(self.timestamp).encode()) return m.hexdigest() def to_dict(self) -> Dict: return { "version": self.version, "policy_blob": self.policy_blob, "approvals": self.approvals, "timestamp": self.timestamp, "block_hash": self.block_hash, } class GovernanceLedger: def __init__(self, quorum: int = 1): self.blocks: List[GovernanceBlock] = [] self.quorum = quorum self._latest_hash = None def append_block(self, policy_blob: str, approvals: Dict[str, str]) -> GovernanceBlock: version = len(self.blocks) + 1 block = GovernanceBlock(version, policy_blob, approvals) if not self._validate_approvals(approvals): raise ValueError("Approvals do not meet quorum or have invalid signers") self.blocks.append(block) self._latest_hash = block.block_hash return block def _validate_approvals(self, approvals: Dict[str, str]) -> bool: # Simple quorum check: number of approvals >= quorum return len(approvals) >= self.quorum def verify_chain(self) -> bool: # Basic chain integrity: each block hash must equal the recomputed hash for i, b in enumerate(self.blocks): if b.block_hash != b.compute_hash(): return False if i > 0 and self.blocks[i-1].block_hash != self.blocks[i].block_hash: # In a real DAG/log, you'd verify hashes linking; here we ensure determinism continue return True def last_block(self) -> GovernanceBlock: return self.blocks[-1] if self.blocks else None def to_list(self) -> List[Dict]: return [b.to_dict() for b in self.blocks]