#!/usr/bin/env python3
"""Standalone verifier for BTI protocol_hash / grid_hash.

Recomputes the two hashes BTI publishes for a frozen study protocol, using the exact
canonicalisation the freeze harness uses (harness/lib/hashing.py in bridgham-lab, private):

    sha256( json.dumps(obj, sort_keys=True, separators=(",", ":")).encode() )

protocol_hash is computed over the *parsed YAML object* for the whole protocol.yaml file,
not over the file's raw bytes -- so `shasum -a 256 protocol.yaml` will NOT reproduce it.
grid_hash is the same recipe applied only to the protocol's `grid` list.

Requires only the Python standard library plus PyYAML (`pip install pyyaml`) -- no
checkout of the private bridgham-lab repository, no other dependency.

Usage:
    python3 verify_protocol_hash.py path/to/protocol.yaml
"""
import hashlib
import json
import sys

try:
    import yaml
except ImportError:
    sys.exit(
        "error: this script requires PyYAML. Install it with:\n"
        "    pip install pyyaml"
    )


def canonical_bytes(obj) -> bytes:
    return json.dumps(obj, sort_keys=True, separators=(",", ":")).encode()


def sha256_hex(obj) -> str:
    return hashlib.sha256(canonical_bytes(obj)).hexdigest()


def main() -> int:
    if len(sys.argv) != 2:
        print(f"usage: {sys.argv[0]} path/to/protocol.yaml", file=sys.stderr)
        return 2

    path = sys.argv[1]
    with open(path, "r") as f:
        protocol = yaml.safe_load(f)

    if "grid" not in protocol:
        sys.exit(f"error: {path} has no top-level 'grid' key; is this a protocol.yaml file?")

    protocol_hash = sha256_hex(protocol)
    grid_hash = sha256_hex(protocol["grid"])

    print(f"protocol_hash: {protocol_hash}")
    print(f"grid_hash:     {grid_hash}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
