From 968ac66a3db382a9dbc9972ce5661edcde7c39e1 Mon Sep 17 00:00:00 2001 From: Tanner Shaw Date: Wed, 23 Aug 2023 12:26:46 -0500 Subject: [PATCH] refactor(identities) rooms now have semaphoreIdentities and hashed identities --- package-lock.json | 8 ++-- package.json | 2 +- prisma/schema.prisma | 35 +++++++++--------- src/crypto/verifier.ts | 4 +- src/data/db.ts | 84 +++++++++++++++++++++++++++++++----------- src/endpoints/index.ts | 4 +- 6 files changed, 89 insertions(+), 48 deletions(-) diff --git a/package-lock.json b/package-lock.json index ded0a0d..846cde3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "body-parser": "^1.20.2", "cors": "^2.8.5", "discreetly-claimcodes": "^1.1.5", - "discreetly-interfaces": "^0.1.34", + "discreetly-interfaces": "^0.1.35", "dotenv": "^16.3.1", "express": "^4.18.2", "express-basic-auth": "^1.2.1", @@ -3469,9 +3469,9 @@ "integrity": "sha512-pQueoGtBJk/FrTfGzepjqYfTLaymS+4t11byI4OcfjWQOagRsD7dtavGcowTVQ7Ib/vjKna5T+71WcgWZaAWuA==" }, "node_modules/discreetly-interfaces": { - "version": "0.1.34", - "resolved": "https://registry.npmjs.org/discreetly-interfaces/-/discreetly-interfaces-0.1.34.tgz", - "integrity": "sha512-7purPOWOowVH44ebdweBdZ4z2RsBQy5/H7xi6PdsHkaw1xwg8u3Ev2US5EdavP1igZ+SzebJdK8jT0ZTjzX8Kg==", + "version": "0.1.35", + "resolved": "https://registry.npmjs.org/discreetly-interfaces/-/discreetly-interfaces-0.1.35.tgz", + "integrity": "sha512-483vYSdwQ3+jPcHJoP3VEeFpfwGNgfFqjIKy/W1sSFZIAzyztTj534jeF9TwXAJqrP5I/3UbEm596NrCuyH3iw==", "dependencies": { "poseidon-lite": "^0.2.0", "rlnjs": "^3.1.4" diff --git a/package.json b/package.json index 3ebfb3e..1505a4a 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "body-parser": "^1.20.2", "cors": "^2.8.5", "discreetly-claimcodes": "^1.1.5", - "discreetly-interfaces": "^0.1.34", + "discreetly-interfaces": "^0.1.35", "dotenv": "^16.3.1", "express": "^4.18.2", "express-basic-auth": "^1.2.1", diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 878e689..962bd17 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -11,23 +11,24 @@ datasource db { } model Rooms { - id String @id @default(auto()) @map("_id") @db.ObjectId - roomId String @unique - name String - rateLimit Int @default(1000) // epoch length in ms - banRateLimit Int @default(1000000) // starting number of epochs banned for - userMessageLimit Int @default(1) // per epoch - membershipType String @default("IDENTITY_LIST") - identities String[] @default([]) - contractAddress String? // RLN_CONTRACT as "chainID:0xADDRESS" - bandadaAddress String? // BANDADA as "url:groupID" - bandadaGroupId String? // Bandada Group ID - bandadaAPIKey String? // Bandada API Key - epochs Epoch[] - messages Messages[] - claimCodes ClaimCodes[] @relation(fields: [claimCodeIds], references: [id]) - claimCodeIds String[] @default([]) @db.ObjectId - type String @default("PUBLIC") + id String @id @default(auto()) @map("_id") @db.ObjectId + roomId String @unique + name String + rateLimit Int @default(1000) // epoch length in ms + banRateLimit Int @default(1000000) // starting number of epochs banned for + userMessageLimit Int @default(1) // per epoch + membershipType String @default("IDENTITY_LIST") + identities String[] @default([]) + semaphoreIdentities String[] @default([]) + contractAddress String? // RLN_CONTRACT as "chainID:0xADDRESS" + bandadaAddress String? // BANDADA as "url:groupID" + bandadaGroupId String? // Bandada Group ID + bandadaAPIKey String? // Bandada API Key + epochs Epoch[] + messages Messages[] + claimCodes ClaimCodes[] @relation(fields: [claimCodeIds], references: [id]) + claimCodeIds String[] @default([]) @db.ObjectId + type String @default("PUBLIC") } model ClaimCodes { diff --git a/src/crypto/verifier.ts b/src/crypto/verifier.ts index 63c3a80..ce74d8e 100644 --- a/src/crypto/verifier.ts +++ b/src/crypto/verifier.ts @@ -52,8 +52,8 @@ async function verifyProof(msg: MessageI, room: RoomI, epochErrorRange = 5): Pro } // Check that the merkle root is correct - if (room.identities && Array.isArray(room.identities)) { - const group = new Group(room.roomId, 20, room.identities as bigint[] | undefined); + if (room.semaphoreIdentities && Array.isArray(room.semaphoreIdentities)) { + const group = new Group(room.roomId, 20, room.semaphoreIdentities as bigint[] | undefined); if (group.root !== proof.snarkProof.publicSignals.root) { console.warn("GROUP ROOT DOESN'T MATCH PROOF ROOT; USE BANDADA"); } diff --git a/src/data/db.ts b/src/data/db.ts index 7313e66..324d1d9 100644 --- a/src/data/db.ts +++ b/src/data/db.ts @@ -29,7 +29,7 @@ export async function getRoomByID(id: string): Promise { id: true, roomId: true, name: true, - identities: true, + semaphoreIdentities: true, rateLimit: true, userMessageLimit: true, membershipType: true, @@ -65,7 +65,7 @@ export async function getRoomsByIdentity(identity: string): Promise { try { const rooms = await prisma.rooms.findMany({ where: { - identities: { + semaphoreIdentities: { has: identity } } @@ -107,7 +107,10 @@ function sanitizeIDC(idc: string): string { } } -export async function updateRoomIdentities(idc: string, roomIds: string[]): Promise { +export async function updateRoomIdentities( + idc: string, + roomIds: string[] +): Promise { const identityCommitment = sanitizeIDC(idc); return await prisma.rooms .findMany({ @@ -122,33 +125,50 @@ export async function updateRoomIdentities(idc: string, roomIds: string[]): Prom }); } -function addIdentityToIdentityListRooms(rooms, identityCommitment: string): unknown { +function addIdentityToIdentityListRooms( + rooms, + identityCommitment: string +): unknown { const identityListRooms = rooms .filter( (room: RoomI) => room.membershipType === 'IDENTITY_LIST' && - !room.identities?.includes( - getRateCommitmentHash( - BigInt(identityCommitment), - BigInt(room.userMessageLimit ? room.userMessageLimit : 1) - ).toString() - ) + !room.semaphoreIdentities?.includes(identityCommitment) ) .map((room) => room.id as string); if (identityListRooms.length > 0) { - return prisma.rooms.updateMany({ - where: { id: { in: identityListRooms } }, - data: { identities: { push: identityCommitment } } - }); + for (const room of rooms) { + return prisma.rooms + .update({ + where: { id: room.id }, + data: { + identities: { + push: getRateCommitmentHash( + BigInt(identityCommitment), + BigInt((room.userMessageLimit as number) ?? 1) + ).toString() + }, + semaphoreIdentities: { push: identityCommitment } + } + }) + .then(() => { + console.debug( + `Successfully added user to Identity List room ${room.roomId}` + ); + }) + .catch((err) => { + console.error(err); + }); + } } } - function addIdentityToBandadaRooms(rooms, identityCommitment: string): void { const bandadaGroupRooms = rooms .filter( (room) => - room.membershipType === 'BANDADA_GROUP' && !room.identities.includes(identityCommitment) + room.membershipType === 'BANDADA_GROUP' && + !room.semaphoreIdentities.includes(identityCommitment) ) .map((room) => room as RoomI); @@ -165,15 +185,25 @@ function addIdentityToBandadaRooms(rooms, identityCommitment: string): void { 'x-api-key': room.bandadaAPIKey } }; - await prisma.rooms.updateMany({ + await prisma.rooms.update({ where: { id: room.id }, - data: { identities: { push: identityCommitment } } + data: { + identities: { + push: getRateCommitmentHash( + BigInt(identityCommitment), + BigInt((room.userMessageLimit as number) ?? 1) + ).toString() + }, + semaphoreIdentities: { push: identityCommitment } + } }); const url = `https://${room.bandadaAddress}/groups/${room.bandadaGroupId}/members/${identityCommitment}`; fetch(url, requestOptions) .then((res) => { if (res.status == 200) { - console.debug(`Successfully added user to Bandada group ${room.bandadaAddress}`); + console.debug( + `Successfully added user to Bandada group ${room.bandadaAddress}` + ); } }) .catch((err) => { @@ -196,7 +226,10 @@ export async function findUpdatedRooms(roomIds: string[]): Promise { } // TODO: Make interface for this return type; which is like a MessageI -export function createSystemMessages(message: string, roomId?: string): Promise { +export function createSystemMessages( + message: string, + roomId?: string +): Promise { const query = roomId ? { where: { roomId } } : undefined; return prisma.rooms .findMany(query) @@ -223,7 +256,10 @@ export function createSystemMessages(message: string, roomId?: string): Promise< }); } -export function removeIdentityFromRoom(idc: string, room: RoomI): Promise { +export function removeIdentityFromRoom( + idc: string, + room: RoomI +): Promise { const updateIdentities = room.identities?.map((identity) => identity === idc ? '0n' : identity ) as string[]; @@ -262,6 +298,9 @@ export async function createRoom( ): Promise { const claimCodes: { claimcode: string }[] = genClaimCodeArray(numClaimCodes); const mockUsers: string[] = genMockUsers(approxNumMockUsers); + const identityCommitments: string[] = mockUsers.map((user) => + getRateCommitmentHash(BigInt(user), BigInt(userMessageLimit)).toString() + ); const roomData = { where: { roomId: genId(serverConfig.id as bigint, roomName).toString() @@ -272,7 +311,8 @@ export async function createRoom( name: roomName, rateLimit: rateLimit, userMessageLimit: userMessageLimit, - identities: mockUsers, + semaphoreIdentities: mockUsers, + identities: identityCommitments, type, bandadaAddress, bandadaGroupId, diff --git a/src/endpoints/index.ts b/src/endpoints/index.ts index 9af3c6a..7476d67 100644 --- a/src/endpoints/index.ts +++ b/src/endpoints/index.ts @@ -52,7 +52,7 @@ export function initEndpoints(app: Express, adminAuth: RequestHandler) { rateLimit, userMessageLimit, membershipType, - identities, + semaphoreIdentities, contractAddress, bandadaAddress, bandadaGroupId, @@ -73,7 +73,7 @@ export function initEndpoints(app: Express, adminAuth: RequestHandler) { roomResult.bandadaGroupId = bandadaGroupId; } if (membershipType === 'IDENTITY_LIST') { - roomResult.identities = identities; + roomResult.semaphoreIdentities = semaphoreIdentities as string[]; } if (type === 'CONTRACT') { roomResult.contractAddress = contractAddress;