<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.29 (Ruby 3.3.8) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-zkproof-polycommit-00" category="info" submissionType="independent" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.28.1 -->
  <front>
    <title abbrev="PCS">Polynomial Commitment Schemes</title>
    <seriesInfo name="Internet-Draft" value="draft-zkproof-polycommit-00"/>
    <author fullname="Ying Tong Lai">
      <organization/>
      <address>
        <email>yingtong.lai@gmail.com</email>
      </address>
    </author>
    <date year="2025" month="May" day="23"/>
    <area>AREA</area>
    <workgroup>WG Working Group</workgroup>
    <keyword>zero-knowledge</keyword>
    <abstract>
      <?line 74?>

<t>This document describes the high-level interface of a polynomial commitment scheme (PCS), a cryptographic primitive used in constructing generic zk-SNARKs. A PCS allows a prover to commit to a polynomial, and later attest to its correct evaluation at a given point. Test vectors and reference implementations for popular instantiations are provided in Appendix A.</t>
    </abstract>
    <note removeInRFC="true">
      <name>About This Document</name>
      <t>
        The latest revision of this draft can be found at <eref target="https://therealyingtong.github.io/draft-zkproof-polycommit/draft-zkproof-polycommit.html"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-zkproof-polycommit/"/>.
      </t>
      <t>Source for this draft and an issue tracker can be found at
        <eref target="https://github.com/therealyingtong/draft-zkproof-polycommit"/>.</t>
    </note>
  </front>
  <middle>
    <?line 78?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>A polynomial commitment scheme (PCS) is a common building block  in the construction of modern generic zk-SNARKs (Fig 1). It allows a prover to commit to a polynomial, and later prove its correct evaluation at a given point. This is used to instantiate oracle access to the prover's polynomial-encoded witness, by introducing a cryptographic hardness assumption (e.g. discrete logarithm hardness).</t>
      <artwork><![CDATA[
             ┌─────────────┐             ┌─────────────┐             ┌─────────────┐
             │             │ polynomial  │             │ interactive │             │ non-interactive
 zerocheck   │ polynomial  │ identities  │ polynomial  │  argument   │ Fiat-Shamir │     argument
────────────►│ interactive ├────────────►│ commitment  ├────────────►│ heuristic   ├─────────────────►
             │ oracle proof│             │ scheme      │             │             │
             │ (PIOP)      │             │ (PCS)       │             │             │
             │             │             │             │             │             │
             └─────────────┘             └─────────────┘             └─────────────┘
]]></artwork>
      <t><em>Fig 1: The components of a modern zk-SNARK.</em></t>
      <t>A polynomial commitment scheme is parameterised over a finite field <tt>WitnessField</tt> for its representation, and a (potentially identical) finite  field <tt>ChallengeField</tt> for its evaluation points. It is also parameterised over an underlying cryptographic hardness assumption, such as a collision-resistant hash function or the elliptic curve discrete logarithm problem.</t>
      <t>NON-NORMATIVE NOTE: In small-field PCSes, challenges are usually drawn from an extension field <tt>ChallengeField</tt>.</t>
      <section anchor="generic-interface">
        <name>Generic interface</name>
        <t>A polynomial commitment scheme provides an interface with the following functions:</t>
        <section anchor="setup">
          <name><tt>setup</tt></name>
          <t>On input the parameters <tt>security_bits</tt>, <tt>num_vars</tt>, <tt>degree_bounds</tt>, and an OPTIONAL randomness generator <tt>rng</tt>, <tt>setup</tt> samples a public <tt>CommitterKey</tt> and <tt>VerifierKey</tt> for the polynomial commitment scheme.
  NON-NORMATIVE NOTE: This generalises over both trusted setups (SRS) and transparent setups.</t>
          <artwork><![CDATA[
fn setup(
    security_bits: usize,
    num_vars: usize,
    degree_bounds: Vec<usize>,
    rng: Option<Rng>,
) -> (CommitterKey, VerifierKey)
]]></artwork>
          <t><strong>Input:</strong></t>
          <ul spacing="normal">
            <li>
              <t><tt>security_bits</tt>: the desired number of bits of security</t>
            </li>
            <li>
              <t><tt>num_vars</tt>: the number of variables in the polynomial
NON-NORMATIVE NOTE: For univariate polynomials, num_vars = 1</t>
            </li>
            <li>
              <t><tt>degree_bounds</tt>: the upper bounds on the degree of each variable in the polynomial; <tt>degree_bounds.len()</tt> MUST equal <tt>num_vars</tt>
NON-NORMATIVE NOTE: For multilinear polynomials, degree_bounds = 1 for each variable</t>
            </li>
            <li>
              <t>(OPTIONAL) <tt>rng</tt>: a randomness generator</t>
            </li>
          </ul>
          <t><strong>Output:</strong></t>
          <ul spacing="normal">
            <li>
              <t><tt>ck</tt>: a committer key used in computing commitments and opening proofs; this contains also the description of finite fields for the witness <tt>WitnessField</tt>, as well as for the challenge <tt>ChallengeField</tt>.</t>
            </li>
            <li>
              <t><tt>vk</tt>: a verifier key used in verifying opening proofs; this contains also the description of finite fields for the witness <tt>WitnessField</tt>, as well as for the challenge <tt>ChallengeField</tt>.</t>
            </li>
          </ul>
        </section>
        <section anchor="commit">
          <name><tt>commit</tt></name>
          <t>On input the committer key <tt>ck</tt>, a polynomial <tt>poly</tt>, and an OPTIONAL random blinding factor <tt>r</tt>, <tt>commit</tt> outputs a binding and optionally hiding commitment <tt>com</tt>.</t>
          <artwork><![CDATA[
fn commit(
    ck: CommitterKey,
    poly: Polynomial<WitnessField>,
    r: Option<WitnessField>
) -> (Commitment, CommitmentState)
]]></artwork>
          <t><strong>Input:</strong></t>
          <ul spacing="normal">
            <li>
              <t><tt>ck</tt>: the committer key</t>
            </li>
            <li>
              <t><tt>poly</tt>: a polynomial with degree at most <tt>deg(X_i) = d_i ≤ D_i</tt> in each variable</t>
            </li>
            <li>
              <t>(OPTIONAL) <tt>r</tt>: a random element from the <tt>WitnessField</tt>; this can be set to <tt>None</tt> if the commitment is non-hiding
  NON-NORMATIVE NOTE: Zero-knowledge protocols often apply non-hiding polynomial commitment schemes to a "masked" polynomial, instead of the actual witness polynomial. The caller is responsible for masking the polynomial before providing it as input to<tt>commit</tt>.</t>
            </li>
          </ul>
          <t><strong>Output:</strong></t>
          <ul spacing="normal">
            <li>
              <t><tt>com</tt>: a binding and optionally hiding polynomial commitment to <tt>poly</tt></t>
            </li>
            <li>
              <t><tt>com_state</tt>: auxiliary state of the commitment, containing information that can be re-used by the committer during the opening phase, such as the commitment randomness.</t>
            </li>
          </ul>
        </section>
        <section anchor="open">
          <name><tt>open</tt></name>
          <t>On input the committer key <tt>ck</tt>, a polynomial <tt>poly</tt>, a commitment <tt>com</tt> to the polynomial, the challenge point <tt>challenge</tt>, and the OPTIONAL random blinding factor <tt>r</tt>, <tt>open</tt> outputs the evaluation <tt>eval = poly(challenge)</tt>, and an opening proof <tt>proof</tt>. The opening proof attests to the claim "<tt>com</tt> commits to a polynomial that evaluates to <tt>eval</tt> at <tt>challenge</tt>".</t>
          <artwork><![CDATA[
fn open(
    ck: CommitterKey,
    poly: Polynomial<WitnessField>,
    com: Commitment,
    com_state: CommitmentState,
    challenge: Challenge,
    r: Option<WitnessField>
) -> Proof
]]></artwork>
          <t><strong>Input:</strong></t>
          <ul spacing="normal">
            <li>
              <t><tt>ck</tt>: the committer key</t>
            </li>
            <li>
              <t><tt>poly</tt>: a polynomial with degree at most <tt>deg(X_i) = d_i ≤ D_i</tt> in each variable</t>
            </li>
            <li>
              <t><tt>com</tt>: a commitment to <tt>poly</tt></t>
            </li>
            <li>
              <t><tt>com_state</tt>: auxiliary state of the commitment</t>
            </li>
            <li>
              <t><tt>challenge</tt>: the evaluation point at which <tt>com</tt> will be opened; this consists of <tt>num_vars</tt> elements from the <tt>ChallengeField</tt>
  NON-NORMATIVE NOTE: In the non-interactive setting, the challenge is derived from the commitment using the Fiat-Shamir transform <xref target="fiat-shamir"/>.</t>
            </li>
            <li>
              <t>(OPTIONAL) <tt>r</tt>: a random element from the <tt>WitnessField</tt>; this MUST equal the <tt>r</tt> previously used in <tt>commit</tt></t>
            </li>
          </ul>
          <t><strong>Output:</strong></t>
          <ul spacing="normal">
            <li>
              <t><tt>proof</tt>: an opening proof attesting to the correctness of the opening</t>
            </li>
          </ul>
        </section>
        <section anchor="verify">
          <name><tt>verify</tt></name>
          <t>On input the verifier key <tt>vk</tt>, a polynomial commitment <tt>com</tt>, the evaluation point <tt>challenge</tt>, the purported opening <tt>eval</tt>, and the opening proof <tt>proof</tt>, <tt>verify</tt>  checks the opening proof, and either accepts or rejects it.</t>
          <artwork><![CDATA[
fn verify(
    vk: VerifierKey,
    com: Commitment,
    challenge: Challenge,
    eval: ChallengeField,
    proof: Proof,
) -> bool
]]></artwork>
          <t><strong>Input:</strong></t>
          <ul spacing="normal">
            <li>
              <t><tt>vk</tt>: the verifier key</t>
            </li>
            <li>
              <t><tt>com</tt>: a polynomial commitment</t>
            </li>
            <li>
              <t><tt>challenge</tt>: the evaluation point at which <tt>com</tt> is opened</t>
            </li>
            <li>
              <t><tt>eval</tt>: the purported evaluation of the committed polynomial at <tt>challenge</tt></t>
            </li>
            <li>
              <t><tt>proof</tt>: the opening proof the claim "<tt>com</tt> commits to a polynomial that evaluates to <tt>eval</tt> at <tt>challenge</tt>"</t>
            </li>
          </ul>
          <t><strong>Output:</strong></t>
          <ul spacing="normal">
            <li>
              <t><tt>verify</tt> outputs <tt>true</tt> if the opening proof is valid, and <tt>false</tt> otherwise</t>
            </li>
          </ul>
        </section>
      </section>
      <section anchor="batched-setting">
        <name>Batched setting</name>
        <t><em>This section is NON-NORMATIVE.</em></t>
        <t>Polynomial commitment schemes MAY support opening in a batched setting. In this setting, a single proof attests to the opening of multiple polynomials at multiple challenges (possibly different sets of challenges for each polynomial).</t>
        <t>Common special cases of the batched setting include:
- opening of a single polynomial at multiple challenges; and
- opening of multiple polynomials at a single challenge</t>
        <section anchor="batchopen">
          <name><tt>batch_open</tt></name>
          <t>On input the committer key <tt>ck</tt>, a vector of polynomials <tt>polys</tt>, a vector of their commitments <tt>coms</tt>, a vector of challenge sets <tt>challenges</tt>, and a vector of OPTIONAL random blinding factors <tt>rs</tt>, <tt>batch_open</tt> outputs the evaluations at each challenge set <tt>Vec&lt;Vec&lt;ChallengeField&gt;&gt;</tt> and a single opening proof <tt>BatchProof</tt>.</t>
          <t>The opening proof attests to the claim that "<tt>com[i]</tt> commits to a polynomial <tt>poly[i]</tt> that opens to <tt>evals[i][j]</tt> at <tt>challenges[i][j]</tt>", for each index <tt>i</tt> in the batch of polynomials, and each index <tt>j</tt> in its corresponding challenge set.</t>
          <artwork><![CDATA[
fn batch_open(
    ck: CommitterKey,
    polys: Vec<Polynomial<WitnessField>>,
    coms: Vec<Commitment>,
    challenges: Vec<Vec<Challenge>>,
    rs: Vec<Option<ChallengeField>>
) -> (Vec<Vec<ChallengeField>>, BatchProof)
]]></artwork>
          <t><strong>Input:</strong></t>
          <ul spacing="normal">
            <li>
              <t><tt>ck</tt>: the committer key</t>
            </li>
            <li>
              <t><tt>polys</tt>: the batch of polynomials to open</t>
            </li>
            <li>
              <t><tt>coms</tt>: the commitments corresponding to <tt>polys</tt>; <tt>coms.len()</tt> MUST equal <tt>polys.len()</tt></t>
            </li>
            <li>
              <t><tt>challenges</tt>: the sets of challenge points at which to evaluate each polynomial; <tt>challenges.len()</tt> MUST equal <tt>polys.len()</tt></t>
            </li>
            <li>
              <t><tt>rs</tt>: the OPTIONAL random blinding factors used in each commitment; <tt>rs.len()</tt> MUST equal <tt>polys.len()</tt></t>
            </li>
          </ul>
          <t><strong>Output:</strong></t>
          <ul spacing="normal">
            <li>
              <t><tt>evals</tt>: the evaluations of each polynomial at each challenge set; <tt>evals.len()</tt> MUST equal <tt>polys.len()</tt>, and each <tt>evals[j].len()</tt> MUST equal the corresponding <tt>challenges[j].len()</tt></t>
            </li>
            <li>
              <t><tt>batch_proof</tt>: an opening proof for the batch opening claim</t>
            </li>
          </ul>
        </section>
        <section anchor="batchverify">
          <name><tt>batch_verify</tt></name>
          <t>On input the verifier key <tt>vk</tt>, a vector of commitments <tt>coms</tt>, a vector of challenge sets <tt>challenges</tt>, a vector of their purported corresponding evaluations <tt>evals</tt>, and an opening proof <tt>BatchProof</tt>, <tt>batch_verify</tt> checks the opening proof, and either accepts or rejects it.</t>
          <artwork><![CDATA[
fn batch_verify(
    vk: VerifierKey,
    coms: Vec<Commitment>,
    challenges: Vec<Vec<ChallengeField>>,
    evals: Vec<Vec<ChallengeField>>,
    proof: BatchProof,
) -> bool
]]></artwork>
          <t><strong>Input:</strong></t>
          <ul spacing="normal">
            <li>
              <t><tt>vk</tt>: the verifier key</t>
            </li>
            <li>
              <t><tt>coms</tt>: a vector of polynomial commitments</t>
            </li>
            <li>
              <t><tt>challenges</tt>: the sets of challenge points at which each commitment was opened; <tt>challenges.len()</tt> MUST equal <tt>coms.len()</tt></t>
            </li>
            <li>
              <t><tt>evals</tt>: the purported openings of each commitment at each challenge set; <tt>evals.len()</tt> MUST equal <tt>coms.len()</tt>, and each <tt>evals[j].len()</tt> MUST equal the corresponding <tt>challenges[j].len()</tt></t>
            </li>
            <li>
              <t><tt>batch_proof</tt>: an opening proof for the batch opening claim</t>
            </li>
          </ul>
          <t><strong>Output:</strong></t>
          <ul spacing="normal">
            <li>
              <t><tt>batch_verify</tt> outputs <tt>true</tt> if the opening proof is valid, and <tt>false</tt> otherwise</t>
            </li>
          </ul>
        </section>
      </section>
    </section>
    <section anchor="concrete-polynomial-commitment-schemes-wip">
      <name>Concrete polynomial commitment schemes (WIP)</name>
      <section anchor="ligero-ahiv17">
        <name>Ligero <xref target="AHIV17"/></name>
        <t>The Ligero <xref target="AHIV17"/> proof system can be used to instantiate a polynomial commitment scheme. It is parameterised over a collision-resistant hash function <tt>CRHScheme</tt>. The following interface is adapted from the arkworks library <xref target="arkworks"/>.</t>
        <t>Both the <tt>LigeroCommitterKey</tt> and <tt>LigeroVerifierKey</tt> are the same type <tt>LigeroParams</tt>:</t>
        <artwork><![CDATA[
struct LigeroParams<CRHScheme> {
    security_bits: usize,
    /// The rate of the Reed-Solomon code.
    code_rate: usize,
}
]]></artwork>
        <section anchor="setup-1">
          <name><tt>setup</tt></name>
          <artwork><![CDATA[
fn setup<CRHScheme>(
    security_bits: usize,
    _num_vars: usize,
    _degree_bounds: Vec<usize>,
    _rng: Option<Rng>,
) -> (CommitterKey<CRHScheme>, VerifierKey<CRHScheme>) {
    let ck = LigeroParams<CRHScheme> {
        security_bits,
        code_rate = 4
    };
    let vk = LigeroParams<CRHScheme> {
        security_bits,
        code_rate = 4
    };
    (ck, vk)
}
]]></artwork>
        </section>
        <section anchor="commit-1">
          <name><tt>commit</tt></name>
          <artwork><![CDATA[
fn commit(
    ck: CommitterKey,
    poly: Polynomial<WitnessField>,
    r: Option<WitnessField>
) -> (Commitment, CommitmentState) {
    // 1. Arrange the coefficients of the polynomial into a matrix,
    // and apply encoding to get `ext_mat`.

    // 2. Create the Merkle tree from the hashes of each column.

    // 3. Obtain the MT root

    (commitment, leaves)
}
]]></artwork>
        </section>
        <section anchor="open-1">
          <name><tt>open</tt></name>
          <artwork><![CDATA[
fn open(
    ck: CommitterKey,
    poly: Polynomial<WitnessField>,
    com: Commitment,
    com_state: CommitmentState,
    challenge: Challenge,
    r: Option<WitnessField>
) -> Proof {
    // 1. Create the Merkle tree from the hashes of each column.

    // 2. Generate vector `b` to left-multiply the matrix.

    // 3. left-multiply the matrix by `b`.

    // 4. Generate t column indices to test the linear combination on.

    // 5. Compute Merkle tree paths for the requested columns.
}
]]></artwork>
        </section>
        <section anchor="verify-1">
          <name><tt>verify</tt></name>
          <artwork><![CDATA[
fn verify(
    vk: VerifierKey,
    com: Commitment,
    challenge: Challenge,
    eval: ChallengeField,
    proof: Proof,
) -> bool {
    // 1. Ask random oracle for the `t` indices where the checks happen.

    // 2. Hash the received columns into leaf hashes.

    // 3. Verify the paths for each of the leaf hashes - this is only run once,

    // 4. Compute the encoding w = E(v).

    // 5. Compute `a`, `b` to right- and left- multiply with the matrix `M`.

    // 6. Probabilistic checks that whatever the prover sent,
    // matches with what the verifier computed for himself.
}
]]></artwork>
        </section>
      </section>
    </section>
    <section anchor="security-considerations-wip">
      <name>Security Considerations (WIP)</name>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document has no IANA actions.</t>
    </section>
    <section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>The authors thank Mary Maller, Pierre Daix-Moreux, Oskar Thorén, Alex Kuzmin, and Manu Sporny, for reviewing a previous edition of this specification.</t>
    </section>
  </middle>
  <back>
    <references anchor="sec-informative-references">
      <name>Informative References</name>
      <reference anchor="arkworks" target="https://arkworks.rs">
        <front>
          <title>arkworks zkSNARK ecosystem</title>
          <author>
            <organization/>
          </author>
          <date/>
        </front>
      </reference>
      <reference anchor="fiat-shamir" target="https://mmaker.github.io/draft-zkproof-sigma-protocols/draft-orru-zkproof-fiat-shamir.html">
        <front>
          <title>draft-orru-zkproofs-fiat-shamir</title>
          <author>
            <organization/>
          </author>
          <date/>
        </front>
      </reference>
      <reference anchor="AHIV17" target="https://dl.acm.org/doi/10.1145/3133956.3134104">
        <front>
          <title>Ligero: Lightweight Sublinear Arguments Without a Trusted Setup</title>
          <author fullname="Scott Ames">
            <organization/>
          </author>
          <author fullname="Carmit Hazay">
            <organization/>
          </author>
          <author fullname="Yuval Ishai">
            <organization/>
          </author>
          <author fullname="Muthuramakrishnan Venkitasubramaniam">
            <organization/>
          </author>
          <date year="2017"/>
        </front>
      </reference>
    </references>
  </back>
  <!-- ##markdown-source:
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
QX+TOwAA

-->

</rfc>
