Pedersen Commitments, Divide-and-Conquer, and the Inner Product Argument

Dankrad Feist has a terrific post explaining Pedersen commitments, a commitment scheme that works on an elliptic curve. The Pedersen commitment ecosystem includes the inner product argument (a protocol for proving that a prover has correctly computed the inner product of two committed vectors) and Bulletproofs (a full proof system built on the inner product argument).

In short, the Pedersen commitment lets you commit to a vector of arbitrary length by giving just a single group element . The inner product argument takes as input two committed vectors and – the prover knows both and , but the verifier only knows the commitments and , which are elements of – and allows the prover to prove to the verifier that their inner product has a certain value. The proof uses a divide-and-conquer trick: at each step, you break the vector of length into two vectors of length , and then you reduce the problem to an inner product of vectors of length .

The goal of this note is to explain how you would think of the inner product argument. We’ll start with a simpler question: when the prover sends the verifier a commitment to a vector , it just looks like a plain old group element. How can the prover prove she knows the vector , without actually revealing ? This will lead us to a simpler version of the divide-and-conquer trick. Then we’ll see how a more complex application of the same algebra gives the inner product argument as well.

Pedersen commitments

To start with, let’s recall how Pedersen commitments work. Suppose you have a group – concretely, let’s say is an elliptic curve over some large finite field. Fix once and for all a bunch of “random” elements of , say . Now suppose you want to commit to a vector , for some . Your commitment is simply the group element

To open your commitment, you simply reveal the full vector , and the other party can verify that the commitment matches the vector.

Why does this work? You want a commitment scheme to have two properties: hiding and binding. Hiding means that it’s hard to recover from the commitment . Binding means that the committer is committed to : it’s hard to find two vectors and such that . We’ll see that our scheme is binding but not hiding.

Let’s assume that the discrete logarithm problem is hard in . For us, this means it’s hard to find such that . (This is widely believed to be true if is a large elliptic curve, for example.) This means it’s hard to find such that . But if , then , so we have proved that Pedersen commitments are binding.

On the other hand, Pedersen commitments as we’ve presented them don’t hide the committed vector. For example, imagine you commit to a vector and send the commitment to someone – but the other person knows that your vector has to be one of a short list of vectors. They can simply test those vectors one by one, computing for each of them, until they find a commitment that matches.

One solution to this is to introduce a “blinding term” , where is chosen at random. Instead of , you send – and to open the commitment, you reveal all of .

The blinding term makes the “guess the committed vector” attack impossible. In fact, since is chosen uniformly at random, the commitment will be statistically equally likely to be any element of . So you have a strong statistical guarantee that the commitment leaks no information at all about the original vector .

Proving you know a vector (Part 1: Hiding)

Let’s suppose a prover sent a commitment to a verifier, but the verifier wants to know that this group element is a commitment to a vector. In other words, the prover has to prove that she knows such that

(The basis elements are publicly known.)

One option is for the prover to simply reveal the scalars . This is unsatisfying, for two reasons. First, the prover doesn’t hide the vector from the verifier. And second, the protocol requires proof length. We’ll see how to achieve a proof that is both hiding and succinct.

Let’s start with hiding. To hide the prover simply chooses a second “blinding vector” and sends the commitment

The verifier responds with some random challenge , and asks the prover to show that is a known linear combination of . The prover replies with the vector

and the verifier checks that indeed

Why does this work? Simple algebra shows that, if the prover is playing honestly, the verifier’s check will pass. But what if the prover is not? The intuitive idea is that, if the prover does not know an expansion for in terms of the vectors , then she won’t be able to give an expansion for – at least, not for most values of . In fact, if the prover knows those expansions for even two values of , say and , then the prover can compute an expansion for itself, since

Here is another way to think about this situation, that will be useful for security proofs later on. Where did the prover get and ? There are basically two ways to get group elements: either the prover computed them from some already-known elements (like , or maybe others), or the prover chose them as new elements (e.g. at random), having no known relations with previously-chosen elements. In either case, let’s write

where are known group elements with no known relations between them. (If the prover chose at random, simply take to be one of the independent group elements, and take .)

Now the basic assumption is that the prover cannot find a nontrivial relation among the elements (except with very small probability of success). The verifier makes the challenge , and the prover responds by revealing some such that

This means that

At this point, either the prover has found a nontrivial relation, or all the coefficients on the ’s and ’s have to match. Since it’s assumed to be hard to find a relation, we can conclude that all the coefficient match. In particular,

for each .

But here’s the catch. The prover chose and before the verifier chose . If and are not both zero, then only one value of can possibly satisfy . The probability that the verifier happened to choose that particular is vanishingly small. So we can conclude that all the ’s and ’s are zero – in other words that

Proving you know a vector (Part 2: Succinctness)

We’ve seen how to prove we know a vector whose commitment is , while keeping the vector hidden. Now let’s try to make the protocol more succinct.

In fact, once we apply the hiding protocol once, we can forget about the hiding issue entirely. If the prover wants to prove knowledge of a private vector such that , the prover and the verifier simply run the protocol above (prover sends , verifier sends ) to reduce to the problem of proving knowledge of a vector whose commitment is . The original and have been replaced with and . There is no longer any need to keep them secret, since the random vector hides everything about anyway.

So, we may as well rename and to and again, and forget the hiding issue entirely.

Now let us suppose is even, and break down our vector of length into two vectors

of length .

While we’re at it, let’s define

and write

define and similarly.

The idea is to replace the vector with a random linear combination , and the group elements with a random linear combination . The new commitment will then be

To make the protocol work, the prover first sends the four group elements , and the verifier checks that . Then the verifier sends random challenges and . Finally, prover and verifier iterate the process, with

and in place of and .

Proving security

Why is this sound? The idea of the proof is the same as before: Suppose the prover sends

If the protocol passes, then the group element

must be a combination of the vectors . Since discrete logarithm is hard, the prover can’t come up with two expressions for the same group element in terms of and – so the -coefficient must be times the coefficient. That is,

This polynomial equality holds for randomly chosen and , so (unless the verifier’s random challenge was very unlucky) the two sides are actually the same polynomial of and . In other words, we can equate coefficients, and obtain: ,

In other words: The thing the prover claimed was was actually , for some known to the prover – and similarly for the other three claims. So (if we rename and ) the prover proved that she knows and such that .

Making the protocol more efficient

It turns out that the verifier doesn’t have to send two independent challenges and . Instead, he can take , so that

Since is already known, this means the prover only has to send the two commitments and before getting back the challenge from the verifier.

Inner product argument

Finally, let’s come back to the inner product argument. Suppose the prover wants to prove that some commitment (group element) is of the form

(Here and are vectors of length . The symbol is short for , an -tuple of group elements, and . Similarly for . The element is a single group element.)

The prover is going to replace both the vectors and and the basis group elements and with random linear combinations. As above, break the vector into two vectors and , each of half the length, so . Similarly for , , .

The naive generalization of the above protocol would be for the verifier to choose four random challenges , and then to replace , , , with the random linear combinations

Before the verifier sends the challenges, the prover would have to send enough data to enable the verifier to compute the new claimed commitment

Since the expression for contains product terms , the prover would have to commit to all the cross-terms:

Then the verifier would send the four challenges , , , , and they would repeat the protocol on the vectors and of half the length.

It turns out we can make the protocol much more efficient by taking

and

Again, this leads to a ton of cancellations. It turns out that instead of the 12 cross-terms shown, the prover can get away with sending just two group elements (the and -terms when is expanded in terms of ).

Of course, one still has to show that this protocol is secure against cheating provers. This is done by the same sort of calculation we did above – if you want to see the details, check out Dankrad’s post.