Skip to content

feat: guest (de)serialization for preprocessing & proof#1224

Closed
quangvdao wants to merge 7 commits intoa16z:mainfrom
quangvdao:quang/optimize-deserialization
Closed

feat: guest (de)serialization for preprocessing & proof#1224
quangvdao wants to merge 7 commits intoa16z:mainfrom
quangvdao:quang/optimize-deserialization

Conversation

@quangvdao
Copy link
Copy Markdown
Contributor

@quangvdao quangvdao commented Jan 25, 2026

Summary

Introduces a Jolt-owned guest encoding (GuestSerialize/GuestDeserialize) optimized for recursion verification, along with a native transport decode layer that converts compressed proof bytes into guest-optimized bytes.

Performance (recursion trace, virtual cycles, fibonacci)

Measured with:

  • cargo run -p recursion --release -- generate --example fibonacci --workdir output
  • RUST_LOG=info cargo run -p recursion --release -- trace --example fibonacci --workdir output

End-to-end deserialize costs (before → after)

  • deserialize preprocessing: ~20,733,462 → 2,330,786 (≈8.9×)
    • generators (PCS::VerifierSetup): ~6,814,769 → 428,262 (≈15.9×)
    • shared/bytecode_preprocessing: ~13,896,414 → 1,882,027 (≈7.4×)
  • deserialize proof: ~10,999,654 → 1,112,059 (≈9.9×)
    • joint_opening_proof (PCS::Proof): ~9,639,572 → 303,868 (≈31.7×)
  • deserialize device: ~2,767 → 2,691 (about the same)

verification remains the dominant cost (~1.19B virtual cycles) and is unchanged by this PR.

Validation policy change (enabled by moving decode out of guest)

Previously, recursion verification deserialized arkworks-encoded proofs/preprocessing inside the guest using unchecked canonical deserialization (Validate::No) to save virtual cycles, meaning incoming curve points were not validated.

With this PR, transport bytes are decoded and validated in native execution (canonical deserialize_compressed, i.e. validated), and only then converted into the guest-optimized encoding. Because this validation happens outside the proved computation, it incurs no zkVM virtual-cycle cost.

Guest decoding remains intentionally unchecked (GuestDeserialize uses new_unchecked for field elements/curve points) because its input is now the trusted output of the native validation+conversion step.

Key Changes

Area Change
guest_serde module New GuestSerialize/GuestDeserialize traits encoding field elements as Montgomery limbs and curve points uncompressed - avoids expensive in-guest decompression/conversion
decompression layer Native decompress_transport_bytes_to_guest_bytes() validates compressed transport bytes and emits guest-optimized encoding
Instruction encoding Switched from JSON to fixed-width binary format for faster preprocessing decode
dory-pcs build Made guest-safe by default; disabled disk-persistence APIs in non-host builds
cycle tracking Gated behind cycle-tracking feature, enabled by default for recursion builds
code cleanup Replaced fully qualified crate::zkvm::guest_serde::* paths with use statements

Motivation

Recursion verification requires deserializing proofs and preprocessing inside the guest. The standard arkworks encoding (compressed points, non-Montgomery field elements) incurs significant in-guest costs:

  • Point decompression requires square root computation
  • Field element conversion to Montgomery form on every deserialize

This PR eliminates those costs by pre-converting on the native side.

Testing

  • cargo check -p jolt-core --features prover
  • cargo clippy -p jolt-core --features prover
  • Recursion example end-to-end test

Review Guidance

Focus on:

  • jolt-core/src/zkvm/guest_serde.rs - the core encoding traits and impls
  • jolt-sdk/src/decompression.rs - the native transport → guest conversion
  • Dory impls in jolt-core/src/poly/commitment/dory/mod.rs

Replace JSON-based Instruction (de)serialization with a fixed-width binary format to
avoid serde_json parsing costs during preprocessing and recursion verification.
Disable dory-pcs default features at the workspace level and enable only the
arkworks backend and cache for recursion/minimal builds; avoid disk-persistence
APIs in non-host builds.
Introduce a Jolt-owned GuestSerialize/GuestDeserialize encoding (Montgomery limbs
and uncompressed curve points) and a native validated transport decode step that
emits guest-optimized bytes consumed by recursion verification.

Also gate cycle-tracking markers behind a feature and enable it by default for
recursion builds.
…atements

Add `use crate::zkvm::guest_serde::{GuestDeserialize, GuestSerialize}` imports
and simplify impl blocks across 8 files to improve readability.
Comment thread jolt-core/src/zkvm/guest_serde.rs Outdated
Use `usize::try_from` with proper error handling instead of `as usize`
to avoid silent truncation of Vec/byte lengths on 32-bit systems.
Tighten guest length prefix encoding/decoding to avoid silent truncation (notably Claims length) and add explicit documentation that GuestDeserialize is unchecked by design for the trusted-host recursion pipeline.
@moodlezoup
Copy link
Copy Markdown
Collaborator

@quangvdao can i close this?

@quangvdao
Copy link
Copy Markdown
Contributor Author

Yes, it's badly outdated. We can revisit this in the future

@quangvdao quangvdao closed this Mar 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants