salvor voboda

Provable Sums (how to get both privacy and transparency)

Privacy and transparency.

Not opposites anymore.

ZK proofs allow for private data that can be checked without revealing it, but how do you get aggregate transparency without the raw data?

Separate what individuals prove from what the system publishes, and you can have both - privacy for the individual, verifiability for the aggregate.

I've been working on a system that uses this pattern to fix a specific problem β€” RSVP inflation at conference weeks, aka. the RSVP problem, aka. the Empty Rooms problem.

This architecture generalizes (with some gotchas), so I thought it was worth sharing. I call the pattern a Provable Sum.

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 the knowing all the right people will be there when you show up.

We can do that while preserving individual privacy, by separating what people prove from what the system publishes.

Two Layers, Two Properties

So, here's the tension I kept hitting:

Most systems pick one. This architecture separates them.

The system I built is called zKal. It's an events calendar, with ticketing built in.

Whoever hosts a zKal instance, whether EF or any local community group, becomes a ticket issuer for their whole community, replacing things like Luma. The difference is they're issuing zero-knowledge anonymous tickets, and broadcasting anonymised event-specific data for the ecosystem.

(Side note: this can actually just integrate with Luma as the backend, giving the event hosts the convenience of sticking with it, plus the exposure to more relevent attendees, and the attendees still get full privacy.)

Individual layer:

zKal issues tickets using the PODs (Provable Object Data), the zero-knowledge credentials schema used by Zupass. The zKal server doesn't even need to store this ticket data β€” the tickets themselves are PODs that only exist in each user's Zupass wallet.

When qualifying for early access to a new event, attendees use selective disclosure through the Z-API query system β€” proving 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 β€” that one more spot was taken.

No identity graph. No central registry.

Aggregate layer:

The zKal instance publishes anonymized signup events β€” not just statistics, but each anonymised signup event, from which statistics are computed.

These get committed to a verifiable public record: Merkle-rooted attestations on ATPROTO or Ethereum Attestation Service.

That's the transparency requirement β€” each event's signup quality score can be reconstructed from the public signup stream. Individual attendance histories cannot.

Two Layers, Two Sets of Needs

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

The trick is getting clear on what actually needs to be provable, and to whom, keeping those separated. Then working out an explicit link between the layers.

Participants need to prove attendence to gain early access. That exists locally in their wallets, never in the public record.

Event hosts need signup stats they can actually rely on. And the the public needs to verify their claims about the committment of their ticket holders, to sense which events will have a solid community. That all goes in the public layer.

Two Trust Models

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.

The Density Index

There's still a catch.

How do you score an event's quality based on participants' history when that history is private?

That's an incentive problem we need to solve. But the answer falls out of the architecture too.

At the selective disclosure step β€” when someone proves eligibility for a ticket β€” the proof carries properties derived from private inputs: recency, event type, event size. Enough to generate a single weight. Not unique, not traceable.

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

When someone RSVPs, their weight reflects skin in the game. The more consistently someone shows up at relevant events, the heavier it gets β€” and the more they have to lose. Losing early access next time actually stings when you've been earning it.

So we have a formula that reveals each event's signup quality in realtime.

Density Index = mean(participant_weights) x penalties (more on these later)

Each RSVP contributes one weight derived from three factors:

That's the score each event on the calendar gets. That's how everyone knows how likely an event is to have a high density of people committed to the its topic.

The game this creates

Right now, event organizers play a simple game: maximize RSVPs, compete on hype. The currency is attention. The usual tactics are free drinks and big-name speakers and aggressive cross-sponsorship with anyone who'll have you. (That's why they all start feeling the same.)

zKal creates a second game. Your event now has a score β€” a public signal of whether your attendees actually show up, how strong your community core is.

That score gets you featured in the calendar. That score tells people with five choices to pick you.

Suddenly, returning members are your most valuable asset. You start caring about which communities you invite, not just how many people you get in the door. My hope is that will benefit events that differentiate, and communities that prioritise support.

The cynical version of this game still exists. A competitive event will notice that pulling their most successful competitors' community members spikes their weight. Two friendly organizers will notice that mutual cross-listing gets them free points.

But the version we're trying to tip people toward is more interesting. When your score compounds with genuine retention β€” people who came last time, brought a friend, came back again β€” you stop optimizing for footfall and start optimizing for your community members' success. You want the kind of attendee who'll be building on what they learned at your event six months later, who'll introduce two people who end up collaborating, who'll come back because last time mattered to them.

That's a different conference experience than the one everyone's been building.

The question is whether the score makes enough organizers play the second game to shift the ecosystem β€” or whether the edge cases eat it first.

Running permutations

That starting model β€” recency Γ— relatedness Γ— size β€” came from first principles. Which is exactly the problem with it. Incentive systems don't fail because the logic is wrong. They fail because games are gonna get gamed.

So I put it under some pressure to test it.

I vibe-coded a kind of shitty Monte Carlo simulator and threw two years of Blockchain Week event listing data at it. No historical attendance records existed, only event listings, so the exercise was about ranging assumptions across scenarios and hunting for the cases where the model broke.

I kept running it over and over, looking for things that looked wrong, adding something to the formula to address it.

Phase 1 β€” the curation problem. Hosts that want to attract a lot of people can select many qualifying communities to maximize their access pool. For example, choose attendees of the biggest or most exclusive events for early access to yours. So we need to limit that.

The simulations showed an optimal range of 3–4 relevant intake events. So the Index score has a "curation penalty" that pushes each event into that range. The farther you go from there, the bigger the penalty, applied on a S-curve.

Phase 2 β€” the collusion problem. A related event adds weight, but this can be faked. We need related events' weights to reflect some consensus of value in the ecosystem. This comes from increasing the weight for events that are selected by others for early access. Nuy sgain, organisers could form small cartels to choose each other's events as related to theirs, to artificially inflate their scores.

A there's the flip side: collusion in a protocol sense is just normal collaboration in the crypto events world. A relatively small group of marketing people know each other and co-promote constantly. The model had to distinguish organic collaboration, which is valuable to the ecosystem, from gaming it artificially for points.

That's where the anti-collusion penalty came from β€” steep degradation when two events cite each other above 40% overlap. So as an event host, you have to be really choosy about which other events you buddy up with.

Phase 3 β€” the long tail. At this point, I realized had to shift the simulations from modeling distributions of event tickets to individually modeling the daily choices of 2,000 participant. Because the penalties had an effect for trickling down demand, and therefore scarcity, from the big name events to more topic-specific conferences.

Scarcity of access changes behavior. When early access is limited for both hosts granting it and participants earning it, two things happen:

  1. mainstream events get more exclusive, and
  2. participants self-select into more specific topics that matter to them.

This shifts high scores from big events toward a long tail of focused rooms (with the exception being the anchor events like ethBerlin that every other event would be happy to draw from). The model was looking good, elevating the events with the strongest community stickiness.

My assumption is that mainstream events matter more to newcomers, and topic-specific ones matter more to the initiated β€” so over time, a system that rewards demonstrated participation should naturally sort people toward deeper, topic-specific events where they'll get the most out of it. That still needs proving in practice.

Phase 4 β€” the cold start problem. Early-stage events with <10 signups were wildly volatile, often swinging into the top and bottom 5 for a short period. A few strong attendees could spike a score; and a few early signups with no attendance history could crater it. Bayesian shrinkage toward the ecosystem mean for events under 20 RSVPs was the last piece β€” stabilizing scores until there's enough data to trust them.

Bootstrapping: The Chicken-and-Egg Problem

A system that rewards attendance history needs attendance history. At launch, there isn't any.

The first idea: reach out to values-aligned organizers, convert their historical attendance data into anonymous credentials. That would give us non-zero Density from day one, verified regulars already present

Then there was a lucky accident. Meerkat is a Q&A system built on Zupass β€” attendees ask questions and vote at events. These can be a separate qualifying proof type that zKal accepts.

I only discovered this deep into the project, when a DoD organizer who turned out to be a Meerkat co-founder reached out on Matrix. Turns out we were friends! I'd hacked alongside the whole team at ethBerlin, but they weren't working on Meerkat yet. I was a solo hacker that year, so when I won and got a bundle of Devconnect tickets as part of the prize, I gave the extras to the other winning teams, which ended up being Meerkat! I had no idea it was them until this conversation surfaced it.

If I can query Meerkat proofs, the bootstrap problem is substantially smaller than it first looked. Event hosts could offer early access to people who asked a question at topic-specific talks at any big Ethereum conference in the last year.

The Two-Layer Pattern

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

This applies to conference attendance here, but the same structure works for any commitment system.

When you want to reward demonstrated behavior without building a surveillance graph, see if Provable Sums get you there.