Skip to content

Comments

feat: recursion (updated)#13

Open
quangvdao wants to merge 26 commits intoa16z:mainfrom
LayerZero-Research:lz-recursion
Open

feat: recursion (updated)#13
quangvdao wants to merge 26 commits intoa16z:mainfrom
LayerZero-Research:lz-recursion

Conversation

@quangvdao
Copy link
Contributor

No description provided.

markosg04 and others added 26 commits November 25, 2025 19:51
- Add src/recursion/ast.rs with ValueId, AstNode, AstOp, AstGraph, AstBuilder
- Integrate AST building into TraceContext with with_ast() and take_ast()
- Add ValueId tracking to TraceG1, TraceG2, TraceGT wrappers
- Instrument all traced operations to record AST nodes when enabled
- Add from_setup/from_proof/from_proof_round helpers for input interning
- Wire AST into verify_recursive with proper input source tracking
- Add integration tests for AST generation and input interning
…T tests

- Add G1Add/G2Add to OpType enum and witness system
- Remove GTNeg from AST (not used in Dory verification)
- Reorder all enum variants to G1 → G2 → GT → Pairing
- Add test_ast_structural_equivalence (witness-gen vs hint-based)
- Add test_ast_opid_witness_join (verify OpId/witness sync)
- Add op_id: Option<OpId> field to AstOp::{G1Add, G2Add}
- Use push_with_opid() in trace.rs for add operations
- Eliminates ambiguity when joining AST↔witness (no 'nth occurrence' needed)
- Remove G1Neg, G2Neg from AstOp enum
- For subtraction, record as G1Add/G2Add (negation is inline, not tracked)
- Standalone negation no longer produces AST nodes
- All remaining operations have op_id for witness linkage
Enables sorting witnesses by OpId for deterministic constraint ordering in Jolt.
…evaluation_proof

verify_recursive was sampling the `d` challenge without first appending
final_e1/final_e2 to the transcript, causing Fiat-Shamir divergence from
the prover. Now matches the transcript sequence in create_evaluation_proof
and verify_evaluation_proof.

Also fixes missing op_id fields in ast.rs test code.
- Add bounds checking in ark_pairing.rs to gracefully fall back to
  non-cached path when cache is too small for the requested operation
- Mark cache initialization tests as #[ignore] since they pollute global
  cache state with random values that break other tests' verification
- Ignored tests can still run in isolation with --ignored flag
- Add level-based parallelism analysis to AstGraph (compute_levels, levels, levels_by_type, level_stats)
- Implement TaskExecutor using rayon::scope for work-stealing parallel evaluation
- Tasks spawn consumers dynamically as dependencies complete, enabling cross-level parallelism
- Add InputProvider and OperationEvaluator traits for backend-agnostic evaluation
- Add benchmark comparing sequential vs parallel evaluation (~8.5x speedup)
…arallel witness expansion

- Add `precompute_challenges()` to extract all Fiat-Shamir challenges in one pass
- Add `ChallengeSet` and `RoundChallenges` structs for challenge storage
- Add `ExecutionMode::Deferred` for two-phase parallel witness generation
- Add `DoryInputProvider` for parallel AST evaluation with setup/proof elements
- Export `HintResult` for upstream crate use
- Update all trace operations to support deferred mode (record hints without witness expansion)

This enables upstream crates (e.g., Jolt) to:
1. Pre-compute challenges (fast, sequential)
2. Run verification in deferred mode (AST + hints, no witnesses)
3. Expand witnesses in parallel using the recorded data
- Remove separate VMV pairing check (was done early, now batched)
- Add e1_init and d2_init tracking for deferred VMV check
- Rewrite final check to match verify_final exactly:
  - Use d² for VMV check terms (d²·D₂_init in RHS, d²·E₁_init in Pair 3)
  - Use single multi_pair with 3 pairs instead of multiple single pairings
- Update input_provider to handle vmv.e1_init and vmv.d2_init
- Fix test to corrupt multi-pairing hint instead of using wrong proof hints
Extract shared verification logic into `verify_with_backend<B>()` generic
over a new `VerifierBackend` trait. This eliminates ~80 lines of duplicate
code between `verify_evaluation_proof` (native) and `verify_recursive`
(tracing) paths.

- Add `VerifierBackend` trait abstracting G1/G2/GT operations
- Add `NativeBackend` for direct computation (zero overhead)
- Add `TracingBackend` wrapping TraceG1/G2/GT for witness generation
- Make TraceG1/G2/GT public with manual Clone impls
- Add test_backend_equivalence confirming both paths produce same results
Make verify_with_backend public so external crates (e.g., Jolt) can
plug in custom VerifierBackend implementations for:
- AST-only construction (build verification DAG without group ops)
- Challenge replay (use precomputed challenges, skip transcript)
- Custom witness strategies
Remove the HintBased and Deferred execution modes, replacing them with
a simpler two-mode architecture:

- WitnessGeneration: Compute operations and record witnesses (prover)
- Symbolic: Build AST only, no computation (verifier recursion)

This eliminates ~500 lines of hint management code. The hint-based
verification path was one strategy for recursion, but upstream systems
like Jolt may prefer different approaches. Now Dory just emits proof
obligations (AST) and lets upstream decide execution strategy.

Key changes:
- Delete hint_map.rs entirely
- Simplify ExecutionMode enum to two variants
- Remove hint lookup/fallback logic from TraceG1/G2/GT operations
- Symbolic mode uses identity placeholders for group elements
- Remove test_hint_verification_with_missing_hints (hint path gone)
- Remove test_hint_map_size_reduction (HintMap deleted)
- Rename test_deferred_mode to test_symbolic_mode
- Update test_ast_structural_equivalence to compare witness-gen vs symbolic
- Simplify test_ast_opid_witness_join to not use hints
- Update verify_recursive docstrings to reference for_symbolic()
- Replace hint-based examples with symbolic mode examples
- Add missing # Errors and # Panics sections per clippy
- Update module-level docs in lib.rs
Add example that prints a nicely formatted AST from Dory verification,
useful for debugging and understanding proof obligations.

Also update recursion.rs example to use symbolic mode instead of the
removed hint-based verification path.
- Format benches/parallel_eval.rs
- Format src/recursion/input_provider.rs
- Format tests/arkworks/cache.rs
- Add .vscode/settings.json with feature flags for rust-analyzer
Removes redundant AstOp::output_type in favor of AstNode::out_ty and clarifies wiring via explicit InputSlot names.
This also adds a small consistency test for input_ids vs input_slots and tidies minor TraceContext/trace helpers.
Drops the internal TaskExecutor-style AST evaluation utility and its bench, since upstreams can evaluate obligations directly from recorded witnesses.
Also re-exports the arkworks BN254 SimpleWitnessBackend/SimpleWitnessGenerator from recursion as a baseline default.
Make SimpleWitnessBackend/SimpleWitnessGenerator generic over any PairingCurve, and parameterize witness structs over group/scalar types.
Introduce a minimal ScalarBits helper to abstract scalar bit decomposition; BN254 ArkFr implements it by default.
Hoist mid-scope imports and shorten repeated module paths for readability, while keeping the build and clippy clean.
Replace per-point projective→affine→prepared conversion with batch
normalization to amortize field inversions. Under the `parallel`
feature, use rayon to prepare points concurrently.
@markosg04 markosg04 self-requested a review February 17, 2026 19:49
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