Skip to content

Commit

Permalink
bbs verification contract, test failing with EvmError: Revert
Browse files Browse the repository at this point in the history
  • Loading branch information
man2706kum committed Sep 3, 2024
1 parent 3420265 commit 3afbef3
Show file tree
Hide file tree
Showing 5 changed files with 305 additions and 57 deletions.
19 changes: 0 additions & 19 deletions script/Counter.s.sol

This file was deleted.

14 changes: 0 additions & 14 deletions src/Counter.sol

This file was deleted.

237 changes: 237 additions & 0 deletions src/bbs_verify.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

// https://github.com/tornadocash/tornado-core/blob/master/contracts/Verifier.sol
library Pairing {
uint256 constant PRIME_Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;

struct G1Point {
uint256 X;
uint256 Y;
}

// Encoding of field elements is: X[0] * z + X[1]
struct G2Point {
uint256[2] X;
uint256[2] Y;
}

/*
* @return The negation of p, i.e. p.plus(p.negate()) should be zero.
*/
function negate(G1Point memory p) internal pure returns (G1Point memory) {
// The prime q in the base field F_q for G1
if (p.X == 0 && p.Y == 0) {
return G1Point(0, 0);
} else {
return G1Point(p.X, PRIME_Q - (p.Y % PRIME_Q));
}
}

/*
* @return r the sum of two points of G1
*/
function plus(
G1Point memory p1,
G1Point memory p2
) internal view returns (G1Point memory r) {
uint256[4] memory input;
input[0] = p1.X;
input[1] = p1.Y;
input[2] = p2.X;
input[3] = p2.Y;
bool success;

// solium-disable-next-line security/no-inline-assembly
assembly {
success := staticcall(sub(gas(), 2000), 6, input, 0xc0, r, 0x60)
// Use "invalid" to make gas estimation work
switch success case 0 { invalid() }
}

require(success, "pairing-add-failed");
}

/*
* @return r the product of a point on G1 and a scalar, i.e.
* p == p.scalar_mul(1) and p.plus(p) == p.scalar_mul(2) for all
* points p.
*/
function scalar_mul(G1Point memory p, uint256 s) internal view returns (G1Point memory r) {
uint256[3] memory input;
input[0] = p.X;
input[1] = p.Y;
input[2] = s;
bool success;
// solium-disable-next-line security/no-inline-assembly
assembly {
success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60)
// Use "invalid" to make gas estimation work
switch success case 0 { invalid() }
}
require(success, "pairing-mul-failed");
}

/* @return The result of computing the pairing check
* e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1
* For example,
* pairing([P1(), P1().negate()], [P2(), P2()]) should return true.
*/
function pairing(
G1Point memory a1,
G2Point memory a2,
G1Point memory b1,
G2Point memory b2,
G1Point memory c1,
G2Point memory c2,
G1Point memory d1,
G2Point memory d2
) internal view returns (bool) {
G1Point[4] memory p1 = [a1, b1, c1, d1];
G2Point[4] memory p2 = [a2, b2, c2, d2];

uint256 inputSize = 24;
uint256[] memory input = new uint256[](inputSize);

for (uint256 i = 0; i < 4; i++) {
uint256 j = i * 6;
input[j + 0] = p1[i].X;
input[j + 1] = p1[i].Y;
input[j + 2] = p2[i].X[0];
input[j + 3] = p2[i].X[1];
input[j + 4] = p2[i].Y[0];
input[j + 5] = p2[i].Y[1];
}

uint256[1] memory out;
bool success;

// solium-disable-next-line security/no-inline-assembly
assembly {
success := staticcall(sub(gas(), 2000), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20)
// Use "invalid" to make gas estimation work
switch success case 0 { invalid() }
}

require(success, "pairing-opcode-failed");

return out[0] != 0;
}
}

library BBS {

using Pairing for *;

// generator of G1
function BP1() internal pure returns (Pairing.G1Point memory) {
return Pairing.G1Point(uint256(1), uint256(2));
}

// generator of G2
function BP2() internal pure returns (Pairing.G2Point memory) {
return Pairing.G2Point([
uint256(10857046999023057135944570762232829481370756359578518086990519993285655852781), uint256(11559732032986387107991004021392285783925812861821192530917403151452391805634)
],
[
uint256(8495653923123431417604973247489272438418190587263600148770280649306958101930), uint256(4082367875863433681332203403145435568316851327593401208105741076214120093531)
]);
}

// negation of generator of G2
function BP2Negate() internal pure returns (Pairing.G2Point memory) {
return Pairing.G2Point([
uint256(10857046999023057135944570762232829481370756359578518086990519993285655852781), uint256(11559732032986387107991004021392285783925812861821192530917403151452391805634)
],
[
uint256(13392588948715843804641432497768002650278120570034223513918757245338268106653), uint256(17805874995975841540914202342111839520379459829704422454583296818431106115052)
]);
}

// set of randomly sampled points from the G1 subgroup,
// api_id = ciphersuite_id || "H2G_HM2S_"
// CIPHERSUITE_ID = "BBS_BLS12381G1_XMD:SHA-256_SSWU_RO_";
function generators() internal pure returns (Pairing.G1Point[32] memory) {

return [
Pairing.G1Point(uint256(20777160656769770296920907689779400362548610292690633793553965468222558198628), uint256(15646964583660897684471766551845809741020611821959915197826685959370263487106)),
Pairing.G1Point(uint256(8536227939158618265175886202535764436304116068200625472123099584539578337421), uint256(5954339734284052721289034903148025734427628037818105080548676273909315194809)),
Pairing.G1Point(uint256(6966706174358697579930351667004530084801148414965274884121192450141672945045), uint256(498137001355230954510980595837383274359060711775308369155468447488137646784)),
Pairing.G1Point(uint256(5438105816700008286121294878063209652767146817832975561511179458352725658814), uint256(13021486400522453264827797557714368123643448446761912363585463162459449483576)),
Pairing.G1Point(uint256(15171615269862876518863358428943843041940125537931654107248803187352985612430), uint256(8586269445696959752467230517015982159589605142846712629705147542333554398226)),
Pairing.G1Point(uint256(5051258433525325219521083013996569208555314039239043276349703928699399069822), uint256(1681200095591041471217584326897093992437898040845292616132300787352510165206)),
Pairing.G1Point(uint256(21753791110380467783584742654428448358401879578443602255216671622947444229131), uint256(12897421398847559438022107398410073458721218334567793302364517965458109325783)),
Pairing.G1Point(uint256(16764643433735538422696377983000462108379103633839334040884164967942899425632), uint256(21668442295160040501298591489870463866263588933839580031841498538860744377064)),
Pairing.G1Point(uint256(4013792417864936116677013992620797522948679222441355805643575852230193971807), uint256(19852825205047261307491565420844666947509925513041998257351294192421458440775)),
Pairing.G1Point(uint256(15235789988489366351078142629661614055604735578863140907495220462928998553454), uint256(20439547806095900407701608374086160199235593142344143339294376261253535125704)),
Pairing.G1Point(uint256(9996721774782352741822533151204121063290685493223672922385484813016764547435), uint256(5385215156704978100874262819044322518580987328116718995648264785451005585049)),
Pairing.G1Point(uint256(5281253127589211866317136159546081932420549096521808911709313169185921240315), uint256(20288355738516256198974876062156075712583149333330237624015549545532548348625)),
Pairing.G1Point(uint256(19726372169683222465353857614018548655417268491715027507748163032820279050001), uint256(15730520802198311908481180389403348070871209305730811316454055853065609274596)),
Pairing.G1Point(uint256(16282107833837338794414548666268543192621108022168534422526344422541233598547), uint256(18839797638941304593430186468859495729298581516557153877529516048112227423101)),
Pairing.G1Point(uint256(18874646234839083109587086472635929908281290527959495976476575081871486139158), uint256(5899268376799611138981545417756396923956604357355852186412920150880814773404)),
Pairing.G1Point(uint256(14067505039747626814907528316498505303099495619235188348953524790328559486810), uint256(7389458255504902601690249514233706134057312606508220806800150482908277143952)),
Pairing.G1Point(uint256(15251189857028682076348637554874405070837309154537315899281290887655859816680), uint256(16018647581228689556732893544203926589846441512412840141045889388189453831778)),
Pairing.G1Point(uint256(8407462810135920786229033311650037150039055119197272220015509905962367850170), uint256(14732513882313499052827330088156636092855864050141475781755997887436735956009)),
Pairing.G1Point(uint256(13750370747778111173930259600316743671647606292973600136889468816552093463131), uint256(4925544525751198104051867872908540244212485100666666131834709922969647364368)),
Pairing.G1Point(uint256(953531922420076853769190318068935673991359154293184324057382801940087541058), uint256(6731416650799582766230739196791467550856695320647303187522338429522254332700)),
Pairing.G1Point(uint256(3173110439651164793311982626309113950349756763187602101531800216231599804928), uint256(5263771206696772457201153819901747129808438505593373196131282748808133634910)),
Pairing.G1Point(uint256(16027186659618718627499438833089566017580893109579552868678260272853087747448), uint256(21669689197811587869325211547657060943650336091419965475925811576944725616226)),
Pairing.G1Point(uint256(2620496790408129640731288723907750415832229288442662087498780982382004803756), uint256(16634155193153187661065141800307333031872218873118737169677190730431489499026)),
Pairing.G1Point(uint256(6309780264175077010538511403382530678267024106768286948652182798683470651010), uint256(10982639597997082531491430076512905403812001970252757816241040537962831959305)),
Pairing.G1Point(uint256(9592682014657652197114295404077004605429496936223920902324738714033691481088), uint256(14198367460357479057844799780559288048118616493274983350996740674423475576784)),
Pairing.G1Point(uint256(19133366293226796741137871486083885980769381521956342048688966627808507290439), uint256(1384224247742243466141266003325617983111978855774830111959515579286697418288)),
Pairing.G1Point(uint256(695990285095860103161233536714697342071230124499514229245010811142354057664), uint256(4880859521053654346795550932209273066894742740446493897902102531384430522307)),
Pairing.G1Point(uint256(18931247865367364266304964492516702793433990171087918161903347545062075665767), uint256(9945539770767347447775431528601480352781102902761543485719881461446315717486)),
Pairing.G1Point(uint256(1072683858589137215167630848551953164378072346728719245546816404388463668797), uint256(9332169772935827172513162711432044685970908789763810575299827679325424183666)),
Pairing.G1Point(uint256(21275808812052109345856593525178828352516671937584975416601023894900566571048), uint256(13165158610144979969982441431462117096010453879273262805716736386147711325322)),
Pairing.G1Point(uint256(1456643669371327517414661572825117577606274230242222820722949822081701218843), uint256(3771723902160285912564981419437554136700904455540292345569375427658737375328)),
Pairing.G1Point(uint256(18147240790321515030764012387388409927697035957099496685209442560219459579776), uint256(960007873849796184736529840000880494495810739716445769161195881582431744269))
];
}
}

contract BBS_Verifier {

uint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
uint256 constant PRIME_Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
using Pairing for *;
using BBS for *;

struct PublicKey {
Pairing.G2Point PK;
}

struct Signature {
Pairing.G1Point A;
uint256 E;
}

function verifySignature(
PublicKey memory pk,
Signature memory sig,
uint256[] memory msgScalar
) public view returns (bool) {

for (uint256 i = 0; i < msgScalar.length; i++) {
require(msgScalar[i] < SNARK_SCALAR_FIELD, "invalid scalar");
}

//TODO: change this
// this domain is calulated from the public key, hence cannot be hardcoded
uint256 domain = uint256(14063053651636558252041470698983588143630819978768317207563375018948447002197);

Pairing.G1Point memory b = BBS.BP1();


b = Pairing.plus(b, Pairing.scalar_mul(BBS.generators()[0], domain));


for (uint256 i = 1; i < msgScalar.length + 1; i++) {
b = Pairing.plus(b, Pairing.scalar_mul(BBS.generators()[i], msgScalar[i - 1]));
}

// TODO: this pairing components are not correct
// test assertion should fail
return Pairing.pairing(sig.A, pk.PK, sig.A, BBS.BP2(), b, BBS.BP2Negate(), BBS.BP1(), BBS.BP2());
}
}
24 changes: 0 additions & 24 deletions test/Counter.t.sol

This file was deleted.

68 changes: 68 additions & 0 deletions test/bbs_verify.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Test, console} from "forge-std/Test.sol";
import {BBS_Verifier, Pairing, BBS} from "../src/bbs_verify.sol";

contract BBS_VerifierTest is Test {

BBS_Verifier.Signature public sig;
BBS_Verifier.PublicKey public pk;

function setUp() public {
sig.A = Pairing.G1Point(
uint256(6518957532561288284806978889353235007147412781973042229655530093817992345893), uint256(14113242567534957219063701299513155388684925141849341005159415617754010843574)
);
sig.E = uint256(1992218171307223762716653896284120426793108996079242542640684935869602299103);

pk.PK = Pairing.G2Point(
[uint256(12645745131803946564517015766083220615208734349162119496713913738635122768190), uint256(18995555010723360870807378930627885936580090638932106191711429555833420406651)],
[uint256(15886074934859455688300902859116025241719978288647494891665273100122551253775), uint256(3610369380377107663814668440952629069799181095497307971279336242375649233639)]
);
}
function test_verify() public {
uint256[31] memory msgScalar = [
uint256(2266124219189018131),
uint256(15553430782966677989),
uint256(12252424663184168987),
uint256(1969625583697874321),
uint256(8798495767124183927),
uint256(4743228516788447402),
uint256(8902949269966882790),
uint256(1449287668463434640),
uint256(16234881692928710824),
uint256(13179618089750662187),
uint256(2132060277757908505),
uint256(7469040032366907693),
uint256(286998145258191934),
uint256(12012091655379394047),
uint256(8227232354837253112),
uint256(4245507022592209702),
uint256(15341480955034186690),
uint256(13372014594622549612),
uint256(4775774716639663789),
uint256(3980695616762244981),
uint256(13661186179188099084),
uint256(11843969393565636405),
uint256(584132371283407898),
uint256(7718042704038564351),
uint256(1113807059037267782),
uint256(12590950049868647788),
uint256(11822948952081078471),
uint256(14688457861979401824),
uint256(4766154862542150769),
uint256(5861875202524790730),
uint256(1386588526036119096)];


uint256[] memory msgS = new uint256[](msgScalar.length);
for (uint256 i = 0; i < msgScalar.length; i++) {
msgS[i] = msgScalar[i];
}
BBS_Verifier verifier;
verifier = new BBS_Verifier();

bool res = verifier.verifySignature(pk, sig, msgS);
assert(res);
}
}

0 comments on commit 3afbef3

Please sign in to comment.