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

Support new POD value types #29

Merged
merged 5 commits into from
Oct 31, 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
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
Loading