Skip to content

feat: replace rolling-hash transcript with Spongefish Fiat-Shamir#15

Closed
shreyas-londhe wants to merge 1 commit intoa16z:mainfrom
shreyas-londhe:main
Closed

feat: replace rolling-hash transcript with Spongefish Fiat-Shamir#15
shreyas-londhe wants to merge 1 commit intoa16z:mainfrom
shreyas-londhe:main

Conversation

@shreyas-londhe
Copy link
Copy Markdown

@shreyas-londhe shreyas-londhe commented Feb 23, 2026

Summary

Migrates Dory's Fiat-Shamir transcript from a custom Blake2b rolling-hash implementation to Spongefish 0.2.0-alpha's NARG transcript model.

Why: The old transcript required maintaining a separate DoryProof struct for serialization alongside the hash-based Fiat-Shamir state. Spongefish
unifies these — the proof is the transcript. This eliminates an entire class of bugs where proof data could be absorbed into the hash in a different
order than it appears in the serialized proof, and gives us domain separation for free via Spongefish's DomainSeparator.

What changed:

  • Proofs are now opaque NARG byte strings (Vec<u8>) instead of a typed DoryProof struct. Prover writes to ProverState, verifier reads from
    VerifierState.
  • dory_domain_separator(sigma, zk) dynamically builds the protocol's domain separator, declaring every absorb/squeeze operation upfront.
  • check_proof_length(proof_bytes, sigma, zk) enables anti-malleability — callers reject proofs with unexpected length since Spongefish silently ignores
    trailing bytes.
  • Transcript trait split into ProverTranscript (infallible absorb/squeeze) and VerifierTranscript (fallible read/squeeze).
  • Deleted DoryProof, ArkDoryProof, Blake2bTranscript, Sigma1Proof, Sigma2Proof structs.
  • Dropped bincode, serde dependencies; replaced blake2/digest with spongefish.
  • Soundness tests rewritten for byte-level proof tampering (bit-flip, truncation, zeroed, cross-instance mixing) since proof internals are no longer
    accessible.

Test plan

  • All 79 tests pass (cargo nextest run --all-features --release)
  • Soundness tests cover byte-level tampering + wrong public inputs
  • Anti-malleability enforced via check_proof_length
  • All 6 examples verified (basic_e2e, homomorphic, homomorphic_mixed_sizes, non_square, zk_e2e, zk_statistical)
  • Benchmarks updated
  • cargo clippy, cargo fmt, cargo doc all clean

@shreyas-londhe shreyas-londhe changed the title Replace rolling-hash transcript with Spongefish Fiat-Shamir feat: replace rolling-hash transcript with Spongefish Fiat-Shamir Feb 23, 2026
Copy link
Copy Markdown

@moodlezoup moodlezoup left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did a quick skim, just one question

ds = FieldDomainSeparator::<Fq12>::add_scalars(ds, 2, "vmv-gt");
ds = GroupDomainSeparator::<G1Projective>::add_points(ds, 1, "vmv-g1");

if zk {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason to use a zk: bool instead of cfg gates, like we do elsewhere?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zk: bool is correct and can't be replaced with #[cfg(feature = "zk")]. The reason is that the zk feature flag controls whether ZK code exists (e.g., ZK mode type, sigma proof functions), but zk: bool on the domain separator controls which DS variant is used for a given proof.

When --all-features is enabled, both Transparent and ZK modes coexist — transparent proofs need a DS without ZK absorbs, and ZK proofs need one with them. A compile-time gate would force all proofs to include ZK elements when the feature is on, breaking transparent proofs.

Replace the custom Blake2b rolling-hash transcript with spongefish's
duplex-sponge construction. Proofs are now opaque NARG byte strings
instead of serialized Proof structs.

Key changes:
- Add CheckedProverState/CheckedVerifierState with InteractionPattern
  enforcement for compile-time protocol structure validation
- Declare reusable sub-patterns (sigma1, sigma2, reduce round, scalar
  product) composed via scoped nesting for diagnostic paths
- Domain separator binds (sigma, zk) into sponge instance
- Remove Proof struct, blake2b transcript, ark_proof, VMVMessage
- Add check_eof() to all tests, benches, and examples
- Use macros to reduce spongefish codec boilerplate
- Pin spongefish to commit 45df37a7 on fork

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@shreyas-londhe
Copy link
Copy Markdown
Author

This PR has been superseded by #17, which includes a cleaner commit history and all the same changes.

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