Zero-knowledge proofs are famous for packing incredible security into tiny proofs, but how do they actually pull that off?

The secret is in the Inner Product Argument (IPA), the mathematical engine behind Bulletproofs.

In this post, we’ll peel it apart step by step and see how it really works, complete with runnable SageMath code you can play with yourself, because nothing beats code for building intuition.

This is part two of a small series on the IPA/Bulletproofs protocol. If you missed part 1, start there for the big picture: High-level intuitions for the Bulletproofs/IPA protocol.

Here, we’ll zoom in on the core of the protocol and uncover the mysterious L and R “cross terms” that make it all click.

If you’re curious, the scripts are up on GitHub.

But let’s warm up first. We’ll start with the bare essentials: no commitments, no elliptic curves, no zero-knowledge magic. Just vectors and inner products. Once that picture is clear, adding the crypto magic (Pedersen commitments) will feel much more natural.

The Inner Product Argument, Step One: No Commitments Yet

We start with two vectors $\vec{a}$ and $\vec{b}$. The prover wants to convince the verifier that their inner product is some value c

$$ \langle \vec{a},\vec{b} \rangle = c $$

Of course, if we’re not hiding anything, the prover could just send both vectors to the verifier. Easy, but boring 🥱. The real challenge is:

That’s where folding comes in.

Folding Vectors to Compress the Proof

We already saw folding in part 1:

Each round halves the length, until we’re left with just a single entry.

For this to work smoothly, we need: