Home

Awesome

GitClaim

A sample app on top of zkemail.nr to claim airdrops by proving Github contributions to eligible repos using PR merge notification emails.

This is only meant to be a learning app, or a starting point for building ZK Email apps in Noir.

Try it out

URL: https://gitclaim.netlify.app/

Find any PR merge notification email in your inbox, download it as .eml file, and upload it to the app.

Running locally

To build the Noir circuit (asuming you have Noir and a backend like bb installed):

cd circuits
sh build.sh

This will compile the code and copy the generated circuit artifact and vkey to the app.

To run the app (a NextJs app)

cd app
yarn
yarn dev

How it works

In this section, we will see how the Noir circuit is designed, what are the tradeoffs, and some of the known issues.

This sections assumes you have some knowledge on how ZKEmail works. If not read more here and here

Identifying PR merge notification emails

Given an email, how do we know it's a PR merge notification email from Github?

There is nothing specific about merging in the email subject. Here is a sample:

Subject: Re: [noir-lang/noir_rsa] chore: add release-please (PR #21)

We have the below text in the body:

...
Merged #220 into feat/circuit-tests.
...

However, one might receive the word Merged in other Github notification emails - for example, when someone replies to an issue created by you with the word Merged. So we cannot reliably say an email is a PR merge notification email just based on the presence of the word Merged.

Upon observation, something unique to PR merge notification emails is there is a schema JSON at the footer of the email that contains a URL with eventId for the key "target". Sample:

{
  ...
  "target": "https://github.com/noir-lang/noir_rsa/pull/21#event-145160848..",
  ...
}

If it was any other kind of notification email, "#event" would not be present. For example, for a PR approval noficiation email, this would be

"target": "https://github.com/noir-lang/noir_rsa/pull/21#pullrequestreview-123.."

But anyone can subscribe to a PR (you are auto subscribed if you review/comment on a PR), and they all receive a notification email when the PR is merged.

We also need to ensure that the prover is the author of the PR. If they are the author, then the email body would contain the below text

You are receiving this because you authored the thread.

So, in our circuit we going to perform both the above checks to ensure the email is a PR merge notification email from Github and the prover is the author of the PR.

This is simply by observation and might not be fool-proof.

SHA precompute

We can precompute SHA-256 up to the portion of the email body that we want to read in circuit. In our case, we can precompute SHA up to the part "You are receiving this because you authored the thread."

This occur towards half of the email body which let us precompute the first half. This would have been difficult if we relied on the "Merged..." text because it occurs at the beginning of th body.

Nullifier

We need to ensure one person cannot claim airdrop multiple times. For this we need a nullifier that is attributed to the prover. The airdrop issuer (a server or a smart contract) will save this nullifier and ensure the same nullifier is not used again.

Github PR merge notification email contains the email address of the author in the CC: field. In our circuit, we use this email address to and hash it to produce the nullifier.

Verification

The repo_name input in the circuit is made public. This will in the "public inputs" part of the proof along with the nullifier.

So during verification, the airdrop issuer will:

To learn more, read the circuit code in main.nr and input generation code inutils.ts which has comments to understand the flow.

Limitations

This is only intended to be a sample app, mainly to explain the strategies around idetifying emails by looking for unique elements, and potentially finding them towards the end of the body to do SHA precompute, and to explain the concept of nullifiers.