Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
13 changes: 11 additions & 2 deletions apps/api/src/cyberfrogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,27 @@ export interface CyberfrogData {
*/
export const parseCyberfrogData = (
signature: string,
nonce: number
nonce: number,
): CyberfrogData => {
try {
const recoveryBit = parseInt(signature.slice(-1));
const recoveryBit = parseInt(signature.charAt(signature.length - 1));
console.log("Recovery bit", recoveryBit);
const remainingBytes = signature.slice(0, -1);
console.log("Remaining bytes", remainingBytes);
const sig = secp256k1.Signature.fromCompact(remainingBytes);
console.log("Signature", sig);
const fullSig = sig.addRecoveryBit(recoveryBit);
console.log("Full signature", fullSig);
const paddedMessage = new Uint8Array(32);
console.log("Padded message", paddedMessage);
const nonceUint8 = numberToUint8Array(nonce);
console.log("Nonce uint8", nonceUint8);
paddedMessage.set(nonceUint8, 0);
console.log("Padded message", paddedMessage);
const hash = sha256.create().update(paddedMessage).digest();
console.log("hash", hash);
const publicKey = bytesToHex(fullSig.recoverPublicKey(hash).toRawBytes());
console.log("Public key recovered", publicKey);
return {
signature: fullSig,
messageHash: hash,
Expand Down
41 changes: 21 additions & 20 deletions apps/api/src/routers/feeds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ export const feedsRouter = router({
.input(
z.object({
feedId: z.string(),
})
}),
)
.output(
z.object({
pod: z.custom<POD>((x) => x instanceof POD),
})
}),
)
.mutation(
async ({
Expand Down Expand Up @@ -80,7 +80,7 @@ export const feedsRouter = router({
const lastFetchedAt = await updateUserFeedState(
tx,
semaphoreId.toString(),
feedId
feedId,
);
if (!lastFetchedAt) {
const e = new Error("User feed state unexpectedly not found!");
Expand All @@ -92,7 +92,7 @@ export const feedsRouter = router({
{
lastFetchedAt,
},
feed
feed,
);
if (nextFetchAt > Date.now()) {
throw new TRPCError({
Expand All @@ -111,14 +111,14 @@ export const feedsRouter = router({

const frogData = generateFrogData(
frogDataSpec,
BigInt(semaphoreId)
BigInt(semaphoreId),
);

const { score: scoreAfterRoll } = await incrementScore(
tx,
semaphoreId.toString(),
// non-frog frog doesn't get point
frogData.biome === Biome.Unknown ? 0 : 1
frogData.biome === Biome.Unknown ? 0 : 1,
);

if (scoreAfterRoll > FROG_SCORE_CAP) {
Expand All @@ -134,13 +134,13 @@ export const feedsRouter = router({
tx,
semaphoreId.toString(),
feedId,
lastFetchedAt
lastFetchedAt,
);
}

const frogPOD = POD.sign(
toFrogPODEntries(frogData),
ISSUER_PRIVATE_KEY
ISSUER_PRIVATE_KEY,
);

return {
Expand All @@ -160,19 +160,19 @@ export const feedsRouter = router({

throw e;
});
}
},
),
getCyberFrog: authedProcedure
.input(
z.object({
signature: z.string(),
nonce: z.number(),
})
}),
)
.output(
z.object({
pod: z.custom<POD>((x) => x instanceof POD),
})
}),
)
.mutation(
async ({
Expand All @@ -189,7 +189,7 @@ export const feedsRouter = router({
const sigValid = secp256k1.verify(
parsedSignature,
messageHash,
publicKey
publicKey,
);
if (!sigValid) {
throw new TRPCError({
Expand Down Expand Up @@ -220,7 +220,7 @@ export const feedsRouter = router({
}

const nullifier = bytesToHex(
sha256.create().update(publicKey).update(nonce.toString()).digest()
sha256.create().update(publicKey).update(nonce.toString()).digest(),
);

// If something fails after this point, the nullifier is not reverted
Expand All @@ -230,7 +230,8 @@ export const feedsRouter = router({
if (!nullifierConsumeSuccess) {
throw new TRPCError({
code: "FORBIDDEN",
message: "Ribbit! Someone already claimed this cyberfrog.",
message:
"Ribbit! Someone already claimed this cyberfrog. Try scanning again.",
});
}

Expand All @@ -247,7 +248,7 @@ export const feedsRouter = router({
const lastFetchedAt = await updateUserFeedState(
tx,
semaphoreId.toString(),
feedId
feedId,
);
if (!lastFetchedAt) {
const e = new Error("User feed state unexpectedly not found!");
Expand All @@ -258,7 +259,7 @@ export const feedsRouter = router({
{
lastFetchedAt,
},
feed
feed,
);
if (nextFetchAt > Date.now()) {
throw new TRPCError({
Expand All @@ -277,14 +278,14 @@ export const feedsRouter = router({

const frogData = generateFrogData(
frogDataSpec,
BigInt(semaphoreId)
BigInt(semaphoreId),
);

const { score: scoreAfterRoll } = await incrementScore(
tx,
semaphoreId.toString(),
// non-frog frog doesn't get point
frogData.biome === Biome.Unknown ? 0 : 1
frogData.biome === Biome.Unknown ? 0 : 1,
);

if (scoreAfterRoll > FROG_SCORE_CAP) {
Expand All @@ -296,7 +297,7 @@ export const feedsRouter = router({

const frogPOD = POD.sign(
toFrogPODEntries(frogData),
ISSUER_PRIVATE_KEY
ISSUER_PRIVATE_KEY,
);

return {
Expand All @@ -316,6 +317,6 @@ export const feedsRouter = router({

throw e;
});
}
},
),
});
14 changes: 10 additions & 4 deletions apps/api/src/setup_cyberfrog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { SerialPort } from "serialport";
import { ReadlineParser } from "@serialport/parser-readline";
import { spawn } from "child_process";
import { logger } from "@frogcrypto/shared";
import { publicKeyToUUID } from "./utils";

/**
* pnpm run setup-cyberfrog will set up a Cyberfrog device for FrogCrypto.
Expand All @@ -28,7 +29,7 @@ interface PortInfo {
async function findESP32Port(): Promise<string> {
const ports: PortInfo[] = await SerialPort.list();
const esp32Port = ports.find((port: PortInfo) =>
port.manufacturer?.toLowerCase().includes("espressif"),
port.manufacturer?.toLowerCase().includes("espressif")
);

if (!esp32Port) {
Expand Down Expand Up @@ -67,18 +68,18 @@ function flashFirmware(port: string): Promise<void> {
const esptool = spawn("esptool.py", args, { env: process.env });

esptool.stdout.on("data", (data: string) => {
console.log(data);
console.log(data.toString());
});

esptool.stderr.on("data", (data: string) => {
console.error(data);
console.error(data.toString());
});

esptool.on("close", (code: number) => {
if (code !== 0) {
console.error(`esptool.py process exited with code ${code.toString()}`);
reject(
new Error(`esptool.py process exited with code ${code.toString()}`),
new Error(`esptool.py process exited with code ${code.toString()}`)
);
} else {
console.info("Flashing complete.");
Expand Down Expand Up @@ -126,6 +127,11 @@ async function main() {
// now we can do whatever we want with the pubkey:
console.log("Public key captured successfully:");
console.log(publicKey);

// get the uuid from the public key
const uuid = publicKeyToUUID(publicKey);
console.log("UUID captured successfully:");
console.log(uuid);
// setupCyberFeed(publicKey)
} catch (error) {
console.error(`An error occurred: ${(error as Error).message}`);
Expand Down
14 changes: 7 additions & 7 deletions apps/api/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export interface UserFeedState {

export function computeUserFeedState(
state: Pick<UserFeed, "lastFetchedAt"> | undefined,
feed: Feed
feed: Feed,
): UserFeedState {
const lastFetchedAt = state?.lastFetchedAt?.getTime() ?? 0;
const nextFetchAt = lastFetchedAt + feed.cooldown * 1000;
Expand All @@ -38,11 +38,11 @@ export function computeUserFeedState(
export function sampleFrogAttribute(
min?: number,
max?: number,
rarity?: Rarity
rarity?: Rarity,
): number {
return _.random(
Math.round(min ?? 0),
Math.round(max ?? (rarity === Rarity.Common ? 7 : 15))
Math.round(max ?? (rarity === Rarity.Common ? 7 : 15)),
);
}

Expand Down Expand Up @@ -74,10 +74,10 @@ export function compareIds(id1: string, id2: string): number {

export function numberToUint8Array(num: number): Uint8Array {
const arr = new Uint8Array(4);
for (let i = 0; i < 4; i++) {
arr[3 - i] = num & 0xff;
num = num >> 8;
}
arr[0] = (num >> 24) & 0xff;
arr[1] = (num >> 16) & 0xff;
arr[2] = (num >> 8) & 0xff;
arr[3] = num & 0xff;
return arr;
}

Expand Down
6 changes: 3 additions & 3 deletions packages/shared/src/auth.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as p from "@parcnet-js/podspec";
import { ticketProofRequest } from "@parcnet-js/ticket-spec";
import { TicketProofRequest as TicketProofRequestType } from "@parcnet-js/ticket-spec";

import { shortCommitment, userPublicKeyToUserId } from "./semaphore";

Expand Down Expand Up @@ -67,7 +67,7 @@ export const DEVCON_7_SIGNER_PUBLIC_KEY =
"YwahfUdUYehkGMaWh0+q3F8itx2h8mybjPmt8CmTJSs";
export const DEVCON_7_EVENT_ID = "5074edf5-f079-4099-b036-22223c0c6995";

export const TicketProofRequest = ticketProofRequest({
export const TicketProofRequest: TicketProofRequestType = {
classificationTuples: [
{
signerPublicKey: DEVCON_7_SIGNER_PUBLIC_KEY,
Expand All @@ -86,4 +86,4 @@ export const TicketProofRequest = ticketProofRequest({
type: "string",
value: "FROGCRYPTO",
},
});
};
Loading