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

Further ticket proof refactoring #15

Merged
merged 3 commits into from
Oct 7, 2024
Merged
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
10 changes: 10 additions & 0 deletions apps/client-web/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# client-web

## 0.0.8

### Patch Changes

- Support for distinct verify and verifyWithProofRequest operations
- Updated dependencies
- @parcnet-js/[email protected]
- @parcnet-js/[email protected]
- @parcnet-js/[email protected]

## 0.0.7

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion apps/client-web/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "client-web",
"private": true,
"version": "0.0.7",
"version": "0.0.8",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
13 changes: 13 additions & 0 deletions apps/client-web/src/client/gpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,19 @@ export class ParcnetGPCProcessor implements ParcnetGPCRPC {
}

public async verify(
proof: GPCProof,
boundConfig: GPCBoundConfig,
revealedClaims: GPCRevealedClaims
): Promise<boolean> {
return gpcVerify(
proof,
boundConfig,
revealedClaims,
new URL("/artifacts", window.location.origin).toString()
);
}

public async verifyWithProofRequest(
proof: GPCProof,
boundConfig: GPCBoundConfig,
revealedClaims: GPCRevealedClaims,
Expand Down
7 changes: 7 additions & 0 deletions apps/docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# docs

## 0.0.2

### Patch Changes

- Support for distinct verify and verifyWithProofRequest operations
2 changes: 1 addition & 1 deletion apps/docs/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "docs",
"type": "module",
"version": "0.0.1",
"version": "0.0.2",
"scripts": {
"dev": "astro dev",
"start": "astro dev",
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/src/content/docs/guides/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ To get started with the Zapp SDK, you will need to install the `@parcnet-js/app-
Next, import the connector package in your application code:

```ts wrap=true title="src/main.ts"
import { connect } from "@parcnet-js/connector";
import { connect } from "@parcnet-js/app-connector";
```

## Connect to Zupass
Expand Down
73 changes: 71 additions & 2 deletions apps/docs/src/content/docs/guides/ticket-proofs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,75 @@ You can add a watermark to your proof, which allows you to uniquely identify a p

If you add a watermark to your proof request, you can check the watermark when later verifying the proof. A typical workflow might involve your client application requesting a random number from your server, which stores the number. The number is passed as a watermark in the proof request, and then you can send the proof to the server for verification. The server then checks that the watermark is equal to the random number it generated. By requiring the watermark to equal some single-use secret value, you ensure that the client cannot re-use a previously-generated proof.

# Verifying a ticket proof
## Verifying a ticket proof

TODO.
Once a proof has been made, you can verify it.

Typically, verification is done by a different person, computer, or program than the one that produced the proof. You don't really need to verify a proof that you just created on the same computer, but if you received a proof from someone else, or if you have an application which sends proofs between, say, a client and a server then you will want to verify any proofs that you receive.

Verification covers a few important principles:
- That, given a `revealedClaims` object which makes certain statements, a proof configuration, and a proof object, the proof object really does correspond to the configuration and revealed claims. If we didn't check this, then the `revealedClaims` might contain data for which there is no proof!
- That the configuration really is the one that you expect it to be. This is important because a proof might really match a set of claims and a configuration, but if the configuration is not the one you expect then the claims might not be valid for your use-case.

### Proof requests

To make this easy to get right, we have a concept of "proof requests". When you call `ticketProofRequest` as described above, you're creating a proof request object which can be used to... request a proof. However, you can also use the proof request when _verifying_ a proof, to ensure that the proof was produced in response to the correct request.

If you're verifying the proof in the browser using the Z API, you can do so like this:

```ts wrap=true title="src/main.ts"
import { ticketProofRequest } from "@parcnet-js/ticket-spec";

const request = ticketProofRequest({
/**
* As per examples above
*/
});

const { proof, boundConfig, revealedClaims } = await z.gpc.prove(request);

const isVerified = await z.gpc.verifyWithProofRequest(proof, boundConfig, revealedClaims, proofRequest);
```

This performs both of the checks described above. Of course, since you're using the same proof request object in both cases, you already know that the proof matches the request!

However, you can use a similar technique when verifying the same proof in another environment, such as on a server:

```ts wrap=true title="src/server.ts"
import { ticketProofRequest } from "@parcnet-js/ticket-spec";
import { gpcVerify } from "@pcd/gpc";
import isEqual from "lodash/isEqual";

const request = ticketProofRequest({
/**
* This should be the same proof request that you use on the client.
* It would be a good idea to define your proof request in a shared module or
* package.
*/
});

// Here we assume that some kind of web framework such as Express is being used
// to receive these variables via a HTTP POST or similar.
const { proof, boundConfig, revealedClaims } = httpRequest.body;

const { proofConfig, membershipLists, externalNullifier, watermark } = request.getProofRequest();

// This is necessary to satisfy the type of `GPCBoundConfig`
proofConfig.circuitIdentifier = boundConfig.circuitIdentifier;

// These changes ensure that the revealed claims say what they are supposed to
revealedClaims.membershipLists = membershipLists;
revealedClaims.watermark = watermark;
if (revealedClaims.owner) {
revealedClaims.owner.externalNullifier = externalNullifier;
}

const isVerified = await gpcVerify(
proof,
proofConfig as GPCBoundConfig,
revealedClaims,
pathToGPCArtifacts // This may vary depending on your installation
);
```

This ensures that our verified proof not only matches the claims that were sent, but that claims are those we expect them to be.
10 changes: 10 additions & 0 deletions examples/test-app/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# test-app

## 1.0.10

### Patch Changes

- Updated dependencies
- @parcnet-js/[email protected]
- @parcnet-js/[email protected]
- @parcnet-js/[email protected]
- @parcnet-js/[email protected]

## 1.0.9

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion examples/test-app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "test-app",
"version": "1.0.9",
"version": "1.0.10",
"private": true,
"type": "module",
"scripts": {
Expand Down
9 changes: 9 additions & 0 deletions packages/app-connector/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# @parcnet-js/app-connector

## 0.0.9

### Patch Changes

- Support for distinct verify and verifyWithProofRequest operations
- Updated dependencies
- @parcnet-js/[email protected]
- @parcnet-js/[email protected]

## 0.0.8

### Patch Changes
Expand Down
4 changes: 2 additions & 2 deletions packages/app-connector/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@parcnet-js/app-connector",
"version": "0.0.8",
"version": "0.0.9",
"license": "GPL-3.0-or-later",
"type": "module",
"main": "dist/index.cjs",
Expand All @@ -22,7 +22,7 @@
"lint": "eslint . --max-warnings 0",
"build": "tsup 'src/**/*@(ts|tsx)' --format cjs,esm --clean --sourcemap",
"prepublish": "tsup 'src/**/*@(ts|tsx)' --format cjs,esm --clean --sourcemap --dts",
"test": "vitest run"
"test": "vitest run --typecheck"
},
"files": ["dist", "LICENSE"],
"dependencies": {
Expand Down
15 changes: 14 additions & 1 deletion packages/app-connector/src/api_wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,25 @@ export class ParcnetGPCWrapper {
}

async verify(
proof: GPCProof,
config: GPCBoundConfig,
revealedClaims: GPCRevealedClaims
): Promise<boolean> {
return this.#api.gpc.verify(proof, config, revealedClaims);
}

async verifyWithProofRequest(
proof: GPCProof,
config: GPCBoundConfig,
revealedClaims: GPCRevealedClaims,
proofRequest: p.PodspecProofRequest
): Promise<boolean> {
return this.#api.gpc.verify(proof, config, revealedClaims, proofRequest);
return this.#api.gpc.verifyWithProofRequest(
proof,
config,
revealedClaims,
proofRequest
);
}
}

Expand Down
15 changes: 13 additions & 2 deletions packages/app-connector/src/rpc_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,15 +173,26 @@ export class ParcnetRPCConnector implements ParcnetRPC, ParcnetEvents {
);
},
verify: async (
proof: GPCProof,
boundConfig: GPCBoundConfig,
revealedClaims: GPCRevealedClaims
): Promise<boolean> => {
return this.#typedInvoke(
"gpc.verify",
[proof, boundConfig, revealedClaims],
ParcnetRPCSchema.gpc.verify
);
},
verifyWithProofRequest: async (
proof: GPCProof,
boundConfig: GPCBoundConfig,
revealedClaims: GPCRevealedClaims,
proofRequest: PodspecProofRequest
): Promise<boolean> => {
return this.#typedInvoke(
"gpc.verify",
"gpc.verifyWithProofRequest",
[proof, boundConfig, revealedClaims, proofRequest],
ParcnetRPCSchema.gpc.verify
ParcnetRPCSchema.gpc.verifyWithProofRequest
);
}
};
Expand Down
7 changes: 7 additions & 0 deletions packages/client-helpers/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @parcnet-js/client-helpers

## 0.0.8

### Patch Changes

- Updated dependencies
- @parcnet-js/[email protected]

## 0.0.7

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/client-helpers/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@parcnet-js/client-helpers",
"version": "0.0.7",
"version": "0.0.8",
"license": "GPL-3.0-or-later",
"type": "module",
"main": "dist/index.js",
Expand Down
8 changes: 8 additions & 0 deletions packages/client-rpc/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# @parcnet-js/client-rpc

## 0.0.6

### Patch Changes

- Support for distinct verify and verifyWithProofRequest operations
- Updated dependencies
- @parcnet-js/[email protected]

## 0.0.5

### Patch Changes
Expand Down
9 changes: 6 additions & 3 deletions packages/client-rpc/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@parcnet-js/client-rpc",
"type": "module",
"version": "0.0.5",
"version": "0.0.6",
"license": "GPL-3.0-or-later",
"main": "dist/index.js",
"module": "dist/index.js",
Expand All @@ -21,7 +21,8 @@
"scripts": {
"lint": "eslint . --max-warnings 0",
"build": "tsup 'src/**/*@(ts|tsx)' --format cjs,esm --clean --sourcemap",
"prepublish": "tsup 'src/**/*@(ts|tsx)' --format cjs,esm --clean --sourcemap --dts"
"prepublish": "tsup 'src/**/*@(ts|tsx)' --format cjs,esm --clean --sourcemap --dts",
"test": "vitest run --typecheck"
},
"files": ["dist", "LICENSE"],
"dependencies": {
Expand All @@ -32,10 +33,12 @@
},
"devDependencies": {
"@parcnet-js/eslint-config": "workspace:*",
"@parcnet-js/podspec": "workspace:*",
"@parcnet-js/typescript-config": "workspace:*",
"@types/snarkjs": "^0.7.8",
"tsup": "^8.2.4",
"typescript": "^5.5"
"typescript": "^5.5",
"vitest": "^2.1.2"
},
"publishConfig": {
"access": "public",
Expand Down
5 changes: 5 additions & 0 deletions packages/client-rpc/src/rpc_interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ export interface ParcnetGPCRPC {
prove: (request: PodspecProofRequest) => Promise<ProveResult>;
canProve: (request: PodspecProofRequest) => Promise<boolean>;
verify: (
proof: GPCProof,
boundConfig: GPCBoundConfig,
revealedClaims: GPCRevealedClaims
) => Promise<boolean>;
verifyWithProofRequest: (
proof: GPCProof,
boundConfig: GPCBoundConfig,
revealedClaims: GPCRevealedClaims,
Expand Down
Loading
Loading