From f448042c00f9a499d0a3cf21392b76c10ead2876 Mon Sep 17 00:00:00 2001 From: Illya Gerasymchuk Date: Sun, 7 Jan 2024 16:24:51 +0200 Subject: [PATCH] feat: implement inside outside polygon commitment circuit --- contracts/src/Polygon.test.ts | 30 +++---- contracts/src/api/proofs/ZKLocusProof.ts | 6 +- contracts/src/api/provers/ZKGeoPointProver.ts | 3 +- contracts/src/logic/Methods.ts | 28 ++++--- .../logic/private/GeoPointInOrOutOfPolygon.ts | 84 +++++++++++++++++++ contracts/src/model/private/Commitment.ts | 13 +-- .../GeoPointInOrOutOfPolygonCircuit.ts | 68 +++++++++++++++ contracts/src/zkprogram/private/Geography.ts | 29 +------ 8 files changed, 196 insertions(+), 65 deletions(-) create mode 100644 contracts/src/logic/private/GeoPointInOrOutOfPolygon.ts create mode 100644 contracts/src/zkprogram/private/GeoPointInOrOutOfPolygonCircuit.ts diff --git a/contracts/src/Polygon.test.ts b/contracts/src/Polygon.test.ts index f26c7df..711252a 100644 --- a/contracts/src/Polygon.test.ts +++ b/contracts/src/Polygon.test.ts @@ -107,17 +107,17 @@ describe('CoordinatesInPolygon', () => { const notInRomaniaCoordinatesSourced: GeoPointProviderCircuitProof = await GeoPointProviderCircuit.fromLiteralGeoPoint(notInRomaniaCoordinates); - proofBrasovCenterCoordinatesInBrasovCenterPolygon = await GeoPointInPolygonCircuit.proveProvidedGeoPointIn3PointPolygon( + proofBrasovCenterCoordinatesInBrasovCenterPolygon = await GeoPointInPolygonCircuit.proveGeoPointIn3PointPolygon( brasovCenterCoordinatesSourced, brasovCenterPolygon ); - proofNotBrasovCenterCoordinatesInBrasovCenterPolygon = await GeoPointInPolygonCircuit.proveProvidedGeoPointIn3PointPolygon( + proofNotBrasovCenterCoordinatesInBrasovCenterPolygon = await GeoPointInPolygonCircuit.proveGeoPointIn3PointPolygon( notBrasovCenterCoordinatesSourced, brasovCenterPolygon ); - proofNotInRomaniaCoordinatesNotInBrasovCenterPolygon = await GeoPointInPolygonCircuit.proveProvidedGeoPointIn3PointPolygon( + proofNotInRomaniaCoordinatesNotInBrasovCenterPolygon = await GeoPointInPolygonCircuit.proveGeoPointIn3PointPolygon( notInRomaniaCoordinatesSourced, brasovCenterPolygon, ); @@ -216,62 +216,62 @@ describe('CoordinatesInPolygon', () => { }); - proofInsideCoordinate1InInsidePolygon1 = await GeoPointInPolygonCircuit.proveProvidedGeoPointIn3PointPolygon( + proofInsideCoordinate1InInsidePolygon1 = await GeoPointInPolygonCircuit.proveGeoPointIn3PointPolygon( insideCoordinate1Sourced, insidePolygon1, ); - proofInsideCoordinate2InInsidePolygon1 = await GeoPointInPolygonCircuit.proveProvidedGeoPointIn3PointPolygon( + proofInsideCoordinate2InInsidePolygon1 = await GeoPointInPolygonCircuit.proveGeoPointIn3PointPolygon( insideCoordinate2Sourced, insidePolygon1, ); - proofInsideCoordinate3InInsidePolygon1 = await GeoPointInPolygonCircuit.proveProvidedGeoPointIn3PointPolygon( + proofInsideCoordinate3InInsidePolygon1 = await GeoPointInPolygonCircuit.proveGeoPointIn3PointPolygon( insideCoordinate3Sourced, insidePolygon1, ); - proofInsideCoordinate1InInsidePolygon2 = await GeoPointInPolygonCircuit.proveProvidedGeoPointIn3PointPolygon( + proofInsideCoordinate1InInsidePolygon2 = await GeoPointInPolygonCircuit.proveGeoPointIn3PointPolygon( insideCoordinate1Sourced, insidePolygon2, ); - proofInsideCoordinate2InInsidePolygon2 = await GeoPointInPolygonCircuit.proveProvidedGeoPointIn3PointPolygon( + proofInsideCoordinate2InInsidePolygon2 = await GeoPointInPolygonCircuit.proveGeoPointIn3PointPolygon( insideCoordinate2Sourced, insidePolygon2, ); - proofInsideCoordinate3InInsidePolygon2 = await GeoPointInPolygonCircuit.proveProvidedGeoPointIn3PointPolygon( + proofInsideCoordinate3InInsidePolygon2 = await GeoPointInPolygonCircuit.proveGeoPointIn3PointPolygon( insideCoordinate3Sourced, insidePolygon2, ); - proofInsideCoordinate1NotInOutsidePolygon1 = await GeoPointInPolygonCircuit.proveProvidedGeoPointIn3PointPolygon( + proofInsideCoordinate1NotInOutsidePolygon1 = await GeoPointInPolygonCircuit.proveGeoPointIn3PointPolygon( insideCoordinate1Sourced, outsidePolygon1, ); - proofInsideCoordinate2NotInOutsidePolygon1 = await GeoPointInPolygonCircuit.proveProvidedGeoPointIn3PointPolygon( + proofInsideCoordinate2NotInOutsidePolygon1 = await GeoPointInPolygonCircuit.proveGeoPointIn3PointPolygon( insideCoordinate2Sourced, outsidePolygon1, ); - proofInsideCoordinate3NotInOutsidePolygon1 = await GeoPointInPolygonCircuit.proveProvidedGeoPointIn3PointPolygon( + proofInsideCoordinate3NotInOutsidePolygon1 = await GeoPointInPolygonCircuit.proveGeoPointIn3PointPolygon( insideCoordinate3Sourced, outsidePolygon1, ); - proofInsideCoordinate1NotInOutsidePolygon2 = await GeoPointInPolygonCircuit.proveProvidedGeoPointIn3PointPolygon( + proofInsideCoordinate1NotInOutsidePolygon2 = await GeoPointInPolygonCircuit.proveGeoPointIn3PointPolygon( insideCoordinate1Sourced, outsidePolygon2, ); - proofInsideCoordinate2NotInOutsidePolygon2 = await GeoPointInPolygonCircuit.proveProvidedGeoPointIn3PointPolygon( + proofInsideCoordinate2NotInOutsidePolygon2 = await GeoPointInPolygonCircuit.proveGeoPointIn3PointPolygon( insideCoordinate2Sourced, outsidePolygon2, ); - proofInsideCoordinate3NotInOutsidePolygon2 = await GeoPointInPolygonCircuit.proveProvidedGeoPointIn3PointPolygon( + proofInsideCoordinate3NotInOutsidePolygon2 = await GeoPointInPolygonCircuit.proveGeoPointIn3PointPolygon( insideCoordinate3Sourced, outsidePolygon2, ); diff --git a/contracts/src/api/proofs/ZKLocusProof.ts b/contracts/src/api/proofs/ZKLocusProof.ts index 953c060..33b0df3 100644 --- a/contracts/src/api/proofs/ZKLocusProof.ts +++ b/contracts/src/api/proofs/ZKLocusProof.ts @@ -1,5 +1,4 @@ -import { Field, JsonProof, ZkProgram} from "o1js"; -import { Bool } from "o1js/dist/node/lib/bool"; +import { Bool, Field, JsonProof, ZkProgram, Cache} from "o1js"; import type { ZKPublicKey } from "../models/ZKPublicKey"; import type { ZKThreePointPolygon } from "../models/ZKThreePointPolygon"; import type { ZKGeoPoint } from "../models/ZKGeoPoint"; @@ -7,9 +6,8 @@ import { GeoPointInPolygonCommitment } from "../../model/private/Commitment"; import { GeoPoint, ThreePointPolygon } from "../../model/Geography"; import { ZKProgramCompileResult} from "./Types"; import { OracleAuthenticatedGeoPointCommitment } from "../../model/private/Oracle"; -import { Cache } from "o1js/dist/node/lib/proof-system/cache"; import { ZKProgramCircuit } from "./Types"; -import { ICompilableZKLocusProof } from "./ICompilableZKLocusProof"; +import { ICompilableZKLocusProof } from "./Interfaces"; diff --git a/contracts/src/api/provers/ZKGeoPointProver.ts b/contracts/src/api/provers/ZKGeoPointProver.ts index 50ab8cf..3ddc673 100644 --- a/contracts/src/api/provers/ZKGeoPointProver.ts +++ b/contracts/src/api/provers/ZKGeoPointProver.ts @@ -4,7 +4,6 @@ import type { ZKThreePointPolygon } from "../models/ZKThreePointPolygon"; import type { ZKGeoPoint } from "../models/ZKGeoPoint"; import { IZKProver } from "./Interfaces"; import { GeoPointInPolygonCircuit, GeoPointInPolygonCircuitProof, GeoPointProviderCircuit, GeoPointProviderCircuitProof } from "../../zkprogram/private/Geography"; -import { ZKLocusProof } from "../proofs/ZKLocusProof"; import { ZKGeoPointInPolygonProof } from "../proofs/ZKGeoPointInPolygonProof"; import { PublicKey, Signature } from "o1js"; import { OracleGeoPointProviderCircuitProof, OracleGeoPointProviderCircuit } from "../../zkprogram/private/Oracle"; @@ -63,7 +62,7 @@ export default function (Base: T) { */ inPolygon: async (polygon: ZKThreePointPolygon): Promise => { const geoPointProof: GeoPointProviderCircuitProof = await GeoPointProviderCircuit.fromLiteralGeoPoint(this.toZKValue()); - const geoPointInPolygonProof: GeoPointInPolygonCircuitProof = await GeoPointInPolygonCircuit.proveProvidedGeoPointIn3PointPolygon(geoPointProof, polygon.toZKValue()); + const geoPointInPolygonProof: GeoPointInPolygonCircuitProof = await GeoPointInPolygonCircuit.proveGeoPointIn3PointPolygon(geoPointProof, polygon.toZKValue()); return new ZKGeoPointInPolygonProof(this, polygon, geoPointInPolygonProof); }, /** diff --git a/contracts/src/logic/Methods.ts b/contracts/src/logic/Methods.ts index d302537..2001794 100644 --- a/contracts/src/logic/Methods.ts +++ b/contracts/src/logic/Methods.ts @@ -4,7 +4,7 @@ import { isPointOnEdgeProvable } from './Geography'; import { GeoPoint, ThreePointPolygon } from '../model/Geography'; import { Int64Prover } from "../math/Provers.js"; -import { GeoPointPolygonInclusionExclusionProof, GeoPointInPolygonCommitment, GeoPointWithTimeStampIntervalInPolygonCommitment } from "../model/private/Commitment"; +import { GeoPointInOutPolygonCommitment, GeoPointInPolygonCommitment, GeoPointWithTimeStampIntervalInPolygonCommitment } from "../model/private/Commitment"; import { TimeStampInterval } from "../model/Time"; import { GeoPointInPolygonCircuitProof, GeoPointProviderCircuitProof, TimeStampIntervalProviderCircuitProof } from "../zkprogram/private/Geography"; import { OracleGeoPointProviderCircuitProof } from "../zkprogram/private/Oracle"; @@ -195,11 +195,13 @@ export function AND( proof1: SelfProof, proof2: SelfProof ): GeoPointInPolygonCommitment { - // IMPORTANT: this has an issue. If I give proof1, which asserts that the user is in Spain, and proof2 that + // IMPORTANT: A caveat of this AND. If you give proof1, which asserts that the user is in Spain, and proof2 that // asserts that the user is not in Romania, then the resulting proof from .AND will say that the user is - // neither in Spain, nor Romania. This is because the AND operation is applied to the `isInPolygon` field - // of the two proofs. This is not the desired behaviour. The desired behaviour is to have a proof that - // asserts that the user is in Spain AND is not in Romania. + // not in Spain AND Romania. This is because the AND operation is applied to the `isInPolygon` field + // of the two proofs. This is coherent with the "isPointInPolygon" logic, as the resulting proof attests + // whether the point IS IN polygon. As such, the AND logic is applied to whether the point IS IN polygon 1 AND IN polygon 2. + + // A separate piece of functionality is is to have a proof that asserts that the user is in Spain AND is not in Romania. // For correctness, this method/proof should opearate ensuring that the values of `isInPolygon` is the same // in both proofs: either both are true, or both are false. If they are different, then the proof should // fail. This way the proof will attest to either the user being inside a set of polygons, or outside of that set. @@ -288,14 +290,14 @@ export function OR( } export function combine( - proof1: SelfProof, - proof2: SelfProof -): GeoPointPolygonInclusionExclusionProof { + proof1: SelfProof, + proof2: SelfProof +): GeoPointInOutPolygonCommitment { proof1.verify(); proof2.verify(); - const proof1PublicOutput: GeoPointPolygonInclusionExclusionProof = proof1.publicOutput; - const proof2PublicOutput: GeoPointPolygonInclusionExclusionProof = proof2.publicOutput; + const proof1PublicOutput: GeoPointInOutPolygonCommitment = proof1.publicOutput; + const proof2PublicOutput: GeoPointInOutPolygonCommitment = proof2.publicOutput; // ensure that the proof is for the same coordinates proof1.publicOutput.coordinatesCommitment.assertEquals( @@ -411,7 +413,7 @@ export function OR( newOutsideCommitment ); - return new GeoPointPolygonInclusionExclusionProof({ + return new GeoPointInOutPolygonCommitment({ insidePolygonCommitment: newInsideCommitment, outsidePolygonCommitment: newOutsideCommitment, coordinatesCommitment: proof1PublicOutput.coordinatesCommitment, @@ -419,7 +421,7 @@ export function OR( } export function fromCoordinatesInPolygonProof( proof: SelfProof -): GeoPointPolygonInclusionExclusionProof { +): GeoPointInOutPolygonCommitment { proof.verify(); const coodinatesInPolygonProof: GeoPointInPolygonCommitment = proof.publicOutput; @@ -434,7 +436,7 @@ export function fromCoordinatesInPolygonProof( coodinatesInPolygonProof.polygonCommitment ); - return new GeoPointPolygonInclusionExclusionProof({ + return new GeoPointInOutPolygonCommitment({ insidePolygonCommitment: insideCommitment, outsidePolygonCommitment: outsideCommitment, coordinatesCommitment: coodinatesInPolygonProof.geoPointCommitment, diff --git a/contracts/src/logic/private/GeoPointInOrOutOfPolygon.ts b/contracts/src/logic/private/GeoPointInOrOutOfPolygon.ts new file mode 100644 index 0000000..c04b1d9 --- /dev/null +++ b/contracts/src/logic/private/GeoPointInOrOutOfPolygon.ts @@ -0,0 +1,84 @@ +import { Empty, Field, Poseidon, Provable, SelfProof } from "o1js"; +import { GeoPointInOutPolygonCommitment, GeoPointInPolygonCommitment } from "../../model/private/Commitment"; +import { GeoPointInPolygonCircuitProof } from "../../zkprogram/private/Geography"; + + +/** + * Creates a GeoPointInOutPolygonCommitment object based on the provided inside and outside proofs. + * + * @param insideProof - The proof of the GeoPoint being inside a polygon. + * @param outsideProof - The proof of the GeoPoint being outside a polygon. + * @returns A GeoPointInOutPolygonCommitment object. + */ +export function fromPointInPolygonProofs( + insideProof: GeoPointInPolygonCircuitProof, + outsideProof: GeoPointInPolygonCircuitProof, +): GeoPointInOutPolygonCommitment { + insideProof.verify(); + const insideProofCommitment: GeoPointInPolygonCommitment = insideProof.publicOutput; + insideProofCommitment.isInPolygon.assertTrue("`insideProof` is not a proof of a GeoPoint being inside a polygon, but rather outside."); + + outsideProof.verify(); + const outsideProofCommitment: GeoPointInPolygonCommitment = outsideProof.publicOutput; + outsideProofCommitment.isInPolygon.assertFalse("`outsideProof` is not a proof of a GeoPoint being outside a polygon, but rather inside."); + + const insideGeoPointCommitment: Field = insideProofCommitment.geoPointCommitment; + const outsideGeoPointCommitment: Field = outsideProofCommitment.geoPointCommitment; + insideGeoPointCommitment.assertEquals(outsideGeoPointCommitment, "`insideProof` and `outsideProof` are not proofs of the same GeoPoint being inside and outside a polygon, respectively.") + + const insidePolygonCommitment: Field = insideProofCommitment.polygonCommitment; + const outsidePolygonCommitment: Field = outsideProofCommitment.polygonCommitment; + + + return new GeoPointInOutPolygonCommitment({ + insidePolygonCommitment: insidePolygonCommitment, + outsidePolygonCommitment: outsidePolygonCommitment, + coordinatesCommitment: insideGeoPointCommitment, + }); +} + + +/** + * Extends a self-proof and a point-in-polygon proof to create a commitment to a GeoPoint inside or outside a polygon. + * If the `pointInPolygonProof` is a proof of the GeoPoint being inside the polygon, then the `selfProof`'s public output + * `insidePolygonCommitment` will be extended with the `pointInPolygonProof`'s public output `polygonCommitment`. + * If the `pointInPolygonProof` is a proof of the GeoPoint being outside the polygon, then the `selfProof`'s public output + * `outsidePolygonCommitment` will be extended with the `pointInPolygonProof`'s public output `polygonCommitment`. + * + * @param selfProof The self-proof of the geo point being inside or outside the polygon. + * @param pointInPolygonProof The point-in-polygon proof of the geo point being inside the polygon. + * @returns The commitment to the geo point inside or outside the polygon. + */ +export function extendWithPointInPolygonProof( + selfProof: SelfProof, + pointInPolygonProof: GeoPointInPolygonCircuitProof, +): GeoPointInOutPolygonCommitment { + selfProof.verify(); + pointInPolygonProof.verify(); + + const selfProofCommitment: GeoPointInOutPolygonCommitment = selfProof.publicOutput; + const pointInPolygonProofCommitment: GeoPointInPolygonCommitment = pointInPolygonProof.publicOutput; + + selfProofCommitment.coordinatesCommitment.assertEquals(pointInPolygonProofCommitment.geoPointCommitment, "`selfProof` and `pointInPolygonProof` are not proofs of the same GeoPoint."); + + const extendedCommitmentInside: GeoPointInOutPolygonCommitment = new GeoPointInOutPolygonCommitment({ + insidePolygonCommitment: Poseidon.hash([pointInPolygonProofCommitment.polygonCommitment, pointInPolygonProofCommitment.polygonCommitment]), + outsidePolygonCommitment: selfProofCommitment.outsidePolygonCommitment, + coordinatesCommitment: pointInPolygonProofCommitment.geoPointCommitment, + }); + + const extendedCommitmentOutside: GeoPointInOutPolygonCommitment = new GeoPointInOutPolygonCommitment({ + insidePolygonCommitment: selfProofCommitment.insidePolygonCommitment, + outsidePolygonCommitment: Poseidon.hash([pointInPolygonProofCommitment.polygonCommitment, pointInPolygonProofCommitment.polygonCommitment]), + coordinatesCommitment: pointInPolygonProofCommitment.geoPointCommitment, + }); + + const extendedCommitment: GeoPointInOutPolygonCommitment = Provable.if( + pointInPolygonProofCommitment.isInPolygon, + GeoPointInOutPolygonCommitment, + extendedCommitmentInside, + extendedCommitmentOutside, + ); + + return extendedCommitment; +} \ No newline at end of file diff --git a/contracts/src/model/private/Commitment.ts b/contracts/src/model/private/Commitment.ts index 96aa1d0..d859a90 100644 --- a/contracts/src/model/private/Commitment.ts +++ b/contracts/src/model/private/Commitment.ts @@ -5,18 +5,21 @@ import { TimeStampInterval } from "../Time.js"; export class GeoPointInPolygonCommitment extends Struct({ polygonCommitment: Field, - // TODO: consider including outSidePolygonCommitment proofs, in order to inlcude the "inner" and "outer" polygon definitions of GeoJSON - //outsidePolygonCommitment: Field, geoPointCommitment: Field, isInPolygon: Bool, }) { toString(): string { return `Polygon Commitment: ${this.polygonCommitment.toString()}\nCoordinates Commitment: ${this.geoPointCommitment.toString()}\nIs In Polygon: ${this.isInPolygon.toString()}`; } -} +}; + -; -export class GeoPointPolygonInclusionExclusionProof extends Struct({ +/** + * Two-dimensional private geolocation commitment. It repreesents a commitment to a GeoPoint being outside a list of polygons and inside a list of polygons. + * + * IMPORTANT: This commitment expression should only be utilized in the case of + */ +export class GeoPointInOutPolygonCommitment extends Struct({ insidePolygonCommitment: Field, outsidePolygonCommitment: Field, coordinatesCommitment: Field, diff --git a/contracts/src/zkprogram/private/GeoPointInOrOutOfPolygonCircuit.ts b/contracts/src/zkprogram/private/GeoPointInOrOutOfPolygonCircuit.ts new file mode 100644 index 0000000..8c4f5ea --- /dev/null +++ b/contracts/src/zkprogram/private/GeoPointInOrOutOfPolygonCircuit.ts @@ -0,0 +1,68 @@ +import { SelfProof, Empty, ZkProgram } from "o1js"; +import { proveProvidedGeoPointIn3PointPolygon } from '../../logic/Methods'; +import { GeoPointInOutPolygonCommitment } from '../../model/private/Commitment'; +import { GeoPointInPolygonCircuitProof, GeoPointInPolygonCircuit } from "./Geography"; +import { extendWithPointInPolygonProof, fromPointInPolygonProofs } from "../../logic/private/GeoPointInOrOutOfPolygon"; + +/* + * This circuit extends the `GeoPointInPolygonCircuit` circuit, by allowing the expression of two-dimensional proofs + * for private geolocation. `GeoPointInPolygonCircuit` allows for the expression of wether a given geogrpahical point (GeoPoint) + * IS IN a polygon. While you can express arbitrary presence assertions thanks to the recursive zkSNARK nature of the .AND and .OR + * methods, in order to express your geolocation as being inside of certain polygons, and outside of certain polygons you would require + * two `GeoPointInPolygonCircuit` proofs. + * + * As such, while `GeoPointInPolygonCircuit` allows for a very powerful and flexible expression of private geolocation proofs, expressing + * and iterperting multidimensional proofs introduces semanthic complexity. + * + * In order to ensure a more secure, intuitve and easy to use system, `GeoPointInOrOutOfPolygonCircuit` allows for the expression of + * wether a given geogrpahical point (GeoPoint) IS IN a list of polygons, and IS OUT OF a list of polygons. + * + * This circuit requires for both, the inside and outside polygon commitments to be present. It is not a possible to create a + * `GeoPointInOrOutOfPolygonCircuitProof` by with only an inside polygon commitment, or only an outside polygon commitment. For this, you + * should use `GeoPointInPolygonCircuitProof`. Such a requirement is a feature by design. In a Zero-Knowledge authenticated and private geolocation proof, + * security is paramount (WOW, security is important in a security-oriented product. Mind blown! 😂). + * + * As such, a careful design for the Zero-Knowledge circuits is necessary. If `GeoPointInOrOutOfPolygonCircuit` allowed for the creation of a proof + * with only an inside polygon commitment, or only an outside polygon commitment, then it would require us to introduce "placeholder" values. + * For example, we could use the placeholder of value 0 for the commitment that is not present. However, this opens up this proof to a subtle + * collision attack, albeit extremely an extremely unlikely one. It would allow for creation of private geolocation proofs which can be interperted + * as either abscence, or a presence for a sequence of polygons whose joint hash is 0. Although this is extremely, extremely, extremely unlikely and + * difficult to achieve, such a design decision maintains the security of zkLocus at the maximum level. We considered a few alternatives as well: + * + * 1. Add two new booleans, e.g. `isInsidePolygonPresent` and `isOutsidePolygonPresent`. This would increase the public output of the proof by almost twice! The complexity and the time to verify the proof + * is directly affected by the size of the public output. While we can optimize this by fitting both values into a single field, this would add computational complexity + * to the cirucit, resulting in a performance reduction, albeit possibly to a smaller extent. + * + * 2. Add nonces. If everything is nonced, the probabily of collision is reduced, but it would add unecessary complexity. Applying nonces + * would be more efficient to do after performing all of the necessary ZK computations, and before sharing the proof. + * +*/ + +export const GeoPointInOrOutOfPolygonCircuit = ZkProgram({ + name: "Geo Point In Or Out Of Polygon Circuit", + + publicOutput: GeoPointInOutPolygonCommitment, + + methods: { + fromPointInPolygonProofs: { + privateInputs: [ + GeoPointInPolygonCircuitProof, // inside of polygon(s) + GeoPointInPolygonCircuitProof, // outside of polgyon(s) + ], + method: fromPointInPolygonProofs, + }, + + /** + * Extension is only possible for an existing proof. This is by design, for both, security, and opitmization reasons. + */ + extendWithPointInPolygonProof: { + privateInputs: [ + (SelfProof), + GeoPointInPolygonCircuitProof, + ], + method: extendWithPointInPolygonProof, + }, + }, +}); + +export const GeoPointInOrOutOfPolygonCircuitProof = ZkProgram.Proof(GeoPointInOrOutOfPolygonCircuit); diff --git a/contracts/src/zkprogram/private/Geography.ts b/contracts/src/zkprogram/private/Geography.ts index 04510a6..8a57d2e 100644 --- a/contracts/src/zkprogram/private/Geography.ts +++ b/contracts/src/zkprogram/private/Geography.ts @@ -1,10 +1,8 @@ import { Experimental, SelfProof, Empty, ZkProgram} from "o1js"; import { AND, OR, proofGeoPointInPolygonCommitmentFromOutput, expandTimeStampInterval, expandTimeStampIntervalRecursive, geoPointFromLiteral, timeStampIntervalFromLiteral, proveProvidedGeoPointIn3PointPolygon, exactGeoPointFromOracle} from '../../logic/Methods'; -import { GeoPointPolygonInclusionExclusionProof, GeoPointCommitment, GeoPointInPolygonCommitment, GeoPointWithTimeStampIntervalInPolygonCommitment } from '../../model/private/Commitment'; +import { GeoPointCommitment, GeoPointInPolygonCommitment, GeoPointWithTimeStampIntervalInPolygonCommitment } from '../../model/private/Commitment'; import { GeoPoint, ThreePointPolygon } from '../../model/Geography'; -import { fromCoordinatesInPolygonProof } from '../../logic/Methods'; -import { combine } from '../../logic/Methods'; import { TimeStampInterval } from "../../model/Time"; import { geoPointWithTimeStampInPolygonAND, geoPointWithTimeStampInPolygonOR, proofAttachSourcedTimestampinterval } from "../../logic/Methods"; import { OracleGeoPointProviderCircuitProof } from "./Oracle"; @@ -82,15 +80,10 @@ export const GeoPointInPolygonCircuit = ZkProgram({ publicOutput: GeoPointInPolygonCommitment, methods: { - proveProvidedGeoPointIn3PointPolygon: { + proveGeoPointIn3PointPolygon: { privateInputs: [GeoPointProviderCircuitProof, ThreePointPolygon], method: proveProvidedGeoPointIn3PointPolygon, }, - - proofFromPublicOutput: { - privateInputs: [GeoPointInPolygonCommitment], - method: proofGeoPointInPolygonCommitmentFromOutput, - }, AND: { privateInputs: [ @@ -110,6 +103,7 @@ export const GeoPointInPolygonCircuit = ZkProgram({ }, }); + export class GeoPointInPolygonCircuitProof extends ZkProgram.Proof(GeoPointInPolygonCircuit) {} @@ -179,21 +173,4 @@ export const GeoPointWithTimestampInPolygonCircuit = Experimental.ZkProgram({ }, }); -// TODO: review if below is needed, and delete if not -export const GeoPointInOrOutOfPolygonCircuit = Experimental.ZkProgram({ - publicOutput: GeoPointPolygonInclusionExclusionProof, - methods: { - fromCoordinatesInPolygonProof: { - privateInputs: [(SelfProof)], - method: fromCoordinatesInPolygonProof, - }, - combine: { - privateInputs: [ - (SelfProof), - (SelfProof), - ], - method: combine, - }, - }, -});