You're a node operator watching a two-output Monero transaction arrive before the October 2018 protocol upgrade. Before you can accept it, your software has to chew through roughly 13 kilobytes of range proof data, verifying that neither output amount is negative, neither overflows the supply cap, and neither reveals a single satoshi of information to you in the process. You do this for every transaction. Every block. The bandwidth bill is quiet but relentless.
That is the problem Bulletproofs were built to kill.
The old way: linear growth, linear pain
A Pedersen commitment is elegant in the way a well-drafted contract clause is elegant: it does exactly one thing, precisely. Commit to a value v by publishing v·G + r·H, where G and H are elliptic curve generators and r is a blinding factor. The verifier learns nothing about v, but the committer can later open it. The commitment itself is compact, a single curve point, roughly 33 bytes on a compressed curve.
The proof that v lies within a range, say 0 to 2⁶⁴, is where things historically ballooned. The classical approach decomposes the value into 64 individual bits and produces a separate sigma protocol proof for each one. Each bit proof runs to roughly 64 bytes. Multiply across 64 bits and you're carrying around 4 kilobytes of proof material per output, before any other transaction data. Add multiple outputs to a single transaction and the size stacks linearly. Verification time stacks with it.
Monero used exactly this construction before Bulletproofs. A two-output RingCT transaction carried range proofs around 13 kilobytes total. That's not a rounding error. It's a meaningful fraction of block space, and it means heavier fees and slower sync for every node on the network.
What Bulletproofs actually do differently
Bulletproofs, introduced by Bünz, Bootle, Poelstra, Wuille, and Maxwell in 2017, replace that linear stack of bit proofs with a single logarithmic-sized argument. The core insight is an inner product argument: instead of proving each bit individually, the prover encodes the entire bit-vector and its powers-of-two weights into two vectors, then proves a single inner product relation holds between them. That one relation implies range membership for the whole value.
The inner product argument is itself the clever part. A naive proof of an inner product over two vectors of length n would require transmitting all n elements, linear again. Bulletproofs use a recursive halving trick: split each vector in half, commit to cross-terms, and reduce the problem to an inner product over vectors of length n/2. Repeat. Each round halves the vector length and adds only two new curve points to the proof. After log₂(n) rounds, the residual vectors are length one, and the whole argument collapses to a constant-size check.
Think of it like a bracketed tournament where each round eliminates half the field. You don't need to watch every individual match to know who won.
For a 64-bit range, that's six rounds of halving, not 64 individual proofs. The resulting proof is roughly 672 bytes, compared to the approximately 4 kilobytes of the bit-by-bit approach: a reduction of over 80 percent in proof size.
The efficiency story gets better with aggregation. If a transaction has two outputs, both needing 64-bit range proofs, the naive approach doubles the proof size to 8 kilobytes. Bulletproofs allow the two ranges to be proven together in a single aggregated argument by concatenating the bit-vectors before applying the inner product protocol. Two outputs cost roughly 738 bytes. Four outputs cost around 802 bytes. The marginal cost of adding another output grows only logarithmically, which is the structural property that matters most here. Proving eight outputs together is barely larger than proving two.
Consider two users, call them Priya and Leon, both sending four-output Monero transactions on either side of the Bulletproofs upgrade. Priya's pre-upgrade transaction carries four separate range proofs totaling roughly 16 kilobytes for those proofs alone. Leon's post-upgrade transaction carries one aggregated Bulletproof of about 802 bytes covering all four outputs. Same cryptographic guarantee. One forty-fifth the proof data. The fees Priya paid were not funding better security; they were funding an inefficient construction that happened to be the best available tool at the time.
After the upgrade, average Monero transaction size dropped by roughly 80 percent almost immediately. Verification time per range proof fell by a factor of around ten compared to the old construction.
One honest caveat
Verification in Bulletproofs is computationally more expensive per proof than verification of a single Schnorr-style sigma protocol, because the recursive structure requires the verifier to perform more elliptic curve scalar multiplications. The size win is real and large. The verification speed win is more modest, and anyone claiming otherwise is selling something. Batch verification, where a node checks many proofs simultaneously using random linear combinations, recovers most of that cost, but the tradeoff exists and deserves acknowledgment in any serious technical evaluation.
Bulletproofs+ (2020) and subsequent constructions have since trimmed another 96 bytes or so off the proof and reduced verifier work further. The logarithmic structure opened a door that linear bit proofs had kept firmly shut, and the field has been walking through it ever since.
So if you're evaluating any privacy protocol that claims efficient range proofs, ask the right question: not whether it uses commitments (almost everything does), but how proof size scales with both the bit-width of the range and the number of outputs. Linear scaling is a structural defect, not an implementation detail. Logarithmic scaling, achieved through an inner product argument or something equivalent, is the bar Bulletproofs set, and the protocols that can't clear it are asking you to pay Priya's fees for Leon's guarantees.