Polynomial commitments and Fiat–Shamir heuristic

In cryptographic schemes like PLONK, the prover needs to commit to certain polynomials to ensure that they do not change these polynomials later in the protocol.

Later in the protocol, the prover usually needs to prove that these polynomials evaluate at a certain point to the claimed values.

But this certain point must not be known ahead of time.

Let’s have a polynomial p(x)p(x). The prover computes the commitment to this polynomial: pcp_c.

At some point in the protocol, the verifier chooses a random χ\chi, gives it to the prover, and the prover returns p¯=p(χ)\bar{p} = p(\chi).

The messages go like:

ProverpcVerifier\text{Prover} \rightarrow p_c \rightarrow \text{Verifier}

ProverχVerifier\text{Prover} \leftarrow \chi \leftarrow \text{Verifier}

The prover then has to prove that it knows a polynomial that evaluates to p¯\bar{p} at χ\chi. We say the prover opens pp at χ\chi.

Remember, when using KZG commitments, the prover computes g(x)g(x) such that:

p(x)p¯=g(x)(xχ)p(x) - \bar{p} = g(x) (x - \chi)

The prover opens p(x)p(x) at χ\chi by sending [g(s)]1[g(s)]_1 to the verifier:

Prover[g(s)]1Verifier\text{Prover} \rightarrow [g(s)]_1 \rightarrow \text{Verifier}

Usually, the prover needs to prove some relations between the polynomials. Let’s say there is another polynomial q(x)q(x). And let’s say the prover would like to prove the relation:

p(x)q(x)+1=0p(x) q(x) + 1 = 0

Let’s denote h(x)=p(x)q(x)+1h(x) = p(x)q(x) + 1.

The prover doesn’t want to reveal p(x)p(x) and q(x)q(x). Instead, it proves that it knows a polynomial that evaluates to p¯\bar{p} at χ\chi and that it knows a polynomial that evaluates to q¯\bar{q} at χ\chi.

The prover computes the commitment to h(x)h(x): [h(s)]1[h(s)]_1. It then computes h1(x)h_1(x) such that:

h(x)h(χ)=h1(x)(xχ)h(x) - h(\chi) = h_1(x) (x - \chi)

The verifier is given p¯\bar p, q¯\bar q, [h(s)]1[h(s)]_1, [h1(s)]1[h_1(s)]_1 and checks whether:

e([h(s)p¯q¯1]1,[1]2)=e([h1(s)]1,[(sχ)]2)e([h(s) - \bar p \bar q - 1]_1, [1]_2) = e([h_1(s)]_1, [(s - \chi)]_2)

Note that [h(s)p¯q¯1]1[h(s) - \bar p \bar q - 1]_1 can be easily computed having [h(s)]1[h(s)]_1, p¯\bar p, and q¯\bar q: [h(s)p¯q¯1]1=[h(s)]1[p¯q¯+1]1[h(s) - \bar p \bar q - 1]_1 = [h(s)]_1 - [\bar p \bar q + 1]_1.

What if the challenge is known ahead of time?

So, what if the prover knows χ\chi ahead of time?

Well, the prover could take an arbitrary polynomial (of the proper degree) that evaluates to p¯q¯\bar p \bar q at χ\chi. Let’s denote such a polynomial by r(x)r(x):

r(χ)=p¯q¯+1r(\chi) = \bar p \bar q + 1

It then computes r1(x)r_1(x) such that:

r(x)r(χ)=r1(x)(xχ)r(x) - r(\chi) = r_1(x) (x - \chi)

The prover sends [r(s)]1[r(s)]_1 and [r1(s)]1[r_1(s)]_1 to the verifier (instead of [h(s)]1[h(s)]_1 and [h1(s)]1[h_1(s)]_1).

The following check that verifier executes turns out to be true:

e([r(s)p¯q¯1]1,[1]2)=e([r1(s)]1,[(sχ)]2)e([r(s) - \bar p \bar q - 1]_1, [1]_2) = e([r_1(s)]_1, [(s - \chi)]_2)

Note that the verifier doesn’t compute [h(s)]1[h(s)]_1 out of [p(s)]1[p(s)]_1 and [q(s)]1[q(s)]_1 because that’s not possible—Kate commitments are not fully homomorphic; they are only additively homomorphic.

Fiat-Shamir

So, it’s crucial that the prover doesn’t know the challenge in advance. However, in real-world applications, it’s often beneficial to reduce communication between the involved parties. The Fiat–Shamir heuristic eliminates the need for the verifier to choose and send a challenge to the prover by computing the challenge using a cryptographic hash function."

However, how to guarantee that the challenge has been computed only after the prover committed to h(x)h(x)? Remember, otherwise the prover could choose some arbitrary r(x)r(x) that evaluates to p¯q¯+1\bar p \bar q + 1 at χ\chi and then commit to r(x)r(x) instead of h(x)h(x).

To prevent such a scenario, the challenge needs to be computed by taking into account the commitment to h(x)h(x).

So, part of the input to hash function to compute the challenge needs to be the commitment to h(x)h(x). Note that the inputs to hash function need to be known to both parties - prover and verifier. Obviously, they both need to compute the challenges.

So, part of the input to the hash function to compute the challenge needs to be the commitment to h(x)h(x). Note that the inputs to the hash function need to be known to both parties—the prover and the verifier. Obviously, they both need to compute the challenge.