Skip to content

Conversation

@Zyra-V21
Copy link

Add BLS12-381 Curve Provider and Dory-PC Backend

Summary

This PR adds support for:

  1. BLS12-381 curve as a new curve provider
  2. Dory-PC as an alternative polynomial commitment scheme

Motivation

BLS12-381 is widely used in production systems (Ethereum 2.0, Zcash) and offers strong security guarantees. Dory-PC provides O(1) commitment size and O(log n) verification.

Changes

New Files

  • src/provider/bls12_381.rs - BLS12-381 curve implementation via halo2curves
  • src/provider/pcs/dory_pc.rs - Dory-PC adapter wrapping quarks-zk crate
  • benches/pcs_comparison.rs - Benchmark comparing Hyrax vs Dory
  • examples/sha256_bls12_381_dory.rs - SHA-256 circuit example with Dory-PC
  • examples/BENCHMARK_RESULTS.md - Benchmark results

Modified Files

  • src/provider/mod.rs - Register BLS12381HyraxEngine and BLS12381DoryEngine
  • src/provider/pcs/mod.rs - Export dory_pc module
  • Cargo.toml - Add dependencies (quarks-zk, ark-* crates)

New Engines

pub struct BLS12381HyraxEngine;  // BLS12-381 with Hyrax-PC
pub struct BLS12381DoryEngine;   // BLS12-381 with Dory-PC

Benchmark Results (Simple Circuit)

Phase Hyrax Dory Notes
Setup 104.58 ms 376.75 µs Dory 278x faster (O(1))
Prove 32.12 ms 502.53 ms Hyrax 15.6x faster
Verify 30.77 ms 254.45 ms Hyrax 8.3x faster

SHA-256 Circuit Results (Heavy Circuit, 131K+ constraints)

Message Setup Prove Verify
256 bytes 856 ms 14,777 ms 1,852 ms
512 bytes 1,413 ms 14,649 ms 1,666 ms

Performance Observations

What works well:

  • Setup scales well - Dory O(1) commitment size means setup doesn't grow proportionally with circuit size
  • Verification is reasonable - O(log n) verification works as expected

Current bottlenecks:

  • Prove time is the main bottleneck - ~65% of prove time (9.5s of 14.7s) is spent in PCS prove due to pairing operations in BLS12-381
  • BLS12-381 pairing operations are inherently slower than secp256r1 group operations (used by T256HyraxEngine)

Potential optimizations (not in scope for this PR):

  • GPU acceleration for MSM and pairing operations
  • Better parallelism in commitment computation
  • Batched pairing verification

Assessment

This is a research-grade implementation. The numbers are expected for:

  • A heavy circuit (SHA-256 with 131K+ constraints)
  • BLS12-381 curve with pairing operations
  • No GPU or hardware acceleration

For production use, significant optimization work would be needed.

Testing

  • 16 new tests for BLS12-381 provider
  • 11 new tests for Dory-PC adapter (correctness + soundness)
cargo test --features dory
cargo bench --bench pcs_comparison --features dory
cargo run --release --example sha256_bls12_381_dory --features dory

Dependencies

New optional

@Zyra-V21
Copy link
Author

@microsoft-github-policy-service agree

Ok(DoryBlind)
}

fn prove(
Copy link
Contributor

Choose a reason for hiding this comment

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

We need a PCS evaluation argument where claimed values are committed.

Copy link
Author

Choose a reason for hiding this comment

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

Current understanding:

  • Spartan stores eval_W in plaintext in SpartanSNARK struct (line 107, spartan.rs)
  • Spartan recomputes comm_eval_W = PCS::commit([eval_W]) in verifier
  • My current DoryEvaluationArgument duplicates the value in value_bytes

Question: Should I:

  1. Remove value_bytes from DoryEvaluationArgument entirely?
  2. If so, how should verify() obtain the value to call quarks-zk::verify_eval(value, ...)?
  3. Should I deserialize from comm_eval parameter, or is the value expected to come from Spartan's proof struct?

Looking at Hyrax-PC, the IPA.verify() implicitly validates the value through the inner product check. Dory's verify_eval() explicitly needs the value parameter.

Could you clarify the expected flow for getting the evaluation value to the PCS verifier?

Thanks

Copy link
Author

Choose a reason for hiding this comment

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

Current implementation stores the claimed value in DoryEvaluationArgument.value (native ArkFr).

The value is implicitly committed through the comm_eval parameter:

  • Prover computes comm_eval = PCS::commit([eval_W], blind) (spartan.rs:306)
  • Verifier receives both comm_eval and arg.value
  • Verifier can check commit([arg.value]) == comm_eval for binding

Is this the pattern you're expecting, or should we handle it differently?

Copy link
Contributor

Choose a reason for hiding this comment

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

Spartan ZK variant does not store evaluation values in plaintext.

Addresses review comment microsoft#1 from @srinathsetty

Changes:
- Updated quarks-zk to v0.1.2 with rerandomization support
- Implemented rerandomize_commitment using Vega paper approach
- Added h_gt generator to DoryCommitmentKey for rerandomization
- Added 3 rigorous tests validating unlinkability and correctness

Reference: Vega paper (eprint 2025/2094) Section 2.1
…ument

- Store DoryPCSEvaluationProof and ArkFr natively (not Vec<u8>)
- Custom serde implementation using ark_serialize
- Addresses review microsoft#3: no hacky manual serialization
Apologies for the noise. Removed:
- examples/benchmarks/** (criterion-generated files)
- PR_DESCRIPTION.md (local reference)

These were included unintentionally in the previous commit.
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