Skip to content

Commit

Permalink
Partial verifier step 7 (#35)
Browse files Browse the repository at this point in the history
* WIP continuing fiat-shamir (step 20)

* Upto step 20 implemented

* Upto step 22

* Upto step 28

* Added tests

* Fix build errors

* Small fix

* Finished fiatshamir, except from some details

* Build fixes

* Fix errors

* Partially implemented PolishToken

* Implemented cell variant in evaluate

* Fix srs

* Format verifier_circuit_tests

* Ignore inv test

* Fixed scalar and polycomm tests

* Added extended euclidean for scalar inverse

* WIP updating VerifierIndex deser

* WIP

* WIP VerifierIndex serde

* Finished VerifierIndex serde

* Added ft_eval1 field to proof serde

* Fix absorbScalars()

* Fixed powers of alpha

* Fix alphas

* Finished fiat-shamir

* Fmt and tidy up rust crate

* Fix clippy

* Added 4th step

* Update kimchi branch

* Fix clippy

* Added step 5

* Added serialization of newly added data

* Added step 6

* Revert "Added step 6"

This reverts commit 98a596d.

* Added step 6

* Fixed step 6

* WIP step 7

* Finished step 7
  • Loading branch information
xqft authored Oct 12, 2023
1 parent f8712b0 commit a9978bb
Show file tree
Hide file tree
Showing 9 changed files with 472 additions and 157 deletions.
51 changes: 51 additions & 0 deletions verifier_circuit/src/poly_commitment/commitment.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Group, Scalar } from "o1js";
import { Sponge } from "../verifier/sponge";

/**
* A polynomial commitment
Expand Down Expand Up @@ -182,3 +183,53 @@ export function bPolyCoefficients(chals: Scalar[]) {

return s;
}

/**
* Contains the evaluation of a polynomial commitment at a set of points.
*/
export class Evaluation
{
/** The commitment of the polynomial being evaluated */
commitment: PolyComm<Group>
/** Contains an evaluation table */
evaluations: Scalar[][]
/** optional degree bound */
degree_bound?: number

constructor(
commitment: PolyComm<Group>,
evaluations: Scalar[][],
degree_bound?: number
) {
this.commitment = commitment;
this.evaluations = evaluations;
this.degree_bound = degree_bound;
}
}

/**
* Contains the batch evaluation
*/
export class AggregatedEvaluationProof
{
sponge: Sponge
evaluations: Evaluation[]
/** vector of evaluation points */
evaluation_points: Scalar[]
/** scaling factor for evaluation point powers */
polyscale: Scalar
/** scaling factor for polynomials */
evalscale: Scalar
/** batched opening proof */
opening: OpeningProof
combined_inner_product: Scalar
}

export class OpeningProof {
/** vector of rounds of L & R commitments */
lr: [Group, Group][]
delta: Group
z1: Scalar
z2: Scalar
sg: Group
}
12 changes: 7 additions & 5 deletions verifier_circuit/src/prover/prover.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Polynomial } from "../polynomial.js"
import { Field, Group, Scalar } from "o1js"
import { PolyComm, bPoly, bPolyCoefficients } from "../poly_commitment/commitment";
import { PolyComm, bPoly, bPolyCoefficients, OpeningProof } from "../poly_commitment/commitment";
import { getLimbs64 } from "../util/bigint";
import { Sponge } from "../verifier/sponge";
import { Verifier, VerifierIndex } from "../verifier/verifier.js";
Expand All @@ -9,26 +9,29 @@ import { GateType } from "../circuits/gate.js";
import { Alphas } from "../alphas.js";
import { Column, PolishToken } from "./expr.js";
import { deserHexScalar } from "../serde/serde_proof.js";
import { range } from "../util/misc.js";

/** The proof that the prover creates from a ProverIndex `witness`. */
export class ProverProof {
evals: ProofEvaluations<PointEvaluations<Scalar[]>>
prev_challenges: RecursionChallenge[]
commitments: ProverCommitments

/** Required evaluation for Maller's optimization */
ft_eval1: Scalar
proof: OpeningProof

constructor(
evals: ProofEvaluations<PointEvaluations<Scalar[]>>,
prev_challenges: RecursionChallenge[],
commitments: ProverCommitments,
ft_eval1: Scalar
ft_eval1: Scalar,
proof: OpeningProof
) {
this.evals = evals;
this.prev_challenges = prev_challenges;
this.commitments = commitments;
this.ft_eval1 = ft_eval1
this.ft_eval1 = ft_eval1;
this.proof = proof;
}

/**
Expand Down Expand Up @@ -329,7 +332,6 @@ export class ProverProof {
.getColumn(col)!;
es.push([[evals.zeta, evals.zetaOmega], undefined]);
};
const range = (n: number) => Array.from({ length: n }, (value, key) => key);

push_column_eval({ kind: "z" })
push_column_eval({ kind: "index", typ: GateType.Generic })
Expand Down
15 changes: 10 additions & 5 deletions verifier_circuit/src/serde/serde_index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Polynomial } from "../polynomial"
import { Alphas } from "../alphas"

export interface PolyCommJSON {
unshifted: { x: string, y: string }[]
unshifted: GroupJSON[]
shifted: null
}

Expand Down Expand Up @@ -103,16 +103,21 @@ interface VerifierIndexJSON {
linearization: LinearizationJSON,
}

export function deserGroup(x: string, y: string): Group {
if (x === "0" && y === "1") {
export interface GroupJSON {
x: string
y: string
}

export function deserGroup(json: GroupJSON): Group {
if (json.x === "0" && json.y === "1") {
return Group.zero
} else {
return Group.from(x, y);
return Group.from(json.x, json.y);
}
}

export function deserPolyComm(json: PolyCommJSON): PolyComm<Group> {
const unshifted = json.unshifted.map(({ x, y }) => deserGroup(x, y));
const unshifted = json.unshifted.map(deserGroup);
let shifted = undefined;
if (json.shifted != null) {
shifted = json.shifted;
Expand Down
32 changes: 27 additions & 5 deletions verifier_circuit/src/serde/serde_proof.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Proof, Scalar } from "o1js"
import { PolyComm } from "../poly_commitment/commitment.js";
import { Group, Proof, Scalar } from "o1js"
import { OpeningProof, PolyComm } from "../poly_commitment/commitment.js";
import { LookupEvaluations, PointEvaluations, ProofEvaluations, ProverCommitments, ProverProof, RecursionChallenge } from "../prover/prover.js"
import { deserPolyComm, PolyCommJSON } from "./serde_index.js";
import { deserPolyComm, PolyCommJSON, deserGroup, GroupJSON } from "./serde_index.js";

type PointEvals = PointEvaluations<Scalar[]>;

Expand Down Expand Up @@ -120,19 +120,41 @@ export function deserProverCommitments(json: ProverCommitmentsJSON): ProverCommi
};
}


interface OpeningProofJSON {
lr: GroupJSON[][] // [GroupJSON, GroupJSON]
delta: GroupJSON
z1: string
z2: string
sg: GroupJSON
}

export function deserOpeningProof(json: OpeningProofJSON): OpeningProof {
return {
lr: json.lr.map((g) => [deserGroup(g[0]), deserGroup(g[1])]),
delta: deserGroup(json.delta),
z1: deserHexScalar(json.z1),
z2: deserHexScalar(json.z2),
sg: deserGroup(json.sg),
}
}

interface ProverProofJSON {
evals: ProofEvalsJSON
prev_challenges: RecursionChallenge[]
commitments: ProverCommitmentsJSON
ft_eval1: string
proof: OpeningProofJSON
}


export function deserProverProof(json: ProverProofJSON): ProverProof {
const { evals, prev_challenges, commitments, ft_eval1 } = json;
const { evals, prev_challenges, commitments, ft_eval1, proof } = json;
return new ProverProof(
deserProofEvals(evals),
prev_challenges,
deserProverCommitments(commitments),
deserHexScalar(ft_eval1)
deserHexScalar(ft_eval1),
deserOpeningProof(proof)
);
}
1 change: 1 addition & 0 deletions verifier_circuit/src/util/misc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const range = (n: number) => Array.from({ length: n }, (value, key) => key);
60 changes: 43 additions & 17 deletions verifier_circuit/src/verifier/batch.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { PolyComm } from "../poly_commitment/commitment.js";
import { AggregatedEvaluationProof, Evaluation, PolyComm } from "../poly_commitment/commitment.js";
import { ProverProof, PointEvaluations, ProofEvaluations, Constants } from "../prover/prover.js";
import { Verifier, VerifierIndex } from "./verifier.js";
import { Group, Scalar } from "o1js";
import { deserHexScalar } from "../serde/serde_proof.js";
import { Column, PolishToken } from "../prover/expr.js";
import { GateType } from "../circuits/gate.js";
import { powScalar } from "../util/scalar.js";
import { range } from "../util/misc.js";

export class Context {
verifier_index: VerifierIndex
Expand All @@ -19,7 +20,7 @@ export class Context {
}

getColumn(col: Column): PolyComm<Group> | undefined {
switch(col.kind) {
switch (col.kind) {
case "witness": return this.proof.commitments.wComm[col.index];
case "coefficient": return this.verifier_index.coefficients_comm[col.index];
case "permutation": return this.verifier_index.sigma_comm[col.index];
Expand Down Expand Up @@ -151,21 +152,46 @@ export class Batch extends Verifier {
chunked_t_comm,
zeta_to_domain_size.sub(Scalar.from(1))));

/*
Compute the commitment to the linearized polynomial $f$. To do this, add the constraints of all of the gates, of the permutation, and optionally of the lookup. (See the separate sections in the constraints section.) Any polynomial should be replaced by its associated commitment, contained in the verifier index or in the proof, unless a polynomial has its evaluation provided by the proof in which case the evaluation should be used in place of the commitment.
Compute the (chuncked) commitment of $ft$ (see Maller’s optimization).
List the polynomial commitments, and their associated evaluations, that are associated to the aggregated evaluation proof in the proof:
recursion
public input commitment
ft commitment (chunks of it)
permutation commitment
index commitments that use the coefficients
witness commitments
coefficient commitments
sigma commitments
lookup commitments
*/
return public_comm;
//~ 7. List the polynomial commitments, and their associated evaluations,
//~ that are associated to the aggregated evaluation proof in the proof:
let evaluations: Evaluation[] = [];

//recursion
evaluations.concat(polys.map(([c, e]) => new Evaluation(c, e)));
// public input
evaluations.push(new Evaluation(public_comm, public_evals));
// ft commitment (chunks)
evaluations.push(new Evaluation(ft_comm, [[ft_eval0], [proof.ft_eval1]]));

for (const col of [
{ kind: "z" },
{ kind: "index", typ: GateType.Generic },
{ kind: "index", typ: GateType.Poseidon },
{ kind: "index", typ: GateType.CompleteAdd },
{ kind: "index", typ: GateType.VarBaseMul },
{ kind: "index", typ: GateType.EndoMul },
{ kind: "index", typ: GateType.EndoMulScalar },
]
.concat(range(Verifier.COLUMNS).map((i) => { return { kind: "witness", index: i } }))
.concat(range(Verifier.COLUMNS).map((i) => { return { kind: "coefficient", index: i } }))
.concat(range(Verifier.PERMUTS - 1).map((i) => { return { kind: "permutation", index: i } })) as Column[]
) {
const eva = proof.evals.getColumn(col)!;
evaluations.push(new Evaluation(context.getColumn(col)!, [eva?.zeta, eva?.zetaOmega]));
}

// prepare for the opening proof verification
let evaluation_points = [oracles.zeta, oracles.zeta.mul(verifier_index.domain_gen)];
const agg_proof: AggregatedEvaluationProof = {
sponge: fq_sponge,
evaluations,
evaluation_points,
polyscale: oracles.v,
evalscale: oracles.u,
opening: proof.proof,
combined_inner_product,
};
return agg_proof;
}

/*
Expand Down
9 changes: 1 addition & 8 deletions verifier_circuit/src/verifier/batching.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,5 @@ test("Partial verification integration test", () => {
const vi = deserVerifierIndex(verifier_index_json);
const proof = deserProverProof(proof_json);

let f_comm = Batch.toBatch(vi, proof, []); // upto step 2 implemented.
let expected_f_comm = new PolyComm<Group>([
Group({
x: Field(0x221b959dacd2052aae26193fca36b53279866a4fbbab0d5a2f828b5fd7778201n),
y: Field(0x058c8f1105cae57f4891eadc9b85c8954e5067190e155e61d66855ace69c16c0n)
})
])
expect(f_comm).toEqual(expected_f_comm)
Batch.toBatch(vi, proof, []); // upto step 2 implemented.
})
Loading

0 comments on commit a9978bb

Please sign in to comment.