Skip to main content

binius_iop_prover/channel/
mod.rs

1// Copyright 2026 The Binius Developers
2
3//! Channel abstraction for interactive oracle protocol (IOP) provers.
4
5pub mod grinding;
6pub mod merge;
7pub mod naive;
8
9use binius_compute::Allocator;
10use binius_field::PackedField;
11use binius_iop::channel::OracleSpec;
12use binius_ip_prover::channel::IPProverChannel;
13use binius_math::{FieldSlice, FieldVec, StructuredBuffer};
14
15/// Channel for IOP provers that extends the IP prover channel with oracle operations.
16///
17/// In an IOP, the prover can:
18/// 1. Send field elements to the verifier via `send_*` methods (inherited)
19/// 2. Sample random challenges via `sample` (inherited)
20/// 3. Commit oracles to the verifier
21/// 4. Respond to oracle queries with opening proofs
22///
23/// # Contract
24///
25/// The caller must call `send_oracle()` exactly `remaining_oracle_specs().len()` times before
26/// calling `prove_oracle_relation()`. Each oracle buffer must match the corresponding
27/// specification. Every committed oracle must be handed back to the channel exactly once with
28/// `finalize_oracle()`.
29pub trait IOPProverChannel<P: PackedField, A: Allocator>: IPProverChannel<P::Scalar> {
30	type Oracle: Clone;
31
32	/// Returns the specifications for the remaining oracles to be committed.
33	///
34	/// This slice shrinks as oracles are committed via `send_oracle()`.
35	fn remaining_oracle_specs(&self) -> &[OracleSpec];
36
37	/// Commits an oracle to the verifier.
38	///
39	/// # Preconditions
40	///
41	/// * `remaining_oracle_specs()` must be non-empty.
42	/// * `buffer.log_len()` must match the expected length from the next oracle spec.
43	fn send_oracle(&mut self, buffer: FieldSlice<'_, P>) -> Self::Oracle;
44
45	/// Generates an opening proof for one oracle linear relation.
46	///
47	/// The relation asserts that `<oracle_poly, transparent> = claim`. An oracle may carry any
48	/// number of relations.
49	///
50	/// The transparent may be zero outside one aligned block, and say so through its structure. A
51	/// channel that understands the structure skips the zeros; any other materializes it.
52	///
53	/// The channel owns the transparent multilinear until the opening runs, so it is drawn from
54	/// the caller's allocator `A` — a pooled buffer stays pooled all the way through the opening.
55	///
56	/// # Preconditions
57	///
58	/// * `remaining_oracle_specs()` must be empty (all oracles committed).
59	/// * `oracle` must be a valid handle returned by `send_oracle()`.
60	/// * `transparent.log_len()` must match the oracle's message length.
61	/// * The claim must already be bound to the transcript, since the coefficient that batches the
62	///   queued relations is drawn only after the queue closes.
63	fn prove_oracle_relation(
64		&mut self,
65		oracle: Self::Oracle,
66		transparent: StructuredBuffer<P, A::Vec<P>>,
67		claim: P::Scalar,
68	);
69
70	/// Gives ownership of the oracle buffer to the channel.
71	///
72	/// The [`Self::send_oracle`] method takes a borrowed reference to an oracle buffer and returns
73	/// a handle to it. In order to prove the oracle relations without unnecessarily cloning the
74	/// buffer, some channel implementations require ownership of the buffer.
75	///
76	/// # Preconditions
77	///
78	/// * `oracle` must be a valid handle returned by `send_oracle()`, not already finalized.
79	/// * `buffer` must equal the buffer previously committed via `send_oracle()`.
80	fn finalize_oracle(&mut self, oracle: Self::Oracle, buffer: FieldVec<P, A>);
81}