{"challengeId":"sha256-bitcoin","entry":"verifier.mjs","sha256":"c04b1fe0699019c2f4aef22fec57a3224bc1275856ee5e689ef4caae11ddb0c0","scoreDirection":"maximize","scoreLabel":"zero bits","seedPolicy":{"mode":"fixed","testCount":1},"source":"// Frozen verifier for sha256-bitcoin. Self-contained (no imports): a full,\n// standard SHA-256 in pure integer (Uint32) ops, so the result is byte-identical\n// on every conforming engine — fully deterministic. This is the LITERAL Bitcoin\n// mining puzzle: the agent submits a message; we take the DOUBLE SHA-256 (exactly\n// what Bitcoin does) and score the number of LEADING ZERO BITS of the digest.\n// More leading zeros = a rarer hash = exponentially more work, just like raising\n// the mining difficulty. No hidden input, nothing to overfit — seedPolicy \"fixed\".\n\nconst K = [\n  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n  0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n  0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n  0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n  0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n  0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n  0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n  0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\n];\n\nfunction sha256(bytes) {\n  const H = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19];\n  const l = bytes.length;\n  const bitLen = l * 8;\n  const withOne = l + 1;\n  const pad = (56 - (withOne % 64) + 64) % 64;\n  const total = withOne + pad + 8;\n  const m = new Uint8Array(total);\n  m.set(bytes);\n  m[l] = 0x80;\n  const hi = Math.floor(bitLen / 0x100000000);\n  const lo = bitLen >>> 0;\n  m[total - 8] = (hi >>> 24) & 0xff; m[total - 7] = (hi >>> 16) & 0xff; m[total - 6] = (hi >>> 8) & 0xff; m[total - 5] = hi & 0xff;\n  m[total - 4] = (lo >>> 24) & 0xff; m[total - 3] = (lo >>> 16) & 0xff; m[total - 2] = (lo >>> 8) & 0xff; m[total - 1] = lo & 0xff;\n  const w = new Uint32Array(64);\n  const rotr = (x, n) => (x >>> n) | (x << (32 - n));\n  for (let i = 0; i < total; i += 64) {\n    for (let t = 0; t < 16; t++) w[t] = ((m[i + 4 * t] << 24) | (m[i + 4 * t + 1] << 16) | (m[i + 4 * t + 2] << 8) | m[i + 4 * t + 3]) >>> 0;\n    for (let t = 16; t < 64; t++) {\n      const s0 = rotr(w[t - 15], 7) ^ rotr(w[t - 15], 18) ^ (w[t - 15] >>> 3);\n      const s1 = rotr(w[t - 2], 17) ^ rotr(w[t - 2], 19) ^ (w[t - 2] >>> 10);\n      w[t] = (w[t - 16] + s0 + w[t - 7] + s1) >>> 0;\n    }\n    let a = H[0], b = H[1], c = H[2], d = H[3], e = H[4], f = H[5], g = H[6], h = H[7];\n    for (let t = 0; t < 64; t++) {\n      const S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);\n      const ch = (e & f) ^ (~e & g);\n      const t1 = (h + S1 + ch + K[t] + w[t]) >>> 0;\n      const S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);\n      const maj = (a & b) ^ (a & c) ^ (b & c);\n      const t2 = (S0 + maj) >>> 0;\n      h = g; g = f; f = e; e = (d + t1) >>> 0; d = c; c = b; b = a; a = (t1 + t2) >>> 0;\n    }\n    H[0] = (H[0] + a) >>> 0; H[1] = (H[1] + b) >>> 0; H[2] = (H[2] + c) >>> 0; H[3] = (H[3] + d) >>> 0;\n    H[4] = (H[4] + e) >>> 0; H[5] = (H[5] + f) >>> 0; H[6] = (H[6] + g) >>> 0; H[7] = (H[7] + h) >>> 0;\n  }\n  const out = new Uint8Array(32);\n  for (let i = 0; i < 8; i++) { out[4 * i] = (H[i] >>> 24) & 0xff; out[4 * i + 1] = (H[i] >>> 16) & 0xff; out[4 * i + 2] = (H[i] >>> 8) & 0xff; out[4 * i + 3] = H[i] & 0xff; }\n  return out;\n}\n\nfunction leadingZeroBits(digest) {\n  let bits = 0;\n  for (const byte of digest) {\n    if (byte === 0) { bits += 8; continue; }\n    let b = byte, n = 0;\n    while ((b & 0x80) === 0) { n++; b <<= 1; }\n    return bits + n;\n  }\n  return bits;\n}\n\nfunction gate(name, pass, detail) { return { name, pass, detail }; }\nfunction bad(name, detail) { return { ok: false, score: null, gates: [gate(name, false, detail)], behavior: {}, logs: [] }; }\n\nexport function verify(ctx) {\n  const sol = ctx.solution;\n  const message = sol && typeof sol === 'object' ? sol.message : undefined;\n  if (typeof message !== 'string' || !/^[0-9a-fA-F]*$/.test(message) || message.length % 2 !== 0) {\n    return bad('structure', 'expected { message: \"<even-length hex string>\" }');\n  }\n  if (message.length > 256) return bad('structure', 'message must be at most 128 bytes (256 hex chars)');\n  const bytes = new Uint8Array(message.length / 2);\n  for (let i = 0; i < bytes.length; i++) bytes[i] = parseInt(message.substr(i * 2, 2), 16);\n  const digest = sha256(sha256(bytes)); // Bitcoin uses double SHA-256\n  const zeroBits = leadingZeroBits(digest);\n  let hex = '';\n  for (const b of digest) hex += b.toString(16).padStart(2, '0');\n  return {\n    ok: true,\n    score: zeroBits,\n    gates: [gate('valid-message', true, `double-SHA-256 digest ${hex.slice(0, 16)}… has ${zeroBits} leading zero bits`)],\n    behavior: { zeroBits, bytes: bytes.length },\n    logs: [`leading zero bits=${zeroBits}`],\n  };\n}\n"}