Skip to content

Refactor public IO commit flow: add digest-based ceno_rt::commit + PUB_IO_COMMIT precompile #1280

Description

@hero78119

Problem

Today ceno_rt::commit compares a guest value against preloaded public IO memory (pubio_read_slice) and asserts equality in guest runtime. This ties commit semantics to a public memory region and a dedicated public-io circuit path.

Current behavior is centered around:

  • ceno_rt/src/mmio.rs (commit<T>, pubio_read_slice)
  • Public IO initialization in host/e2e paths (ceno_host, ceno_zkvm/src/e2e.rs)
  • PublicValues.public_io: Vec<u32> in ceno_zkvm/src/scheme.rs

We want to move to digest-based commit semantics handled by syscall + precompile, and remove the old public IO memory/circuit flow.

Proposal

1) Rewrite guest API: ceno_rt::commit

  • Change ceno_rt::commit signature to accept raw bytes:
    • pub fn commit(data: &[u8])
  • Internally:
    • Compute Keccak digest (via tiny_keccak)
    • Convert digest into [u32; 16], where each element stores one u16 limb in the low 16 bits
  • Send digest limbs through a new syscall (PUB_IO_COMMIT-style syscall)

2) Add syscall + precompile path

  • Introduce new syscall for public-io commit digest submission
  • Implement new precompile: pubio_commit
  • Assume syscall payload is always Keccak digest limbs ([u32; 16] with 16-bit limbs)

3) Extend public values

  • Update PublicValues to include extra digest field:
    • e.g. pubio_digest: [u32; 16]
  • Wire this through proving/verification/public input queries as needed

4) Update host/CLI/e2e input preparation

  • In ceno_zkvm/src/e2e.rs and ceno_cli, prepare public io from args by:
    • serializing bytes (same format as guest input expectation)
    • computing Keccak digest
    • converting to [u32; 16] limbs
  • Pass digest limbs into PublicValues instead of raw public IO memory vector semantics

5) Remove old public IO circuit/memory path

  • Remove original public-io-memory-related circuit plumbing now replaced by precompile
  • Remove dependencies on loading/verifying public IO via dedicated memory range where no longer required

Scope / Affected Areas

  • Runtime guest API:
    • ceno_rt/src/mmio.rs
    • ceno_rt/src/lib.rs exports
  • Syscall/ecall handling:
    • new syscall opcode/plumbing
    • instruction wiring near existing ecall paths (see ceno_zkvm/src/instructions/riscv/ecall/halt.rs for style/context)
  • Precompile:
    • add pubio_commit module and registration
  • Public values and PI query:
    • ceno_zkvm/src/scheme.rs (PublicValues, constructor, index/query, MLE usage if needed)
  • Execution pipeline:
    • ceno_zkvm/src/e2e.rs
    • ceno_cli public io arg handling (ceno_cli/src/commands/common_args/ceno.rs)
  • Cleanup:
    • remove/deprecate old public-io-specific circuit/memory plumbing

Implementation Checklist

  • Change ceno_rt::commit API to commit(&[u8])
  • Add Keccak hashing + digest-to-[u32;16] limb conversion in runtime
  • Define and wire new PUB_IO_COMMIT syscall
  • Implement/register pubio_commit precompile
  • Add digest field to PublicValues and update constructors/consumers
  • Update e2e.rs to compute and pass digest limbs
  • Update ceno-cli to hash public io args and produce digest limbs
  • Remove old public io memory-based circuit path
  • Update guest examples (e.g. examples/examples/fibonacci.rs) to new commit usage

Acceptance Criteria

  • Guest programs can call ceno_rt::commit(&[u8]) without reading from public-io memory
  • Prover/verifier agree on public commitment via digest limbs ([u32;16], low-16-bit populated)
  • PublicValues includes commitment digest and verification uses it
  • CLI/e2e public input path produces identical digest/limbs to runtime rules
  • Old public io memory circuit path is removed and no longer required
  • Existing e2e flows pass with updated commitment mechanism

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions