{
  "type": "ZkVmReceipt",
  "system": "risc0",
  "receiptFormat": "groth16-bn254",
  "imageId": "sha256:a1a0bc89b5b1febaeda3519f6dbade0fa5ac16beeb143c4e1b01689573567bc6",
  "seal": "INeYg8wvmehr2Zk6oi8dNRmKqm/iOL50gg+Y5UBptGQLfKYmfzOqdpPtNXnAcBDx/JfM62rbf2qS9dOjTsJI/wqo3bKTd4StqeFtKHog4SVSeoRGYB/YSoLy4CGIdZMZAfQmxp008XwmVRwAM2rgkNuGUEIUSvDXe3SLaY/fEwQEg1HeYMS6lyCqjdKMh6a+HtKh7vk9PUP6RY654MiQUCwlVa+8Jvl5M/XULIq6QwnFxAxRhOOYgMks3EqlJMfcFouno74QYA8rw+9s7NEfZc0anhOi/+rdIp07uJVeJMURAyXZP/dLttJyWQf0lARtASeaGimzFu1ifVUkFkBM4g==",
  "journal": {
    "chaingraph_version": "0.4.0",
    "kernel_digest": "sha256:8f2fed1a5536e8df4848f7026a0126867f1ee41058c3aac5f5bbaf57e9dc5cae",
    "output": {
      "challenge": {
        "reasons": [
          "challenge.id is required and must be non-empty -- this node never mints an authoritative id (that would require holding a server-side HMAC secret, out of scope by the red lines), the caller’s own server issues and binds it per draft-httpauth-payment-00",
          "challenge.realm is required",
          "challenge.intent must be \"session\" or \"charge\"",
          "challenge.amount is required",
          "challenge.currency is required",
          "challenge.recipient is required (a receiving address string -- never a private key; this node never holds or generates key material, and never becomes the merchant of record on the caller’s behalf)",
          "challenge.escrowContract is required and must be a 20-byte hex address (methodDetails.escrowContract per the Tempo session/charge method spec)"
        ],
        "verdict": "CHALLENGE_INDETERMINATE",
        "wwwAuthenticate": null
      },
      "memo": {
        "decodesUtf8": null,
        "isZero": null,
        "reasons": [],
        "referenceMatch": null,
        "value": null,
        "verdict": "MEMO_SKIPPED"
      },
      "reasons": [
        "challenge.id is required and must be non-empty -- this node never mints an authoritative id (that would require holding a server-side HMAC secret, out of scope by the red lines), the caller’s own server issues and binds it per draft-httpauth-payment-00",
        "challenge.realm is required",
        "challenge.intent must be \"session\" or \"charge\"",
        "challenge.amount is required",
        "challenge.currency is required",
        "challenge.recipient is required (a receiving address string -- never a private key; this node never holds or generates key material, and never becomes the merchant of record on the caller’s behalf)",
        "challenge.escrowContract is required and must be a 20-byte hex address (methodDetails.escrowContract per the Tempo session/charge method spec)"
      ],
      "receipt": {
        "paymentReceipt": null,
        "verdict": "RECEIPT_WITHHELD_CHALLENGE_INDETERMINATE"
      },
      "scope_note": "Verifies a Tempo Machine Payments Protocol (MPP) session voucher offline (ecrecover, no RPC/database lookup), validates a TIP-20 32-byte memo structurally, and validates/renders a merchant-side HTTP 402 Payment challenge plus a Payment-Receipt-shaped binding to an optional subject execution_hash. Never holds a private key, never signs, never escrows third-party funds, never initiates a payment, never operates a live endpoint -- every field is caller-supplied and echoed, nothing is fetched or resolved independently. Sources: github.com/tempoxyz/mpp-specs (MIT/Apache-2) and github.com/tempoxyz/tempo tips/verify/src/TIP20ChannelReserve.sol (primary contract source for the Voucher typehash and ChannelState fields).",
      "voucher": {
        "channelDeposit": "10000",
        "channelId": "0x1111111111111111111111111111111111111111111111111111111111111111",
        "channelSettled": "0",
        "cumulativeAmount": "0",
        "deltaAmount": "0",
        "digest": "0x120f55f8a7882e910a610eee39804322550259090a4c5692100f216927c14752",
        "expectedSigner": "0x7e5f4552091a69125d5dfcb7b8c2659029395bdf",
        "onChainSettleNote": "Off-chain MPP session acceptance and on-chain TIP20ChannelReserve.settle() apply the SAME cumulativeAmount at two different layers with different strictness: settle() reverts AmountNotIncreasing when cumulativeAmount <= channel.settled (strict increase only), while the off-chain session server treats cumulativeAmount === settled as an idempotent retry (safe to accept, no double-charge). This node reports the off-chain verdict.",
        "protocolVersion": "v2",
        "reasons": [],
        "recoveredSigner": "0x7e5f4552091a69125d5dfcb7b8c2659029395bdf",
        "verdict": "VOUCHER_IDEMPOTENT_RETRY"
      }
    }
  }
}
