Bulletproofs ZKP: Zero Knowledge and Succinct Proofs for Inner Products

Bulletproofs ZKPs allow a prover to prove knowledge of an inner product with a logarithmic-sized proof. Bulletproofs do not require a trusted setup.

In the previous chapters, we showed how to prove knowledge of an inner product without revealing the vectors or the inner product, albeit with a proof of size O(n)\mathcal{O}(n) where nn is the length of the vector. We also showed how to prove knowledge of an inner product using logarithmic-sized data, but without the zero knowledge property.

In this chapter, we combine the algorithms together to demonstrate the Bulletproof ZK algorithm.

(This work if part of a series on ZK Bulletproofs.)

Problem Statement

The prover and verifier agree on two elliptic curve basis vectors G\mathbf{G} and H\mathbf{H} of length nn and elliptic curve points QQ and BB. The discrete log relationships between all these points are unknown.

The prover has vectors a\mathbf{a} and b\mathbf{b} with inner product vv. The prover commits a\mathbf{a} and b\mathbf{b} to AA as A=a,G+b,H+αBA =\langle\mathbf{a},\mathbf{G}\rangle + \langle\mathbf{b},\mathbf{H}\rangle + \alpha B where α\alpha is a blinding term. The prover commits V=a,bQ+γBV = \langle\mathbf{a},\mathbf{b}\rangle Q + \gamma B.

The prover sends (A,V)(A, V) to to the verifier and aims to prove that a\mathbf{a} and b\mathbf{b} are committed to AA and their inner product is committed to VV. The verifier does not learn the vectors or the inner product.

The size of the proof must be O(logn)\mathcal{O}(\log n).

The Bulletproof ZK Algorithm

The prover generates random scalars {α,β,γ,τ1,τ2}\set{\alpha, \beta,\gamma,\tau_1,\tau_2} and random vectors {sL,sR}\set{\mathbf{s}_L,\mathbf{s}_R} and computes the commitments

A=a,G+b,H+αBS=sL,G+sR,H+βBV=vQ+γB\begin{align} A &= \langle\mathbf{a},\mathbf{G}\rangle + \langle\mathbf{b},\mathbf{H}\rangle+\alpha B\\ S &= \langle\mathbf{s}_L,\mathbf{G}\rangle + \langle\mathbf{s}_R,\mathbf{H}\rangle+\beta B\\ V &= vQ + \gamma B \\ \end{align}

The prover prepares (but does not send) vector polynomials

l(x)=a+sLxr(x)=b+sRxt(x)=l(x),r(x)=a,b+(a,sR+b,sL)x+(sL,sR)x2\begin{align*} \mathbf{l}(x) &= \mathbf{a} + \mathbf{s}_Lx\\ \mathbf{r}(x) &= \mathbf{b} + \mathbf{s}_Rx\\ t(x)&=\langle\mathbf{l}(x),\mathbf{r}(x)\rangle = \langle\mathbf{a},\mathbf{b}\rangle+(\langle\mathbf{a},\mathbf{s}_R\rangle + \langle\mathbf{b},\mathbf{s}_L\rangle) x+(\langle\mathbf{s}_L,\mathbf{s}_R\rangle)x^2 \end{align*}

AA is a commitment to the constant terms of the vector polynomial, SS is a commitment to the linear terms, and VV is a commitment to the inner product.

The prover creates commitments to the coefficients of t(x)t(x) as

T1=(a,sR+b,sL)Q+τ1BT2=sL,sRQ+τ2B\begin{align*} T_1 &= (\langle\mathbf{a},\mathbf{s}_R\rangle + \langle\mathbf{b},\mathbf{s}_L\rangle)Q + \tau_1B\\ T_2 &= \langle\mathbf{s}_L,\mathbf{s}_R\rangle Q + \tau_2B \end{align*}

Note that VV is a commitment to the constant coefficient of t(x)t(x), and T1T_1 and T2T_2 are commitments to the linear and quadratic coefficients of t(x)t(x), respectively.

The prover sends (A,S,V,T1,T2)(A, S, V, T_1, T_2) to the verifier.

The verifier responds with random value uu.

The prover then evaluates the polynomials at uu and creates proofs that they were evaluated correctly:

lu=l(u)=a+sLuru=r(u)=b+sRutu=t(u)=v+(a,sR+b,sL)u+sL,sRu2πlr=α+βuπt=γ+τ1u+τ2u2\begin{align*} \mathbf{l}_u &= \mathbf{l}(u) = \mathbf{a} + \mathbf{s}_Lu \\ \mathbf{r}_u &= \mathbf{r}(u) = \mathbf{b} + \mathbf{s}_Ru \\ t_u &= t(u) =v + (\langle\mathbf{a},\mathbf{s}_R\rangle + \langle\mathbf{b},\mathbf{s}_L\rangle)u + \langle\mathbf{s}_L,\mathbf{s}_R\rangle u^2\\ \pi_{lr} &=\alpha+\beta u\\ \pi_t &= \gamma + \tau_1u + \tau_2u^2\\ \end{align*}

Previously, the prover transmits (lu,ru,tu,πlr,πt)(\mathbf{l}_u, \mathbf{r}_u, t_u, \pi_{lr}, \pi_t) so the verifier could check that

tu=?lu,ruA+Su=?lu,G+ru,H+πlrBtuQ=?V+T1u+T2u2πtB\begin{align*} t_u&\stackrel{?}=\langle\mathbf{l}_u,\mathbf{r}_u\rangle\\ A + Su &\stackrel{?}{=} \langle \mathbf{l}_u, \mathbf{G} \rangle + \langle \mathbf{r}_u, \mathbf{H} \rangle + \pi_{lr} B\\ t_u Q &\stackrel{?}{=} V + T_1 u + T_2 u^2 - \pi_t B\\ \end{align*}

but this would be linear in size due to the vectors lu\mathbf{l}_u and ru\mathbf{r}_u. Instead, the prover commits lu\mathbf{l}_u and ru\mathbf{r}_u as

C=lu,G+ru,HC=\langle\mathbf{l}_u,\mathbf{G}\rangle+\langle\mathbf{r}_u,\mathbf{H}\rangle

and sends (C,tu,πlr,πt)(C, t_u, \pi_{lr}, \pi_t).

We can re-arrange the first two verifier checks as follows:

tu=?lu,ruA+SuπlrB=?lu,G+ru,H\begin{align*} t_u&\stackrel{?}=\langle\mathbf{l}_u,\mathbf{r}_u\rangle\\ A + Su -\pi_{lr}B&\stackrel{?}{=} \langle \mathbf{l}_u, \mathbf{G} \rangle + \langle \mathbf{r}_u, \mathbf{H} \rangle\\ \end{align*}

Observe that if we set P=A+SuπlrBP = A + Su -\pi_{lr}B, then this is the same problem statement as proving PP holds commitments to two vectors lu\mathbf{l}_u and ru\mathbf{r}_u with respect to the basis vectors G\mathbf{G} and H\mathbf{H}, and that lu\mathbf{l}_u and ru\mathbf{r}_u have an inner product of tut_u. Therefore, we can reuse the logarithmic-size proof of knowledge of a commitment opening to PP.

For this proof, we do not need secrecy because lu\mathbf{l}_u and ru\mathbf{r}_u were made public anyway in the previous algorithm.

Now that the verifier has all the necessary data, the prover engages in an interactive proof to prove that CC holds the commitments to lu\mathbf{l}_u and ru\mathbf{r}_u and that their inner product is tut_u:

\texttt{prove_commitments_log}(C + t_uQ, \mathbf{G}, \mathbf{H}, Q, \mathbf{l}_u, \mathbf{r}_u)

That subroutine will prove that tu=?lu,rut_u\stackrel{?}=\langle\mathbf{l}_u,\mathbf{r}_u\rangle and C=?lu,G+ru,HC\stackrel{?}{=} \langle \mathbf{l}_u, \mathbf{G} \rangle + \langle \mathbf{r}_u, \mathbf{H} \rangle without having to send lu\mathbf{l}_u and ru\mathbf{r}_u. It also only sends logarithmic-sized data. Note that the recursive algorithm from the previous chapter uses a commitment P=a,G+b,H+a,bQP = \langle \mathbf{a}, \mathbf{G} \rangle + \langle \mathbf{b}, \mathbf{H} \rangle + \langle\mathbf{a},\mathbf{b}\rangle Q, so the verifier needs to add in the “QQ portion” themselves. Now the verifier can be assured that

tu=?lu,ruC=?lu,G+ru,H\begin{align*} t_u&\stackrel{?}=\langle\mathbf{l}_u,\mathbf{r}_u\rangle\\ C&\stackrel{?}{=} \langle \mathbf{l}_u, \mathbf{G} \rangle + \langle \mathbf{r}_u, \mathbf{H} \rangle\\ \end{align*}

Finally, the verifier checks that

C=?A+SuπlrBtuQ=?V+T1u+T2u2πtB\begin{align*} C&\stackrel{?}=A + Su-\pi_{lr}B\\ t_u Q &\stackrel{?}{=} V + T_1 u + T_2 u^2 - \pi_t B \end{align*}

Recall that AA and SS are commitments to the constant and linear terms of the vector polynomials l(x)\mathbf{l}(x) and r(x)\mathbf{r}(x), respectively. The first check ensures that the vectors committed to CC are evaluations of those polynomials at uu.

The second check is to ensure that t(u)t(u) was evaluated correctly, given the commitments to the coefficients VV, T1T_1, and T2T_2.

Non-interactivity via the Fiat Shamir Transform

In practice, this algorithm is made non-interactive via the Fiat Shamir Transform. Instead of asking the verifier for randomness, the prover generates randomness by concatenating all the data it has transmitted so far and hashing that. The verifier then re-hashes the data to ensure the prover generated the randomness correctly.

It is critical that the hash include all previous data transmissions, otherwise the implementation will have a frozen heart vulnerability.

Next steps

In practice, problems of practical interest consist of multiple inner products. For example, a Rank 1 Constraint System:

LaRa=OaL\mathbf{a}\circ R\mathbf{a} = O\mathbf{a}

is really 3n3n inner products (e.g. multiplying a\mathbf{a} by the nn rows of LL and so on for RR and OO) and a single Hadamard product. Therefore, it will be handy to know some mathematical tricks for combining multiple inner products into a single one so that we don’t have to send 3n3n Bulletproofs. We will learn how to accomplish this in our upcoming chapter on random linear combinations.

Furthermore, some useful problems can be directly encoded as an inner product, notably the range proof or the subset sum problem. In those situations, we can skip encoding the problem as an arithmetic circuit and directly encode it as an inner product. To increase the flexibility of our inner product representation, as well as to lay the ground work for understanding random linear combinations, we will learn some inner product algebra in the next chapter.

Exercise: Combine the previous exercises to prove that A=a,G+b,H+αBA =\langle\mathbf{a},\mathbf{G}\rangle + \langle\mathbf{b},\mathbf{H}\rangle + \alpha B where a\mathbf{a} and b\mathbf{b} are vectors of length 4. Your proof should be both succinct and zero knowledge. Create an interactive proof for the sake of simplicity. Refer to this repository for the exercises.

Ready to Get Started?Join Thousands of Users Today

Start your free trial now and experience the difference. No credit card required.

© 2025 Better-Start. All rights reserved.