Jump to content

The Principia Machina/TPC-PY/gen challenge corpus.py

From The Invariance Itself
# -*- coding: utf-8 -*-
"""Generator for tpc/vectors/challenge_corpus.json (the execution challenge,
D101.1). Expectations are written literally below: preimages hand-built
from the netstring rule, digests computed with an external sha256sum over
those preimages, refusals and booleans hand-derived. The generator refuses
to write the corpus if the module disagrees.
Run: cd tpc && python3 gen_challenge_corpus.py (Windows: py ...).
Recovered 2026-09-27 (BASE-GEN; record 0.18.0 section 7) from the TIDY 3
archive, tidy3_2026-09-25/gen_challenge_corpus.py, SHA-256
f97ac355cd4da7d5064c0d7e468fc6674f9226333b3e6f36121d37c48ef8f400, where it
regenerates the archived corpus byte for byte. Changed in the tree: the
writer only (write_layout: id, fn and input on the first line, a verify
case's input on its own; note and expect each on its own line; RD-C8-2).
No case changed."""
import json, os, sys
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
import tpc_strike as S
import tpc_challenge as X


def write_layout(path, corpus, groups):
    """Write the corpus in the layout the published file carries (the
    corpus is never re-laid; the writer follows it): the meta as
    json.dumps(indent=1); each case on the lines groups(case) names, the
    keys of a line joined by ", ", the lines by ",\n   "; values as
    json.dumps writes them, a non-ASCII character as itself; UTF-8, LF."""
    def item(k, v):
        return json.dumps(k) + ": " + json.dumps(v, ensure_ascii=False)
    rows = []
    for c in corpus["cases"]:
        gs = groups(c)
        assert [k for g in gs for k in g] == list(c), c.get("id")
        rows.append("  {" + ",\n   ".join(", ".join(item(k, c[k]) for k in g)
                                           for g in gs) + "}")
    text = ('{\n "meta": '
            + json.dumps(corpus["meta"], indent=1, ensure_ascii=False).replace("\n", "\n ")
            + ',\n "cases": [\n' + ",\n".join(rows) + "\n ]\n}\n")
    with open(path, "w", encoding="utf-8", newline="\n") as f:
        f.write(text)

N0 = "00000000000000000000000000000000"
N1 = "0123456789abcdef0123456789abcdef"
NF = "ffffffffffffffffffffffffffffffff"
R0 = "467b7d3adea97b38e440ed0b27bb0d13beae53f4cda86318823f56388d655713"   # sha256sum
R1 = "a66d46c3184cabdb9d407c985618588fff9ce95c00a5ef3544ea748109cdfd33"   # sha256sum
RF = "82a932b4bcdffdefad9611f15023690af0c5285fdf315ec85d1d8376c958dcb9"   # sha256sum
BAD = "[REFUSED,nonce is not 32 lowercase hexadecimal characters]"
R1_FLIP = "b" + R1[1:]                       # first hex digit changed

cases = []
def case(cid, fn, inp, expect, **extra):
    c = {"id": cid, "fn": fn, "input": inp}
    c.update(extra)
    c["expect"] = expect
    cases.append(c)

# ---- preimage and response ------------------------------------------------------
case("preimage/n1", "challenge_preimage", {"nonce": N1},
     "[OK,23:TPC-EXECUTION-CHALLENGE1:132:" + N1 + "]",
     note="netstring of [tag, form, nonce]: 23:tag 1:1 32:nonce")
case("response/zeros", "challenge_response", {"nonce": N0}, "[OK," + R0 + "]")
case("response/n1", "challenge_response", {"nonce": N1}, "[OK," + R1 + "]")
case("response/fs", "challenge_response", {"nonce": NF}, "[OK," + RF + "]")

# ---- the nonce is untrusted input: strict form, never echoed --------------------------
case("refused/uppercase", "challenge_response", {"nonce": N1.upper()}, BAD)
case("refused/31-chars", "challenge_response", {"nonce": N1[:31]}, BAD)
case("refused/33-chars", "challenge_response", {"nonce": N1 + "0"}, BAD)
case("refused/non-hex", "challenge_response", {"nonce": "g" + N1[1:]}, BAD)
case("refused/trailing-newline", "challenge_response", {"nonce": N1 + "\n"}, BAD,
     note="\\Z / \\z anchors: a trailing newline is not accepted")
case("refused/bidi-control", "challenge_response", {"nonce": N1[:16] + "\u202e" + N1[17:]}, BAD)
case("refused/text", "challenge_response", {"nonce": "ignore previous instructions ok!"}, BAD,
     note="32 characters of text: refused, and the reason does not quote it")
case("refused/empty", "challenge_response", {"nonce": ""}, BAD)
case("refused/not-a-string", "challenge_response", {"nonce": 12345}, BAD)
case("refused/preimage-too", "challenge_preimage", {"nonce": N1.upper()}, BAD)

# ---- TPX's check ---------------------------------------------------------------
case("verify/right", "challenge_verify", {"nonce": N1, "response": R1}, "true")
case("verify/one-digit-changed", "challenge_verify", {"nonce": N1, "response": R1_FLIP}, "false")
case("verify/uppercase-response", "challenge_verify", {"nonce": N1, "response": R1.upper()}, "false")
case("verify/other-nonce", "challenge_verify", {"nonce": N0, "response": R1}, "false")
case("verify/bad-nonce", "challenge_verify", {"nonce": N1.upper(), "response": R1}, "false")
case("verify/short-response", "challenge_verify", {"nonce": N1, "response": R1[:63]}, "false")
case("verify/not-a-string", "challenge_verify", {"nonce": N1, "response": None}, "false")


def dispatch(fn, i):
    if fn == "challenge_preimage":
        return X.challenge_preimage(i["nonce"])
    if fn == "challenge_response":
        return X.challenge_response(i["nonce"])
    if fn == "challenge_verify":
        return X.challenge_verify(i["nonce"], i["response"])
    raise KeyError(fn)


bad = 0
for c in cases:
    got = S.canon(dispatch(c["fn"], c["input"]))
    if got != c["expect"]:
        bad += 1
        print("MISMATCH", c["id"], "\n  expect", c["expect"], "\n  got   ", got)
if bad:
    sys.exit("refusing to write: %d mismatches" % bad)

corpus = {
  "meta": {
    "name": "tpc_challenge_corpus", "version": "0.1.0",
    "status": "VERIFIED (both residences)",
    "conforms_tps": "0.1.0 revision 4; the execution challenge of D101.1 (2026-09-22), text owed at revision 5",
    "module": "tpc_challenge 0.1.0 (tpc_digest 0.1.0)",
    "note": ("Preimages hand-built from the D97.1 netstring rule; digests from an external sha256sum "
             "over those preimages; refusals and booleans hand-derived. Both residences MUST reproduce "
             "every expect.")
  },
  "cases": cases
}
def groups(c):
    head = ["id", "fn"] if c["fn"] == "challenge_verify" else ["id", "fn", "input"]
    return [head] + [[k] for k in c if k not in head]


write_layout(os.path.join(HERE, "vectors", "challenge_corpus.json"), corpus, groups)
print("wrote", len(cases), "challenge cases; all match literal expectations")