From fbf86e5592636880cb1cff1c786e36fa8a194d1f Mon Sep 17 00:00:00 2001 From: gabrielbosio Date: Wed, 1 Nov 2023 22:54:21 +0100 Subject: [PATCH 01/14] Change o1js branch to wasm_kzg_prover --- .gitmodules | 4 ++-- verifier_circuit/o1js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index d7733a57..6a7fd23a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,7 @@ [submodule "verifier_circuit/o1js"] path = verifier_circuit/o1js - url = https://github.com/lambdaclass/o1js.git - branch = kzg_prover + url = https://github.com/lambdaclass/o1js.git + branch = wasm_kzg_prover [submodule "demo/eth_verifier/lib/forge-std"] path = demo/eth_verifier/lib/forge-std url = https://github.com/foundry-rs/forge-std diff --git a/verifier_circuit/o1js b/verifier_circuit/o1js index 9e968760..8ee03d4c 160000 --- a/verifier_circuit/o1js +++ b/verifier_circuit/o1js @@ -1 +1 @@ -Subproject commit 9e968760b768bd7b9fa203d8134c68b21a777a28 +Subproject commit 8ee03d4c96141a878bd2037740bfe42849e1a1ff From be646cdd5c49d00a1f17a076e547318bafb55e32 Mon Sep 17 00:00:00 2001 From: gabrielbosio Date: Wed, 1 Nov 2023 23:36:39 +0100 Subject: [PATCH 02/14] [WIP] Add foreign field, scalar and group --- verifier_circuit/package-lock.json | 2 +- verifier_circuit/src/SRS.ts | 22 +++++++++-------- .../src/foreign_fields/foreign_field.ts | 3 +++ .../src/foreign_fields/foreign_group.ts | 24 +++++++++++++++++++ .../src/foreign_fields/foreign_scalar.ts | 3 +++ verifier_circuit/src/main.ts | 4 ++-- verifier_circuit/src/verifier/verifier.ts | 12 ++++++---- 7 files changed, 52 insertions(+), 18 deletions(-) create mode 100644 verifier_circuit/src/foreign_fields/foreign_field.ts create mode 100644 verifier_circuit/src/foreign_fields/foreign_group.ts create mode 100644 verifier_circuit/src/foreign_fields/foreign_scalar.ts diff --git a/verifier_circuit/package-lock.json b/verifier_circuit/package-lock.json index 2444461a..0fe7ff07 100644 --- a/verifier_circuit/package-lock.json +++ b/verifier_circuit/package-lock.json @@ -11071,7 +11071,7 @@ } }, "o1js": { - "version": "0.13.1", + "version": "0.13.0", "dev": true, "license": "Apache-2.0", "dependencies": { diff --git a/verifier_circuit/src/SRS.ts b/verifier_circuit/src/SRS.ts index 208fb127..7a702e37 100644 --- a/verifier_circuit/src/SRS.ts +++ b/verifier_circuit/src/SRS.ts @@ -2,6 +2,8 @@ import lagrange_bases_json from "../test/lagrange_bases.json" assert { type: "js import { Field, Group, Scalar } from "o1js"; import { BlindedCommitment, PolyComm } from "./poly_commitment/commitment.js"; import { readFileSync } from "fs"; +import { ForeignGroup } from "./foreign_fields/foreign_group"; +import { ForeignField } from "./foreign_fields/foreign_field"; let srs_json; try { @@ -11,7 +13,7 @@ try { srs_json = { g: [ ["24533576165769248459550833334830854594262873459712423377895708212271843679280", - "1491943283321085992458304042389285332496706344738505795532548822057073739620"] + "1491943283321085992458304042389285332496706344738505795532548822057073739620"] ], h: [ "15427374333697483577096356340297985232933727912694971579453397496858943128065", @@ -36,22 +38,22 @@ interface LagrangeBaseJSON { export class SRS { /// The vector of group elements for committing to polynomials in coefficient form - g: Group[]; + g: ForeignGroup[]; /// A group element used for blinding commitments - h: Group; + h: ForeignGroup; /// Commitments to Lagrange bases, per domain size - lagrangeBases: Map[]> + lagrangeBases: Map[]> static createFromJSON() { - let g: Group[] = g_json.map((g_i_json) => this.#createGroupFromJSON(g_i_json)); + let g: ForeignGroup[] = g_json.map((g_i_json) => this.#createGroupFromJSON(g_i_json)); let h = this.#createGroupFromJSON(h_json); return new SRS(g, h); } static #createGroupFromJSON(group_json: string[]) { - return Group({ x: Field.from(group_json[0]), y: Field.from(group_json[1]) }); + return new ForeignGroup(ForeignField.from(group_json[0]), ForeignField.from(group_json[1])); } - static #createLagrangeBasesFromJSON(json: LagrangeBaseJSON): Map[]> { + static #createLagrangeBasesFromJSON(json: LagrangeBaseJSON): Map[]> { let map_unshifted = (unshifted: { x: string, y: string }[]) => unshifted.map(({ x, y }) => this.#createGroupFromJSON([x, y])) //let map_shifted = (shifted: { x: string, y: string } | undefined) => @@ -59,11 +61,11 @@ export class SRS { let map_shifted = (_shifted: null) => undefined; let lagrange_bases = json[32].map(({ unshifted, shifted }) => - new PolyComm(map_unshifted(unshifted), map_shifted(shifted))); - return new Map[]>([[32, lagrange_bases]]); + new PolyComm(map_unshifted(unshifted), map_shifted(shifted))); + return new Map[]>([[32, lagrange_bases]]); } - constructor(g: Group[], h: Group) { + constructor(g: ForeignGroup[], h: ForeignGroup) { this.g = g; this.h = h; this.lagrangeBases = SRS.#createLagrangeBasesFromJSON(lagrange_bases_json); diff --git a/verifier_circuit/src/foreign_fields/foreign_field.ts b/verifier_circuit/src/foreign_fields/foreign_field.ts new file mode 100644 index 00000000..40d00775 --- /dev/null +++ b/verifier_circuit/src/foreign_fields/foreign_field.ts @@ -0,0 +1,3 @@ +import { Field, createForeignField } from "o1js"; + +export class ForeignField extends createForeignField(Field.ORDER) { } diff --git a/verifier_circuit/src/foreign_fields/foreign_group.ts b/verifier_circuit/src/foreign_fields/foreign_group.ts new file mode 100644 index 00000000..047ca58c --- /dev/null +++ b/verifier_circuit/src/foreign_fields/foreign_group.ts @@ -0,0 +1,24 @@ +import { Struct } from "o1js"; +import { ForeignField } from "./foreign_field.js"; + +export class ForeignGroup { + x: ForeignField; + y: ForeignField; + + constructor(x: ForeignField, y: ForeignField) { + this.x = x; + this.y = y; + } + + static zero() { + return new ForeignGroup(ForeignField.from(0), ForeignField.from(0)); + } + + assertEquals(g: ForeignGroup, message?: string) { + let { x: x1, y: y1 } = this; + let { x: x2, y: y2 } = g; + + x1.assertEquals(x2, message); + y1.assertEquals(y2, message); + } +} diff --git a/verifier_circuit/src/foreign_fields/foreign_scalar.ts b/verifier_circuit/src/foreign_fields/foreign_scalar.ts new file mode 100644 index 00000000..f4433deb --- /dev/null +++ b/verifier_circuit/src/foreign_fields/foreign_scalar.ts @@ -0,0 +1,3 @@ +import { Scalar, createForeignField } from "o1js"; + +export class ForeignScalar extends createForeignField(Scalar.ORDER) { } diff --git a/verifier_circuit/src/main.ts b/verifier_circuit/src/main.ts index 3888216c..7effff8b 100644 --- a/verifier_circuit/src/main.ts +++ b/verifier_circuit/src/main.ts @@ -38,7 +38,7 @@ let public_input = [sg, sg_scalar, expected]; let keypair = await Verifier.generateKeypair(); console.log("Proving with Ethereum backend..."); -let proofKZG = await Verifier.proveKZG([], public_input, keypair); +// let proofKZG = await Verifier.proveKZG([], public_input, keypair); console.log("Proving with Mina backend..."); let proof = await Verifier.prove([], public_input, keypair); @@ -51,7 +51,7 @@ if (!isValid) { } console.log("Writing KZG proof into file..."); -writeFileSync("../proof.mpk", proofKZG); +// writeFileSync("../proof.mpk", proofKZG); // ---------------------------------------------------- console.log('Shutting down O1JS...'); diff --git a/verifier_circuit/src/verifier/verifier.ts b/verifier_circuit/src/verifier/verifier.ts index a76e6600..c6f2a0ed 100644 --- a/verifier_circuit/src/verifier/verifier.ts +++ b/verifier_circuit/src/verifier/verifier.ts @@ -7,6 +7,8 @@ import { Sponge } from './sponge.js'; import { Alphas } from '../alphas.js'; import { Polynomial } from '../polynomial.js'; import { Linearization, PolishToken } from '../prover/expr.js'; +import { ForeignScalar } from '../foreign_fields/foreign_scalar.js'; +import { ForeignGroup } from '../foreign_fields/foreign_group.js'; let steps: bigint[][]; try { @@ -131,7 +133,7 @@ export class Verifier extends Circuit { static readonly PERMUTATION_CONSTRAINTS: number = 3; @circuitMain - static main(@public_ sg: Group, @public_ sg_scalar: Scalar, @public_ expected: Group) { + static main(@public_ sg: ForeignGroup, @public_ sg_scalar: ForeignScalar, @public_ expected: ForeignGroup) { let nonzero_length = g.length; let max_rounds = Math.ceil(Math.log2(nonzero_length)); let padded_length = Math.pow(2, max_rounds); @@ -141,9 +143,9 @@ export class Verifier extends Circuit { points = points.concat(g); points = points.concat(Array(padding).fill(Group.zero)); - let scalars = [Scalar.from(0)]; + let scalars = [ForeignScalar.from(0)]; //TODO: Add challenges and s polynomial (in that case, using Scalars we could run out of memory) - scalars = scalars.concat(Array(padded_length).fill(Scalar.from(1))); + scalars = scalars.concat(Array(padded_length).fill(ForeignScalar.from(1))); assert(points.length == scalars.length, "The number of points is not the same as the number of scalars"); points.push(sg); @@ -153,8 +155,8 @@ export class Verifier extends Circuit { } // Naive algorithm - static msm(points: Group[], scalars: Scalar[]) { - let result = Group.zero; + static msm(points: ForeignGroup[], scalars: ForeignScalar[]) { + let result = ForeignGroup.zero(); for (let i = 0; i < points.length; i++) { let point = points[i]; From a3205ce917a9aa332579ba56c3963d83dcd9a3df Mon Sep 17 00:00:00 2001 From: gabrielbosio Date: Thu, 2 Nov 2023 23:07:48 +0100 Subject: [PATCH 03/14] [WIP] Use foreign fields We should remove the SRS usage because it takes too long. Foreign group addition works, but scaling doesn't. See logs before keypair generation to check that. --- verifier_circuit/src/SRS.ts | 50 +++---- .../src/foreign_fields/foreign_group.ts | 127 +++++++++++++++++- verifier_circuit/src/main.ts | 29 +++- verifier_circuit/src/verifier/verifier.ts | 17 ++- verifier_circuit/tsconfig.json | 5 +- 5 files changed, 192 insertions(+), 36 deletions(-) diff --git a/verifier_circuit/src/SRS.ts b/verifier_circuit/src/SRS.ts index 7a702e37..b20ca4fe 100644 --- a/verifier_circuit/src/SRS.ts +++ b/verifier_circuit/src/SRS.ts @@ -2,8 +2,8 @@ import lagrange_bases_json from "../test/lagrange_bases.json" assert { type: "js import { Field, Group, Scalar } from "o1js"; import { BlindedCommitment, PolyComm } from "./poly_commitment/commitment.js"; import { readFileSync } from "fs"; -import { ForeignGroup } from "./foreign_fields/foreign_group"; -import { ForeignField } from "./foreign_fields/foreign_field"; +import { ForeignGroup } from "./foreign_fields/foreign_group.js"; +import { ForeignField } from "./foreign_fields/foreign_field.js"; let srs_json; try { @@ -53,34 +53,34 @@ export class SRS { static #createGroupFromJSON(group_json: string[]) { return new ForeignGroup(ForeignField.from(group_json[0]), ForeignField.from(group_json[1])); } - static #createLagrangeBasesFromJSON(json: LagrangeBaseJSON): Map[]> { - let map_unshifted = (unshifted: { x: string, y: string }[]) => - unshifted.map(({ x, y }) => this.#createGroupFromJSON([x, y])) - //let map_shifted = (shifted: { x: string, y: string } | undefined) => - // shifted ? this.#createGroupFromJSON([shifted.x, shifted.y]) : undefined; - let map_shifted = (_shifted: null) => undefined; + // static #createLagrangeBasesFromJSON(json: LagrangeBaseJSON): Map[]> { + // let map_unshifted = (unshifted: { x: string, y: string }[]) => + // unshifted.map(({ x, y }) => this.#createGroupFromJSON([x, y])) + // //let map_shifted = (shifted: { x: string, y: string } | undefined) => + // // shifted ? this.#createGroupFromJSON([shifted.x, shifted.y]) : undefined; + // let map_shifted = (_shifted: null) => undefined; - let lagrange_bases = json[32].map(({ unshifted, shifted }) => - new PolyComm(map_unshifted(unshifted), map_shifted(shifted))); - return new Map[]>([[32, lagrange_bases]]); - } + // let lagrange_bases = json[32].map(({ unshifted, shifted }) => + // new PolyComm(map_unshifted(unshifted), map_shifted(shifted))); + // return new Map[]>([[32, lagrange_bases]]); + // } constructor(g: ForeignGroup[], h: ForeignGroup) { this.g = g; this.h = h; - this.lagrangeBases = SRS.#createLagrangeBasesFromJSON(lagrange_bases_json); + // this.lagrangeBases = SRS.#createLagrangeBasesFromJSON(lagrange_bases_json); } - /* - * Turns a non-hiding polynomial commitment into a hidding polynomial commitment. Transforms each given `` into `( + wH, w)`. - */ - maskCustom(com: PolyComm, blinders: PolyComm): BlindedCommitment | undefined { - let commitment = com - .zip(blinders) - .map(([g, b]) => { - let g_masked = this.h.scale(b); - return g_masked.add(g); - }); - return { commitment: commitment, blinders: blinders } - } + // /* + // * Turns a non-hiding polynomial commitment into a hidding polynomial commitment. Transforms each given `` into `( + wH, w)`. + // */ + // maskCustom(com: PolyComm, blinders: PolyComm): BlindedCommitment | undefined { + // let commitment = com + // .zip(blinders) + // .map(([g, b]) => { + // let g_masked = this.h.scale(b); + // return g_masked.add(g); + // }); + // return { commitment: commitment, blinders: blinders } + // } } diff --git a/verifier_circuit/src/foreign_fields/foreign_group.ts b/verifier_circuit/src/foreign_fields/foreign_group.ts index 047ca58c..e0425286 100644 --- a/verifier_circuit/src/foreign_fields/foreign_group.ts +++ b/verifier_circuit/src/foreign_fields/foreign_group.ts @@ -1,5 +1,6 @@ -import { Struct } from "o1js"; +import { Bool, Field, Provable } from "o1js"; import { ForeignField } from "./foreign_field.js"; +import { ForeignScalar } from "./foreign_scalar.js"; export class ForeignGroup { x: ForeignField; @@ -14,6 +15,11 @@ export class ForeignGroup { return new ForeignGroup(ForeignField.from(0), ForeignField.from(0)); } + isZero() { + // only the zero element can have x = 0, there are no other (valid) group elements with x = 0 + return this.x.equals(ForeignField.from(0)); + } + assertEquals(g: ForeignGroup, message?: string) { let { x: x1, y: y1 } = this; let { x: x2, y: y2 } = g; @@ -21,4 +27,123 @@ export class ForeignGroup { x1.assertEquals(x2, message); y1.assertEquals(y2, message); } + + equals(g: ForeignGroup) { + let { x: x1, y: y1 } = this; + let { x: x2, y: y2 } = g; + + let x_are_equal = x1.equals(x2); + let y_are_equal = y1.equals(y2); + + return x_are_equal.and(y_are_equal); + } + + add(g: ForeignGroup) { + // TODO: Make provable and use foreign EC constraints + + const { x: x1, y: y1 } = this; + const { x: x2, y: y2 } = g; + + let inf = Provable.witness(Bool, () => + x1.equals(x2).and(y1.equals(y2).not()) + ); + + let s = Provable.witness(ForeignField, () => { + if (x1.equals(x2).toBoolean()) { + let x1_squared = x1.mul(x1); + return x1_squared.add(x1_squared).add(x1_squared).mul(y1.add(y1).inv()); + } else return y2.sub(y1).mul(x2.sub(x1).inv()); + }); + + let x3 = Provable.witness(ForeignField, () => { + return s.mul(s).sub(x1.add(x2)); + }); + + let y3 = Provable.witness(ForeignField, () => { + return s.mul(x1.sub(x3)).sub(y1); + }); + + // similarly to the constant implementation, we check if either operand is zero + // and the implementation above (original OCaml implementation) returns something wild -> g + 0 != g where it should be g + 0 = g + let gIsZero = g.isZero(); + let thisIsZero = this.isZero(); + + let bothZero = gIsZero.and(thisIsZero); + + let onlyGisZero = gIsZero.and(thisIsZero.not()); + let onlyThisIsZero = thisIsZero.and(gIsZero.not()); + + let isNegation = inf; + + let isNewElement = bothZero + .not() + .and(isNegation.not()) + .and(onlyThisIsZero.not()) + .and(onlyGisZero.not()); + + const zero_g = ForeignGroup.zero(); + + return Provable.switch( + [bothZero, onlyGisZero, onlyThisIsZero, isNegation, isNewElement], + ForeignGroup, + [zero_g, this, g, zero_g, new ForeignGroup(x3, y3)] + ); + } + + scale(s: ForeignScalar) { + let coefficient = s.toBits(); + let current = new ForeignGroup(this.x, this.y); + let result = ForeignGroup.zero(); + + while (coefficient.length > 0) { + result = Provable.if(coefficient[coefficient.length - 1], ForeignGroup, result.add(current), result); + current = current.add(current); + coefficient.pop(); + } + + return result; + } + + static sizeInFields() { + return ForeignField.sizeInFields() * 2; + } + + static fromFields(fields: Field[]) { + let x = fields.slice(0, 3); + let y = fields.slice(3); + + return new ForeignGroup(ForeignField.fromFields(x), ForeignField.fromFields(y)); + } + + toFields() { + return [...this.x.toFields(), ...this.y.toFields()]; + } + + static toFields(g: ForeignGroup) { + return g.toFields(); + } + + static toAuxiliary() { + return []; + } + + static check(g: ForeignGroup) { + try { + const a = 0n; + const b = 5n; + const { x, y } = g; + + let x2 = x.mul(x); + let x3 = x2.mul(x); + let ax = x.mul(a); // this will obviously be 0, but just for the sake of correctness + + // we also check the zero element (0, 0) here + let isZero = x.equals(0).and(y.equals(0)); + + isZero.or(x3.add(ax).add(b).equals(y.mul(y))).assertTrue(); + } catch (error) { + if (!(error instanceof Error)) return error; + throw `${`Element (x: ${g.x}, y: ${g.y}) is not an element of the group.`}\n${error.message}`; + } + } } diff --git a/verifier_circuit/src/main.ts b/verifier_circuit/src/main.ts index 7effff8b..28ea27ea 100644 --- a/verifier_circuit/src/main.ts +++ b/verifier_circuit/src/main.ts @@ -1,7 +1,10 @@ import { readFileSync, writeFileSync } from "fs"; -import { Group, Scalar } from "o1js"; +import { Field, Group, Scalar } from "o1js"; import { Verifier } from "./verifier/verifier.js"; import { exit } from "process"; +import { ForeignGroup } from "./foreign_fields/foreign_group.js"; +import { ForeignField } from "./foreign_fields/foreign_field.js"; +import { ForeignScalar } from "./foreign_fields/foreign_scalar.js"; let inputs: { sg: bigint[], z1: bigint, expected: bigint[] }; try { @@ -29,11 +32,25 @@ console.log('O1JS loaded'); console.log("Generating keypair..."); // Convert JSON inputs to O1JS inputs so that we can pass them to the circuit -let sg = new Group({ x: inputs.sg[0], y: inputs.sg[1] }); -let expected = new Group({ x: inputs.expected[0], y: inputs.expected[1] }); -let z1 = Scalar.from(inputs.z1); -let sg_scalar = z1.neg().sub(Scalar.from(1)); -let public_input = [sg, sg_scalar, expected]; +let sg_x = ForeignField.from(inputs.sg[0]); +let sg_y = ForeignField.from(inputs.sg[1]); +let expected_x = ForeignField.from(inputs.expected[0]) +let expected_y = ForeignField.from(inputs.expected[1]); +let z1 = ForeignScalar.from(inputs.z1); +let sg_scalar = z1.neg().sub(ForeignScalar.from(1)); +let public_input = [sg_x, sg_y, sg_scalar, expected_x, expected_y]; + +let generator = new ForeignGroup(new ForeignField(Group.generator.x.toBigInt()), new ForeignField(Group.generator.y.toBigInt())); +console.log("ADD"); +let native_add = Group({ x: inputs.sg[0], y: inputs.sg[1] }).add(Group.generator); +let foreign_add = new ForeignGroup(sg_x, sg_y).add(new ForeignGroup(generator.x, generator.y)); +console.log("native", native_add.x.toBigInt(), native_add.y.toBigInt()); +console.log("foreign", foreign_add.x.toBigInt(), foreign_add.y.toBigInt()); +console.log("SCALE"); +let native_scale = Group({ x: inputs.sg[0], y: inputs.sg[1] }).scale(inputs.z1); +let foreign_scale = new ForeignGroup(sg_x, sg_y).scale(z1); +console.log("native", native_scale.x.toBigInt(), native_scale.y.toBigInt()); +console.log("foreign", foreign_scale.x.toBigInt(), foreign_scale.y.toBigInt()); let keypair = await Verifier.generateKeypair(); diff --git a/verifier_circuit/src/verifier/verifier.ts b/verifier_circuit/src/verifier/verifier.ts index c6f2a0ed..6df3cfc9 100644 --- a/verifier_circuit/src/verifier/verifier.ts +++ b/verifier_circuit/src/verifier/verifier.ts @@ -9,6 +9,7 @@ import { Polynomial } from '../polynomial.js'; import { Linearization, PolishToken } from '../prover/expr.js'; import { ForeignScalar } from '../foreign_fields/foreign_scalar.js'; import { ForeignGroup } from '../foreign_fields/foreign_group.js'; +import { ForeignField } from '../foreign_fields/foreign_field.js'; let steps: bigint[][]; try { @@ -19,6 +20,10 @@ try { let { g, h } = SRS.createFromJSON(); +// TODO: we are slicing G because we are implementing the foreign EC operations in o1js +// This is too slow, so we are using less elements. +g = g.slice(0, 4); + /** * Will contain information necessary for executing a verification */ @@ -133,7 +138,8 @@ export class Verifier extends Circuit { static readonly PERMUTATION_CONSTRAINTS: number = 3; @circuitMain - static main(@public_ sg: ForeignGroup, @public_ sg_scalar: ForeignScalar, @public_ expected: ForeignGroup) { + static main(@public_ sg_x: ForeignField, @public_ sg_y: ForeignField, @public_ sg_scalar: ForeignScalar, @public_ expected_x: ForeignField, @public_ expected_y: ForeignField) { + let sg = new ForeignGroup(sg_x, sg_y); let nonzero_length = g.length; let max_rounds = Math.ceil(Math.log2(nonzero_length)); let padded_length = Math.pow(2, max_rounds); @@ -141,7 +147,7 @@ export class Verifier extends Circuit { let points = [h]; points = points.concat(g); - points = points.concat(Array(padding).fill(Group.zero)); + points = points.concat(Array(padding).fill(ForeignGroup.zero())); let scalars = [ForeignScalar.from(0)]; //TODO: Add challenges and s polynomial (in that case, using Scalars we could run out of memory) @@ -151,7 +157,11 @@ export class Verifier extends Circuit { points.push(sg); scalars.push(sg_scalar); - Verifier.msm(points, scalars).assertEquals(expected); + let actual = Verifier.msm(points, scalars); + let expected = new ForeignGroup(expected_x, expected_y); + console.log("actual", actual.x, actual.y); + console.log("expected", expected.x, expected.y); + actual.assertEquals(expected); } // Naive algorithm @@ -159,6 +169,7 @@ export class Verifier extends Circuit { let result = ForeignGroup.zero(); for (let i = 0; i < points.length; i++) { + console.log(i); let point = points[i]; let scalar = scalars[i]; let scaled = point.scale(scalar); diff --git a/verifier_circuit/tsconfig.json b/verifier_circuit/tsconfig.json index 58ae6352..10855617 100644 --- a/verifier_circuit/tsconfig.json +++ b/verifier_circuit/tsconfig.json @@ -24,6 +24,9 @@ "resolveJsonModule": true }, "include": [ - "./src" + "./src/main.ts", + "./src/foreign_fields/", + "./src/SRS.ts", + "./src/verifier/verifier.ts", ] } From af21a87f2e9ab855618d902901f8ba3cca02d363 Mon Sep 17 00:00:00 2001 From: gabrielbosio Date: Fri, 3 Nov 2023 15:38:23 +0100 Subject: [PATCH 04/14] Implement ec ops in o1js and simplify circuit --- public_input_gen/src/main.rs | 96 ++----------------- .../src/foreign_fields/foreign_group.ts | 2 +- verifier_circuit/src/main.ts | 12 --- verifier_circuit/src/verifier/verifier.ts | 64 +------------ 4 files changed, 8 insertions(+), 166 deletions(-) diff --git a/public_input_gen/src/main.rs b/public_input_gen/src/main.rs index 33eaad0f..7f5011ae 100644 --- a/public_input_gen/src/main.rs +++ b/public_input_gen/src/main.rs @@ -2,12 +2,8 @@ use std::fs; use ark_ec::short_weierstrass_jacobian::GroupAffine; use ark_ec::{AffineCurve, ProjectiveCurve}; -use ark_ff::{BigInteger256, PrimeField}; use kimchi::mina_curves::pasta::{Fp, Fq, Pallas, PallasParameters}; -use kimchi::o1_utils::{math, FieldHelpers}; -use kimchi::poly_commitment::srs::SRS; -use kimchi::precomputed_srs; -use num_traits::identities::Zero; +use kimchi::o1_utils::FieldHelpers; use num_traits::One; use serde::Serialize; use state_proof::{OpeningProof, StateProof}; @@ -27,33 +23,11 @@ fn main() { Err(_) => StateProof::default(), }; - let srs: SRS = precomputed_srs::get_srs(); - write_srs_into_file(&srs); - // create and verify proof based on the witness - prove_and_verify(&srs, state_proof.proof.openings.proof); -} - -fn write_srs_into_file(srs: &SRS) { - println!("Writing SRS into file..."); - let mut g = srs - .g - .iter() - .map(|g_i| format!("[\"{}\",\"{}\"],", g_i.x.to_biguint(), g_i.y.to_biguint())) - .collect::>() - .concat(); - // Removes last comma - g.pop(); - let h = format!( - "[\"{}\",\"{}\"]", - srs.h.x.to_biguint(), - srs.h.y.to_biguint() - ); - let srs_json = format!("{{\"g\":[{}],\"h\":{}}}", g, h); - fs::write("../verifier_circuit/test/srs.json", srs_json).unwrap(); + prove_and_verify(state_proof.proof.openings.proof); } -fn prove_and_verify(srs: &SRS, opening: OpeningProof) { +fn prove_and_verify(opening: OpeningProof) { // verify the proof (propagate any errors) println!("Verifying dummy proof..."); @@ -63,7 +37,7 @@ fn prove_and_verify(srs: &SRS, opening: OpeningProof) { false, ); let z1_felt = Fq::from_hex(&opening.z_1[2..]).unwrap(); - let value_to_compare = compute_msm_for_verification(srs, &sg_point, &z1_felt); + let value_to_compare = compute_verification(&sg_point, &z1_felt); fs::write( "../verifier_circuit/src/inputs.json", @@ -83,68 +57,10 @@ fn prove_and_verify(srs: &SRS, opening: OpeningProof) { .unwrap(); } -fn compute_msm_for_verification( - srs: &SRS, - sg: &Pallas, - z1: &Fq, -) -> GroupAffine { +fn compute_verification(sg: &Pallas, z1: &Fq) -> GroupAffine { let rand_base_i = Fq::one(); let sg_rand_base_i = Fq::one(); let neg_rand_base_i = -rand_base_i; - let nonzero_length = srs.g.len(); - let max_rounds = math::ceil_log2(nonzero_length); - let padded_length = 1 << max_rounds; - let padding = padded_length - nonzero_length; - let mut points = vec![srs.h]; - points.extend(srs.g.clone()); - points.extend(vec![Pallas::zero(); padding]); - let mut scalars = vec![Fq::zero(); padded_length + 1]; - - points.push(*sg); - scalars.push(neg_rand_base_i * z1 - sg_rand_base_i); - - let s = vec![Fq::one(); srs.g.len()]; - let terms: Vec<_> = s.iter().map(|s_i| sg_rand_base_i * s_i).collect(); - scalars - .iter_mut() - .skip(1) - .zip(terms) - .for_each(|(scalar, term)| { - *scalar += term; - }); - println!("Number of scalars: {}", scalars.len()); - - // verify the equation - let scalars: Vec<_> = scalars.iter().map(|x| x.into_repr()).collect(); - // VariableBaseMSM::multi_scalar_mul(&points, &scalars) - naive_msm(&points, &scalars) -} - -fn naive_msm(points: &[Pallas], scalars: &[BigInteger256]) -> Pallas { - let mut steps = vec![]; - let mut result = Pallas::zero(); - - for i in 0..points.len() { - result += &points[i].mul(scalars[i]).into_affine(); - steps.push(result); - } - fs::write( - "../verifier_circuit/src/steps.json", - serde_json::to_string( - &steps - .iter() - .map(|step| { - [ - step.x.to_biguint().to_string(), - step.y.to_biguint().to_string(), - ] - }) - .collect::>(), - ) - .unwrap(), - ) - .unwrap(); - - result + sg.mul(neg_rand_base_i * z1 - sg_rand_base_i).into_affine() } diff --git a/verifier_circuit/src/foreign_fields/foreign_group.ts b/verifier_circuit/src/foreign_fields/foreign_group.ts index e0425286..a289c00d 100644 --- a/verifier_circuit/src/foreign_fields/foreign_group.ts +++ b/verifier_circuit/src/foreign_fields/foreign_group.ts @@ -91,7 +91,7 @@ export class ForeignGroup { } scale(s: ForeignScalar) { - let coefficient = s.toBits(); + let coefficient = s.toBits().reverse(); let current = new ForeignGroup(this.x, this.y); let result = ForeignGroup.zero(); diff --git a/verifier_circuit/src/main.ts b/verifier_circuit/src/main.ts index 28ea27ea..53cbd478 100644 --- a/verifier_circuit/src/main.ts +++ b/verifier_circuit/src/main.ts @@ -40,18 +40,6 @@ let z1 = ForeignScalar.from(inputs.z1); let sg_scalar = z1.neg().sub(ForeignScalar.from(1)); let public_input = [sg_x, sg_y, sg_scalar, expected_x, expected_y]; -let generator = new ForeignGroup(new ForeignField(Group.generator.x.toBigInt()), new ForeignField(Group.generator.y.toBigInt())); -console.log("ADD"); -let native_add = Group({ x: inputs.sg[0], y: inputs.sg[1] }).add(Group.generator); -let foreign_add = new ForeignGroup(sg_x, sg_y).add(new ForeignGroup(generator.x, generator.y)); -console.log("native", native_add.x.toBigInt(), native_add.y.toBigInt()); -console.log("foreign", foreign_add.x.toBigInt(), foreign_add.y.toBigInt()); -console.log("SCALE"); -let native_scale = Group({ x: inputs.sg[0], y: inputs.sg[1] }).scale(inputs.z1); -let foreign_scale = new ForeignGroup(sg_x, sg_y).scale(z1); -console.log("native", native_scale.x.toBigInt(), native_scale.y.toBigInt()); -console.log("foreign", foreign_scale.x.toBigInt(), foreign_scale.y.toBigInt()); - let keypair = await Verifier.generateKeypair(); console.log("Proving with Ethereum backend..."); diff --git a/verifier_circuit/src/verifier/verifier.ts b/verifier_circuit/src/verifier/verifier.ts index 6df3cfc9..e33f615a 100644 --- a/verifier_circuit/src/verifier/verifier.ts +++ b/verifier_circuit/src/verifier/verifier.ts @@ -1,4 +1,3 @@ -import assert from 'assert'; import { readFileSync } from 'fs'; import { circuitMain, Circuit, Group, Scalar, public_, Field } from 'o1js'; import { PolyComm } from '../poly_commitment/commitment.js'; @@ -18,12 +17,6 @@ try { steps = []; } -let { g, h } = SRS.createFromJSON(); - -// TODO: we are slicing G because we are implementing the foreign EC operations in o1js -// This is too slow, so we are using less elements. -g = g.slice(0, 4); - /** * Will contain information necessary for executing a verification */ @@ -140,63 +133,8 @@ export class Verifier extends Circuit { @circuitMain static main(@public_ sg_x: ForeignField, @public_ sg_y: ForeignField, @public_ sg_scalar: ForeignScalar, @public_ expected_x: ForeignField, @public_ expected_y: ForeignField) { let sg = new ForeignGroup(sg_x, sg_y); - let nonzero_length = g.length; - let max_rounds = Math.ceil(Math.log2(nonzero_length)); - let padded_length = Math.pow(2, max_rounds); - let padding = padded_length - nonzero_length; - - let points = [h]; - points = points.concat(g); - points = points.concat(Array(padding).fill(ForeignGroup.zero())); - - let scalars = [ForeignScalar.from(0)]; - //TODO: Add challenges and s polynomial (in that case, using Scalars we could run out of memory) - scalars = scalars.concat(Array(padded_length).fill(ForeignScalar.from(1))); - assert(points.length == scalars.length, "The number of points is not the same as the number of scalars"); - - points.push(sg); - scalars.push(sg_scalar); - - let actual = Verifier.msm(points, scalars); + let actual = sg.scale(sg_scalar); let expected = new ForeignGroup(expected_x, expected_y); - console.log("actual", actual.x, actual.y); - console.log("expected", expected.x, expected.y); actual.assertEquals(expected); } - - // Naive algorithm - static msm(points: ForeignGroup[], scalars: ForeignScalar[]) { - let result = ForeignGroup.zero(); - - for (let i = 0; i < points.length; i++) { - console.log(i); - let point = points[i]; - let scalar = scalars[i]; - let scaled = point.scale(scalar); - result = result.add(scaled); - } - - return result; - } - - // Naive algorithm (used for debugging) - static msmDebug(points: Group[], scalars: Scalar[]) { - let result = Group.zero; - - if (steps.length === 0) { - console.log("Steps file not found, skipping MSM check"); - } - - for (let i = 0; i < points.length; i++) { - let point = points[i]; - let scalar = scalars[i]; - result = result.add(point.scale(scalar)); - - if (steps.length > 0 && (result.x.toBigInt() != steps[i][0] || result.y.toBigInt() != steps[i][1])) { - console.log("Result differs at step", i); - } - } - - return result; - } } From 1c7c7c0e87adc1d3e60eec8fd01a1bba9c9719e5 Mon Sep 17 00:00:00 2001 From: gabrielbosio Date: Fri, 3 Nov 2023 15:46:01 +0100 Subject: [PATCH 05/14] Simplify circuit even more --- public_input_gen/src/main.rs | 40 ++++++++++++++----- .../src/foreign_fields/foreign_group.ts | 14 ------- verifier_circuit/src/main.ts | 4 +- verifier_circuit/src/verifier/verifier.ts | 6 ++- 4 files changed, 34 insertions(+), 30 deletions(-) diff --git a/public_input_gen/src/main.rs b/public_input_gen/src/main.rs index 7f5011ae..a286d198 100644 --- a/public_input_gen/src/main.rs +++ b/public_input_gen/src/main.rs @@ -1,10 +1,10 @@ use std::fs; use ark_ec::short_weierstrass_jacobian::GroupAffine; -use ark_ec::{AffineCurve, ProjectiveCurve}; use kimchi::mina_curves::pasta::{Fp, Fq, Pallas, PallasParameters}; use kimchi::o1_utils::FieldHelpers; -use num_traits::One; +use kimchi::poly_commitment::srs::SRS; +use kimchi::precomputed_srs; use serde::Serialize; use state_proof::{OpeningProof, StateProof}; @@ -23,11 +23,33 @@ fn main() { Err(_) => StateProof::default(), }; + let srs: SRS = precomputed_srs::get_srs(); + write_srs_into_file(&srs); + // create and verify proof based on the witness - prove_and_verify(state_proof.proof.openings.proof); + prove_and_verify(&srs, state_proof.proof.openings.proof); } -fn prove_and_verify(opening: OpeningProof) { +fn write_srs_into_file(srs: &SRS) { + println!("Writing SRS into file..."); + let mut g = srs + .g + .iter() + .map(|g_i| format!("[\"{}\",\"{}\"],", g_i.x.to_biguint(), g_i.y.to_biguint())) + .collect::>() + .concat(); + // Removes last comma + g.pop(); + let h = format!( + "[\"{}\",\"{}\"]", + srs.h.x.to_biguint(), + srs.h.y.to_biguint() + ); + let srs_json = format!("{{\"g\":[{}],\"h\":{}}}", g, h); + fs::write("../verifier_circuit/test/srs.json", srs_json).unwrap(); +} + +fn prove_and_verify(srs: &SRS, opening: OpeningProof) { // verify the proof (propagate any errors) println!("Verifying dummy proof..."); @@ -37,7 +59,7 @@ fn prove_and_verify(opening: OpeningProof) { false, ); let z1_felt = Fq::from_hex(&opening.z_1[2..]).unwrap(); - let value_to_compare = compute_verification(&sg_point, &z1_felt); + let value_to_compare = compute_verification(srs, &sg_point); fs::write( "../verifier_circuit/src/inputs.json", @@ -57,10 +79,6 @@ fn prove_and_verify(opening: OpeningProof) { .unwrap(); } -fn compute_verification(sg: &Pallas, z1: &Fq) -> GroupAffine { - let rand_base_i = Fq::one(); - let sg_rand_base_i = Fq::one(); - let neg_rand_base_i = -rand_base_i; - - sg.mul(neg_rand_base_i * z1 - sg_rand_base_i).into_affine() +fn compute_verification(srs: &SRS, sg: &Pallas) -> GroupAffine { + *sg + srs.h } diff --git a/verifier_circuit/src/foreign_fields/foreign_group.ts b/verifier_circuit/src/foreign_fields/foreign_group.ts index a289c00d..5c51c43e 100644 --- a/verifier_circuit/src/foreign_fields/foreign_group.ts +++ b/verifier_circuit/src/foreign_fields/foreign_group.ts @@ -90,20 +90,6 @@ export class ForeignGroup { ); } - scale(s: ForeignScalar) { - let coefficient = s.toBits().reverse(); - let current = new ForeignGroup(this.x, this.y); - let result = ForeignGroup.zero(); - - while (coefficient.length > 0) { - result = Provable.if(coefficient[coefficient.length - 1], ForeignGroup, result.add(current), result); - current = current.add(current); - coefficient.pop(); - } - - return result; - } - static sizeInFields() { return ForeignField.sizeInFields() * 2; } diff --git a/verifier_circuit/src/main.ts b/verifier_circuit/src/main.ts index 53cbd478..b6273d1f 100644 --- a/verifier_circuit/src/main.ts +++ b/verifier_circuit/src/main.ts @@ -36,9 +36,7 @@ let sg_x = ForeignField.from(inputs.sg[0]); let sg_y = ForeignField.from(inputs.sg[1]); let expected_x = ForeignField.from(inputs.expected[0]) let expected_y = ForeignField.from(inputs.expected[1]); -let z1 = ForeignScalar.from(inputs.z1); -let sg_scalar = z1.neg().sub(ForeignScalar.from(1)); -let public_input = [sg_x, sg_y, sg_scalar, expected_x, expected_y]; +let public_input = [sg_x, sg_y, expected_x, expected_y]; let keypair = await Verifier.generateKeypair(); diff --git a/verifier_circuit/src/verifier/verifier.ts b/verifier_circuit/src/verifier/verifier.ts index e33f615a..e394c31d 100644 --- a/verifier_circuit/src/verifier/verifier.ts +++ b/verifier_circuit/src/verifier/verifier.ts @@ -17,6 +17,8 @@ try { steps = []; } +let { h } = SRS.createFromJSON(); + /** * Will contain information necessary for executing a verification */ @@ -131,9 +133,9 @@ export class Verifier extends Circuit { static readonly PERMUTATION_CONSTRAINTS: number = 3; @circuitMain - static main(@public_ sg_x: ForeignField, @public_ sg_y: ForeignField, @public_ sg_scalar: ForeignScalar, @public_ expected_x: ForeignField, @public_ expected_y: ForeignField) { + static main(@public_ sg_x: ForeignField, @public_ sg_y: ForeignField, @public_ expected_x: ForeignField, @public_ expected_y: ForeignField) { let sg = new ForeignGroup(sg_x, sg_y); - let actual = sg.scale(sg_scalar); + let actual = sg.add(h); let expected = new ForeignGroup(expected_x, expected_y); actual.assertEquals(expected); } From 95ca8d91a2ef0a430cb1fdc126e62ad1799f189c Mon Sep 17 00:00:00 2001 From: gabrielbosio Date: Fri, 3 Nov 2023 16:06:39 +0100 Subject: [PATCH 06/14] Disable failing tests These tests will be fixed when they use ForeignGroup instead of Group. For now, we are prioritizing integration. --- verifier_circuit/src/{SRS.test.ts => SRS.test.ts.disabled} | 0 .../src/verifier/{batching.test.ts => batching.test.ts.disabled} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename verifier_circuit/src/{SRS.test.ts => SRS.test.ts.disabled} (100%) rename verifier_circuit/src/verifier/{batching.test.ts => batching.test.ts.disabled} (100%) diff --git a/verifier_circuit/src/SRS.test.ts b/verifier_circuit/src/SRS.test.ts.disabled similarity index 100% rename from verifier_circuit/src/SRS.test.ts rename to verifier_circuit/src/SRS.test.ts.disabled diff --git a/verifier_circuit/src/verifier/batching.test.ts b/verifier_circuit/src/verifier/batching.test.ts.disabled similarity index 100% rename from verifier_circuit/src/verifier/batching.test.ts rename to verifier_circuit/src/verifier/batching.test.ts.disabled From 340e0a61b7ec6a7089c8089bda46a2d8ddeef977 Mon Sep 17 00:00:00 2001 From: gabrielbosio Date: Tue, 7 Nov 2023 22:37:15 +0100 Subject: [PATCH 07/14] Add KZG prover project --- .gitmodules | 4 ++++ kzg_prover/Cargo.toml | 8 ++++++++ kzg_prover/proof-systems | 1 + kzg_prover/src/main.rs | 3 +++ 4 files changed, 16 insertions(+) create mode 100644 kzg_prover/Cargo.toml create mode 160000 kzg_prover/proof-systems create mode 100644 kzg_prover/src/main.rs diff --git a/.gitmodules b/.gitmodules index 6a7fd23a..a6bdff09 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,3 +5,7 @@ [submodule "demo/eth_verifier/lib/forge-std"] path = demo/eth_verifier/lib/forge-std url = https://github.com/foundry-rs/forge-std +[submodule "kzg_prover/proof-systems"] + path = kzg_prover/proof-systems + url = https://github.com/lambdaclass/proof-systems.git + branch = wasm_kzg_prover diff --git a/kzg_prover/Cargo.toml b/kzg_prover/Cargo.toml new file mode 100644 index 00000000..09d2c805 --- /dev/null +++ b/kzg_prover/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "kzg_prover" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/kzg_prover/proof-systems b/kzg_prover/proof-systems new file mode 160000 index 00000000..fcb5f9e0 --- /dev/null +++ b/kzg_prover/proof-systems @@ -0,0 +1 @@ +Subproject commit fcb5f9e02baf5b189199be2c9ace7a5ffa307a26 diff --git a/kzg_prover/src/main.rs b/kzg_prover/src/main.rs new file mode 100644 index 00000000..e7a11a96 --- /dev/null +++ b/kzg_prover/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} From bc388b52c5eb17837b2ee2ef98a285de0a0f25f0 Mon Sep 17 00:00:00 2001 From: gabrielbosio Date: Wed, 8 Nov 2023 22:59:38 +0100 Subject: [PATCH 08/14] Create dummy quotient --- kzg_prover/.gitignore | 1 + kzg_prover/Cargo.lock | 908 +++++++++++++++++++++++++++++++++++++++ kzg_prover/Cargo.toml | 7 + kzg_prover/proof-systems | 2 +- kzg_prover/src/main.rs | 140 +++++- 5 files changed, 1056 insertions(+), 2 deletions(-) create mode 100644 kzg_prover/.gitignore create mode 100644 kzg_prover/Cargo.lock diff --git a/kzg_prover/.gitignore b/kzg_prover/.gitignore new file mode 100644 index 00000000..2f7896d1 --- /dev/null +++ b/kzg_prover/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/kzg_prover/Cargo.lock b/kzg_prover/Cargo.lock new file mode 100644 index 00000000..bae3e899 --- /dev/null +++ b/kzg_prover/Cargo.lock @@ -0,0 +1,908 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "ark-bn254" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea691771ebbb28aea556c044e2e5c5227398d840cee0c34d4d20fa8eb2689e8c" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea978406c4b1ca13c2db2373b05cc55429c3575b8b21f1b9ee859aa5b03dd42" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "num-traits", + "rayon", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rayon", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0f78f47537c2f15706db7e98fe64cc1711dbf9def81218194e17239e53e5aa" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown", + "rayon", +] + +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.9.0", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dd4e5f0bf8285d5ed538d27fab7411f3e297908fd93c62195de8bee3f199e82" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand", + "rayon", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bcs" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b6598a2f5d564fb7855dc6b06fd1c38cff5a72bd8b863a4d021938497b440a" +dependencies = [ + "serde", + "thiserror", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cpufeatures" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "disjoint-set" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d102f1a462fdcdddce88d6d46c06c074a2d2749b262230333726b06c52bb7585" + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "groupmap" +version = "0.1.0" +dependencies = [ + "ark-ec", + "ark-ff", + "rand", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "internal-tracing" +version = "0.1.0" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "kimchi" +version = "0.1.0" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-poly", + "ark-serialize", + "blake2", + "disjoint-set", + "groupmap", + "hex", + "internal-tracing", + "itertools", + "mina-curves", + "mina-poseidon", + "num-bigint", + "num-derive", + "num-integer", + "num-traits", + "o1-utils", + "once_cell", + "poly-commitment", + "rand", + "rand_core", + "rayon", + "rmp-serde", + "serde", + "serde_with", + "strum", + "strum_macros", + "thiserror", + "turshi", +] + +[[package]] +name = "kzg_prover" +version = "0.1.0" +dependencies = [ + "ark-bn254", + "ark-ec", + "ark-poly", + "ark-std", + "kimchi", + "num-traits", + "poly-commitment", +] + +[[package]] +name = "libc" +version = "0.2.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mina-curves" +version = "0.1.0" +dependencies = [ + "ark-ec", + "ark-ff", +] + +[[package]] +name = "mina-poseidon" +version = "0.1.0" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-poly", + "mina-curves", + "o1-utils", + "once_cell", + "rand", + "rayon", + "serde", + "serde_with", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", + "rand", + "serde", +] + +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "o1-utils" +version = "0.1.0" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-poly", + "ark-serialize", + "bcs", + "hex", + "num-bigint", + "num-integer", + "num-traits", + "rand", + "rand_core", + "rayon", + "serde", + "serde_with", + "sha2", + "thiserror", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pest" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "poly-commitment" +version = "0.1.0" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-poly", + "ark-serialize", + "blake2", + "groupmap", + "itertools", + "mina-curves", + "mina-poseidon", + "o1-utils", + "once_cell", + "rand", + "rand_core", + "rayon", + "rmp-serde", + "serde", + "serde_with", + "thiserror", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rmp" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20" +dependencies = [ + "byteorder", + "num-traits", + "paste", +] + +[[package]] +name = "rmp-serde" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bffea85eea980d8a74453e5d02a8d93028f3c34725de143085a844ebe953258a" +dependencies = [ + "byteorder", + "rmp", + "serde", +] + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + +[[package]] +name = "serde" +version = "1.0.192" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.192" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "serde_with" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +dependencies = [ + "serde", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strum" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" + +[[package]] +name = "strum_macros" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 1.0.109", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "turshi" +version = "0.1.0" +dependencies = [ + "ark-ff", + "hex", + "o1-utils", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] diff --git a/kzg_prover/Cargo.toml b/kzg_prover/Cargo.toml index 09d2c805..cdb587e5 100644 --- a/kzg_prover/Cargo.toml +++ b/kzg_prover/Cargo.toml @@ -6,3 +6,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +kimchi = { path = "proof-systems/kimchi", version = "0.1.0" } +poly-commitment = { path = "proof-systems/poly-commitment", version = "0.1.0" } +ark-bn254 = "0.3.0" +ark-ec = "0.3.0" +ark-poly = "0.3.0" +ark-std = "0.3.0" +num-traits = "0.2.17" diff --git a/kzg_prover/proof-systems b/kzg_prover/proof-systems index fcb5f9e0..347f26ba 160000 --- a/kzg_prover/proof-systems +++ b/kzg_prover/proof-systems @@ -1 +1 @@ -Subproject commit fcb5f9e02baf5b189199be2c9ace7a5ffa307a26 +Subproject commit 347f26ba673e0d78fb199e902f7a9cea206468e5 diff --git a/kzg_prover/src/main.rs b/kzg_prover/src/main.rs index e7a11a96..34c20cce 100644 --- a/kzg_prover/src/main.rs +++ b/kzg_prover/src/main.rs @@ -1,3 +1,141 @@ +use ark_ec::short_weierstrass_jacobian::GroupAffine; +use ark_poly::{ + univariate::DenseOrSparsePolynomial, univariate::DensePolynomial, Polynomial, + Radix2EvaluationDomain, UVPolynomial, +}; +use ark_std::{rand, UniformRand}; +use kimchi::circuits::{ + constraints::{selector_polynomial, ConstraintSystem}, + domains::EvaluationDomains, + gate::{CircuitGate, GateType}, polynomials::generic::testing::create_circuit, +}; +use num_traits::{One, Zero}; +use poly_commitment::{ + evaluation_proof::{combine_polys, DensePolynomialOrEvaluations}, + pairing_proof::PairingSRS, + PolyComm, SRS, +}; + +type PolynomialsToCombine<'a> = &'a [( + DensePolynomialOrEvaluations<'a, ark_bn254::Fr, Radix2EvaluationDomain>, + Option, + PolyComm, +)]; + fn main() { - println!("Hello, world!"); + let rng = &mut rand::rngs::OsRng; + + let gates: Vec> = create_circuit(0, 0); + const ZK_ROWS: usize = 3; + let domain_size = gates.len() + ZK_ROWS; + let domain = EvaluationDomains::create(domain_size).unwrap(); + + let disable_gates_checks = false; + + // Foreign field addition constraint selector polynomial + let foreign_field_add_selector8 = selector_polynomial( + GateType::ForeignFieldAdd, + &gates, + &domain, + &domain.d8, + disable_gates_checks, + ); + + let cs = ConstraintSystem::::create(gates) + .build() + .unwrap(); + + let x = ark_bn254::Fr::rand(rng); + let srs = PairingSRS::create(x, cs.domain.d1.size as usize); + + let evaluations_form = |e| DensePolynomialOrEvaluations::Evaluations(e, cs.domain.d1); + + let non_hiding = |d1_size: usize| PolyComm { + unshifted: vec![ark_bn254::Fr::zero(); d1_size], + shifted: None, + }; + + const NUM_CHUNKS: usize = 1; + + let polynomials = vec![( + evaluations_form(&foreign_field_add_selector8), + None, + non_hiding(NUM_CHUNKS), + )]; + + // Dummy values + let zeta = ark_bn254::Fr::rand(rng); + let omega = cs.domain.d1.group_gen; + let zeta_omega = zeta * omega; + let v = ark_bn254::Fr::rand(rng); + + create_proof_quotient(&srs, &polynomials, &[zeta, zeta_omega], v); +} + +fn create_proof_quotient( + srs: &PairingSRS>, + plnms: PolynomialsToCombine, // vector of polynomial with optional degree bound and commitment randomness + elm: &[ark_bn254::Fr], // vector of evaluation points + polyscale: ark_bn254::Fr, // scaling factor for polynoms +) -> Option> { + let (p, _) = combine_polys::< + GroupAffine, + Radix2EvaluationDomain, + >(plnms, polyscale, srs.full_srs.g.len()); + let evals: Vec<_> = elm.iter().map(|pt| p.evaluate(pt)).collect(); + + let quotient_poly = { + let eval_polynomial = eval_polynomial(elm, &evals); + let divisor_polynomial = divisor_polynomial(elm); + let numerator_polynomial = &p - &eval_polynomial; + let (quotient, remainder) = DenseOrSparsePolynomial::divide_with_q_and_r( + &numerator_polynomial.into(), + &divisor_polynomial.into(), + )?; + if !remainder.is_zero() { + return None; + } + quotient + }; + + Some( + srs.full_srs + .commit_non_hiding("ient_poly, 1, None) + .unshifted[0], + ) +} + +/// The polynomial that evaluates to each of `evals` for the respective `elm`s. +fn eval_polynomial( + elm: &[ark_bn254::Fr], + evals: &[ark_bn254::Fr], +) -> DensePolynomial { + let zeta = elm[0]; + let zeta_omega = elm[1]; + let eval_zeta = evals[0]; + let eval_zeta_omega = evals[1]; + + // The polynomial that evaluates to `p(zeta)` at `zeta` and `p(zeta_omega)` at + // `zeta_omega`. + // We write `p(x) = a + bx`, which gives + // ```text + // p(zeta) = a + b * zeta + // p(zeta_omega) = a + b * zeta_omega + // ``` + // and so + // ```text + // b = (p(zeta_omega) - p(zeta)) / (zeta_omega - zeta) + // a = p(zeta) - b * zeta + // ``` + let b = (eval_zeta_omega - eval_zeta) / (zeta_omega - zeta); + let a = eval_zeta - b * zeta; + DensePolynomial::from_coefficients_slice(&[a, b]) +} + +/// The polynomial that evaluates to `0` at the evaluation points. +fn divisor_polynomial(elm: &[ark_bn254::Fr]) -> DensePolynomial { + elm.iter() + .map(|value| DensePolynomial::from_coefficients_slice(&[-(*value), ark_bn254::Fr::one()])) + .reduce(|poly1, poly2| &poly1 * &poly2) + .unwrap() } From 516a7be9f43b2458f50672d132017142f2863108 Mon Sep 17 00:00:00 2001 From: gabrielbosio Date: Wed, 8 Nov 2023 23:21:10 +0100 Subject: [PATCH 09/14] Add generic selector --- kzg_prover/src/main.rs | 49 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/kzg_prover/src/main.rs b/kzg_prover/src/main.rs index 34c20cce..6328a00f 100644 --- a/kzg_prover/src/main.rs +++ b/kzg_prover/src/main.rs @@ -1,13 +1,14 @@ use ark_ec::short_weierstrass_jacobian::GroupAffine; use ark_poly::{ - univariate::DenseOrSparsePolynomial, univariate::DensePolynomial, Polynomial, + univariate::DenseOrSparsePolynomial, univariate::DensePolynomial, Evaluations, Polynomial, Radix2EvaluationDomain, UVPolynomial, }; use ark_std::{rand, UniformRand}; use kimchi::circuits::{ constraints::{selector_polynomial, ConstraintSystem}, domains::EvaluationDomains, - gate::{CircuitGate, GateType}, polynomials::generic::testing::create_circuit, + gate::{CircuitGate, GateType}, + polynomials::generic::testing::create_circuit, }; use num_traits::{One, Zero}; use poly_commitment::{ @@ -32,7 +33,6 @@ fn main() { let disable_gates_checks = false; - // Foreign field addition constraint selector polynomial let foreign_field_add_selector8 = selector_polynomial( GateType::ForeignFieldAdd, &gates, @@ -45,6 +45,24 @@ fn main() { .build() .unwrap(); + let generic_selector = + Evaluations::>::from_vec_and_domain( + cs.gates + .iter() + .map(|gate| { + if matches!(gate.typ, GateType::Generic) { + ark_bn254::Fr::one() + } else { + ark_bn254::Fr::zero() + } + }) + .collect(), + cs.domain.d1, + ) + .interpolate(); + + let generic_selector4 = generic_selector.evaluate_over_domain_by_ref(cs.domain.d4); + let x = ark_bn254::Fr::rand(rng); let srs = PairingSRS::create(x, cs.domain.d1.size as usize); @@ -55,13 +73,25 @@ fn main() { shifted: None, }; + let fixed_hiding = |d1_size: usize| PolyComm { + unshifted: vec![ark_bn254::Fr::one(); d1_size], + shifted: None, + }; + const NUM_CHUNKS: usize = 1; - let polynomials = vec![( - evaluations_form(&foreign_field_add_selector8), - None, - non_hiding(NUM_CHUNKS), - )]; + let polynomials = vec![ + ( + evaluations_form(&foreign_field_add_selector8), + None, + non_hiding(NUM_CHUNKS), + ), + ( + evaluations_form(&generic_selector4), + None, + fixed_hiding(NUM_CHUNKS), + ), + ]; // Dummy values let zeta = ark_bn254::Fr::rand(rng); @@ -69,7 +99,8 @@ fn main() { let zeta_omega = zeta * omega; let v = ark_bn254::Fr::rand(rng); - create_proof_quotient(&srs, &polynomials, &[zeta, zeta_omega], v); + let quotient = create_proof_quotient(&srs, &polynomials, &[zeta, zeta_omega], v).unwrap(); + println!("{:?}", quotient); } fn create_proof_quotient( From 6baf783506e394ada9ef77d90c0474cf66949473 Mon Sep 17 00:00:00 2001 From: gabrielbosio Date: Thu, 9 Nov 2023 16:57:40 +0100 Subject: [PATCH 10/14] Complete min KZG prover with dummy gates --- kzg_prover/Cargo.lock | 1 + kzg_prover/Cargo.toml | 1 + kzg_prover/src/main.rs | 249 +++++++++++++++++++++++++++++++---------- 3 files changed, 189 insertions(+), 62 deletions(-) diff --git a/kzg_prover/Cargo.lock b/kzg_prover/Cargo.lock index bae3e899..ee967b2a 100644 --- a/kzg_prover/Cargo.lock +++ b/kzg_prover/Cargo.lock @@ -423,6 +423,7 @@ version = "0.1.0" dependencies = [ "ark-bn254", "ark-ec", + "ark-ff", "ark-poly", "ark-std", "kimchi", diff --git a/kzg_prover/Cargo.toml b/kzg_prover/Cargo.toml index cdb587e5..a9ba9860 100644 --- a/kzg_prover/Cargo.toml +++ b/kzg_prover/Cargo.toml @@ -10,6 +10,7 @@ kimchi = { path = "proof-systems/kimchi", version = "0.1.0" } poly-commitment = { path = "proof-systems/poly-commitment", version = "0.1.0" } ark-bn254 = "0.3.0" ark-ec = "0.3.0" +ark-ff = "0.3.0" ark-poly = "0.3.0" ark-std = "0.3.0" num-traits = "0.2.17" diff --git a/kzg_prover/src/main.rs b/kzg_prover/src/main.rs index 6328a00f..fe6671d7 100644 --- a/kzg_prover/src/main.rs +++ b/kzg_prover/src/main.rs @@ -1,20 +1,30 @@ -use ark_ec::short_weierstrass_jacobian::GroupAffine; +use std::ops::Neg; + +use ark_ec::{ + msm::VariableBaseMSM, short_weierstrass_jacobian::GroupAffine, AffineCurve, PairingEngine, +}; +use ark_ff::PrimeField; use ark_poly::{ - univariate::DenseOrSparsePolynomial, univariate::DensePolynomial, Evaluations, Polynomial, - Radix2EvaluationDomain, UVPolynomial, + univariate::DenseOrSparsePolynomial, univariate::DensePolynomial, EvaluationDomain, + Evaluations, Polynomial, Radix2EvaluationDomain, UVPolynomial, +}; +use ark_std::{ + rand::{self, rngs::StdRng, SeedableRng}, + UniformRand, }; -use ark_std::{rand, UniformRand}; use kimchi::circuits::{ - constraints::{selector_polynomial, ConstraintSystem}, + constraints::ConstraintSystem, domains::EvaluationDomains, gate::{CircuitGate, GateType}, polynomials::generic::testing::create_circuit, }; use num_traits::{One, Zero}; use poly_commitment::{ + commitment::{combine_commitments, combine_evaluations, Evaluation}, evaluation_proof::{combine_polys, DensePolynomialOrEvaluations}, - pairing_proof::PairingSRS, - PolyComm, SRS, + pairing_proof::{PairingProof, PairingSRS}, + srs::SRS, + PolyComm, SRS as _, }; type PolynomialsToCombine<'a> = &'a [( @@ -24,26 +34,134 @@ type PolynomialsToCombine<'a> = &'a [( )]; fn main() { - let rng = &mut rand::rngs::OsRng; + let rng = &mut StdRng::from_seed([0u8; 32]); let gates: Vec> = create_circuit(0, 0); + + let cs = ConstraintSystem::::create(gates) + .build() + .unwrap(); + const ZK_ROWS: usize = 3; let domain_size = gates.len() + ZK_ROWS; let domain = EvaluationDomains::create(domain_size).unwrap(); - let disable_gates_checks = false; + let n = domain.d1.size as usize; + let x = ark_bn254::Fr::rand(rng); + + let srs = create_srs(x, n, domain); + + let polynomials = create_selector_dense_polynomials(cs, domain); + + let comms: Vec<_> = polynomials + .iter() + .map(|p| srs.full_srs.commit(p, 1, None, rng)) + .collect(); + + let polynomials_and_blinders: Vec<( + DensePolynomialOrEvaluations<_, Radix2EvaluationDomain<_>>, + _, + _, + )> = polynomials + .iter() + .zip(comms.iter()) + .map(|(p, comm)| { + let p = DensePolynomialOrEvaluations::DensePolynomial(p); + (p, None, comm.blinders.clone()) + }) + .collect(); + + let evaluation_points = vec![ark_bn254::Fr::rand(rng), ark_bn254::Fr::rand(rng)]; + + let evaluations: Vec<_> = polynomials + .iter() + .zip(comms) + .map(|(p, commitment)| { + let evaluations = evaluation_points + .iter() + .map(|x| { + // Inputs are chosen to use only 1 chunk + vec![p.evaluate(x)] + }) + .collect(); + Evaluation { + commitment: commitment.commitment, + evaluations, + degree_bound: None, + } + }) + .collect(); + + let polyscale = ark_bn254::Fr::rand(rng); + + let pairing_proof = PairingProof::>::create( + &srs, + polynomials_and_blinders.as_slice(), + &evaluation_points, + polyscale, + ) + .unwrap(); + + let poly_commitment = create_poly_commitment(&evaluations, polyscale); + let evals = combine_evaluations(&evaluations, polyscale); + let blinding_commitment = srs.full_srs.h.mul(pairing_proof.blinding); + let eval_commitment = srs + .full_srs + .commit_non_hiding(&eval_polynomial(&evaluation_points, &evals), 1, None) + .unshifted[0] + .into_projective(); + + let divisor_commitment = srs + .verifier_srs + .commit_non_hiding(&divisor_polynomial(&evaluation_points), 1, None) + .unshifted[0]; + let numerator_commitment = { poly_commitment - eval_commitment - blinding_commitment }; + let generator = ark_bn254::G2Affine::prime_subgroup_generator(); - let foreign_field_add_selector8 = selector_polynomial( - GateType::ForeignFieldAdd, - &gates, - &domain, - &domain.d8, - disable_gates_checks, + println!("numerator:"); + println!("{}", numerator_commitment); + println!("generator:"); + println!("{}", generator); + println!("quotient:"); + println!("{}", pairing_proof.quotient.neg()); + println!("divisor:"); + println!("{}", divisor_commitment); + + println!( + "valid: {:?}", + pairing_proof.verify(&srs, &evaluations, polyscale, &evaluation_points) ); +} - let cs = ConstraintSystem::::create(gates) - .build() - .unwrap(); +fn create_poly_commitment( + evaluations: &Vec>>, + polyscale: ark_ff::Fp256, +) -> ark_ec::short_weierstrass_jacobian::GroupProjective { + let poly_commitment = { + let mut scalars: Vec = Vec::new(); + let mut points = Vec::new(); + combine_commitments( + evaluations, + &mut scalars, + &mut points, + polyscale, + ark_bn254::Fr::from(1), + ); + let scalars: Vec<_> = scalars.iter().map(|x| x.into_repr()).collect(); + + VariableBaseMSM::multi_scalar_mul(&points, &scalars) + }; + poly_commitment +} + +fn create_selector_dense_polynomials( + cs: ConstraintSystem>, + domain: EvaluationDomains>, +) -> Vec>> { + let foreign_field_add_selector = + selector_polynomial(GateType::ForeignFieldAdd, &cs.gates, &domain, &domain.d8); + let foreign_field_add_selector8 = + foreign_field_add_selector.evaluate_over_domain_by_ref(domain.d8); let generic_selector = Evaluations::>::from_vec_and_domain( @@ -63,53 +181,32 @@ fn main() { let generic_selector4 = generic_selector.evaluate_over_domain_by_ref(cs.domain.d4); - let x = ark_bn254::Fr::rand(rng); - let srs = PairingSRS::create(x, cs.domain.d1.size as usize); - - let evaluations_form = |e| DensePolynomialOrEvaluations::Evaluations(e, cs.domain.d1); + let polynomials: Vec<_> = vec![foreign_field_add_selector, generic_selector]; + polynomials +} - let non_hiding = |d1_size: usize| PolyComm { - unshifted: vec![ark_bn254::Fr::zero(); d1_size], - shifted: None, - }; +fn create_srs( + x: ark_ff::Fp256, + n: usize, + domain: EvaluationDomains>, +) -> PairingSRS> { + let mut srs = SRS::::create_trusted_setup(x, n); + let verifier_srs = SRS::::create_trusted_setup(x, 3); + srs.add_lagrange_basis(domain.d1); - let fixed_hiding = |d1_size: usize| PolyComm { - unshifted: vec![ark_bn254::Fr::one(); d1_size], - shifted: None, - }; - - const NUM_CHUNKS: usize = 1; - - let polynomials = vec![ - ( - evaluations_form(&foreign_field_add_selector8), - None, - non_hiding(NUM_CHUNKS), - ), - ( - evaluations_form(&generic_selector4), - None, - fixed_hiding(NUM_CHUNKS), - ), - ]; - - // Dummy values - let zeta = ark_bn254::Fr::rand(rng); - let omega = cs.domain.d1.group_gen; - let zeta_omega = zeta * omega; - let v = ark_bn254::Fr::rand(rng); - - let quotient = create_proof_quotient(&srs, &polynomials, &[zeta, zeta_omega], v).unwrap(); - println!("{:?}", quotient); + PairingSRS { + full_srs: srs, + verifier_srs, + } } -fn create_proof_quotient( +fn create_proof( srs: &PairingSRS>, plnms: PolynomialsToCombine, // vector of polynomial with optional degree bound and commitment randomness elm: &[ark_bn254::Fr], // vector of evaluation points polyscale: ark_bn254::Fr, // scaling factor for polynoms -) -> Option> { - let (p, _) = combine_polys::< +) -> Option>> { + let (p, blinding_factor) = combine_polys::< GroupAffine, Radix2EvaluationDomain, >(plnms, polyscale, srs.full_srs.g.len()); @@ -129,11 +226,15 @@ fn create_proof_quotient( quotient }; - Some( - srs.full_srs - .commit_non_hiding("ient_poly, 1, None) - .unshifted[0], - ) + let quotient = srs + .full_srs + .commit_non_hiding("ient_poly, 1, None) + .unshifted[0]; + + Some(PairingProof { + quotient, + blinding: blinding_factor, + }) } /// The polynomial that evaluates to each of `evals` for the respective `elm`s. @@ -170,3 +271,27 @@ fn divisor_polynomial(elm: &[ark_bn254::Fr]) -> DensePolynomial { .reduce(|poly1, poly2| &poly1 * &poly2) .unwrap() } + +/// Create selector polynomial for a circuit gate +fn selector_polynomial( + gate_type: GateType, + gates: &[CircuitGate], + domain: &EvaluationDomains, + target_domain: &Radix2EvaluationDomain, +) -> DensePolynomial { + // Coefficient form + Evaluations::<_, Radix2EvaluationDomain<_>>::from_vec_and_domain( + gates + .iter() + .map(|gate| { + if gate.typ == gate_type { + ark_bn254::Fr::one() + } else { + ark_bn254::Fr::zero() + } + }) + .collect(), + domain.d1, + ) + .interpolate() +} From 3e76c5255ce4c5133d06db975275b2facef72036 Mon Sep 17 00:00:00 2001 From: gabrielbosio Date: Thu, 9 Nov 2023 20:11:02 +0100 Subject: [PATCH 11/14] Read gates array from file --- kzg_prover/.gitignore | 1 + kzg_prover/Cargo.lock | 73 +++++++++++++++++++++++++++++++++++ kzg_prover/Cargo.toml | 4 ++ kzg_prover/src/main.rs | 38 +++++++++++++----- kzg_prover/src/snarky_gate.rs | 63 ++++++++++++++++++++++++++++++ verifier_circuit/src/main.ts | 39 +++++-------------- 6 files changed, 178 insertions(+), 40 deletions(-) create mode 100644 kzg_prover/src/snarky_gate.rs diff --git a/kzg_prover/.gitignore b/kzg_prover/.gitignore index 2f7896d1..29a783b4 100644 --- a/kzg_prover/.gitignore +++ b/kzg_prover/.gitignore @@ -1 +1,2 @@ target/ +gates.json diff --git a/kzg_prover/Cargo.lock b/kzg_prover/Cargo.lock index ee967b2a..a1ed704f 100644 --- a/kzg_prover/Cargo.lock +++ b/kzg_prover/Cargo.lock @@ -382,6 +382,12 @@ dependencies = [ "either", ] +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + [[package]] name = "kimchi" version = "0.1.0" @@ -427,8 +433,12 @@ dependencies = [ "ark-poly", "ark-std", "kimchi", + "num", "num-traits", "poly-commitment", + "rmp-serde", + "serde", + "serde_json", ] [[package]] @@ -476,6 +486,20 @@ dependencies = [ "serde_with", ] +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + [[package]] name = "num-bigint" version = "0.4.4" @@ -489,6 +513,15 @@ dependencies = [ "serde", ] +[[package]] +name = "num-complex" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +dependencies = [ + "num-traits", +] + [[package]] name = "num-derive" version = "0.3.3" @@ -510,6 +543,29 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.17" @@ -699,6 +755,12 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + [[package]] name = "scopeguard" version = "1.2.0" @@ -743,6 +805,17 @@ dependencies = [ "syn 2.0.39", ] +[[package]] +name = "serde_json" +version = "1.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "serde_with" version = "1.14.0" diff --git a/kzg_prover/Cargo.toml b/kzg_prover/Cargo.toml index a9ba9860..254aba61 100644 --- a/kzg_prover/Cargo.toml +++ b/kzg_prover/Cargo.toml @@ -14,3 +14,7 @@ ark-ff = "0.3.0" ark-poly = "0.3.0" ark-std = "0.3.0" num-traits = "0.2.17" +rmp-serde = "1.1.2" +serde_json = "1.0.108" +serde = "1.0.192" +num = "0.4.1" diff --git a/kzg_prover/src/main.rs b/kzg_prover/src/main.rs index fe6671d7..5907f923 100644 --- a/kzg_prover/src/main.rs +++ b/kzg_prover/src/main.rs @@ -1,7 +1,10 @@ -use std::ops::Neg; +mod snarky_gate; + +use std::{fs, ops::Neg}; use ark_ec::{ msm::VariableBaseMSM, short_weierstrass_jacobian::GroupAffine, AffineCurve, PairingEngine, + ProjectiveCurve, }; use ark_ff::PrimeField; use ark_poly::{ @@ -12,11 +15,14 @@ use ark_std::{ rand::{self, rngs::StdRng, SeedableRng}, UniformRand, }; -use kimchi::circuits::{ - constraints::ConstraintSystem, - domains::EvaluationDomains, - gate::{CircuitGate, GateType}, - polynomials::generic::testing::create_circuit, +use kimchi::{ + circuits::{ + constraints::ConstraintSystem, + domains::EvaluationDomains, + gate::{CircuitGate, GateType}, + polynomials::generic::testing::create_circuit, + }, + o1_utils::FieldHelpers, }; use num_traits::{One, Zero}; use poly_commitment::{ @@ -26,6 +32,7 @@ use poly_commitment::{ srs::SRS, PolyComm, SRS as _, }; +use snarky_gate::SnarkyGate; type PolynomialsToCombine<'a> = &'a [( DensePolynomialOrEvaluations<'a, ark_bn254::Fr, Radix2EvaluationDomain>, @@ -36,14 +43,14 @@ type PolynomialsToCombine<'a> = &'a [( fn main() { let rng = &mut StdRng::from_seed([0u8; 32]); - let gates: Vec> = create_circuit(0, 0); + let gates = read_gates_file(); let cs = ConstraintSystem::::create(gates) .build() .unwrap(); const ZK_ROWS: usize = 3; - let domain_size = gates.len() + ZK_ROWS; + let domain_size = cs.gates.len() + ZK_ROWS; let domain = EvaluationDomains::create(domain_size).unwrap(); let n = domain.d1.size as usize; @@ -115,7 +122,8 @@ fn main() { .verifier_srs .commit_non_hiding(&divisor_polynomial(&evaluation_points), 1, None) .unshifted[0]; - let numerator_commitment = { poly_commitment - eval_commitment - blinding_commitment }; + let numerator_commitment = + (poly_commitment - eval_commitment - blinding_commitment).into_affine(); let generator = ark_bn254::G2Affine::prime_subgroup_generator(); println!("numerator:"); @@ -128,11 +136,21 @@ fn main() { println!("{}", divisor_commitment); println!( - "valid: {:?}", + "Is KZG proof valid?: {:?}", pairing_proof.verify(&srs, &evaluations, polyscale, &evaluation_points) ); } +fn read_gates_file() -> Vec>> { + let gates_json = fs::read_to_string("gates.json").unwrap(); + let snarky_gates: Vec = serde_json::from_str(&gates_json).unwrap(); + + snarky_gates + .iter() + .map(|gate| gate.clone().into()) + .collect() +} + fn create_poly_commitment( evaluations: &Vec>>, polyscale: ark_ff::Fp256, diff --git a/kzg_prover/src/snarky_gate.rs b/kzg_prover/src/snarky_gate.rs new file mode 100644 index 00000000..2bfc84f4 --- /dev/null +++ b/kzg_prover/src/snarky_gate.rs @@ -0,0 +1,63 @@ +use std::array; + +use kimchi::{ + circuits::{ + gate::{CircuitGate, GateType}, + wires::{Wire, PERMUTS}, + }, + o1_utils::FieldHelpers, +}; +use num::BigInt; +use serde::Deserialize; + +#[derive(Debug, Clone, Deserialize)] +pub struct SnarkyGate { + pub r#type: String, + pub wires: Vec, + pub coeffs: Vec, +} + +#[derive(Debug, Clone, Deserialize)] +pub struct SnarkyWire { + pub col: usize, + pub row: usize, +} + +impl Into for SnarkyWire { + fn into(self) -> Wire { + Wire { + row: self.row, + col: self.col, + } + } +} + +impl Into> for SnarkyGate { + fn into(self) -> CircuitGate { + let typ = if self.r#type == "Generic" { + GateType::Generic + } else if self.r#type == "ForeignFieldAdd" { + GateType::ForeignFieldAdd + } else if self.r#type == "Zero" { + GateType::Zero + } else if self.r#type == "RangeCheck0" { + GateType::RangeCheck0 + } else if self.r#type == "RangeCheck1" { + GateType::RangeCheck1 + } else { + panic!("{} is not a valid GateType", self.r#type) + }; + + let wires: [Wire; PERMUTS] = array::from_fn(|i| self.wires[i].clone().into()); + let coeffs: Vec = self + .coeffs + .iter() + .map(|coeff| { + let coeff_bigint = coeff.parse::().unwrap(); + ark_bn254::Fr::from_biguint(&coeff_bigint.to_biguint().unwrap()).unwrap() + }) + .collect(); + + CircuitGate { typ, wires, coeffs } + } +} diff --git a/verifier_circuit/src/main.ts b/verifier_circuit/src/main.ts index b6273d1f..afbaa893 100644 --- a/verifier_circuit/src/main.ts +++ b/verifier_circuit/src/main.ts @@ -1,12 +1,9 @@ import { readFileSync, writeFileSync } from "fs"; -import { Field, Group, Scalar } from "o1js"; +import { Provable } from "o1js"; import { Verifier } from "./verifier/verifier.js"; -import { exit } from "process"; -import { ForeignGroup } from "./foreign_fields/foreign_group.js"; import { ForeignField } from "./foreign_fields/foreign_field.js"; -import { ForeignScalar } from "./foreign_fields/foreign_scalar.js"; -let inputs: { sg: bigint[], z1: bigint, expected: bigint[] }; +let inputs: { sg: bigint[], expected: bigint[] }; try { inputs = JSON.parse(readFileSync("./src/inputs.json", "utf-8")); } catch (e) { @@ -14,13 +11,12 @@ try { inputs = { sg: [ - 974375293919604067421642828992042234838532512369342211368018365361184475186n, - 25355274914870068890116392297762844888825113893841661922182961733548015428069n + 12368675093154914445558499940566677159678085503548847273105352744110357023892n, + 13928325837869340024710380561463559827724328563792462791279614459373822978261n ], - z1: 8370756341770614687265652169950746150853295615521166276710307557441785774650n, expected: [ - 23971162515526044551720809934508194276417125006800220692822425564390575025467n, - 27079223568793814179815985351796131117498018732446481340536149855784701006245n + 26065081609142297706924822385337762030176473849954371733717621265428419437080n, + 25403161885444353082762527911380081866142600044068732571611330580992014688540n ] }; } @@ -29,32 +25,15 @@ console.log('O1JS loaded'); // ---------------------------------------------------- -console.log("Generating keypair..."); - // Convert JSON inputs to O1JS inputs so that we can pass them to the circuit let sg_x = ForeignField.from(inputs.sg[0]); let sg_y = ForeignField.from(inputs.sg[1]); let expected_x = ForeignField.from(inputs.expected[0]) let expected_y = ForeignField.from(inputs.expected[1]); -let public_input = [sg_x, sg_y, expected_x, expected_y]; - -let keypair = await Verifier.generateKeypair(); - -console.log("Proving with Ethereum backend..."); -// let proofKZG = await Verifier.proveKZG([], public_input, keypair); - -console.log("Proving with Mina backend..."); -let proof = await Verifier.prove([], public_input, keypair); -console.log("Verifying..."); -let isValid = await Verifier.verify(public_input, keypair.verificationKey(), proof); -console.log("Is valid proof:", isValid); - -if (!isValid) { - exit(); -} -console.log("Writing KZG proof into file..."); -// writeFileSync("../proof.mpk", proofKZG); +console.log("Writing circuit into file..."); +let { gates } = Provable.constraintSystem(() => Verifier.main(sg_x, sg_y, expected_x, expected_y)); +writeFileSync("../kzg_prover/gates.json", JSON.stringify(gates)); // ---------------------------------------------------- console.log('Shutting down O1JS...'); From 709c726228957e1b036193654fbe66b6f5e3306e Mon Sep 17 00:00:00 2001 From: gabrielbosio Date: Thu, 9 Nov 2023 20:45:22 +0100 Subject: [PATCH 12/14] Integrate verifier circuit with prover --- Makefile | 6 +++++- polling_service/run.sh | 27 ++++++++++++++++++++------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index e30e72a7..a8dbc265 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,10 @@ run: @echo "Generating public input for verifier circuit..." @cd public_input_gen && cargo r --release @echo "Done!" - @echo "Proving verifier circuit..." + @echo "Creating circuit gates..." @cd verifier_circuit && npm i && make @echo "Done!" + @echo "Creating KZG proof..." + @cd kzg_prover && cargo r --release + @echo "Done!" + diff --git a/polling_service/run.sh b/polling_service/run.sh index d740b6eb..ffe40178 100644 --- a/polling_service/run.sh +++ b/polling_service/run.sh @@ -1,11 +1,24 @@ -curl -d '{"query": "{ - bestChain(maxLength: 1) { - protocolStateProof { - base64 +#!/bin/sh + +fetchproof() { + curl -d '{"query": "{ + bestChain(maxLength: 1) { + protocolStateProof { + base64 + } } - } -}"}' -H 'Content-Type: application/json' http://5.9.57.89:3085/graphql | sed -e 's@{\"data\":{\"bestChain":\[{\"protocolStateProof\":{\"base64\":\"@@' \ - | sed -e 's@\(.*\)\"}}]}}@\1====@' | fold -w 4 | sed '$ d' | tr -d '\n' > proof.txt + }"}' -H 'Content-Type: application/json' http://5.9.57.89:3085/graphql +} + +PROOF=$(fetchproof) + +if [ $? -eq 0 ] +then + echo $PROOF | sed -e 's@{\"data\":{\"bestChain":\[{\"protocolStateProof\":{\"base64\":\"@@' \ + | sed -e 's@\(.*\)\"}}]}}@\1====@' | fold -w 4 | sed '$ d' | tr -d '\n' > proof.txt +else + echo "Couldn't connect to Mina node. Using old proof file." +fi git clone https://github.com/lambdaclass/mina.git mina_1_4_0 cd mina_1_4_0 From 3b301999d33e8cb3885cecc1880519b673b3d8a4 Mon Sep 17 00:00:00 2001 From: Gabriel Bosio <38794644+gabrielbosio@users.noreply.github.com> Date: Thu, 9 Nov 2023 17:45:07 -0300 Subject: [PATCH 13/14] Send warning to stderr Co-authored-by: Pablo Deymonnaz --- polling_service/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polling_service/run.sh b/polling_service/run.sh index 89d2fe2f..f8231563 100644 --- a/polling_service/run.sh +++ b/polling_service/run.sh @@ -17,7 +17,7 @@ then echo $PROOF | sed -e 's@{\"data\":{\"bestChain":\[{\"protocolStateProof\":{\"base64\":\"@@' \ | sed -e 's@\(.*\)\"}}]}}@\1====@' | fold -w 4 | sed '$ d' | tr -d '\n' > proof.txt else - echo "Warning: Couldn't connect to Mina node. Using old proof file." + >&2 echo "Warning: Couldn't connect to Mina node. Using old proof file." fi git clone https://github.com/lambdaclass/mina.git mina_1_4_0 From 73a7cee17b896aa826fd62b68ca418bc44954768 Mon Sep 17 00:00:00 2001 From: gabrielbosio Date: Thu, 9 Nov 2023 21:49:09 +0100 Subject: [PATCH 14/14] Normalize bash script indentation --- polling_service/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polling_service/run.sh b/polling_service/run.sh index f8231563..7f4ebfdd 100644 --- a/polling_service/run.sh +++ b/polling_service/run.sh @@ -17,7 +17,7 @@ then echo $PROOF | sed -e 's@{\"data\":{\"bestChain":\[{\"protocolStateProof\":{\"base64\":\"@@' \ | sed -e 's@\(.*\)\"}}]}}@\1====@' | fold -w 4 | sed '$ d' | tr -d '\n' > proof.txt else - >&2 echo "Warning: Couldn't connect to Mina node. Using old proof file." + >&2 echo "Warning: Couldn't connect to Mina node. Using old proof file." fi git clone https://github.com/lambdaclass/mina.git mina_1_4_0