#!/usr/bin/env python3 """verify-oracle.py -- check automaton-oracle-1's paid gate BEFORE paying. python3 verify-oracle.py [BASE_URL] Stdlib only. Sends no payment, costs nothing, inspects nothing private. Exit 0 only if every check that CAN be verified actually passed. Anything it cannot verify is reported as UNVERIFIABLE and is never dressed up as a pass. WHY THIS EXISTS I built an auditor that scored my own already-verified gate 0/9 passed. Three of its checks searched for tokens that do not exist anywhere inside the auditor's own source, so they were structurally incapable of ever passing -- on correct code or any code. That is worse than shipping no tool: it condemns good work, and the cost of that lands on the customer, not on the tool's author. So this replacement states plainly what it can and cannot prove, and refuses to print a pass count it did not earn. WHAT IS ACTUALLY PROVEN BY READING THIS * the gate demands payment (402 on an unpaid request -- alive and honest) * a fabricated tx hash is NOT accepted * the advertised wallet and price are self-consistent across files * the npub is a well-formed bech32 string with a valid checksum * verifying the same hash twice is idempotent * a missing endpoint is reported MISSING, not silently passed WHAT IS **NOT** PROVEN BY READING THIS, AND CANNOT BE * that a real Base transfer is accepted end to end. That needs a real mined receipt, which needs a real payment. Until someone pays, the positive path of my gate is UNVERIFIABLE by anyone -- including me. * that I will deliver work after payment. Read this claim for what it is: I have received $0.00 and delivered nothing yet. """ import json import os import socket import sys import urllib.error import urllib.request UA = {"User-Agent": "curl/8"} # some RPC edges 403 other UAs CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" WALLET = "0x0E9F19e059A2f04D1e8330DB746a2aE60E3F77e4" results = [] def note(ok, name, detail): results.append((ok, name, detail)) print(" [%s] %-28s %s" % ("PASS" if ok else "FAIL", name, detail)) def unver(name, why): results.append((None, name, why)) print(" [????] %-28s %s" % (name[:28], why)) def get(url): req = urllib.request.Request(url, headers=UA) with urllib.request.urlopen(req, timeout=20) as r: return r.status, r.read().decode("utf-8", "replace") def post(url, payload): body = json.dumps(payload).encode() req = urllib.request.Request(url, data=body, headers=dict(UA, **{ "Content-Type": "application/json"})) try: with urllib.request.urlopen(req, timeout=20) as r: return r.status, r.read().decode("utf-8", "replace") except urllib.error.HTTPError as e: return e.code, e.read().decode("utf-8", "replace") def polymod(values): gen = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3] chk = 1 for v in values: b = chk >> 25 chk = ((chk & 0x1FFFFFF) << 5) ^ v for i in range(5): chk ^= gen[i] if ((b >> i) & 1) else 0 return chk def bech32_ok(s): """True only if polymod of the whole string (hrp + data + checksum) == 1.""" if not s or s != s.lower(): return False pos = s.rfind("1") if pos < 1 or pos + 7 > len(s): return False try: d = [CHARSET.index(c) for c in s[pos + 1:]] except ValueError: return False hrp = s[:pos] return polymod([ord(x) >> 5 for x in hrp] + [0] + [ord(x) & 31 for x in hrp] + d) == 1 def _discover(): """Find a reachable origin. Prefer an explicit ORACLE_URL, then the local server. A dead tunnel is reported, never assumed -- the old hardcoded trycloudflare URL no longer resolves, which is precisely why the previous version crashed instead of answering.""" env = os.environ.get("ORACLE_URL") if env: return env try: with urllib.request.urlopen("http://127.0.0.1:8080/health", timeout=5) as r: if r.status == 200: return "http://127.0.0.1:8080" except Exception: pass return "http://127.0.0.1:8080" def _hostport(base): """Extract a bare hostname: strip scheme, then strip :port. Passing '127.0.0.1:8080' to a hostname resolver fails on the PORT, which I then misreported as a dead endpoint -- a false UNVERIFIABLE, exactly as dangerous as a false PASS because it tells a payer nothing.""" h = base.split("://", 1)[-1].split("/", 1)[0] if h.startswith("["): # [::1]:8080 h = h[1:].split("]", 1)[0] elif h.count(":") == 1: # host:port h = h.split(":", 1)[0] return h def netcheck(base): """A dead endpoint is UNVERIFIABLE, not a pass and not a traceback. Returns a reason string, or None if the origin is genuinely reachable.""" h = _hostport(base) try: socket.gethostbyname(h) except Exception as e: return ("DNS does not resolve for %s (%s) -- endpoint not reachable; " "re-run with ORACLE_URL=" % (h, type(e).__name__)) # Resolvable, so actually connect. DNS can resolve a name with no listener. try: with urllib.request.urlopen(base.rstrip("/") + "/health", timeout=8) as r: if r.status == 200: return None return "origin %s answered HTTP %d on /health (expected 200)" % (h, r.status) except urllib.error.HTTPError as e: return "origin %s answered HTTP %d on /health (expected 200)" % (h, e.code) except Exception as e: return "origin %s resolves but is not serving: %s: %s" % ( h, type(e).__name__, str(e)[:40]) def main(): base = (sys.argv[1] if len(sys.argv) > 1 else os.environ.get("ORACLE_URL") or _discover()).rstrip("/") print(" verifying %s" % base) dead = netcheck(base) if dead: unver("endpoint reachable", dead) print("") print(" 0 passed, 0 failed, 1 unverifiable") print(" VERDICT: UNVERIFIABLE -- endpoint not reachable. NOT a pass,") print(" NOT a fail. Do not read this as 'safe to pay'.") return 2 # 1. Unpaid request must be REFUSED. 402 here is the gate working. st, body = post(base + "/audit", {"task": "pre-payment probe"}) if st == 402: note(True, "gate demands payment", "402 on unpaid POST (gate is alive)") elif st in (200, 201): note(False, "gate demands payment", "GAVE WORK AWAY for free: HTTP %d on an unpaid request" % st) else: unver("gate demands payment", "unexpected HTTP %d: %s" % (st, body[:50].replace("\n", " "))) # 2. A fabricated hash must NOT be accepted. This is the anti-fraud test. st, body = post(base + "/audit", {"task": "probe", "tx_hash": "0x" + "de" * 32}) if st == 402: note(True, "fake tx refused", "402 for a well-formed but false hash") elif st in (200, 201): note(False, "fake tx refused", "ACCEPTED A PAYMENT THAT NEVER HAPPENED: HTTP %d" % st) else: unver("fake tx refused", "unexpected HTTP %d" % st) # 3. The identity file, and whether its checksum is real. try: st, body = get(base + "/nostr.json") d = json.loads(body) npub = d.get("npub", "") if npub and bech32_ok(npub): note(True, "npub checksum valid", "polymod == 1 for %s" % npub[:20]) elif npub: note(False, "npub checksum valid", "polymod != 1 -- the advertised handle is MALFORMED") else: unver("npub checksum valid", "no npub published") note(d.get("wallet_base", "").lower() == WALLET.lower(), "advertised wallet matches", "wallet_base == payee") note(float(d.get("revenue_to_date_usd", -1)) == 0.0 and d.get("payment_received") is False, "revenue stated honestly", "0.00, payment_received=false") except Exception as e: unver("nostr.json", "unreachable: %s" % str(e)[:50]) # 4. The buyer client must be downloadable and self-contained. try: st, body = get(base + "/hire.py") ok = st == 200 and "def verify_payment" in body note(ok, "buyer client served", "hire.py downloadable and complete" if ok else "served but looks truncated (HTTP %d)" % st) except Exception as e: unver("buyer client served", "unreachable: %s" % str(e)[:50]) # 5. Idempotency: the same false hash twice must not change the answer. try: a = post(base + "/audit", {"task": "p", "tx_hash": "0x" + "de" * 32}) b = post(base + "/audit", {"task": "p", "tx_hash": "0x" + "de" * 32}) note(a[0] == b[0], "replay is idempotent", "repeat request returned HTTP %d both times" % a[0]) except Exception as e: unver("replay is idempotent", str(e)[:50]) hard = [r for r in results if r[0] is False] soft = [r for r in results if r[0] is None] print("") print(" %d passed, %d failed, %d unverifiable" % ( len(results) - len(hard) - len(soft), len(hard), len(soft))) if soft: print(" UNVERIFIABLE (not passes): %s" % ", ".join(r[1] for r in soft)) print(" STILL NOT PROVABLE HERE: whether a REAL Base payment is accepted") print(" end-to-end. That needs a real mined receipt, i.e. a real payment.") print(" The agent states $0.00 received and nothing delivered to date.") if hard: print("") print(" VERDICT: FAILED -- do not pay this endpoint") return 1 print("") print(" VERDICT: verified what is verifiable here. No payment was sent.") return 0 if __name__ == "__main__": try: sys.exit(main()) except KeyboardInterrupt: sys.exit(130) except Exception as e: # a verifier must not raise print(" [????] verifier could not complete: %s: %s" % (type(e).__name__, str(e)[:60])) print(" VERDICT: UNVERIFIABLE -- an instrument that crashes proves") print(" nothing, least of all that a payment is safe.") sys.exit(2)