{"challengeId":"fastpath","entry":"verifier.mjs","sha256":"8ed924f9659a78ec0fd41d8dde88cd657ca9732a4428067bf05c9f6de92277e5","scoreDirection":"minimize","scoreLabel":"multiplications","seedPolicy":{"mode":"fiat-shamir","testCount":24},"source":"// Frozen verifier for fastpath. Self-contained (no imports): it interprets the\n// candidate's addition-chain artifact and returns a Verdict. It never executes\n// agent code — build() already ran in the sandbox and handed us plain data.\n// This file is part of the challenge's PROTECTED surface.\n\nconst TARGET = 255n; // the exponent E\nconst P = 2147483647n; // 2^31 - 1, a Mersenne prime\nconst MAX_STEPS = 1024;\n\nfunction gate(name, pass, detail) {\n  return { name, pass, detail };\n}\nfunction bad(name, detail) {\n  return { ok: false, score: null, gates: [gate(name, false, detail)], behavior: {}, logs: [] };\n}\n\n// Independent reference: x^exp mod mod by binary exponentiation.\nfunction refModPow(base, exp, mod) {\n  let r = 1n;\n  let b = base % mod;\n  let e = exp;\n  while (e > 0n) {\n    if (e & 1n) r = (r * b) % mod;\n    b = (b * b) % mod;\n    e >>= 1n;\n  }\n  return r;\n}\n\nexport function verify(ctx) {\n  const sol = ctx.solution;\n  if (!sol || typeof sol !== 'object' || !Array.isArray(sol.steps)) {\n    return bad('structure', 'expected { steps: [[i, j], ...] }');\n  }\n  const steps = sol.steps;\n  if (steps.length === 0) return bad('structure', 'chain has no steps');\n  if (steps.length > MAX_STEPS) return bad('structure', `too many steps (> ${MAX_STEPS})`);\n\n  // Build the exponent chain, validating indices as we go.\n  const e = [1n];\n  let doublings = 0;\n  for (let k = 0; k < steps.length; k++) {\n    const s = steps[k];\n    if (!Array.isArray(s) || s.length !== 2) return bad('structure', `step ${k} must be a pair [i, j]`);\n    const [i, j] = s;\n    if (!Number.isInteger(i) || !Number.isInteger(j) || i < 0 || j < 0 || i >= e.length || j >= e.length) {\n      return bad('structure', `step ${k} references an out-of-range index`);\n    }\n    if (i === j) doublings++;\n    e.push(e[i] + e[j]);\n  }\n\n  const reached = e[e.length - 1];\n  if (reached !== TARGET) {\n    return {\n      ok: false,\n      score: null,\n      gates: [gate('reaches-target', false, `final exponent ${reached} (want ${TARGET})`)],\n      behavior: {},\n      logs: [],\n    };\n  }\n\n  // Anti-overfit: evaluate the chain at random bases drawn from the seed and\n  // compare against an independent modpow. A valid chain matches for every base.\n  const rng = ctx.rng;\n  const n = Math.max(1, ctx.testCount | 0);\n  let firstFail = '';\n  for (let t = 0; t < n && !firstFail; t++) {\n    const x = BigInt(2 + Math.floor(rng() * (1 << 20)));\n    const v = [x % P];\n    for (const [i, j] of steps) v.push((v[i] * v[j]) % P);\n    const got = v[v.length - 1];\n    const want = refModPow(x, TARGET, P);\n    if (got !== want) firstFail = `x=${x}: chain gave ${got}, want ${want}`;\n  }\n\n  const gates = [\n    gate('reaches-target', true, `final exponent is ${TARGET}`),\n    gate('evaluates-x^E', !firstFail, firstFail || `${n} random bases reproduce x^${TARGET} mod p`),\n  ];\n  const ok = gates.every((g) => g.pass);\n  return {\n    ok,\n    score: ok ? steps.length : null,\n    gates,\n    behavior: { mults: steps.length, doublings },\n    logs: [`mults=${steps.length} doublings=${doublings}`],\n  };\n}\n"}