Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

combineCommitments and evalPolynomial for final verification in the smart contract #106

Merged
merged 80 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
0c80f28
Added public input evals
xqft Nov 17, 2023
915c3e2
Fixes
xqft Nov 17, 2023
6ddd98d
Absorb public evals
xqft Nov 17, 2023
ddc0ffc
Added combined_evals and others
xqft Nov 20, 2023
ad0758c
Added get alphas
xqft Nov 20, 2023
36d39b6
Minor
xqft Nov 20, 2023
baf4c3c
Progress on ft eval
xqft Nov 21, 2023
244bf96
Added combined inner prod
xqft Nov 21, 2023
17c56ce
Fixing comb inn prod
xqft Nov 21, 2023
f12cbef
Fixed 3d array prob
xqft Nov 22, 2023
7336424
Merge branch 'main' into eth_verifier_fs2
xqft Nov 22, 2023
25d26ce
Fix compile errors:
xqft Nov 22, 2023
992fe28
Add error
xqft Nov 22, 2023
1dba6ef
README
pablodeymo Nov 23, 2023
bf15151
Deserialize VerifierIndex from KZG prover and fixes (#89)
xqft Nov 30, 2023
4be4433
Merge branch 'main' into eth_verifier_fs2
xqft Nov 30, 2023
85af66c
Remove repeated lines
gabrielbosio Nov 30, 2023
b7182a6
Remove unused import
gabrielbosio Nov 30, 2023
7ba792f
Change o1js submodule commit
xqft Dec 1, 2023
2e8c790
Changed commit again
xqft Dec 1, 2023
bdfb512
Ethereum verifier continued (#92)
xqft Dec 4, 2023
816e3ac
Added perm scalars
xqft Dec 4, 2023
c6daa59
Added PolishToken
xqft Dec 4, 2023
f974e93
Added new test circuit for the KZG prover
xqft Dec 5, 2023
8fdebcb
Added better comment to polishtoken
xqft Dec 5, 2023
e368ffc
RPN progress
xqft Dec 5, 2023
752abb4
Finished preliminary rpn evaluation
xqft Dec 6, 2023
3ecc60d
Fixes
xqft Dec 6, 2023
b96c571
Test verifier index from new circuit
xqft Dec 6, 2023
8220f09
WIP fixes for deserialization
xqft Dec 7, 2023
d6b54eb
Final fixes
xqft Dec 8, 2023
1ed168a
Deserialized part of the prover proof
xqft Dec 8, 2023
2c31f7c
Deserialize public evals
xqft Dec 11, 2023
af96bca
Deserialize rest of evals
xqft Dec 11, 2023
2a1a57b
Finish deserializing index and proof
xqft Dec 11, 2023
9839350
Integrated verifier with deserializer
xqft Dec 11, 2023
e4a7813
Merge branch 'main' into eth_verifier_continued3
xqft Dec 12, 2023
39fc6cc
Inicial code and comments for final_verify function
pablodeymo Dec 12, 2023
a9ddd81
Added lagrange bases deserialization
xqft Dec 13, 2023
30e9f12
Fixes
xqft Dec 13, 2023
77b0412
Added PairingURS and started deser function
xqft Dec 13, 2023
f120707
Finished writing URS deserializer and forge script
xqft Dec 14, 2023
57434c5
Fix EncodedMap non-string keys
xqft Dec 14, 2023
be87534
Merge branch 'main' into eth_verifier_integrate_deser
xqft Dec 14, 2023
571f8d4
Remove duplicated function
xqft Dec 14, 2023
7f17a60
Remove logs
xqft Dec 15, 2023
79943a9
Random URS and lagrange bases
xqft Dec 15, 2023
5f1ad80
Temporarily remove URS serialization
xqft Dec 18, 2023
b706662
Small fixes
xqft Dec 18, 2023
8cc7dd4
minor spaces
pablodeymo Dec 18, 2023
6b32356
Merge branch 'eth_verifier_integrate_deser' into eth_final_verify
pablodeymo Dec 18, 2023
008d880
Cargo lock updated
pablodeymo Dec 18, 2023
1bc0052
eval_polynomial function in solidity
pablodeymo Dec 19, 2023
8b34362
Merge branch 'main' into eth_final_verify
pablodeymo Dec 21, 2023
58046d7
Evaluation struct
pablodeymo Dec 21, 2023
5830542
first attemp of combineCommitments
pablodeymo Dec 22, 2023
7d4f2d0
Evaluation corrected
pablodeymo Dec 22, 2023
7766374
wip
pablodeymo Dec 22, 2023
b529169
Merge branch 'main' into eth_final_verify
pablodeymo Jan 2, 2024
4413c5b
function deserializeScalar removed
pablodeymo Jan 2, 2024
9b748fe
correction in combineCommitments
pablodeymo Jan 2, 2024
4195e4c
changing format
pablodeymo Jan 3, 2024
0afd2bc
format deserialize
pablodeymo Jan 3, 2024
d4bce8c
Merge branch 'main' into eth_final_verify
pablodeymo Jan 3, 2024
99ef9ab
format Commitment.sol
pablodeymo Jan 3, 2024
68ed453
reformat code to avoid merge conflicts
pablodeymo Jan 3, 2024
d173301
Merge branch 'format' into eth_final_verify
pablodeymo Jan 3, 2024
c83f108
changes in Fields reverted
pablodeymo Jan 3, 2024
7597cb7
Fields.sol modified to avoid conflics
pablodeymo Jan 3, 2024
5dd88c7
eval_polynomial changed to view
pablodeymo Jan 3, 2024
8ff7ab1
Merge branch 'main' into eth_final_verify
pablodeymo Jan 3, 2024
f807933
Small fixes in comments
pablodeymo Jan 3, 2024
720075b
Merge branch 'format_small' into eth_final_verify
pablodeymo Jan 3, 2024
2d279ba
shifted attribute added in PolyComm
pablodeymo Jan 3, 2024
1a3d091
Merge branch 'main' into eth_final_verify
pablodeymo Jan 3, 2024
87d5910
combineCommitments
pablodeymo Jan 3, 2024
f99cefe
comment removed
pablodeymo Jan 3, 2024
d0dc4fb
Reordering code in order to merge it
pablodeymo Jan 4, 2024
732eb8e
fn name change
pablodeymo Jan 4, 2024
0afb5e5
Remove unnecessary code comments
pablodeymo Jan 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions eth_verifier/lib/Commitment.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ function random_lagrange_bases(PairingURS storage urs, uint256 domain_size) {

// WARN: The field shifted is optional but in Solidity we can't have that.
// for our test circuit it's not necessary, we can just ignore it, using infinity.
//BN254.G1Point shifted;
struct PolyComm {
BN254.G1Point[] unshifted;
BN254.G1Point shifted;
}

// @notice this structure flattens the fields of `PolyComm`.
Expand All @@ -76,7 +76,9 @@ function poly_comm_unflat(PolyCommFlat memory com) pure returns (PolyComm[] memo
unshifted[j] = com.unshifteds[index];
index++;
}
res[i] = PolyComm(unshifted);
// TODO: shifted is fixed to infinity
BN254.G1Point memory shifted = BN254.point_at_inf();
res[i] = PolyComm(unshifted, shifted);
}
}

Expand Down Expand Up @@ -106,7 +108,9 @@ function polycomm_msm(PolyComm[] memory com, Scalar.FE[] memory elm) view return
if (com.length == 0 || elm.length == 0) {
BN254.G1Point[] memory z = new BN254.G1Point[](1);
z[0] = BN254.point_at_inf();
return PolyComm(z);
// TODO: shifted is fixed to infinity
BN254.G1Point memory shifted = BN254.point_at_inf();
return PolyComm(z, shifted);
}

if (com.length != elm.length) {
Expand Down Expand Up @@ -150,7 +154,9 @@ function polycomm_msm(PolyComm[] memory com, Scalar.FE[] memory elm) view return
BN254.G1Point memory chunk_msm = naive_msm(points, scalars);
unshifted[chunk] = chunk_msm;
}
return PolyComm(unshifted);
// TODO: shifted is fixed to infinity
BN254.G1Point memory shifted = BN254.point_at_inf();
return PolyComm(unshifted, shifted);
}

// @notice Execute a simple multi-scalar multiplication
Expand Down Expand Up @@ -189,7 +195,9 @@ function mask_custom(URS storage urs, PolyComm memory com, Scalar.FE[] memory bl
unshifted[i] = (g_masked.add(com.unshifted[i]));
}

return BlindedCommitment(PolyComm(unshifted), blinders);
// TODO: shifted is fixed to infinity
BN254.G1Point memory shifted = BN254.point_at_inf();
return BlindedCommitment(PolyComm(unshifted, shifted), blinders);
}

// @notice multiplies each commitment chunk of f with powers of zeta^n
Expand All @@ -208,7 +216,9 @@ function chunk_commitment(PolyComm memory self, Scalar.FE zeta_n) view returns (
BN254.G1Point[] memory unshifted = new BN254.G1Point[](1);
unshifted[0] = res;

return PolyComm(unshifted);
// TODO: shifted is fixed to infinity
BN254.G1Point memory shifted = BN254.point_at_inf();
return PolyComm(unshifted, shifted);
}

// @notice substracts two polynomial commitments
Expand Down
12 changes: 12 additions & 0 deletions eth_verifier/lib/Evaluations.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
pragma solidity >=0.4.16 <0.9.0;

import "./bn254/Fields.sol";
import "./Polynomial.sol";
import "./Commitment.sol";

struct PointEvaluations {
/// evaluation at the challenge point zeta
Expand All @@ -16,3 +18,13 @@ struct PointEvaluationsArray {
/// Evaluation at `zeta . omega`, the product of the challenge point and the group generator
Scalar.FE[] zeta_omega;
}

/// Contains the evaluation of a polynomial commitment at a set of points.
struct Evaluation {
/// The commitment of the polynomial being evaluated
PolyComm commitment; // TODO: Dense
/// Contains an evaluation table
Scalar.FE[][] evaluations;
/// optional degree bound
uint128 degree_bound;
}
10 changes: 6 additions & 4 deletions eth_verifier/lib/msgpack/Deserialize.sol
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,9 @@ library MsgPk {
EncodedMap memory buffer = abi.decode(unshifted_arr.values[i], (EncodedMap));
unshifted[i] = BN254.g1Deserialize(bytes32(deser_buffer(buffer)));
}
// TODO: shifted part

return PolyComm(unshifted);
// TODO: shifted is fixed to infinity
BN254.G1Point memory shifted = BN254.point_at_inf();
return PolyComm(unshifted, shifted);
}

function deser_prover_proof(Stream memory self, ProverProof storage prover_proof) external {
Expand Down Expand Up @@ -509,7 +509,9 @@ library MsgPk {
unshifted[k] = BN254.g1Deserialize(bytes32(deser_buffer(unshifted_buffer)));
}

polycomms[j] = PolyComm(unshifted);
// TODO: shifted is fixed to infinity
BN254.G1Point memory shifted = BN254.point_at_inf();
polycomms[j] = PolyComm(unshifted, shifted);
}

lagrange_bases_unshifted[abi.decode(map.keys[i], (uint256))] = poly_comm_flat(polycomms);
Expand Down
152 changes: 150 additions & 2 deletions eth_verifier/src/Verifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import "../lib/expr/PolishToken.sol";
import "../lib/expr/ExprConstants.sol";

using {BN254.neg} for BN254.G1Point;
using {Scalar.neg, Scalar.mul, Scalar.add, Scalar.pow} for Scalar.FE;
using {Scalar.neg, Scalar.mul, Scalar.add, Scalar.inv, Scalar.sub, Scalar.pow} for Scalar.FE;
using {AlphasLib.get_alphas} for Alphas;
using {Polynomial.evaluate} for Polynomial.Dense;

Expand Down Expand Up @@ -152,7 +152,9 @@ contract KimchiVerifier {
for (uint256 i = 0; i < chunk_size; i++) {
blindings[i] = urs.full_urs.h;
}
public_comm = PolyComm(blindings);
// TODO: shifted is fixed to infinity
BN254.G1Point memory shifted = BN254.point_at_inf();
public_comm = PolyComm(blindings, shifted);
} else {
Scalar.FE[] memory elm = new Scalar.FE[](public_inputs.length);
for (uint256 i = 0; i < elm.length; i++) {
Expand Down Expand Up @@ -246,6 +248,104 @@ contract KimchiVerifier {
}
}

/// The polynomial that evaluates to each of `evals` for the respective `elm`s.
function evalPolynomial(Scalar.FE[] memory elm, Scalar.FE[] memory evals)
public
view
returns (Polynomial.Dense memory)
{
require(elm.length == evals.length, "lengths don\'t match");
require(elm.length == 2, "length must be 2");
Scalar.FE zeta = elm[0];
Scalar.FE zeta_omega = elm[1];
Scalar.FE eval_zeta = evals[0];
Scalar.FE 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
// ```

// Compute b
Scalar.FE num_b = eval_zeta_omega.add(eval_zeta.neg());
Scalar.FE den_b_inv = zeta_omega.add(zeta.neg()).inv();
Scalar.FE b = num_b.mul(den_b_inv);

// Compute a
Scalar.FE a = eval_zeta.sub(b.mul(zeta));

Scalar.FE[] memory coeffs = new Scalar.FE[](2);
coeffs[0] = a;
coeffs[1] = b;
return Polynomial.Dense(coeffs);
}

function combineCommitments(Evaluation[] memory evaluations, Scalar.FE polyscale, Scalar.FE rand_base)
internal
returns (Scalar.FE[] memory)
{
uint256 vec_length = 0;
// Calculate the max length of the points and scalars vectors
// Iterate over the evaluations
for (uint256 i = 0; i < evaluations.length; i++) {
// Filter out evaluations with an empty commitment
if (evaluations[i].commitment.unshifted.length == 0) {
continue;
}

vec_length += evaluations[i].commitment.unshifted.length + 1;
}
BN254.G1Point[] memory points = new BN254.G1Point[](vec_length);
Scalar.FE[] memory scalars = new Scalar.FE[](vec_length);
uint256 index = 0; // index of the element to assign in the vectors

// Initialize xi_i to 1
Scalar.FE xi_i = Scalar.FE.wrap(1);

// Iterate over the evaluations
for (uint256 i = 0; i < evaluations.length; i++) {
// Filter out evaluations with an empty commitment
if (evaluations[i].commitment.unshifted.length == 0) {
continue;
}

// iterating over the polynomial segments
for (uint256 j = 0; j < evaluations[i].commitment.unshifted.length; j++) {
// Add the scalar rand_base * xi_i to the scalars vector
scalars[index] = rand_base.mul(xi_i);
// Add the point to the points vector
points[index] = evaluations[i].commitment.unshifted[j];

// Multiply xi_i by polyscale
xi_i = xi_i.mul(polyscale);

// Increment the index
index++;
}

// If the evaluation has a degree bound and a non-zero shifted commitment
if (evaluations[i].degree_bound > 0 && evaluations[i].commitment.shifted.x != 0) {
// Add the scalar rand_base * xi_i to the scalars vector
scalars[index] = rand_base.mul(xi_i);
// Add the point to the points vector
points[index] = evaluations[i].commitment.shifted;

// Multiply xi_i by polyscale
xi_i = xi_i.mul(polyscale);
// Increment the index
index++;
}
}
}

/*
This is a list of steps needed for verification.

Expand All @@ -267,6 +367,54 @@ contract KimchiVerifier {
6. Check numerator == scaled_quotient
*/

function final_verify(Scalar.FE[] memory public_inputs) public {
/*
pub fn verify(
&self,
srs: &PairingSRS<Pair>, // SRS
evaluations: &Vec<Evaluation<G>>, // commitments to the polynomials
polyscale: G::ScalarField, // scaling factor for polynoms
elm: &[G::ScalarField], // vector of evaluation points
) -> bool {
let poly_commitment = {
let mut scalars: Vec<F> = Vec::new();
let mut points = Vec::new();
combine_commitments(
evaluations,
&mut scalars,
&mut points,
polyscale,
F::one(), // TODO: This is inefficient
);
let scalars: Vec<_> = scalars.iter().map(|x| x.into_repr()).collect();

VariableBaseMSM::multi_scalar_mul(&points, &scalars)
};

let evals = combine_evaluations(evaluations, polyscale);
let blinding_commitment = srs.full_srs.h.mul(self.blinding);
let divisor_commitment = srs
.verifier_srs
.commit_non_hiding(&divisor_polynomial(elm), 1, None)
.unshifted[0];

let eval_commitment = srs
.full_srs
.commit_non_hiding(&eval_polynomial(elm, &evals), 1, None)
.unshifted[0]
.into_projective();
let numerator_commitment = { poly_commitment - eval_commitment - blinding_commitment };

let numerator = Pair::pairing(
numerator_commitment,
Pair::G2Affine::prime_subgroup_generator(),
);
let scaled_quotient = Pair::pairing(self.quotient, divisor_commitment);
numerator == scaled_quotient
}
*/
}

/* TODO WIP
function deserialize_proof(
uint256[] calldata public_inputs,
Expand Down