Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project: "Invite only" #20

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions inviteonly/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Invite only

This project is for proving you have received an invitation by email to an event.

Your identity is kept private by utilizing the ZK capabilities of zkEmail and Aztec.

## Challenge Selection
The selected challenge is "zkEmail Guardian".

## Team information

Lauri Peltonen, ZK developer.

## Technical Approach

Utilize zkEmail to prove that the user has received an email from a certain email address and that the email includes a certain keyword.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool idea, have you looked into particular event platforms and what comes in their confirmation emails? Eg Meetup, Luma, ...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was more thinking of aiming this to more personal invitations. But those event platforms would probably make sense as well...


If time, create a minimal frontend.

## Expected Outcomes

A way for anyone to prove that they are invited to an event, without exposing their email address. If time permits, a crude website to demonstrate - otherwise interaction through CLI.

## Credits

This project utilizes heavily code from https://github.com/saleel/gitclaim .

microbecode marked this conversation as resolved.
Show resolved Hide resolved
## Lessons Learned (For Submission)

- What are the most important takeaways from your project?
- Are there any patterns or best practices that you've learned that would be useful for other projects?
- Highlight reusable code patterns, key code snippets, and best practices - what are some of the ‘lego bricks’ you’ve built, and how could someone else best use them?

## Project Links (For Submission)

Please provide links to any relevant documentation, code, or other resources that you've used in your project.

## Video Demo (For Submission)

Please provide a link to a video demo of your project. The demo should be no longer than 5 minutes and should include a brief intro to your team and your project.
4 changes: 4 additions & 0 deletions inviteonly/app/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
SUPABASE_URL=
SUPABASE_SERVICE_ROLE_KEY=
NEXT_PUBLIC_GOOGLE_CLIENT_ID=
# TEMP_DIR=/tmp
2 changes: 2 additions & 0 deletions inviteonly/app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.next
node_modules
1 change: 1 addition & 0 deletions inviteonly/app/assets/circuit-vkey.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,51,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,47,240,230,242,231,107,40,32,83,148,206,64,135,127,91,243,155,28,19,179,103,102,182,153,218,193,142,86,212,208,110,6,43,119,255,206,171,204,206,119,6,100,87,230,110,133,11,152,218,246,201,44,20,14,2,98,140,238,31,98,62,62,46,20,171,230,231,128,69,171,179,98,125,163,4,13,74,114,13,206,85,113,67,141,197,214,59,129,54,118,47,159,204,247,140,10,129,217,70,107,127,201,253,197,13,12,94,132,169,255,0,52,107,30,69,84,20,32,5,81,37,141,185,236,160,31,184,17,156,179,222,33,130,20,0,179,168,218,187,32,220,232,162,5,236,99,20,106,195,153,45,150,236,46,160,240,120,205,250,11,162,103,235,75,178,148,55,229,74,154,161,102,49,234,110,202,19,142,253,191,181,70,193,48,81,238,239,18,198,166,128,5,105,105,149,239,221,95,248,222,115,193,149,51,21,140,19,102,181,247,205,89,189,229,253,130,225,31,255,73,190,155,138,29,240,244,168,130,254,229,239,153,176,21,65,209,172,201,236,14,197,167,68,16,21,185,226,200,139,141,220,200,54,241,190,4,229,32,143,168,182,116,43,7,206,104,24,231,93,167,151,79,168,194,255,219,31,51,148,9,72,11,153,12,34,244,125,18,53,82,98,93,158,220,25,212,27,4,153,157,195,195,55,33,124,144,92,111,232,48,185,237,220,217,239,69,114,220,137,34,40,229,250,65,26,205,176,46,68,102,102,176,210,75,203,123,219,118,44,231,177,144,78,201,225,170,1,218,44,73,151,34,78,40,64,16,199,110,52,140,169,249,118,189,81,195,172,100,247,242,175,241,145,85,164,175,163,128,7,35,70,15,128,4,41,154,217,220,252,222,79,126,108,171,45,84,241,88,145,0,26,151,132,71,139,15,160,196,236,114,181,140,150,111,6,31,88,206,232,225,48,35,240,26,9,178,239,102,135,94,240,69,171,90,61,9,164,166,27,193,255,158,150,230,166,127,168,37,113,65,154,153,89,95,229,29,110,46,83,130,40,25,171,189,255,113,101,71,173,27,247,44,128,190,227,91,110,172,78,19,174,10,193,52,211,129,202,77,63,156,190,214,194,106,185,58,128,46,10,203,135,62,169,150,177,242,254,60,14,21,85,15,93,81,166,195,100,131,200,10,94,195,62,151,173,165,223,56,131,23,42,119,69,167,79,35,38,20,114,222,199,181,105,24,95,102,69,56,117,44,61,84,228,145,129,134,201,56,45,108,111,16,228,55,161,192,25,93,153,204,216,226,75,44,99,7,205,234,92,110,55,40,105,135,166,71,146,236,237,198,151,200,235,241,182,240,50,65,104,164,182,123,7,23,199,114,227,1,210,41,159,57,74,204,166,7,111,155,16,64,236,44,169,24,154,253,222,114,67,84,227,138,78,71,96,133,44,135,141,7,29,169,203,229,3,102,153,229,146,71,214,89,154,137,16,25,88,15,42,111,247,117,155,66,54,64,129,208,129,123,30,28,0,198,141,169,34,76,173,140,136,184,85,71,145,74,147,45,5,70,61,197,120,38,19,219,45,20,156,200,103,38,183,20,26,220,167,159,158,96,39,126,7,216,241,105,108,46,98,15,128,90,156,93,161,212,211,107,130,225,111,185,215,221,218,20,0,103,201,156,84,10,143,171,86,219,197,126,93,27,98,234,166,225,148,123,217,190,151,219,95,49,135,209,150,72,116,18,72,77,5,36,203,227,84,128,183,83,64,91,192,225,25,27,42,156,82,199,179,245,103,199,143,22,24,130,236,19,150,23,52,5,63,93,14,183,185,232,140,119,240,39,50,178,168,133,69,246,65,103,116,98,17,38,36,207,56,82,106,37,202,16,45,103,124,147,51,86,162,41,12,33,190,217,46,232,120,183,4,125,11,57,128,205,89,204,151,240,181,66,45,107,15,35,32,105,157,87,188,231,72,239,0,223,5,176,16,72,60,114,195,199,255,112,167,47,8,66,185,99,15,230,44,31,175,1,142,210,201,179,190,235,129,18,3,59,222,194,21,7,116,138,112,215,109,14,52,200,74,1,251,24,185,239,138,208,71,28,39,248,188,139,107,19,72,35,233,134,125,191,181,236,199,204,88,208,181,92,224,198,45,22,163,172,18,240,90,123,12,26,225,246,200,34,248,86,54,242,73,29,177,4,154,145,2,227,183,200,149,65,218,232,145,21,71,47,194,212,247,28,59,27,158,146,5,9,49,254,12,8,167,137,19,167,22,164,92,105,23,222,212,21,156,91,246,191,17,161,52,21,107,177,156,8,145,47,141,29,174,92,118,95,145,15,61,84,183,52,152,103,131,34,186,250,141,160,57,152,73,68,121,84,230,151,188,23,96,99,77,78,39,240,228,12,86,245,41,133,127,137,87,90,18,24,211,10,232,121,230,127,197,67,123,16,233,78,249,5,123,140,212,103,176,245,247,81,49,150,106,4,181,76,61,43,233,12,86,14,212,109,118,223,227,120,15,208,2,35,246,27,77,123,18,254,141,26,126,189,49,2,31,60,74,83,195,106,12,98,97,73,243,120,60,227,27,240,43,129,69,147,93,11,157,71,27,173,195,27,77,187,88,56,0,5,91,195,111,26,10,6,58,62,12,19,114,51,163,131,35,183,139,128,67,4,214,163,60,27,91,101,204,195,42,8,91,7,134,163,98,158,135,138,91,87,13,254,219,161,99,117,239,79,13,121,146,13,46,111,192,46,148,51,59,32,19,78,134,246,22,11,25,173,210,142,22,15,186,171,91,16,185,181,138,214,4,121,49,2,180,132,144,66,152,149,9,246,213,240,216,108,149,138,148,207,158,34,53,220,222,122,92,160,53,67,18,178,32,84,96,13,126,207,74,41,62,93,170,108,151,61,86,242,226,204,223,22,77,3,103,209,123,139,53,110,140,186,182,178,30,63,215,29,30,52,209,117,188,71,157,19,41,143,160,214,55,56,148,82,104,186,92,223,173,161,247,217,88,152,22,175,104,109,33,9,80,30,195,94,195,123,117,17,109,84,169,252,22,158,232,253,128,207,167,88,78,15,200,70,19,230,207,62,69,60,245,41,27,163,143,206,35,88,139,157,60,79,154,229,63,126,107,188,172,209,101,22,213,124,18,22,184,203,46,204,182,152,255,48,79,134,138,155,226,30,167,102,243,254,149,191,174,12,216,239,235,243,81,159,91,187,191,23,45,147,164,222,143,239,83,42,173,250,36,28,127,202,212,192,82,155,155,174,135,204,202,196,84,165,178,108,50,44,160,23,150,189,145,13,159,193,166,27,51,248,89,125,108,8,154,56,130,250,101,104,218,217,175,153,222,66,214,147,20,238,164,175,62,251,220,137,83,243,250,43,31,243,169,246,9,27,82,156,84,191,62,36,93,100,72,53,245,235,112,27,43,178,20,74,24,155,245,210,83,12,255,21,224,56,143,52,25,128,160,214,33,5,64,41,44,235,98,70,100,35,90,210,202,154,216,197,30,83,120,244,208,235,218,16,150,6,158,29,153,50,182,9,249,111,21,38,51,0,133,202,229,225,72,204,224,81,9,25,113,218,132,166,191,230,41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,42,224,45,28,60,16,32,97,149,48,220,105,120,221,95,56,124,227,73,182,212,62,181,56,172,40,55,239,200,37,149,21,38,38,255,229,51,47,108,149,236,211,109,4,218,255,49,169,161,35,164,183,176,12,120,62,175,225,244,57,137,120,147,96]
1 change: 1 addition & 0 deletions inviteonly/app/assets/circuit.json

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions inviteonly/app/components/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react";

function Header() {
return (
<header className="navbar">
<div className="logo">
GitClaim
</div>
</header>
);
}

export default function Layout({ children }: { children: React.ReactNode }) {
return (
<>
<Header />
<div className="container">{children}</div>
</>
)
}
5 changes: 5 additions & 0 deletions inviteonly/app/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
69 changes: 69 additions & 0 deletions inviteonly/app/next.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import dotenv from 'dotenv';
import webpack from "webpack";

dotenv.config();

/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
outputFileTracingIncludes: {
'/api/claim-airdrop': [
'./node_modules/@aztec/bb.js/dest/node/barretenberg_wasm/**/*',
'./node_modules/@aztec/bb.js/dest/node/barretenberg_wasm/barretenberg_wasm_thread/factory/node/thread.worker.js'
],
'/api/claim-airdrop/': [
'./node_modules/@aztec/bb.js/dest/node/barretenberg_wasm/**/*',
'./node_modules/@aztec/bb.js/dest/node/barretenberg_wasm/barretenberg_wasm_thread/factory/node/thread.worker.js'
],
},
},
reactStrictMode: true,
sassOptions: {
includePaths: ['./'],
},
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'developers.google.com',
},
],
},
env: {
NEXT_PUBLIC_GOOGLE_CLIENT_ID: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID,
},
webpack: (config) => {
config.experiments = {
asyncWebAssembly: true,
syncWebAssembly: true,
layers: true,
}
config.plugins.push(
new webpack.NormalModuleReplacementPlugin(/^node:/, (resource) => {
resource.request = resource.request.replace(/^node:/, "");
})
);
return config
},
async headers() {
// These headers are necessary to enabled SharedArrayBuffer
// which is needed for multi-threaded proof generation
return [
{
source: '/:path*',
headers: [
{
key: 'Cross-Origin-Embedder-Policy',
value: 'require-corp',
},
{
key: 'Cross-Origin-Opener-Policy',
value: 'same-origin',
},
],
},
];
},
};

export default nextConfig;
54 changes: 54 additions & 0 deletions inviteonly/app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"name": "ui",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@mach-34/zkemail-nr": "^1.1.0",
"@noir-lang/backend_barretenberg": "0.35.0-999071b.nightly",
"@noir-lang/noir_js": "0.35.0-999071b.nightly",
"@supabase/supabase-js": "^2.45.4",
"bulma": "^1.0.2",
"cal-sans": "^1.0.1",
"dotenv": "^16.4.5",
"idb-keyval": "^6.2.1",
"next": "14.2.11",
"react": "^18",
"react-dom": "^18",
"react-dropzone": "^14.2.9",
"sass": "^1.78.0"
},
"resolutions": {
"@zk-email/helpers": "6.1.6",
"@aztec/bb.js": "https://gitpkg.vercel.app/saleel/aztec-packages/barretenberg/ts?master"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"eslint": "^8",
"eslint-config-next": "14.2.11",
"typescript": "^5",
"webpack": "^5.95.0"
},
"eslintConfig": {
"extends": [
"next/core-web-vitals",
"next/typescript"
],
"rules": {
"max-len": [
"error",
{
"code": 120
}
]
}
},
"packageManager": "[email protected]+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
11 changes: 11 additions & 0 deletions inviteonly/app/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { AppProps } from "next/app";
import Layout from "../components/layout";
import "../styles/main.scss";

export default function MyApp({ Component, pageProps }: AppProps) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
);
}
13 changes: 13 additions & 0 deletions inviteonly/app/pages/_document.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
return (
<Html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
62 changes: 62 additions & 0 deletions inviteonly/app/pages/api/claim-airdrop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { verifyProof } from '../../utils';

type ResponseData = {
success: boolean;
message: string;
};

// WARNING!
// In-memory storage for nullifiers
// This will be reset during every server restart
// Replace with a database for actual use
const usedNullifiers = new Set<string>();

export default async function handler(
req: NextApiRequest,
res: NextApiResponse<ResponseData>
) {
if (req.method !== 'POST') {
return res.status(405).json({ success: false, message: 'Method Not Allowed' });
}

const { proof, publicInputs } = req.body;

if (!proof || !publicInputs) {
return res.status(400).json({ success: false, message: 'Missing proof or public inputs' });
}

try {
// Verify the proof
const isValid = await verifyProof(proof, publicInputs);
if (!isValid) {
return res.status(400).json({ success: false, message: 'Invalid proof' });
}

// Construct the repo URL string from the first 50 bytes of publicInputs
/* const repoUrlBytes = publicInputs.slice(0, 50);
const repoUrl = repoUrlBytes.map((byte: number) => String.fromCharCode(byte)).join('').trim();
*/
// Check if the repo is eligible
/* if (!isEligibleRepo(repoUrl)) {
return res.status(403).json({ success: false, message: 'Repository is not eligible for the airdrop' });
} */

// Extract nullifier from public inputs
const nullifier = publicInputs[50];

// Check if nullifier has been used before
if (usedNullifiers.has(nullifier)) {
return res.status(400).json({ success: false, message: 'User already claimed the airdrop (nullifier found)' });
}

// Store the nullifier
usedNullifiers.add(nullifier);

// Airdrop claimed successfully
return res.status(200).json({ success: true, message: 'Airdrop claimed successfully' });
} catch (error) {
console.error('Error claiming airdrop:', error);
return res.status(500).json({ success: false, message: 'Internal server error' });
}
}
Loading