Skip to content

Commit

Permalink
GPC verification via API
Browse files Browse the repository at this point in the history
  • Loading branch information
robknight committed Sep 14, 2024
1 parent af58f24 commit d893f1e
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 55 deletions.
26 changes: 21 additions & 5 deletions apps/client-web/src/client/gpc.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { ConnectorAdvice } from "@parcnet/client-helpers";
import { ParcnetGPCRPC, ProveResult } from "@parcnet/client-rpc";
import { PodspecProofRequest, proofRequest } from "@parcnet/podspec";
import {
GPCBoundConfig,
GPCProof,
GPCRevealedClaims,
gpcVerify
} from "@pcd/gpc";
import { Dispatch } from "react";
import { ClientAction } from "../state";
import { PODCollection } from "./pod_collection";
Expand Down Expand Up @@ -41,7 +47,6 @@ export class ParcnetGPCProcessor implements ParcnetGPCRPC {
const advice = this.advice;

return new Promise((resolve) => {
console.log("proving");
this.advice.showClient();
this.dispatch({
type: "set-proof-in-progress",
Expand All @@ -57,9 +62,20 @@ export class ParcnetGPCProcessor implements ParcnetGPCRPC {
});
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
public async verify(pcd: any): Promise<boolean> {
console.log(pcd);
return true;
public async verify(
proof: GPCProof,
boundConfig: GPCBoundConfig,
revealedClaims: GPCRevealedClaims,
pr: PodspecProofRequest
): Promise<boolean> {
const config = proofRequest(pr).getProofRequest().proofConfig;
config.circuitIdentifier = boundConfig.circuitIdentifier;

return gpcVerify(
proof,
config as GPCBoundConfig,
revealedClaims,
new URL("/artifacts", window.location.origin).toString()
);
}
}
29 changes: 19 additions & 10 deletions examples/test-app/src/apis/GPC.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ const request: PodspecProofRequest = {

export function GPC(): ReactNode {
const { z, connected } = useParcnetClient();
const [proof, setProof] = useState<ProveResult>();
const [verified, _setVerified] = useState<boolean | undefined>();
const [proveResult, setProveResult] = useState<ProveResult>();
const [verified, setVerified] = useState<boolean | undefined>();

return !connected ? null : (
<div>
Expand Down Expand Up @@ -75,16 +75,16 @@ const gpcProof = await z.gpc.prove(request);
<TryIt
onClick={async () => {
try {
setProof(await z.gpc.prove(request));
setProveResult(await z.gpc.prove(request));
} catch (e) {
console.log(e);
}
}}
label="Get GPC Proof"
/>
{proof && (
{proveResult && (
<pre className="whitespace-pre-wrap">
{JSONBig.stringify(proof, null, 2)}
{JSONBig.stringify(proveResult, null, 2)}
</pre>
)}
</div>
Expand All @@ -93,18 +93,27 @@ const gpcProof = await z.gpc.prove(request);
Verify a GPC proof like this:
<code className="block text-xs font-base rounded-md p-2 whitespace-pre-wrap">
{`
const verified = await z.gpc.verify(proof);
const verified = await z.gpc.verify(proof, config, revealedClaims, request);
`}
</code>
</p>
{!proof && (
{!proveResult && (
<span>Generate a proof above, then we can verify it.</span>
)}
{proof && (
{proveResult && (
<TryIt
onClick={() => {
onClick={async () => {
try {
// setVerified(await z.gpc.verify(proof));
if (proveResult.success) {
setVerified(
await z.gpc.verify(
proveResult.proof,
proveResult.boundConfig,
proveResult.revealedClaims,
request
)
);
}
} catch (e) {
console.log(e);
}
Expand Down
5 changes: 1 addition & 4 deletions examples/test-app/src/apis/PODSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -403,10 +403,7 @@ function DeletePOD({ z }: { z: ParcnetAPI }): ReactNode {

function SubscribeToPODs({ z }: { z: ParcnetAPI }): ReactNode {
const [pods, setPODs] = useState<POD[]>([]);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const [subscription, setSubscription] = useState<Subscription<any> | null>(
null
);
const [subscription, setSubscription] = useState<Subscription | null>(null);

return (
<div>
Expand Down
21 changes: 8 additions & 13 deletions packages/app-connector/src/api_wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
ProveResult
} from "@parcnet/client-rpc";
import * as p from "@parcnet/podspec";
import { GPCProof, GPCRevealedClaims } from "@pcd/gpc";
import { GPCBoundConfig, GPCProof, GPCRevealedClaims } from "@pcd/gpc";
import { POD } from "@pcd/pod";
import { EventEmitter } from "eventemitter3";
import { PodspecProofRequest } from "../../podspec/src/index.js";
Expand All @@ -18,16 +18,12 @@ import { ParcnetRPCConnector } from "./rpc_client.js";
* It also allows the caller to run the query immediately, which is useful on
* first creating the subscription, before any updates are available.
*/
export class Subscription<E extends p.EntriesSchema> {
export class Subscription {
#emitter: EventEmitter;
#query: p.PodSpec<E>;
#query: p.PodSpec;
#api: ParcnetPODWrapper;

constructor(
query: p.PodSpec<E>,
emitter: EventEmitter,
api: ParcnetPODWrapper
) {
constructor(query: p.PodSpec, emitter: EventEmitter, api: ParcnetPODWrapper) {
this.#emitter = emitter;
this.#query = query;
this.#api = api;
Expand Down Expand Up @@ -64,14 +60,12 @@ class ParcnetPODWrapper {
});
}

async query<E extends p.EntriesSchema>(query: p.PodSpec<E>): Promise<POD[]> {
async query(query: p.PodSpec): Promise<POD[]> {
const pods = await this.#api.pod.query(query.schema);
return pods.map((pod) => POD.deserialize(pod));
}

async subscribe<E extends p.EntriesSchema>(
query: p.PodSpec<E>
): Promise<Subscription<E>> {
async subscribe(query: p.PodSpec): Promise<Subscription> {
const subscriptionId = await this.#api.pod.subscribe(query.schema);
const emitter = new EventEmitter();
const subscription = new Subscription(query, emitter, this);
Expand Down Expand Up @@ -107,10 +101,11 @@ class ParcnetGPCWrapper {

async verify<P extends Record<string, object>>(
proof: GPCProof,
config: GPCBoundConfig,
revealedClaims: GPCRevealedClaims,
proofRequest: PodspecProofRequest<P>
): Promise<boolean> {
return this.#api.gpc.verify(proof, revealedClaims, proofRequest);
return this.#api.gpc.verify(proof, config, revealedClaims, proofRequest);
}
}

Expand Down
15 changes: 6 additions & 9 deletions packages/app-connector/src/rpc_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import {
RPCMessageType,
SubscriptionUpdateResult
} from "@parcnet/client-rpc";
import { EntriesSchema, PodspecProofRequest } from "@parcnet/podspec";
import { GPCProof, GPCRevealedClaims } from "@pcd/gpc";
import { PodspecProofRequest } from "@parcnet/podspec";
import { GPCBoundConfig, GPCProof, GPCRevealedClaims } from "@pcd/gpc";
import { EventEmitter } from "eventemitter3";
import { z, ZodFunction, ZodTuple, ZodTypeAny } from "zod";
import { DialogController } from "./adapters/iframe.js";
Expand Down Expand Up @@ -115,9 +115,7 @@ export class ParcnetRPCConnector implements ParcnetRPC, ParcnetEvents {
this.#emitter = new EventEmitter();

this.pod = {
query: async <E extends EntriesSchema>(
query: PODQuery<E>
): Promise<string[]> => {
query: async (query: PODQuery): Promise<string[]> => {
return this.#typedInvoke(
"pod.query",
[query],
Expand All @@ -138,9 +136,7 @@ export class ParcnetRPCConnector implements ParcnetRPC, ParcnetEvents {
ParcnetRPCSchema.shape.pod.shape.delete
);
},
subscribe: async <E extends EntriesSchema>(
query: PODQuery<E>
): Promise<string> => {
subscribe: async (query: PODQuery): Promise<string> => {
return this.#typedInvoke(
"pod.subscribe",
[query],
Expand Down Expand Up @@ -172,12 +168,13 @@ export class ParcnetRPCConnector implements ParcnetRPC, ParcnetEvents {
},
verify: async (
proof: GPCProof,
boundConfig: GPCBoundConfig,
revealedClaims: GPCRevealedClaims,
proofRequest: PodspecProofRequest
): Promise<boolean> => {
return this.#typedInvoke(
"gpc.verify",
[proof, revealedClaims, proofRequest],
[proof, boundConfig, revealedClaims, proofRequest],
ParcnetRPCSchema.shape.gpc.shape.verify
);
}
Expand Down
7 changes: 4 additions & 3 deletions packages/client-rpc/src/rpc_interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { GPCBoundConfig, GPCProof, GPCRevealedClaims } from "@pcd/gpc";
* These interfaces are implemented in rpc_client.ts.
*/

export type PODQuery<E extends EntriesSchema> = PODSchema<E>;
export type PODQuery = PODSchema<EntriesSchema>;

export interface SubscriptionUpdateResult {
subscriptionId: string;
Expand All @@ -35,6 +35,7 @@ export interface ParcnetGPCRPC {
canProve: (request: PodspecProofRequest) => Promise<boolean>;
verify: (
proof: GPCProof,
boundConfig: GPCBoundConfig,
revealedClaims: GPCRevealedClaims,
proofRequest: PodspecProofRequest
) => Promise<boolean>;
Expand All @@ -46,10 +47,10 @@ export interface ParcnetIdentityRPC {

export interface ParcnetPODRPC {
// Returns array of serialized PODs
query: <E extends EntriesSchema>(query: PODQuery<E>) => Promise<string[]>;
query: (query: PODQuery) => Promise<string[]>;
insert: (serializedPod: string) => Promise<void>;
delete: (signature: string) => Promise<void>;
subscribe: <E extends EntriesSchema>(query: PODQuery<E>) => Promise<string>;
subscribe: (query: PODQuery) => Promise<string>;
unsubscribe: (subscriptionId: string) => Promise<void>;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/podspec/src/parse/pod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export interface StrongPOD<T extends PODEntries> extends POD {
* A PodSpec is a specification for a POD, including its schema and any
* additional constraints.
*/
export class PodSpec<E extends EntriesSchema> {
export class PodSpec<E extends EntriesSchema = EntriesSchema> {
public readonly schema: PODSchema<EntriesSchemaLiteral<E>>;

public entries(): EntriesSchemaLiteral<E> {
Expand Down
16 changes: 6 additions & 10 deletions packages/podspec/src/schemas/pod.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import { PODValue } from "@pcd/pod";
import { EntriesSchema, EntriesSchemaLiteral } from "./entries.js";

/**
* Schema for a tuple of entries.
*/
export type PODTupleSchema<E extends EntriesSchema> = {
entries: (keyof (E & { $signerPublicKey: never }) & string)[];
isMemberOf?: PODValue[][];
isNotMemberOf?: PODValue[][];
};

/**
* Schema for validating a POD.
*/
export type PODSchema<E extends EntriesSchema> = {
entries: EntriesSchemaLiteral<E>;
tuples?: PODTupleSchema<EntriesSchemaLiteral<E>>[];
tuples?: {
entries: (keyof (EntriesSchemaLiteral<E> & { $signerPublicKey: never }) &
string)[];
isMemberOf?: PODValue[][];
isNotMemberOf?: PODValue[][];
}[];
signerPublicKey?: {
isMemberOf?: string[];
isNotMemberOf?: string[];
Expand Down

0 comments on commit d893f1e

Please sign in to comment.