Skip to content

Ark-IOP + Ark-VC#25

Draft
z-tech wants to merge 71 commits into
mainfrom
z-tech/ior-with-ark-vc
Draft

Ark-IOP + Ark-VC#25
z-tech wants to merge 71 commits into
mainfrom
z-tech/ior-with-ark-vc

Conversation

@z-tech
Copy link
Copy Markdown
Collaborator

@z-tech z-tech commented May 4, 2026

Description

  • IORs. IOR trait + prove_ior!/verify_ior! macros. Same shape per phase. Layout reorganized around it.
  • ark-vc. Protocol code now generic over V: MultiVectorCommitment<Alphabet = F>. Zero merkle/hasher/shape/cap in src/. Concrete instantiation only in tests/benches. Opening proofs go through the spongefish transcript via V::open_multiple/V::check_multiple; auth_0/auth_j gone from WARPProof. Three small upstream PRs landed: spongefish bridges for MerkleSchemeCommitment, bounded PartialEq/Eq, dropped WarpShape.
  • Other integrations. gr1cs. effsc + spongefish 0.7.0.
  • Soundness. R1CS::description serializes the full matrix triple — index() binds the relation.
  • Perf. Rayon-parallel evaluate_bundled. Fused (f + ω·p)·t in TC sumcheck.
  • Observability. Op-counter + cpu_ns JSON tracing, iai-callgrind benches.
  • Tests. Negative-path verifier suite + FS audit.
  • API. Paper-letter fields → <letter>_<descriptive> (e.g. rt_merkle_rootsrt_commitments). WARP::new(ck, vk) not hasher. WARPConfig(l1, l2), l derived. Renames: BundledPESATPolyPredicate, ToPolySystemArithmetize, WARPProverKey.kk_num_witness_vars. Modules: crypto/merkle/crypto/vc.rs, oracles/indexed_merkle.rsoracles/indexed.rs.

Test plan

  • cargo test --lib --tests
  • cargo clippy --all-targets
  • iai-callgrind benches

z-tech and others added 27 commits March 20, 2026 16:26
Extracts WARP::prove and ::verify into per-phase modules under
src/protocol/phases/ (pesat, twin_constraint, ood, batching, proximity),
with a shared Oracle<F> type in src/protocol/oracle.rs that owns the
codeword and a lazily-materialised multilinear extension. lib.rs is
now an orchestrator that threads oracles and accumulator state through
the phases.

Adds tracing spans at each phase boundary, gated behind a new `profile`
cargo feature that optionally pulls in tracing-subscriber via
src/profile.rs. Release builds do not pull tracing-subscriber as a
direct dep of warp.

Sets up docs/paper-mods/ as a living spec of notation modifications to
the Warp paper, paired 1:1 with Rust modules. mod1_oracle.tex authored
in full; mod2/3/4 stubbed for downstream plans. Framing stays inside
IOP/BCS rather than moving to AHP.

No behavior change: 14/14 tests pass (BLS12-381 + Goldilocks warp_test,
query + relation tests), clippy clean under --all-features.
Restructures src/profile.rs into a module directory with four parts,
all gated behind the existing `profile` cargo feature:

- counters: thread-local Cell<u64> counters with a `count_ops!` macro.
  Snapshots + deltas let a subscriber diff across a span's lifetime.
  Tracks coarse call-site events (MerkleTreeBuilds, MerklePathsGenerated,
  MleMaterializations, OracleLeafQueries, OraclePointQueries,
  TwinConstraintRounds, BatchingRounds, OodPointQueries, EncodeCalls,
  MerklePathsVerified). Field-level op counts are out of scope — they
  need an F newtype or an arkworks fork; deferred.

- timing: `thread_cpu_ns()` via clock_gettime(CLOCK_THREAD_CPUTIME_ID)
  on Linux and macOS. Distinguishes blocked-on-IO from blocked-on-compute
  in a way wall-time cannot.

- rss: `peak_rss_bytes()` via getrusage(RUSAGE_SELF), normalising the
  Linux-kB vs macOS-bytes discrepancy.

- layer: a tracing `Layer` that captures a span's counters + timing +
  rss on enter, differences them on close, and emits one newline-
  delimited JSON record per span. Schema tag `warp.profile.v1`;
  per-record fields are {phase, wall_ns, cpu_ns, rss_delta_bytes,
  counters, dimensions}. Dimensions come from span numeric fields
  (log_l, log_m, log_n, etc.), captured via a tracing Visit.

Phase modules and the Oracle are instrumented at call sites so the JSON
records carry meaningful counter deltas. Without the feature every
count_ops! call and every timing/rss wrapper compiles to a no-op.

tests/profile_json.rs is a feature-gated integration test that installs
the JSON layer against an in-memory sink, runs a full hashchain prove,
and asserts every phase emits a well-formed record. It's the reference
shape Plan B's regression detector will consume.

Verification matrix (all green):
  - cargo test (no features)        : 14/14
  - cargo test --features profile   : 14/14 + profile_json 1/1
  - cargo clippy --all-targets      : clean
  - cargo clippy --all-targets --all-features : clean
Adds a deterministic instruction-count bench for WARP::prove, intended
as the regression signal for a future CI gate. Complements the existing
criterion wall-time bench (which stays informational).

- benches/iai_phases.rs: one library_benchmark for `prove` at the
  unit-test parameter shape (l1=4, s=2, t=7, hashchain=10). v1 scope
  is intentionally narrow — the docstring explains why the parameterised
  `#[bench::case(setup = ...)]` form didn't compile under iai-callgrind
  0.14 from this crate's bench root. Plumbing more sizes is deferred.

- Cargo.toml: iai-callgrind 0.14 as a dev-dep, second `[[bench]]`
  entry wired with `harness = false`.

- benches/docker/Dockerfile.iai: slim Debian image with valgrind + the
  iai-callgrind-runner binary pre-installed, for macOS hosts where
  valgrind has been unsupported since Big Sur.

- Makefile: `bench-wall` (criterion, any host), `bench-ci` (iai
  natively, Linux/valgrind required), `bench-ci-local` (builds and
  runs the Docker image with cargo registry/git/target caches mounted
  from target/iai-docker-cache/ so arkworks isn't redownloaded each
  run). Plus `test` and `clippy` convenience targets.

- benches/README.md: explains the split (noisy wall time vs
  deterministic instruction count), installation, Docker pathway, and
  v1 scope limits.

Deferred (tracked in the plan): multiple parameter points, baseline
capture + commit, and the GitHub Actions workflow that gates PRs.
Those come as small separate commits so the CI change can be reviewed
on its own.

Verification:
  - cargo check / --features profile    : clean
  - cargo build --bench iai_phases      : clean (run needs valgrind)
  - cargo build --bench warp_rs         : clean
  - cargo clippy --all-features         : clean
  - cargo test                          : 14/14 (unchanged)
Adds src/params/ — given (λ, |F|, code rate, list-decoding regime),
pick the minimum (s, t) that achieves λ bits of soundness on a
Reed–Solomon code.

- types: Regime::{Provable, Conjectured}, SecurityLevel, Params,
  SoundnessBound, ParamError. SoundnessBound::meets(λ) answers the
  "is this enough?" question directly.

- select(λ, field_bits, code_rate, regime) → Params. Uses the
  Johnson-bound proximity-query formula (provable: t ≥ 2λ/log₂(1/ρ),
  conjectured: t ≥ λ/log₂(1/ρ)), with a field-admissibility check
  (log₂|F| ≥ λ + 40) to ensure polylog noise terms are negligible.

- validate(params, field_bits, code_rate, regime, target): the
  inverse — computes the achieved soundness and reports per-term
  admissibility so callers can see partial failures.

- presets::PRESETS: canonical (λ, rate, regime) → (s, t) rows for
  80/128-bit targets at common rates (1/2, 1/8). A test enforces
  that every row matches `select` output, so drift between the
  table and the formulas is caught at build time.

- src/bin/warp-params.rs: dependency-free CLI with `select`,
  `validate`, and `table` subcommands. Dumps PRESETS as TSV and
  exits non-zero if a validate call doesn't meet the target.

- docs/paper-mods/mod4_parameter_selection.tex: replaces the stub
  with the full derivation, citing STIR / WHIR for the proximity-
  gap bounds and marking the deferred items (batching-sumcheck
  calibration of s, non-RS codes, a reference table with matching
  proofs).

The hard-coded `s=8, t=7` in warp_test is intentionally unchanged
for this pass — those are functional-test shapes, not security
values. A later pass can thread PRESETS through callers that care
about real targets.

Verification:
  - 23 tests pass (14 original + 9 new in params::tests)
  - cargo clippy, both feature configs: clean
  - ./target/debug/warp-params table prints PRESETS; select / validate
    round-trip; validate correctly rejects insufficient (s, t)
Adds the two highest-value pieces of test hardening from the plan;
the rest (proptest, golden serialization, xtask ref lint, runtime
F-S harness) is deferred and tracked in the todo list.

tests/verifier_negative.rs
- Shared `make_fixture()` runs the full two-phase accumulation so l2 > 0
  and every cleanly-reachable `VerifierError` variant is triggerable.
- One test per tamperable field, each confirming the verifier rejects
  the proof with the *specific* expected error (not just "some error"):
    * CodeEvaluationPoint (α tamper)
    * CircuitEvaluationPoint (β.0 and β.1 tampers — two tests)
    * NumShiftQueries (truncate shift_query_answers)
    * ShiftQueryIndex (swap auth_0 paths)
    * ShiftQuery (tamper shift_query_answer value)
    * NumL2Instances (truncate auth_j)
    * Target (tamper μ)
- A happy-path test keeps the fixture honest.
- Docstring enumerates the variants we did NOT reach through
  single-field tampering (SpongeFish/ArkError wrap lower-level errors;
  NumSumcheckRounds is transcript-derived; SumcheckRound is unraised
  in current code).

docs/audits/fiat_shamir.md
- Ordered, line-for-line mapping of every prover-side transcript write
  to its verifier-side read. 25 steps, each with file:line links on
  both sides.
- A "what reviewers should spot-check" section calls out the specific
  squeeze-before-absorb patterns F-S-soundness bugs tend to take.
- Scope: this is a **manual** audit (compensating control). The
  runtime ordering harness that would make drift undetectable at CI
  time is deferred because it requires instrumenting spongefish; noted
  explicitly at the bottom of the doc.

Verification:
  - 23/23 unit tests + 9/9 negative-path tests pass
  - cargo clippy, both feature configs: clean
Five small fixups called out during the Plan T post-mortem. No
behaviour changes — all tests keep passing on both feature configs.

1. Move the big `warp_test` / `warp_test_goldilocks` suites from
   `src/lib.rs` into `tests/integration_warp.rs`. They're end-to-end
   prove / verify / decide runs; keeping them as inline unit tests
   kept the file ~340 lines longer than necessary. `src/lib.rs` is
   now 500 lines (down from 844); the test content is unchanged.

2. Normalise phase-fn visibility to `pub`. Before, `pesat::prove`
   was `pub(crate)` while the other four phases' `prove` / `verify`
   / `verify_claim` entry points were `pub`. All output structs
   (`Oracle`, `OodOutput`, `BatchingOutput`, etc.) are already `pub`,
   so there was no reason for `pesat` to be the odd one out.
   `PesatOutput` promoted from `pub(crate)` → `pub` for the same
   reason.

3. Cross-reference lint audit — verified every module in `src/params`,
   `src/protocol/phases`, plus `src/protocol/oracle.rs` and
   `src/bin/warp-params.rs`, carries a doc-comment reference to its
   paired `docs/paper-mods/modN_*.tex`. No drift.

4. `presets::lookup` now takes an exact `(num, den)` pair instead of
   `f64` with an epsilon-compare. Preserves the caller's intent
   (`1/2` is distinct from `0.5`); the CLI plumbs a small `Rate` enum
   through parsing so ratios hit the preset table while bare decimals
   fall through to the computed-value branch.

5. Remove the `let _ = Counter::ALL.len()` silencer in
   `profile/layer.rs`. The import it was suppressing was an artifact
   of an earlier iteration and isn't needed now; dropping it and the
   `Counter` import lets clippy stay clean.

Verification:
  - cargo test                       : 33/33 pass (22 unit + 2 integ
    + 9 negative)
  - cargo test --features profile    : 34/34 pass (adds profile_json)
  - cargo clippy --all-features -Dwarnings : clean
  - warp-params select verified with both `1/2` and `0.5` inputs
Captures the changelog entries that were uncommitted in the working
tree at the start of the Plan 0 / O / B / P / T refactor session.
Describes the already-landed sumcheck work in the preceding five
commits (a66f122 .. 312e220): inner-product sumcheck 2-coefficient
round messages, RoundPolyEvaluator adoption, twin-constraint
coefficient count reduction, and the ark-ff rev pin.
Covers every personal Claude Code artefact (custom agents, plans,
skills, settings.json, settings.local.json) for this repo — not just
the local-settings file that was already ignored. Nothing under
.claude/ has ever been tracked here, so this is a purely
belt-and-suspenders tightening: the next `git add .` can't pick up
anything from the directory.
Co-authored-by: winderica <winderica@gmail.com>
Integrate redesigned Efficient Sumcheck
Resolutions:

- Cargo.toml: adopt main's clean 0.6 dep stack — drop the stale
  [patch.crates-io] block (z-tech/smallfp-absorb branch no longer
  exists; algebra rev 285dac2 was 0.5-era), bump dev-deps to 0.6.0
  to match. Use main's spongefish 0.7.0 + ark-codes z-tech fork
  pin. Keep cleanup's tracing/profile additions and `profile` feat.
- src/lib.rs, src/relations/{description.rs,r1cs/mod.rs,r1cs/hashchain/relation.rs},
  src/serialize.rs, src/protocol/mod.rs, src/error.rs: take
  cleanup's structural versions (phase modules, AccumulatorWitness
  struct, gr1cs migration via into_inner()/get_predicate_num_constraints).
- src/crypto/merkle/blake3.rs, src/protocol/domainsep/mod.rs:
  delete (cleanup intent — replaced by ark_crypto_primitives::merkle_tree::configs
  and protocol/transcript/{prover,verifier}.rs respectively).
- src/utils/poly.rs: keep (still used by protocol/phases/batching.rs).
- src/lib.rs: rewrite two `sumcheck_verify` call sites to the
  5-arg API used by effsc main (returns SumcheckResult{challenges,
  final_claim} — caller does the oracle check externally).
- src/protocol/phases/twin_constraint.rs: handle effsc main's
  `coefficient_lsb::final_value` calling convention — odd halves
  arrive empty in the singleton case. Compute h(singleton) directly
  (MLE of u at α_singleton + bundled R1CS at z, β_singleton, scaled
  by τ_singleton) and emit `[h, -h]` so g(0)+g(1) == h.

cargo test: 33 passed (22 unit + 2 integration + 9 verifier-negative).
@z-tech z-tech mentioned this pull request May 4, 2026
@z-tech

This comment was marked as outdated.

z-tech added 10 commits May 8, 2026 00:13
Mirror of WarpPipeline.prove() on the verifier side. Walks the same
five-phase shape — PESAT, TwinConstraint, OOD, Batching, Proximity —
plus the inter-phase transcript reads (td_digest, eta, nu_0) and the
shift-query / oracle-handle plumbing.

Design choices:
- WarpPipelineVerifyInputs takes the minimum the orchestrator must
  pass in: the pre-parsed AccumulatorInstance (parse_statement is
  orchestrator-owned because it precedes all phase work), the
  acc_mu_first scalar (Batching's final-claim multiplier), and a
  borrowed WARPProof. Other items the orchestrator caches before the
  call (acc_alpha_first, acc_beta_*_first) stay outside the pipeline
  because they're only used by the post-Batching consistency checks
  that cross-reference data from before the call.
- WarpPipelineVerified returns the per-phase reduced statements the
  orchestrator still needs (pesat for taus, tc for gamma, batching for
  alpha) plus debug artifacts (eta, nu_0, queries, nus). Kept minimal:
  no field that WARP::verify doesn't touch after the inline pipeline
  block ends.
- The arity checks on shift_query_answers.len() / auth_j.len() live in
  the pipeline since every phase past the OOD→Batching glue reads from
  the proof and assumes the shape matches. The post-Batching (alpha,
  beta) consistency checks stay in the orchestrator because they
  consume cached prior-accumulator state.

WARP::verify is unchanged in this commit — switching it to call this
method comes in a follow-up.
Mirror of the WARP::prove rewrite in 0f81cce. WARP::verify now:

1. Parses the transcript-side statement (l1 fresh + l2 acc).
2. Caches prior-accumulator values needed by post-pipeline checks
   (acc_alpha_first, acc_beta_*_first, acc_mu_first, l2_taus, l2_xs).
3. Builds WarpPipeline + WarpPipelineConfig.
4. Calls pipeline.verify(...) with WarpPipelineVerifyInputs { parsed_acc,
   acc_mu_first, proof }.
5. Runs the two post-pipeline consistency checks (alpha + beta against
   the prior single-entry accumulator) — these stay in the orchestrator
   because they cross-reference data outside the pipeline's scope.

Drops imports for the per-phase types the orchestrator no longer
constructs directly (Pesat/TwinConstraint/Ood/Batching/Proximity
struct types, the per-phase Statement/VerifierInputs types, IOR trait,
MerkleIndexedOracle, QueryIndices, warp_scheme).

WARP::verify is now ~80 lines, down from ~200. The full test suite
(2/2 integration + 9/9 verifier_negative + 1/1 composition_demo)
passes — the verify-side pipeline produces transcript-identical
output to the prior inline orchestration.
The pipeline-as-a-single-prove-call shape (commits 0f81cce / 25ac3e8)
hid the protocol structure behind one opaque call. To understand what
WARP does, a reader had to context-switch from lib.rs to composition.rs
and reconstruct the phase ordering from the IOR machinery.

This commit restores lib.rs as a self-documenting protocol map. Each
phase appears as a labeled section — Phase 2 (PESAT), Phase 3a
(TwinConstraint), Phase 3b (bundled η/ν₀, td_new commit, absorbs),
Phase 3c (OOD), Phase 3c→3d glue (sample queries), Phase 3d
(Batching), Phase 3e (Proximity) — readable top-to-bottom in order.

What's preserved from the migration:
- WarpPipeline still holds the five phase instances built once with
  their setup borrows (code, hasher, r1cs, bundled_pesat). The
  orchestrator calls phases via `pipeline.pesat.prove(...)` etc., so
  phase setup isn't duplicated across every prove() call. Pipeline
  serves as a *typed bag of phases* rather than an opaque executor.
- WarpPipeline.prove() and .verify() stay as alternative single-call
  entry points used by tests/composition_demo.rs.
- Pipeline trait + Then<A,B> in composition.rs / then.rs survive
  untouched as library pieces for any future composition research.
- The GAT migration (360f6dc) stays — decoupled lifetimes are a strict
  improvement regardless of the orchestrator shape.

The two body-swap commits (0f81cce, 25ac3e8) effectively get reverted
in spirit but the restoration goes through `pipeline.<phase>` not
fresh phase struct construction, keeping the data-container win from
the migration without paying the legibility cost.

All 11 tests still pass; transcript-identical to both prior shapes.
Reshape the orchestrator around two principles surfaced in design
discussion:

1. **Every step is an IOR**, including the inter-phase glue. The bridge
   between TwinConstraint and OOD (η / ν₀ / td_new commit, deferred
   discharge) and the shift-query sampling between OOD and Batching
   were previously inline orchestrator code; both are now first-class
   IORs in `src/protocol/phases/{bridge.rs, sample_queries.rs}` with
   the full IOR-trait signature, even where the Statement/Witness
   fields are degenerate. Uniformity: one abstraction, used everywhere.

2. **Destructure on every IOR output.** Instead of opaque step-wrapper
   types hiding the protocol values, the choreography in `WARP::prove` /
   `WARP::verify` destructures each `ReducedStatement` and
   `ReducedWitness` by name at the call site:

       let (PesatReducedStatement { mus, taus }, _,
            PesatReducedWitness { codewords, td_0 }) =
           pesat_phase.prove(...)?;

   The reader sees, on each phase line: which IOR runs, what flows in
   (named struct fields), what flows out (named bindings). Paper-aligned
   notation visible throughout the orchestrator.

Bridge IOR (`src/protocol/phases/bridge.rs`):
  - Statement: (ζ₀, β_τ, log_m, n_minus_k)
  - Witness: (z, f) — prover's reduced state from TC
  - ProverInputs: (bundled_pesat, hasher, code_len)
  - VerifierInputs: (deferred, γ) — for discharging TC's deferred check
  - ReductionInputs/ReducedStatement: (η, ν₀, td_new_root)
  - ReducedWitness: (td_new, new_x, new_w)
  - Prover-side: computes η, ν₀, splits z, commits td_new, absorbs.
  - Verifier-side: reads td_digest/η/ν₀, discharges deferred check.

SampleQueries IOR (`src/protocol/phases/sample_queries.rs`):
  - Statement: (log_n, t)
  - ReductionInputs/ReducedStatement: QueryIndices
  - Trivially: one round of verifier randomness, no prover messages.

Deletes the pipeline machinery the choreography subsumes:
- `src/protocol/composition.rs` (WarpPipeline + Pipeline trait sketch)
- `src/protocol/then.rs` (generic Then<A,B>)
- `tests/composition_demo.rs` (exercised WarpPipeline directly)

`WARP::prove` and `WARP::verify` now construct phase structs inline
(stateless or borrowing &self.params data, so no setup repeated work).
Same transcript-identical output as before; all 33 tests (22 lib + 2
integration + 9 verifier-negative) pass.
…e star

Replaces the IOR trait's formal Statement / Witness / ProverInputs /
ReductionInputs / ReducedStatement / ProofString / ReducedWitness /
VerifierInputs / VerifierOutputs split with a single ProverInput +
ProverOutput and VerifierInput + VerifierOutput pair, plus a NAME
constant. Removes reduce_statement from the trait (each IOR's
implementation preserves the single-source-of-truth pattern via a
private helper where the reduction is non-trivial — e.g.,
TwinConstraint).

The new shape is the user-facing primary abstraction. No wrapper
trait, no Step, no Pipeline. Per-IOR types follow a uniform port
convention:

  ProverOutput { reduced, carry, [proof] }
  VerifierOutput { reduced, carry }

with:
  - `reduced` — public reduced claim (same type on both sides; both
                endpoints recompute via shared private helper)
  - `carry`   — endpoint-local state needed by later IORs (empty fields
                use `()` type for uniformity)
  - `proof`   — only present where the IOR produces proof material
                (Proximity)

Bridge and SampleQueries become first-class IORs (trivial cases of the
shape) so the orchestrator stays IOR-uniform end to end.

WARP::prove and WARP::verify are now a destructured choreography of
seven IOR calls — each block names the IOR, its input fields, and its
output ports at the call site:

    let PesatProverOutput {
        reduced: PesatReduced { mus, taus },
        carry: PesatProverCarry { codewords, td_0 },
    } = pesat_ior.prove(prover_state, PesatProverInput { l1, log_m,
        witnesses: &witnesses })?;

Reading lib.rs is now reading the WARP protocol map.

Renames `src/protocol/phases/` → `src/protocol/iors/` and the
`BatchingStatement::from_phase_outputs` constructor → `from_ior_outputs`
to drop the residual "phase" vocabulary (paper-section comments like
"IOR 1: PESAT" remain — those are paper alignment, not internal terms).

Tests transcript-identical: 22 lib + 2 integration + 9 verifier-negative
all pass.
Reverts the trait collapse from 94ac227. The IOR trait is back to its
formal 9-type shape — Statement, Witness, ProverInputs, VerifierInputs,
ReductionInputs, ReducedStatement, ProofString, ReducedWitness,
VerifierOutputs — plus `reduce_statement` for the single-source-of-truth
reduction. That's what an IOR actually is, in the paper sense. The
prior collapse made it just "endpoint protocol with prover/verifier
inputs/outputs" — not an IOR.

Additions on top of the restored trait:

1. `const NAME: &'static str;` on the trait. Each IOR labels itself.

2. `Statement` is now a GAT: `type Statement<'a> where Self: 'a;`.
   Allows statements to borrow from upstream-IOR outputs (none do
   today; the GAT just removes the future barrier).

3. Helper structs + macros for ergonomic call sites:
   - `IorProveResult<R, P, W> { reduced, proof, witness }`
   - `IorVerifyResult<R, V> { reduced, outputs }`
   - `prove_ior!` / `verify_ior!` macros wrapping `IOR::prove` /
     `IOR::verify` tuple returns into the named-field structs.

The choreography in `WARP::prove` / `WARP::verify` now reads:

    let IorProveResult {
        reduced: PesatReducedStatement { mus, taus },
        proof: _,
        witness: PesatReducedWitness { codewords, td_0 },
    } = prove_ior!(
        pesat_ior,
        prover_state,
        statement: PesatStatement { l1, log_m },
        witness: PesatWitness { witnesses: &witnesses },
        inputs: (),
    )?;

Every paper concept is named — statement, witness, inputs, reduced,
proof, witness. The IOR trait stays formal. The macro hides only the
tuple-packaging syntax, not the reduction shape.

Bridge and SampleQueries stay as IORs with the full formal trait
implemented (degenerate but legitimate — Bridge's "proof string" is
its transcript writes; SampleQueries' "witness" is `()`).

Renames `src/protocol/phases/` → `src/protocol/iors/` and updates all
imports. Variable names use the `_ior` suffix throughout.

Tests transcript-identical: 22 lib + 2 integration + 9 verifier-negative
all pass.
Removes AccumulatorEntry, AccumulatorWitnessEntry, push_entry/from_entries,
and PesatOutput (all orphaned from the pre-IOR refactor). Renames
from_phase_outputs -> from_ior_outputs. Cuts the long narrative blocks in
iors/mod.rs and aligns module docstrings on "IOR" rather than "phase".
Moves the IOR trait to src/protocol/ior.rs (its own conceptual anchor),
demotes src/protocol/iors/mod.rs to an ordered list of concrete IORs.
Promotes oracle vocabulary under src/protocol/oracles/ (evaluation,
indexed_merkle, query_indices). Splits the bulky lib.rs into src/warp/
(scheme + prove + verify + decide + accumulator + proof + params + keys),
leaving lib.rs as a table of contents. Renames traits.rs to
accumulation.rs to name the abstraction it carries. Trims README and
profiling example to match.

No behavior change; 22 lib + 2 integration + 9 verifier-negative tests
still pass.
@z-tech z-tech force-pushed the z-tech/ior-with-ark-vc branch from c0540d3 to 98b154d Compare May 12, 2026 14:18
z-tech added 8 commits May 12, 2026 16:25
Items 1-9 of the aggressive review:
- delete docs/paper-mods/slides/{iors.tex,iors.pdf} (~2200 lines of
  beamer source/PDF that doesn't belong in this repo)
- delete src/accumulation.rs trait — only ever impl'd by WARP; the
  trait + 30-line *_impl delegation layer was pure indirection
- delete examples/profile_iors.rs — broken example (wrong hasher type,
  wrong WARP::new arity); not in CI
- drop unused AccumulatorInstance / AccumulatorWitness is_empty/len
- drop the //! IOR signature ... bullet blocks; the type aliases below
  are the spec
- stateless IORs (Ood, SampleQueries, Batching, Bridge) become unit-
  ish tuple structs with #[derive(Default)] — kills the
  new()/Default/{<'a, F>{phantom...}} boilerplate
- prelude module deleted; flatten to top-level re-exports
- trim tracing-subscriber features from 5 to 3 (drop json, ansi)
- aggressive comment trim everywhere: drop narrative module headers,
  field doc-comments that restate field names, section dividers in
  prove/verify
Comment thread src/protocol/ior.rs Outdated
Comment thread src/warp/prove.rs Outdated
@z-tech z-tech requested review from dmpierre and winderica May 13, 2026 15:04
@z-tech
Copy link
Copy Markdown
Collaborator Author

z-tech commented May 13, 2026

@dmpierre @winderica 🙏 big review lots of progress here and would like to continue iterating later. lmk when you have time.

@z-tech z-tech changed the title IOR trait + ark-vc/ark-mt integration IOR trait + ark-vc May 13, 2026
@z-tech
Copy link
Copy Markdown
Collaborator Author

z-tech commented May 14, 2026

@dmpierre @winderica had to push hope you weren't already reviewing. I want to move both this repo and also the ark-codes repo. We should coordinate so that you can both get authorship credit in the move.

@z-tech z-tech changed the title IOR trait + ark-vc Ark-IOP + Ark-VC May 14, 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.

1 participant