#!/usr/bin/env python3
# WhaleRoom receipt-chain verifier — stdlib only, no dependencies. Recomputes EVERY hash from the
# PUBLISHED data so you never take WhaleRoom's word for it.
#
#   python3 verify.py                         # verify the whole live chain at whaleroomhq.com/proof
#   python3 verify.py --base ./proof          # verify a local copy (a directory)
#
# It proves TIMING + INTEGRITY only: that the published bytes are unchanged and correctly hash-chained.
# It does NOT prove the inputs are true/fair or that the signals are profitable. And always ALSO check each
# receipt_hash against its Telegram witness post — the /proof/ page can be faked by the host; the witness cannot.
import sys, json, hashlib, os
try:
    import urllib.request
except Exception:
    urllib = None

def canon(obj):
    # MUST byte-match PHP json_encode(JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE) over recursively ksort-ed keys.
    return json.dumps(obj, sort_keys=True, separators=(',', ':'), ensure_ascii=False)

def sha(b):
    if isinstance(b, str):
        b = b.encode('utf-8')
    return hashlib.sha256(b).hexdigest()

def fetch(base, path):
    if base.startswith('http'):
        return urllib.request.urlopen(base.rstrip('/') + '/' + path, timeout=25).read()
    with open(os.path.join(base, path), 'rb') as f:
        return f.read()

def main():
    base = 'https://whaleroomhq.com/proof'
    args = sys.argv[1:]
    i = 0
    while i < len(args):
        if args[i] == '--base':
            base = args[i + 1]; i += 2
        else:
            i += 1
    receipts = [json.loads(l) for l in fetch(base, 'receipts.jsonl').decode('utf-8').splitlines() if l.strip()]
    ruleset_bytes = fetch(base, 'ruleset/v1.json')
    ok = True
    prev = '0' * 64
    for idx, rc in enumerate(receipts):
        rh = rc.get('receipt_hash')
        env = {k: v for k, v in rc.items() if k != 'receipt_hash'}
        hash_ok  = (sha(canon(env)) == rh)
        chain_ok = (rc.get('prev') == prev)
        parts = ['hash=' + ('OK' if hash_ok else 'FAIL'), 'chain=' + ('OK' if chain_ok else 'FAIL')]
        step_ok = hash_ok and chain_ok
        if rc.get('type') == 'genesis':
            rs_ok = (sha(ruleset_bytes) == rc.get('ruleset_sha256'))
            parts.append('ruleset=' + ('OK' if rs_ok else 'FAIL')); step_ok = step_ok and rs_ok
        else:
            d = rc.get('date')
            cons = fetch(base, 'data/consensus-%s.jsonl' % d)
            cons = cons[:-1] if cons.endswith(b'\n') else cons   # hashed WITHOUT the trailing newline
            cons_ok = (sha(cons) == rc.get('consensus_sha256'))
            parts.append('consensus=' + ('OK' if cons_ok else 'FAIL')); step_ok = step_ok and cons_ok
            if rc.get('raw_snapshot_sha256'):
                try:
                    raw_ok = (sha(fetch(base, 'data/pos-%s.jsonl' % d)) == rc.get('raw_snapshot_sha256'))
                    parts.append('raw_snapshot=' + ('OK' if raw_ok else 'FAIL')); step_ok = step_ok and raw_ok
                except Exception as e:
                    parts.append('raw_snapshot=SKIP')
        ok = ok and step_ok
        print('[%d] %-7s %-10s %s' % (idx, rc.get('type', ''), rc.get('date', ''), '  '.join(parts)))
        prev = rh
    print('\nRESULT:', 'ALL CHECKS PASSED (%d receipts)' % len(receipts) if ok else 'VERIFICATION FAILED')
    print('This verifies TIMING + INTEGRITY only. Cross-check each receipt_hash against its Telegram witness post.')
    sys.exit(0 if ok else 2)

if __name__ == '__main__':
    main()
