salvor voboda

Proof Projectors

Everyone's focused on what ZK proofs hide. We're missing what they can usefully reveal.

Reputation, attendance, commitment, these used to require surveillance infrastructure. We're rightly moving away from that.

But those signals served real purposes. Communities need legibility to coordinate: is this restaurant safe to eat at, is this contractor reliable, did people actually show up, is this neighborhood getting the services it was promised.

ZK proofs now let us rebuild those public signals without the surveillance. Privacy and transparency are not opposites anymore.

I've been working on a system that does this for a specific problem, and the architecture generalizes, so I thought it was worth sharing. (And the gotchas too.)

I call the pattern a Proof Projector.

A Proof Projector is a system that takes privately held proofs and emits public, verifiable signals about a group, a state, or an aggregate β€” without revealing the underlying personal data. It separates what individuals prove from what the system publishes.

That makes it broad enough for attendance, reputation, eligibility, coordination metrics, and other cases where you want social legibility without a surveillance graph.

The RSVP Problem

I got pulled into this problem by Ligi and Afri, some of the organisers of ethBerlin and Protocol Berg. They're the anchor events of Berlin Blockchain Week.

At Blockchain Weeks, no-shows are a big problem. RSVPs are free options. Collecting them is rational. Organizers compensate by inflating capacity, competing on hype, stacking events against each other.

High-signal rooms β€” round-table dinners, technical meetups, problem-solving groups, reading clubs, even the good workshops β€” get washed away under the hype.

And the big events suffer too. The whole system optimizes for attention, not cohesion. You ping between events, feeling like the party moved somewhere else just before you arrived. And there are amazing talks given to echoey rooms that could've been buzzing with great people and projects. When you're back on a plane, you're somehow less connected than you hoped. Ethereum's flagship event in Thailand was badly affected by this β€” Devcon itself had empty rooms. Everyone was guessing which side event was the hot one, and the sad reality was people were stuck in Bangkok traffic for the whole week.

A fix is making demonstrated participation matter. Signalling which events have sign ups from people who actually show up about those topics. It makes the game less about raw numbers, and more about knowing all the right people will be there when you show up.

I've been attempting to do that with zKal, a privacy perserving community calendar I hacked last ethBerlin.

The Proof Projector

We want data to be transparent, composable. But we want claims about data to be verifiable without revealing the data itself. Most systems pick one. Proof Projection makes you separate them into two layers.

Shine a light onto a wall, over dozens of complex, overlapping 3D shapes and they cast a single 2D silhouette. You can clearly see the outline, but it's physically impossible to reverse-engineer the exact geometry of any single shape hiding inside the mass.

A Proof Projector creates that structural asymmetry. The objects are our complex personal histories, represented mathematically as high-dimensional polynomials inside a zero-knowledge circuit. The public information is the shadow on the wall, reduced to a one-dimensional number.

The proof layer

At the personal layer, we use Zupass and the POD system. The user holds their private history, credentials, and attendance data entirely in their own wallet.

When qualifying for access to a new event, they emit only a zero-knowledge proof about a specific property of that history, using selective disclosure through the Z-API query system. They prove they hold a valid attendance proof matching a qualifying event, without revealing which event, when, or any linkable identifier.

The issuer only verifies that you're eligible for a ticket at a given access phase: the first tickets are open to prior attendees, then to attendees of related events. The ticket issuer doesn't need to know who you are, and they don't need to store any record of you other than ticket inventory for each event. You just tally that one more spot was taken.

No identity graph. No central registry.

For each signup, the Projector Function produces a single number, a weight, that's projected into the aggregate layer.

Only the weight enters the aggregate layer. The person doesn't.

The aggregate layer

The aggregate layer is public, designed for transparency. That's why it never sees personal data.

The weights it receives get committed to a public record so anyone can verify them and the indexes that are calculated based on them. For immutability, you could use Merkle-rooted attestations on ATPROTO or something like Ethereum Attestation Service.

Those weights are then combined through an aggregate function to produce the public index. This means each event's signup quality score can be reconstructed from the public signup stream. Individual attendance histories cannot.

The Projector Function

The pattern works because the two layers don’t leak into each other.

You have to get clear on what needs to be provable, and to whom, then define the link between layers.

The Projector Function does that. It sits at the boundary between the two layers: it accepts a ZK proof from the personal layer, verifies it, derives a single anonymous value from it, and emits that value into the public layer.

Absolutely nothing else crosses the boundary.

In zKal's case, participants need to prove attendance to prior events to request tickets. Event hosts need signup stats they can actually rely on. The public needs to verify claims about the commitment of their ticket holders, to sense which events will have a solid community.

All of that goes in the public layer.

zKal

For Berlin Blockchain Week, I built zKal. It's an events calendar with ticketing built in, except the tickets are all ZK Proofs using Zupass.

Whoever hosts a zKal instance, whether EF or any local community group, becomes a ticket issuer for their whole community, which can both integrate platforms like Luma as backends, or replace them. Either way, this moves an ecosystem into zero-knowledge anonymous tickets, and lets the whole ecosystem see useful data that helps it improve.

In this role as calendar and ticket issuer, zKal mediates between private individual interactions and public aggregate data. That's where the Proof Projector pattern does its work.

The zKal instance publishes anonymized signup events that include the specific event and a single weight expressing the value of that person's signup to the event. The weight is higher if they have a good attendance history for this event, or related topics.

The crucial property is that you can't connect the outputs back to the inputs; the math discards information. It's one-way by construction.

Trust model

A future version could use a recursive ZK Proof system, like o1 Lab's Kimchi, so the issuer publishes a ZK proof that they checked the ticket applicant's ZK proofs correctly. That would mean full cryptographic verification from public data all the way back to the individual (and still private) attendance proofs: fully "trustless". (Zupass doesn't use Kimchi, or support this kind of true recursion.)

But since each layer can have different trust assumptions, a simpler version is possible.

I rely on a Verifiable Credential from the issuer. That makes the calendar host an issuer for event reputation in their ecosystem, with the same trust model as any VC system. The event hosts or attendees always provide proof to the issuer, and the ticket issuer verifies it and then signs attestations for public record.

In this simpler version, we only trust the issuer to attest they did the eligibility check honestly.

So we have ZK proofs to protect personal data and issue tickets. And VCs for event stats and quality metrics.

What a Proof Projector Must Guarantee

The Proof Projector pattern doesn't get you off the hook on correlation attacks. While the cryptographic proofs can't be reverse-engineered, observing the output values and timing of the Projector can leak metadata.

We need to carefully manage the frequency and granularity of what gets projected. For the pattern to hold, three properties are required:

  1. ZK proofs with private inputs. The proof must be generated from data that never leaves the user's device.
  2. Non-unique outputs. The value emitted into the public layer must not be unique to the individual. The output set needs to be small enough that any given value is plausibly shared by many participants.
  3. Non-correlatable outputs. Patterns across outputs can re-identify people. Some approaches help here: minimizing the possible output set (fewer distinct values means more cover), selecting among eligible inputs privately (ideally randomly), obfuscating timing with batcheing and/or random delays.

In zKal, we don't know which matching tickets a participant selected to compute their weight. That's chosen deterministically (the highest weight attendance proof you have), which isn't randomly, but at least chose from a private set of options.

The Density Index

There's still a catch. The Proof Projector gives you the architecture. It doesn't tell you what to project or how to aggregate.

Choosing privacy sharpens that question rather than dodging it. When you can't see raw attendance history, you're forced to ask: what's the minimum signal, derived from private inputs, that still tells you something real? What aggregate function produces a public number worth acting on?

In our case, how can visible participation history actually shift which events rise, which communities cohere, which rooms fill with the people who matter to each other?

That's a design problem in its own right. It's part incentive mechanism, part community scoring, part game theory. My answer to it for the RSVP Problem is The Density Index. (Which I'll write more about later.)

Use the pattern

Private and transparent aren't opposites. The trick is separating the layers:

When you want social legibility without a surveillance graph, if you're working with attendance, reputation, eligibility, or coordination, see if Proof Projectors get you there.