The Principia Machina/TPC-PY/gen challenge corpus.py
Appearance
# -*- 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")