Skip to content

Commit

Permalink
feat: extend ZKGeoPoint prover to support recursive ZKGeoPointInPolyg…
Browse files Browse the repository at this point in the history
…onProofs, and generation of PointInOrOutOfPolygonCircuitProof
  • Loading branch information
iluxonchik committed Jan 11, 2024
1 parent a398b29 commit c65a807
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 1 deletion.
3 changes: 3 additions & 0 deletions contracts/src/api/provers/IZKGeoPointProver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ import type { ZKGeoPointInPolygonProof } from "../proofs/ZKGeoPointInPolygonProo
import type { ZKExactGeoPointCircuitProof } from "../proofs/ZKExactGeoPointCircuitProof";
import type { ZKGeoPointProviderCircuitProof } from "../proofs/ZKGeoPointProviderCircuitProof";
import type { ZKExactGeolocationMetadataCircuitProof } from "../proofs/ZKExactGeolocationMetadataCircuitProof";
import type { ZKGeoPointInOrOutOfPolygonCircuitProof } from "../proofs/ZKGeoPointInOrOutOfPolygonCircuitProof";

export type ZKGeoPointConstructor = new (...args: any[]) => ZKGeoPoint;

export interface IZKGeoPointProver extends IZKProver {

Prove: {
inPolygon: (polygon: ZKThreePointPolygon) => Promise<ZKGeoPointInPolygonProof>;
inPolygons: (polygons: ZKThreePointPolygon[]) => Promise<ZKGeoPointInPolygonProof[]>;
combinePointInPolygonProofs: () => Promise<ZKGeoPointInOrOutOfPolygonCircuitProof>;
authenticateFromIntegrationOracle: (publicKey: ZKPublicKey, signature: ZKSignature) => Promise<ZKGeoPointProviderCircuitProof>;
exactGeoPoint: () => Promise<ZKExactGeoPointCircuitProof>;
attachMetadata: (metadata: string) => Promise<ZKExactGeolocationMetadataCircuitProof>;
Expand Down
75 changes: 74 additions & 1 deletion contracts/src/api/provers/ZKGeoPointProver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ import type { ZKExactGeolocationMetadataCircuitProof } from "../proofs/ZKExactGe
import { ExactGeolocationMetadataCircuit, ExactGeolocationMetadataCircuitProof } from "../../zkprogram/public/Metadata";
import { Bytes64, SHA3_512 } from "../sha3/SHA3";
import { ZKGeoPointConstructor, IZKGeoPointProver } from "./IZKGeoPointProver";
import type { ZKGeoPointInOrOutOfPolygonCircuitProof } from "../proofs/ZKGeoPointInOrOutOfPolygonCircuitProof";
import { GeoPointInOrOutOfPolygonCircuit, GeoPointInOrOutOfPolygonCircuitProof } from "../../zkprogram/private/GeoPointInOrOutOfPolygonCircuit";

type PolygonProofs = {
insidePolygonProofs: ZKGeoPointInPolygonProof[];
outsidePolygonProofs: ZKGeoPointInPolygonProof[];
};


/**
* Enhances a ZKGeoPoint with methods for generating zero-knowledge proofs.
Expand All @@ -34,6 +42,12 @@ export default function <T extends ZKGeoPointConstructor>(Base: T) {
*/
private exactGeolocationMetadataProof: ZKExactGeolocationMetadataCircuitProof | null = null;

private inPolygonProof: PolygonProofs = {
insidePolygonProofs: [],
outsidePolygonProofs: [],
};



getIntegrationOracleProofOrError(): ZKGeoPointProviderCircuitProof {
if (this.integrationOracleProof === null) {
Expand All @@ -53,7 +67,31 @@ export default function <T extends ZKGeoPointConstructor>(Base: T) {
const geoPointInPolygonProof: GeoPointInPolygonCircuitProof = await GeoPointInPolygonCircuit.proveGeoPointIn3PointPolygon(geoPointProof, polygon.toZKValue());

const { ZKGeoPointInPolygonProof } = await import("../proofs/ZKGeoPointInPolygonProof");
return new ZKGeoPointInPolygonProof(this, polygon, geoPointInPolygonProof);
const zkPointInPolygonProof: ZKGeoPointInPolygonProof = new ZKGeoPointInPolygonProof(this, polygon, geoPointInPolygonProof);

// record the proof in the appropriate collection, depending on whether the ZKGeoPoint is inside or outside the polygon
if (zkPointInPolygonProof.UnverifiedProofData.isInside) {
this.inPolygonProof.insidePolygonProofs.push(zkPointInPolygonProof);
} else {
this.inPolygonProof.outsidePolygonProofs.push(zkPointInPolygonProof);
}
return zkPointInPolygonProof;
},

inPolygons: async(polygons: ZKThreePointPolygon[]): Promise<ZKGeoPointInPolygonProof[]> => {
if (polygons.length === 0) {
throw new Error("'polygons' must contain at least one polygon.")
}

const { ZKGeoPointInPolygonProof } = await import("../proofs/ZKGeoPointInPolygonProof");
const proofs: ZKGeoPointInPolygonProof[] = [];
for (const polygon of polygons) {
const proof: ZKGeoPointInPolygonProof = await this.Prove.inPolygon(polygon);
proofs.push(proof);
}

return proofs;

},
/**
* Authenticates the ZKGeoPoint using a signature from an Integration Oracle.
Expand Down Expand Up @@ -128,7 +166,42 @@ export default function <T extends ZKGeoPointConstructor>(Base: T) {
this.exactGeolocationMetadataProof = new ZKExactGeolocationMetadataCircuitProof(this, metadata, exactGeolocationMetadataProof);

return this.exactGeolocationMetadataProof;
},

combinePointInPolygonProofs: async (): Promise<ZKGeoPointInOrOutOfPolygonCircuitProof> => {
if (this.inPolygonProof.insidePolygonProofs.length === 0) {
throw new Error("Cannot combine proofs for a ZKGeoPoint that has not been proven to be inside of any polygons. It's requied to have both, inside and outside polygon proofs. If you only have one set, you can combine them together with .AND and/or .OR methods.");
}

if (this.inPolygonProof.outsidePolygonProofs.length === 0) {
throw new Error("Cannot combine proofs for a ZKGeoPoint that has not been proven to be outside of any polygons. It's requied to have both, inside and outside polygon proofs. If you only have one set, you can combine them together with .AND and/or .OR methods.");
}

const insidePolygonProofs: ZKGeoPointInPolygonProof[] = this.inPolygonProof.insidePolygonProofs;
const outsidePolygonProofs: ZKGeoPointInPolygonProof[] = this.inPolygonProof.outsidePolygonProofs;

const firstInsidePolygonProof: ZKGeoPointInPolygonProof = insidePolygonProofs[0];
const firstOutsidePolygonProof: ZKGeoPointInPolygonProof = outsidePolygonProofs[0];

for (const insidePolygonProof of insidePolygonProofs.slice(1)) {
await firstInsidePolygonProof.AND(insidePolygonProof);
}

for (const outsidePolygonProof of outsidePolygonProofs.slice(1)) {
await firstOutsidePolygonProof.AND(outsidePolygonProof);
}

const insidePolygonProofRaw: GeoPointInPolygonCircuitProof = firstInsidePolygonProof.proof;
const outsidePolygonProofRaw: GeoPointInPolygonCircuitProof = firstOutsidePolygonProof.proof;

const proof: GeoPointInOrOutOfPolygonCircuitProof = await GeoPointInOrOutOfPolygonCircuit.fromPointInPolygonProofs(insidePolygonProofRaw, outsidePolygonProofRaw);

const { ZKGeoPointInOrOutOfPolygonCircuitProof } = await import("../proofs/ZKGeoPointInOrOutOfPolygonCircuitProof");
const zkProof: ZKGeoPointInOrOutOfPolygonCircuitProof = new ZKGeoPointInOrOutOfPolygonCircuitProof(this, proof);
return zkProof;

}

};

private async exactGeoPointForIntegrationOracle(): Promise<ZKExactGeoPointCircuitProof> {
Expand Down

0 comments on commit c65a807

Please sign in to comment.