Skip to content

Commit

Permalink
Support new POD value types (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
robknight authored Oct 31, 2024
1 parent e1a97f3 commit 7b37763
Show file tree
Hide file tree
Showing 22 changed files with 632 additions and 114 deletions.
6 changes: 6 additions & 0 deletions .changeset/fair-hairs-bow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@parcnet-js/client-rpc": minor
"@parcnet-js/podspec": minor
---

Support new PODValue types
9 changes: 9 additions & 0 deletions .changeset/shaggy-feet-kick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@parcnet-js/app-connector": patch
"@parcnet-js/ticket-spec": patch
"@parcnet-js/client-rpc": patch
"@parcnet-js/podspec": patch
"client-web": patch
---

Bump dependencies on POD and GPC
8 changes: 4 additions & 4 deletions apps/client-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
"@parcnet-js/client-helpers": "workspace:*",
"@parcnet-js/client-rpc": "workspace:*",
"@parcnet-js/podspec": "workspace:*",
"@pcd/gpc": "^0.3.0",
"@pcd/pod": "^0.4.0",
"@pcd/proto-pod-gpc-artifacts": "^0.9.0",
"@pcd/gpc": "^0.4.0",
"@pcd/pod": "^0.5.0",
"@pcd/proto-pod-gpc-artifacts": "^0.13.0",
"@radix-ui/react-dialog": "^1.1.1",
"@semaphore-protocol/core": "^4.4.1",
"@semaphore-protocol/core": "^4.5.0",
"@semaphore-protocol/identity": "3.15.2",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
Expand Down
20 changes: 10 additions & 10 deletions apps/client-web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { listen } from "@parcnet-js/client-helpers/connection/iframe";
import type { Zapp } from "@parcnet-js/client-rpc";
import type { EntriesSchema, ProofConfigPODSchema } from "@parcnet-js/podspec";
import { proofRequest } from "@parcnet-js/podspec";
import { gpcProve } from "@pcd/gpc";
import { type GPCProofInputs, gpcProve } from "@pcd/gpc";
import type { POD } from "@pcd/pod";
import { POD_INT_MAX, POD_INT_MIN } from "@pcd/pod";
import type { Dispatch, ReactNode } from "react";
Expand Down Expand Up @@ -130,9 +130,10 @@ function ProvePODInfo({
})
.filter(
([_, entry]) =>
!!entry.isMemberOf ||
!!entry.isNotMemberOf ||
!!(entry.type === "int" && entry.inRange)
entry.type !== "null" &&
(!!entry.isMemberOf ||
!!entry.isNotMemberOf ||
!!(entry.type === "int" && entry.inRange))
);

return (
Expand All @@ -155,7 +156,7 @@ function ProvePODInfo({
{schema.pod.meta?.labelEntry
? pod.content
.asEntries()
[schema.pod.meta.labelEntry].value.toString()
[schema.pod.meta.labelEntry].value?.toString()
: pod.signature.substring(0, 16)}
</option>
);
Expand All @@ -171,7 +172,7 @@ function ProvePODInfo({
<Fragment key={`${name}-${entryName}`}>
<div>{entryName}</div>
<div>
{selectedPODEntries?.[entryName].value.toString() ?? "-"}
{selectedPODEntries?.[entryName].value?.toString() ?? "-"}
</div>
</Fragment>
);
Expand All @@ -183,7 +184,7 @@ function ProvePODInfo({
{entriesWithConstraints.map(([entryName, entry]) => {
return (
<div key={`${name}-${entryName}-constraints`} className="my-1">
{entry.isMemberOf && (
{entry.type !== "null" && entry.isMemberOf && (
<div>
<span className="font-semibold">{entryName}</span> is member
of list:{" "}
Expand All @@ -196,7 +197,7 @@ function ProvePODInfo({
</Reveal>
</div>
)}
{entry.isNotMemberOf && (
{entry.type !== "null" && entry.isNotMemberOf && (
<div>
<span className="font-semibold">{entryName}</span> is not
member of list:{" "}
Expand Down Expand Up @@ -294,7 +295,7 @@ export function Prove({
const prs = proofRequest(
proveOperation.proofRequest
).getProofRequest();
const inputs = {
const inputs: GPCProofInputs = {
pods: proveOperation.selectedPods as Record<string, POD>,
membershipLists: prs.membershipLists,
watermark: prs.watermark,
Expand All @@ -303,7 +304,6 @@ export function Prove({
externalNullifier: prs.externalNullifier
}
};
console.log(inputs);
gpcProve(
{
...prs.proofConfig,
Expand Down
4 changes: 2 additions & 2 deletions packages/app-connector/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
"dependencies": {
"@parcnet-js/client-rpc": "workspace:*",
"@parcnet-js/podspec": "workspace:*",
"@pcd/gpc": "^0.3.0",
"@pcd/pod": "^0.4.0",
"@pcd/gpc": "^0.4.0",
"@pcd/pod": "^0.5.0",
"nanoevents": "^9.0.0",
"valibot": "^0.42.0"
},
Expand Down
4 changes: 2 additions & 2 deletions packages/client-rpc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
"files": ["dist", "LICENSE"],
"dependencies": {
"@parcnet-js/podspec": "workspace:*",
"@pcd/gpc": "^0.3.0",
"@pcd/pod": "^0.4.0",
"@pcd/gpc": "^0.4.0",
"@pcd/pod": "^0.5.0",
"valibot": "^0.42.0"
},
"devDependencies": {
Expand Down
40 changes: 40 additions & 0 deletions packages/client-rpc/src/schema_elements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,22 @@ export const PODValueSchema = v.variant("type", [
v.object({
type: v.literal("eddsa_pubkey"),
value: v.string()
}),
v.object({
type: v.literal("boolean"),
value: v.boolean()
}),
v.object({
type: v.literal("date"),
value: v.date()
}),
v.object({
type: v.literal("bytes"),
value: v.instance(Uint8Array)
}),
v.object({
type: v.literal("null"),
value: v.null()
})
]);

Expand Down Expand Up @@ -57,6 +73,30 @@ export const DefinedEntrySchema = v.variant("type", [
isNotMemberOf: v.optional(v.array(PODValueSchema)),
isRevealed: v.optional(v.boolean()),
equalsEntry: v.optional(v.string())
}),
v.object({
type: v.literal("null")
}),
v.object({
type: v.literal("bytes"),
isMemberOf: v.optional(v.array(PODValueSchema)),
isNotMemberOf: v.optional(v.array(PODValueSchema))
}),
v.object({
type: v.literal("date"),
isMemberOf: v.optional(v.array(PODValueSchema)),
isNotMemberOf: v.optional(v.array(PODValueSchema)),
inRange: v.optional(
v.object({
min: v.bigint(),
max: v.bigint()
})
)
}),
v.object({
type: v.literal("boolean"),
isMemberOf: v.optional(v.array(PODValueSchema)),
isNotMemberOf: v.optional(v.array(PODValueSchema))
})
]);

Expand Down
4 changes: 2 additions & 2 deletions packages/podspec/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
},
"files": ["dist", "./README.md", "./LICENSE"],
"dependencies": {
"@pcd/gpc": "^0.3.0",
"@pcd/pod": "^0.4.0"
"@pcd/gpc": "^0.4.0",
"@pcd/pod": "^0.5.0"
},
"devDependencies": {
"@parcnet-js/eslint-config": "workspace:*",
Expand Down
10 changes: 6 additions & 4 deletions packages/podspec/src/gpc/proof_request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,10 @@ function makeProofRequest<P extends NamedPODs>(
schema.type === "optional" ? schema.innerType : schema;

const isRevealed = proofConfigPODSchema.revealed?.[entryName] ?? false;
const isMemberOf = entrySchema.isMemberOf;
const isNotMemberOf = entrySchema.isNotMemberOf;
const isMemberOf =
entrySchema.type === "null" ? undefined : entrySchema.isMemberOf;
const isNotMemberOf =
entrySchema.type === "null" ? undefined : entrySchema.isNotMemberOf;
const inRange =
(entrySchema.type === "cryptographic" || entrySchema.type === "int") &&
entrySchema.inRange;
Expand Down Expand Up @@ -173,11 +175,11 @@ function makeProofRequest<P extends NamedPODs>(
};
podConfig.entries[entryName] = entryConfig;

if (entrySchema.isMemberOf) {
if (entrySchema.type !== "null" && entrySchema.isMemberOf) {
membershipLists[`allowlist_${podName}_${entryName}`] =
entrySchema.isMemberOf;
}
if (entrySchema.isNotMemberOf) {
if (entrySchema.type !== "null" && entrySchema.isNotMemberOf) {
membershipLists[`blocklist_${podName}_${entryName}`] =
entrySchema.isNotMemberOf;
}
Expand Down
35 changes: 30 additions & 5 deletions packages/podspec/src/parse/entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,21 @@ import type {
PodspecUnexpectedInputEntryIssue
} from "../error.js";
import { IssueCode, PodspecError } from "../error.js";
import { booleanCoercer, checkPODBooleanValue } from "../schemas/boolean.js";
import { bytesCoercer, checkPODBytesValue } from "../schemas/bytes.js";
import {
checkPODCryptographicValue,
cryptographicCoercer
} from "../schemas/cryptographic.js";
import { checkPODDateValue, dateCoercer } from "../schemas/dates.js";
import {
checkPODEdDSAPublicKeyValue,
eddsaPublicKeyCoercer
} from "../schemas/eddsa_pubkey.js";
import type { EntriesSchema, EntriesTupleSchema } from "../schemas/entries.js";
import type { EntrySchema } from "../schemas/entry.js";
import { checkPODIntValue, intCoercer } from "../schemas/int.js";
import { checkPODNullValue, nullCoercer } from "../schemas/null.js";
import { checkPODStringValue, stringCoercer } from "../schemas/string.js";
import type { EntriesOutputType } from "../type_inference.js";
import { deepFreeze } from "../utils.js";
Expand All @@ -30,14 +34,22 @@ const COERCERS: Record<PODValue["type"], (data: unknown) => unknown> = {
string: stringCoercer,
int: intCoercer,
eddsa_pubkey: eddsaPublicKeyCoercer,
cryptographic: cryptographicCoercer
cryptographic: cryptographicCoercer,
boolean: booleanCoercer,
bytes: bytesCoercer,
date: dateCoercer,
null: nullCoercer
};

const TYPE_VALIDATORS = {
string: checkPODStringValue,
int: checkPODIntValue,
eddsa_pubkey: checkPODEdDSAPublicKeyValue,
cryptographic: checkPODCryptographicValue
cryptographic: checkPODCryptographicValue,
boolean: checkPODBooleanValue,
bytes: checkPODBytesValue,
date: checkPODDateValue,
null: checkPODNullValue
};

/**
Expand All @@ -61,6 +73,10 @@ const VALID_ENTRY_SCHEMA_TYPES = [
"string",
"cryptographic",
"eddsa_pubkey",
"boolean",
"bytes",
"date",
"null",
"optional"
] as const;

Expand Down Expand Up @@ -118,7 +134,10 @@ export class EntriesSpec<const E extends EntriesSchema> {
* @returns A ParseResult containing either a valid result or list of issues.
*/
public safeParse(
input: Record<string, PODValue | string | bigint | number>,
input: Record<
string,
PODValue | string | bigint | number | boolean | Uint8Array | null | Date
>,
options: EntriesParseOptions<E> = DEFAULT_ENTRIES_PARSE_OPTIONS,
path: string[] = []
): ParseResult<EntriesOutputType<E>> {
Expand All @@ -129,7 +148,10 @@ export class EntriesSpec<const E extends EntriesSchema> {
* As {@link safeParse} but will throw an exception if errors are encountered.
*/
public parse(
input: Record<string, PODValue | string | bigint | number>,
input: Record<
string,
PODValue | string | bigint | number | boolean | Uint8Array | null | Date
>,
options: EntriesParseOptions<E> = DEFAULT_ENTRIES_PARSE_OPTIONS,
path: string[] = []
): EntriesOutputType<E> {
Expand Down Expand Up @@ -191,7 +213,10 @@ export const DEFAULT_ENTRIES_PARSE_OPTIONS: EntriesParseOptions<EntriesSchema> =
*/
export function safeParseEntries<E extends EntriesSchema>(
schema: E,
input: Record<string, PODValue | string | bigint | number>,
input: Record<
string,
PODValue | string | bigint | number | boolean | Uint8Array | null | Date
>,
options: EntriesParseOptions<E> = DEFAULT_ENTRIES_PARSE_OPTIONS,
path: string[] = []
): ParseResult<EntriesOutputType<E>> {
Expand Down
37 changes: 30 additions & 7 deletions packages/podspec/src/parse/entry.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import type { PODCryptographicValue, PODIntValue } from "@pcd/pod";
import type {
PODCryptographicValue,
PODDateValue,
PODIntValue
} from "@pcd/pod";
import { checkBigintBounds } from "@pcd/pod/podChecks";
import type { PodspecBaseIssue, PodspecNotInRangeIssue } from "../error.js";
import { IssueCode } from "../error.js";
Expand Down Expand Up @@ -63,12 +67,19 @@ export function parseEntry<S extends DefinedEntrySchema>(
}
}

const checkedForMatches = safeMembershipChecks(schema, value, options, path);
if (!checkedForMatches.isValid) {
if (options.exitEarly) {
return FAILURE(checkedForMatches.issues);
} else {
issues.push(...checkedForMatches.issues);
if (schema.type !== "null") {
const checkedForMatches = safeMembershipChecks(
schema,
value,
options,
path
);
if (!checkedForMatches.isValid) {
if (options.exitEarly) {
return FAILURE(checkedForMatches.issues);
} else {
issues.push(...checkedForMatches.issues);
}
}
}

Expand All @@ -95,5 +106,17 @@ export function parseEntry<S extends DefinedEntrySchema>(
}
}

if (schema.type === "date") {
if (schema.inRange) {
const { min, max } = schema.inRange;
checkBigintBounds(
"",
BigInt((value as PODDateValue).value.getTime()),
min,
max
);
}
}

return issues.length > 0 ? FAILURE(issues) : SUCCESS(value);
}
Loading

0 comments on commit 7b37763

Please sign in to comment.