#!/usr/bin/env python3
"""Check a CAIN-42 restore-validation result without trusting the site that serves it.

No CAIN imports; needs Python 3.8+ and `cryptography`.

  python3 verify_restore_validation.py https://clawx.click/evidence/restore-validation/latest.json \\
      --key https://cainstudio.online/proof/bundle/claims/evidence-root.pub.json

  SIGNATURE  the result's digest re-hashes and is signed by the evidence-root key fetched from
             ANOTHER site (--key), not the key the result carries
  VERDICT    the verdict is PASS only if every replica passed every check
  ANCHOR     for both clusters (cain-mr-01, cain-mr-02) each backup's head decision is
             compared with the public commit certificate at that height
             (https://cainstudio.online/api/v1/live-cluster/qc/<height>?cluster=<id>).
             This compares decision hashes only; to check the certificate's signatures
             too, use verify_pbft_qc_bundle.py with the cluster's pinned membership.
"""
from __future__ import annotations

import base64
import hashlib
import json
import sys
import urllib.request

from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey

PUBLIC_QC = "https://cainstudio.online/api/v1/live-cluster/qc/{}?cluster={}"


def get(url):
    with urllib.request.urlopen(urllib.request.Request(url, headers={"User-Agent": "cain42-verify"}), timeout=60) as r:
        return json.loads(r.read())


def canon(o) -> bytes:
    return json.dumps(o, sort_keys=True, separators=(",", ":"), ensure_ascii=True).encode()


def main(argv):
    if len(argv) != 3 or argv[1] != "--key":
        print(__doc__); return 2
    doc, key = get(argv[0]), get(argv[2])["public_key_b64"]
    body = {k: v for k, v in doc.items() if k not in ("digest", "evidence_root_public_key_b64", "signature_b64")}
    digest = hashlib.sha256(canon(body)).hexdigest()
    ok_sig = digest == doc.get("digest")
    try:
        Ed25519PublicKey.from_public_bytes(base64.b64decode(key)).verify(base64.b64decode(doc["signature_b64"]), digest.encode())
    except Exception:  # noqa: BLE001
        ok_sig = False
    print(f"[{'PASS' if ok_sig else 'FAIL'}] SIGNATURE  digest {digest[:16]}, evidence-root key {key[:16]}... (from --key)")
    all_pass = all(r.get("pass") and all(c["pass"] for c in r.get("checks", {}).values())
                   for cl in doc["clusters"] for r in cl["replicas"])
    ok_verdict = (doc["verdict"] == "PASS") == all_pass
    print(f"[{'PASS' if ok_verdict else 'FAIL'}] VERDICT    stated {doc['verdict']}, recomputed {'PASS' if all_pass else 'FAIL'}")
    ok_anchor = True
    for cl in doc["clusters"]:
        for r in cl["replicas"]:
            line = f"{cl['cluster_id']} {r['replica']} ({r['region']}, backup held in {r.get('backup_held_in')}) height {r.get('height')}"
            if r.get("height"):
                live = get(PUBLIC_QC.format(r["height"], cl["cluster_id"]))["commit_qc"]["decision_hash"]
                same = live == r.get("head_decision_hash")
                ok_anchor &= same
                print(f"[{'PASS' if same else 'FAIL'}] ANCHOR     {line}: public certificate {live[:16]} == backup {str(r.get('head_decision_hash'))[:16]}")
            else:
                print(f"[----] ANCHOR     {line}: {'PASS' if r.get('pass') else 'FAIL'} as reported (no height to anchor)")
    good = ok_sig and ok_verdict and ok_anchor and doc["verdict"] == "PASS"
    print(f"\n{'VERIFIED' if good else 'INVALID'}: restore validation of {doc['at']}")
    return 0 if good else 1


if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))
