Skip to content

Proof binding

OCH-1.1 carries verifier outputs in flat, static ABI-encoded publicValues. The hub checks their common prefix before it calls the verifier and releases escrow.

Every verifier family begins publicValues with these three 32-byte words:

abi.encode(
uint256 taskId,
bytes32 inputHash,
bytes32 outputHash,
// program-specific static fields follow
)

The 96-byte prefix connects the proof to:

  • the target on-chain task;
  • the input commitment stored when the task opened; and
  • the deterministic output recorded when settlement completes.

Every additional field uses a static ABI type. The entire encoding stays 32-byte aligned, remains at or below 1,024 bytes, and matches the verifier family’s exact expected length.

For submitResult(taskId, proof, publicValues, outputURI), the deployed hub enforces:

  1. the caller is the selected delegatee and the task is active within submitDeadline;
  2. 0 < proof.length <= 131072;
  3. 96 <= publicValues.length <= 1024 and publicValues.length % 32 == 0;
  4. outputURI is at most 200 bytes;
  5. the verifier family’s exact publicValues length;
  6. the decoded task ID equals the submitted taskId;
  7. the decoded input hash equals task.inputHash;
  8. the decoded output hash is a non-zero bytes32 value; and
  9. the task’s verifier accepts the proof and public values.

The hub also enforces its escrow and verifier-integrity conditions before settlement.

After these checks, the hub stores outputHash, pays the stored delegatee, and emits the full publicValues in TaskCompleted.

STATS_V1 proves statistics over up to 4,096 uint64 values. Its input commitment is:

inputHash = keccak256(abi.encode(values));

The deterministic output contains:

  • n: uint32 — the number of values;
  • sum: uint256 — their sum;
  • min: uint64 — the minimum, or 0 for an empty input; and
  • max: uint64 — the maximum, or 0 for an empty input.

The output commitment is:

statsBytes = abi.encode(n, sum, min, max);
outputHash = keccak256(statsBytes);

STATS_V1 uses this exact 224-byte layout:

abi.encode(
uint256 taskId,
bytes32 inputHash,
bytes32 outputHash,
uint32 n,
uint256 sum,
uint64 min,
uint64 max
)

Seven static ABI words make the layout straightforward to reproduce and verify. The same inputHash appears in task storage and the proof; the Bid’s specHash binds selection to the TaskSpec that names the plaintext commitment. The resulting outputHash appears in both contract storage and TaskCompleted.

See OCH-1.1 protocol for the complete commitment chain and Task lifecycle for the settlement transaction.