Skip to content

Commit

Permalink
Mock data for KZGv2 #111
Browse files Browse the repository at this point in the history
  • Loading branch information
vo-nil committed Mar 19, 2024
1 parent a966939 commit 178d627
Show file tree
Hide file tree
Showing 7 changed files with 309 additions and 25 deletions.
55 changes: 53 additions & 2 deletions contracts/algebra/bn254.sol
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,59 @@ library bn254_crypto {
});
}

// ECADD
function ecadd(types.g1_point memory a, types.g1_point memory b)
internal view returns(types.g1_point memory res)
{
validateG1Point(a);
validateG1Point(b);
bool success;

assembly {
let mPtr := mload(0x40)
mstore(mPtr, mload(a))
mstore(add(mPtr, 0x20), mload(add(a, 0x20)))
mstore(add(mPtr, 0x40), mload(b))
mstore(add(mPtr, 0x60), mload(add(b, 0x20)))
success := staticcall(
gas(),
6,
mPtr,
0x80,
mload(res),
0x40
)
}
require(success, "ECADD check failed!");
}

// ECMUL
function ecmul(types.g1_point memory a, uint256 s)
internal view returns(types.g1_point memory res)
{
validateG1Point(a);
bool success;

assembly {
let mPtr := mload(0x40)
mstore(mPtr, mload(a))
mstore(add(mPtr, 0x20), mload(add(a, 0x20)))
mstore(add(mPtr, 0x40), s)
success := staticcall(
gas(),
6,
mPtr,
0x60,
mload(res),
0x40
)
}
require(success, "ECMUL check failed!");
}


/// Evaluate the following pairing product:
/// e(a1, a2).e(-b1, b2) == 1
/// e(a1, a2).e(b1, b2) == 1
function pairingProd2(
types.g1_point memory a1,
types.g2_point memory a2,
Expand Down Expand Up @@ -159,4 +210,4 @@ library bn254_crypto {
}
require(is_well_formed, "Bn254: G1 point not on curve, or is malformed");
}
}
}
107 changes: 86 additions & 21 deletions contracts/commitments/batched_kzg_verifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,37 +21,102 @@ import "./batched_fri_verifier.sol";
import "../algebra/polynomial.sol";
import "../basic_marshalling.sol";
import "../algebra/bn254.sol";
import "../../contracts/interfaces/modular_verifier.sol";

import "hardhat/console.sol";

library batched_kzg_verifier {

function verify_proof(
/*
uint256[] memory commitments,
types.kzg_proof_type memory kzg_proof,
types.g1_point[] memory commitments,
uint256[] memory Z,
uint256[] memory U,
types.transcript_data memory tr_state,
types.kzg_params_type memory kzg_params*/)
types.kzg_params_type memory kzg_params,
types.kzg_proof_type memory kzg_proof)
internal view returns (bool result) {
unchecked {

uint256 i;

/* 1. send to transcript all commitments */
for (i = 0; i < kzg_params.commitments_num; ++i ) {
transcript.update_transcript_b32(tr_state, bytes32(commitments[i].x));
transcript.update_transcript_b32(tr_state, bytes32(commitments[i].y));
}
for (i = 0; i < kzg_params.points_num; ++i ) {
transcript.update_transcript_b32(tr_state, bytes32(Z[i]));
}
for (i = 0; i < kzg_params.points_num; ++i ) {
transcript.update_transcript_b32(tr_state, bytes32(U[i]));
}
/* TWICE ? */
for (i = 0; i < kzg_params.commitments_num; ++i ) {
transcript.update_transcript_b32(tr_state, bytes32(commitments[i].x));
transcript.update_transcript_b32(tr_state, bytes32(commitments[i].y));
}
for (i = 0; i < kzg_params.points_num; ++i ) {
transcript.update_transcript_b32(tr_state, bytes32(Z[i]));
}
for (i = 0; i < kzg_params.points_num; ++i ) {
transcript.update_transcript_b32(tr_state, bytes32(U[i]));
}

/* 2. challenge theta from transcript */
uint256 theta = transcript.get_field_challenge(tr_state, bn254_crypto.r_mod);

/* 3. send pi_1 to transcript */
transcript.update_transcript_b32(tr_state, bytes32(kzg_proof.pi_1.x));
transcript.update_transcript_b32(tr_state, bytes32(kzg_proof.pi_1.y));

/* 4. challenge theta_2 from transcript */
uint256 theta_2 = transcript.get_field_challenge(tr_state, bn254_crypto.r_mod);

types.g1_point memory a1 = bn254_crypto.new_g1(
13537094572093675138513973797244805699587981214733746302150278342976640424397,
9554926369995100646077410167290930878381045633071770559944038420370185418405);
/* check theta and theta_2 values */
if(theta != kzg_params.theta) {
console.log("wrong theta: ", theta);
console.log("expecting : ", kzg_params.theta);
}

types.g2_point memory a2 = bn254_crypto.new_g2(
10857046999023057135944570762232829481370756359578518086990519993285655852781,
11559732032986387107991004021392285783925812861821192530917403151452391805634,
8495653923123431417604973247489272438418190587263600148770280649306958101930,
4082367875863433681332203403145435568316851327593401208105741076214120093531);
if(theta_2 != kzg_params.theta_2) {
console.log("wrong theta_2 :", theta_2);
console.log("expecting : ", kzg_params.theta_2);
}

/* 5. for a set of commitments construct F */

types.g1_point memory b1 = bn254_crypto.new_g1(
18537193526015835698554895901144353361264554539198746530791998564522770502405,
15073207450244909649956103901894317250233986784535780985960937295179118615068);
uint256 theta_i = 1;
types.g1_point memory F = bn254_crypto.new_g1(0,0);
uint256 rsum = 0;
uint256 tmp;
uint256 r_i;

types.g2_point memory b2 = bn254_crypto.new_g2(
15512671280233143720612069991584289591749188907863576513414377951116606878472,
18551411094430470096460536606940536822990217226529861227533666875800903099477,
13376798835316611669264291046140500151806347092962367781523498857425536295743,
1711576522631428957817575436337311654689480489843856945284031697403898093784);
for (i = 0; i < kzg_params.commitments_num; ++i) {
tmp = 13537094572093675138513973797244805699587981214733746302150278342976640424397;
r_i = mulmod(theta_i, tmp, bn254_crypto.r_mod);
types.g1_point memory f = bn254_crypto.ecmul(commitments[i], r_i);
F = bn254_crypto.ecadd(F, f);
tmp = 9554926369995100646077410167290930878381045633071770559944038420370185418405;
r_i = mulmod(r_i, tmp, bn254_crypto.r_mod);
rsum = addmod(rsum, r_i, bn254_crypto.r_mod);
theta_i = mulmod(theta_i, theta, bn254_crypto.r_mod);
}

return bn254_crypto.pairingProd2(a1,a2, b1,b2);
types.g1_point memory F_last = bn254_crypto.ecmul(bn254_crypto.P1(), rsum);
F_last.x = bn254_crypto.p_mod - F_last.x;
F = bn254_crypto.ecadd(F, F_last);

tmp= 11559732032986387107991004021392285783925812861821192530917403151452391805634;
F_last = bn254_crypto.ecmul(kzg_proof.pi_1, tmp);
F_last.x = bn254_crypto.p_mod - F_last.x;
F = bn254_crypto.ecadd(F, F_last);

F_last = bn254_crypto.ecmul(kzg_proof.pi_1, theta_2);
F = bn254_crypto.ecadd(F, F_last);

types.g2_point memory g2 = bn254_crypto.P2();

return bn254_crypto.pairingProd2(F , g2, kzg_proof.pi_2, kzg_params.verification_key);
}
}
}
123 changes: 123 additions & 0 deletions contracts/test/bn254/bn254_test.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//---------------------------------------------------------------------------//
// Copyright (c) 2024 Vasiliy Olekhov <[email protected]>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//---------------------------------------------------------------------------//
pragma solidity ^0.8.0;

import '../../../contracts/commitments/batched_kzg_verifier.sol';
import "../../../contracts/interfaces/modular_verifier.sol";
import 'hardhat/console.sol';

contract kzg_estimation is IModularVerifier {

/**
* @dev Initializes verifier
*/
function initialize(
address lookup_argument_contract_address,
address gate_argument_contract_address,
address commitment_contract_address) public
{

}

/**
* @dev Verifies proof
*/
function verify(
bytes calldata blob,
uint256[] calldata public_input
) public returns (bool result)
{

types.g1_point[] memory commitments;
commitments = new types.g1_point[](4);

commitments[0].x = 0x0c44878bb8ff269d74d4c82a460b47503e72178c24ea96b071db39f540083856;
commitments[0].y = 0x15e1d289c6429156a6812b89f5f2b9c5adbcae41274c88a317d7b394e15a339;
commitments[1].x = 0x1a61eddcc2d2c249e4fea2895bf5d5c258dccd230ce16b355e22da9ccef3d796;
commitments[1].y = 0x88dfa0426989fe5b61b796b53fb18bd72b74bc513524e62ba8c0651366d1e96;
commitments[2].x = 0x00a81266b641f4305269eaf67036ee6a5d532143cbc706c1e97c7a84ba769d14;
commitments[2].y = 0x347d40c1e4471ca1423f38a73aec0a009819eff6571813db1620156d4719b67;
commitments[3].x = 0x5804dfe02a750643061c878b6d938cb74c621375c63c77cde1eb3804b8206d80;
commitments[3].y = 0x2501fa3f32e1cd9b04d66803dc467373c9f4f8fe285e2d53422fe9e508fe75e3;

uint256[] memory Z;
Z = new uint256[](12);
Z[ 0] = 0x0000000000000000000000000000000000000000000000000000000000000701;
Z[ 1] = 0x000000000000000000000000000000000000000000000000000000000000601c;
Z[ 2] = 0x000000000000000000000000000000000000000000000000000312e5a822d164;
Z[ 3] = 0x00000000000000000000000000000000000000000000000000000000000010f7;
Z[ 4] = 0x000000000000000000000000000000000000000000000000000000000000e03c;
Z[ 5] = 0x00000000000000000000000000000000000000000000000000076a1399d05b27;
Z[ 6] = 0x00000000000000000000000000000000000000000000000000000000000000c4;
Z[ 7] = 0x0000000000000000000000000000000000000000000000000000000000001aed;
Z[ 8] = 0x000000000000000000000000000000000000000000000000000000000001605c;
Z[ 9] = 0x00000000000000000000000000000000000000000000000000000000000024e3;
Z[10] = 0x000000000000000000000000000000000000000000000000000000000001e07c;
Z[11] = 0x0000000000000000000000000000000000000000000000000011eef27398435f;

uint256[] memory U;
U = new uint256[](12);
U[ 0] = 0x0000000000000000000000000000000000000000000000000000007c9471f41d;
U[ 1] = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f52c1ef629ad;
U[ 2] = 0x00000000000000000000000000000000000000000000000000000014c3686fe3;
U[ 3] = 0x000000000000000000000000000000000000000000000000000001267d4b52fb;
U[ 4] = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f49e87961425;
U[ 5] = 0x0000000000000000000000000000000000000000000000000000003114e2256d;
U[ 6] = 0x00000000000000000000000000000000000000000000000000000000000111e1;
U[ 7] = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effe5941;
U[ 8] = 0x00000000000000000000000000000000000000000000000000000000000095a3;
U[ 9] = 0x000000000000000000000000000000000000000000000000000002ac7f620cdf;
U[10] = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f35985d7ec49;
U[11] = 0x00000000000000000000000000000000000000000000000000000072153b8fdd;

types.kzg_params_type memory kzg_params;

kzg_params.commitments_num = 4;
kzg_params.points_num = 12;
kzg_params.theta = 0x146669b8f0f804db1f65879b69ebd1eb5a62d5a304f397fe2214f1a09512289;
kzg_params.theta_2 = 0x60ccd0177322ae60e62f674ae1f0594ef507a2296f0fe7ea45537a2493e5c6a;
kzg_params.verification_key = bn254_crypto.new_g2(
18551411094430470096460536606940536822990217226529861227533666875800903099477,
15512671280233143720612069991584289591749188907863576513414377951116606878472,
1711576522631428957817575436337311654689480489843856945284031697403898093784,
13376798835316611669264291046140500151806347092962367781523498857425536295743);


types.kzg_proof_type memory kzg_proof;
kzg_proof.pi_1 = bn254_crypto.new_g1(
0x2a5962762ebd3540336267427860b210e8cd10ceb111d10c279ca20d3419c36f,
0x79cc53475493803aac3f585ccaf63d893d009dc8c143160098327542c4c6d87);
kzg_proof.pi_2 = bn254_crypto.new_g1(
0x28fbae026e8b174c26e0ab3ad4d3e523fa0ed914cfc4b81d206b985108471305,
0x21532211d9b11dc61e52f52f66f2408d577278b6fc33c6fe83f3a8d089ad1a1c);
/*
kzg_proof.pi_1 = bn254_crypt.new_g1(
0x2a5962762ebd3540336267427860b210e8cd10ceb111d10c279ca20d3419c36f,
0x79cc53475493803aac3f585ccaf63d893d009dc8c143160098327542c4c6d87);
kzg_proof.pi_2 = bn254_crypt.new_g1(
0x28fbae026e8b174c26e0ab3ad4d3e523fa0ed914cfc4b81d206b985108471305,
0x21532211d9b11dc61e52f52f66f2408d577278b6fc33c6fe83f3a8d089ad1a1c);
*/

types.transcript_data memory tr_state;
transcript.init_transcript(tr_state, hex"");

result = batched_kzg_verifier.verify_proof(commitments, Z, U, tr_state, kzg_params, kzg_proof);
emit VerificationResult(result);
}

}
6 changes: 4 additions & 2 deletions contracts/types.sol
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,13 @@ library types {
uint256 commitments_num;
uint256 theta;
uint256 theta_2;
uint256 points_num;
types.g2_point verification_key;
}

struct kzg_proof_type {
g1_point pi_1;
g1_point pi_2;
types.g1_point pi_1;
types.g1_point pi_2;
}

struct fri_state_type {
Expand Down
15 changes: 15 additions & 0 deletions deploy/test-kzg-verifier.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const hre = require('hardhat')
const {getNamedAccounts} = hre

module.exports = async function () {
const {deployments, getNamedAccounts} = hre;
const {deploy} = deployments;
const {deployer, tokenOwner} = await getNamedAccounts();

await deploy('kzg_estimation', {
from: deployer,
log: true,
});
}

module.exports.tags = ['testKZGVerifierFixture']
12 changes: 12 additions & 0 deletions tasks/modular-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,15 @@ task("verify-circuit-proof")
let circuit = test.test;
process.exit((await verify_circuit_proof(modular_path, circuit)) ? 0 : 1);
});

task("verify-kzg")
.setAction(async (hre) => {
console.log("Verify KZG");
await deployments.fixture(['testKZGVerifierFixture']);
const v = await ethers.getContract('kzg_estimation');
const proof = [];
const public_input = [];
const receipt = await (await v.verify(proof, public_input, {gasLimit: 30_500_000})).wait();
console.log("⛽Gas used: ", receipt.gasUsed.toNumber());
// console.log(receipt);
});
16 changes: 16 additions & 0 deletions test/kzg-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const hre = require('hardhat')

/* global BigInt */

describe('KZG test', function () {
const {deployments} = hre;

it("Pairing precompile test", async function () {
await deployments.fixture(['testKZGVerifierFixture']);
const v = await ethers.getContract('kzg_estimation');
let x = await v.verify({gasLimit: 30_500_000});
console.log(x.gasUsed);
const receipt = await (await v.test_kzg({gasLimit: 30_500_000})).wait();
console.log("⛽Gas used: ", receipt.gasUsed.toNumber());
});
})

0 comments on commit 178d627

Please sign in to comment.