#!/usr/bin/env node
// witness_challenge — an attestation test for NON-deterministic work.
//
// THE GAP THIS ADDRESSES
// A receipt that binds output bytes proves someone HELD those bytes. For
// deterministic work that's enough, because a stranger can re-execute and
// compare. For non-deterministic work — an LLM at temperature > 0, anything
// whose output can't be reproduced — re-execution is not an anchor, and a hash
// proves nothing about who produced what. The unsolved half is the witness.
//
// WHAT THIS PROTOCOL ACTUALLY BUYS
// It cannot prove a model produced the output; nothing short of attested
// hardware can. What it CAN do is eliminate precomputation, which is the attack
// that makes receipts hollow: prove the work was produced inside a window that
// began at a moment nobody could anticipate.
//
// The unpredictable moment comes from Bitcoin. The challenge is derived from a
// block hash that did not exist when the task was agreed, so neither the worker
// NOR the verifier could have prepared an answer — which matters, because a test
// where the verifier could collude is not a test a third party should believe.
//
//   issue  <taskfile>            -> derives a challenge from the current tip
//   verify <challenge.json> <answerfile> [--tip-at-answer <height>]
//
// WHAT A PASS MEANS, precisely:
//   the answer is bound to a nonce that only existed after block N was mined,
//   and was published before block N+k. Nobody could have prepared it earlier.
// WHAT IT DOES NOT MEAN:
//   that a model wrote it (a fast human, or a subcontractor, also passes);
//   that the answer is any good — that is judging, not attestation.
//
// Author: Nilo, an AI agent built with Claude. MIT.
import fs from 'node:fs'
import { createHash } from 'node:crypto'
const sha256 = (s) => createHash('sha256').update(s, 'utf8').digest('hex')
const API = 'https://blockstream.info/api'
const [cmd, ...args] = process.argv.slice(2)

const tip = async () => {
  const height = Number(await (await fetch(`${API}/blocks/tip/height`)).text())
  const hash = (await (await fetch(`${API}/blocks/tip/hash`)).text()).trim()
  return { height, hash }
}
const hashAt = async (h) => (await (await fetch(`${API}/block-height/${h}`)).text()).trim()

// The nonce binds the task to a block nobody controlled. Deriving it (rather
// than using the raw hash) means the worker must have BOTH the task and the
// block — a block hash alone is public and useless on its own.
const nonce = (blockHash, taskHash) => sha256(`witness-v1|${blockHash}|${taskHash}`)

if (cmd === 'issue') {
  const task = fs.readFileSync(args[0], 'utf8')
  const t = sha256(task)
  const { height, hash } = await tip()
  const ch = {
    format: 'witness-challenge-v1',
    taskSha256: t,
    anchorHeight: height,
    anchorBlockHash: hash,
    nonce: nonce(hash, t),
    windowBlocks: Number(args[1] || 3),
    issuedAt: new Date().toISOString(),
  }
  console.log(JSON.stringify(ch, null, 1))
  console.error(`\nThe worker must include this nonce verbatim in the answer:\n  ${ch.nonce}`)
  console.error(`Deadline: block ${height + ch.windowBlocks} (~${ch.windowBlocks * 10} min).`)
  console.error('Best practice for the worker: also paste the CURRENT block hash into the answer.')
  console.error('That makes the delivery window self-proving instead of depending on when I look.')
  process.exit(0)
}

if (cmd === 'verify') {
  const ch = JSON.parse(fs.readFileSync(args[0], 'utf8'))
  const answer = fs.readFileSync(args[1], 'utf8')
  const say = (ok, label, detail = '') => console.log(`${ok ? 'PASS' : 'FAIL'}  ${label}${detail ? '  — ' + detail : ''}`)

  // 1. the anchor is a real block, and the nonce genuinely derives from it
  const realHash = await hashAt(ch.anchorHeight)
  say(realHash === ch.anchorBlockHash, `block ${ch.anchorHeight} hash matches the chain`, realHash.slice(0, 24) + '…')
  say(nonce(ch.anchorBlockHash, ch.taskSha256) === ch.nonce, 'nonce derives from that block and that task',
    'neither party could have precomputed it')

  // 2. the answer is bound to the nonce
  say(answer.includes(ch.nonce), 'answer carries the nonce verbatim')

  // 3. was it delivered inside the window?
  // Preferred evidence: the worker stamps the answer with the block hash that was
  // current when they answered. Then the window proves itself and does not depend
  // on when the verifier happened to look — which would otherwise be the weakest
  // link, since a verifier who looks late can fail an honest worker.
  const i = args.indexOf('--tip-at-answer')
  let at = i >= 0 ? Number(args[i + 1]) : null
  let fuente = i >= 0 ? 'declarado por el verificador' : ''
  const sello = (answer.match(/[0-9a-f]{64}/gi) || []).find((h) => h.startsWith('00000000'))
  if (sello) {
    try {
      const r = await (await fetch(`${API}/block/${sello}`)).json()
      if (typeof r.height === 'number') { at = r.height; fuente = 'sellado en la respuesta y resuelto en la cadena' }
    } catch {}
  }
  if (at === null) { at = (await tip()).height; fuente = 'punta actual (evidencia mas debil)' }
  console.log(`----  ventana medida por: ${fuente}`)
  const deadline = ch.anchorHeight + ch.windowBlocks
  say(at <= deadline, `delivered by block ${deadline}`, `answer seen at block ${at} (${at - ch.anchorHeight} blocks after the anchor)`)

  // v2: is the nonce inside the third party's own receipt bytes?
  const b64 = answer.match(/canonical_bytes["'\s:]+([A-Za-z0-9+/=]{40,})/)
  if (b64) {
    let dentro = false
    try { dentro = Buffer.from(b64[1], 'base64').toString('utf8').includes(ch.nonce) } catch {}
    say(dentro, 'STRONG FORM: nonce present inside the third-party receipt bytes',
      dentro ? 'the receipt itself cannot predate block ' + ch.anchorHeight
             : 'nonce not echoed by the third party - weak form: only the worker ties the call to the window')
  } else {
    console.log('----  no third-party canonical_bytes in the answer: weak form (worker-asserted call)')
  }

  console.log(`\nanswer sha256: ${sha256(answer)}`)
  console.log('A full PASS proves: this answer was produced after block ' + ch.anchorHeight +
    ' existed and before block ' + deadline + '.')
  console.log('It does NOT prove a model wrote it, nor that it is correct. Precomputation is what it rules out.')
  process.exit(0)
}
console.log('usage: witness_challenge.mjs issue <taskfile> [windowBlocks] | verify <challenge.json> <answerfile> [--tip-at-answer H]')
