Skip to content

Commit

Permalink
Fix Put public inputs in the transcirpt
Browse files Browse the repository at this point in the history
  • Loading branch information
jbaylina committed Apr 5, 2022
1 parent f5ebdc1 commit 304c18d
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 66 deletions.
44 changes: 34 additions & 10 deletions build/main.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -6025,6 +6025,7 @@ async function plonkSetup(r1csName, ptauName, zkeyName, logger) {
const nPublic = r1cs.nOutputs + r1cs.nPubInputs;

await processConstraints();
if (global.gc) {global.gc();}

const fdZKey = await binFileUtils.createBinFile(zkeyName, "zkey", 1, 14, 1<<22, 1<<24);

Expand Down Expand Up @@ -6060,16 +6061,27 @@ async function plonkSetup(r1csName, ptauName, zkeyName, logger) {


await writeAdditions(3, "Additions");
if (global.gc) {global.gc();}
await writeWitnessMap(4, 0, "Amap");
if (global.gc) {global.gc();}
await writeWitnessMap(5, 1, "Bmap");
if (global.gc) {global.gc();}
await writeWitnessMap(6, 2, "Cmap");
if (global.gc) {global.gc();}
await writeQMap(7, 3, "Qm");
if (global.gc) {global.gc();}
await writeQMap(8, 4, "Ql");
if (global.gc) {global.gc();}
await writeQMap(9, 5, "Qr");
if (global.gc) {global.gc();}
await writeQMap(10, 6, "Qo");
if (global.gc) {global.gc();}
await writeQMap(11, 7, "Qc");
if (global.gc) {global.gc();}
await writeSigma(12, "sigma");
if (global.gc) {global.gc();}
await writeLs(13, "lagrange polynomials");
if (global.gc) {global.gc();}

// Write PTau points
////////////
Expand All @@ -6079,6 +6091,7 @@ async function plonkSetup(r1csName, ptauName, zkeyName, logger) {
await fdPTau.readToBuffer(buffOut, 0, (domainSize+6)*sG1, sectionsPTau[2][0].p);
await fdZKey.write(buffOut);
await binFileUtils.endWriteSection(fdZKey);
if (global.gc) {global.gc();}


await writeHeaders();
Expand Down Expand Up @@ -6601,10 +6614,13 @@ async function plonk16Prove(zkeyFileName, witnessFileName, logger) {

async function round2() {

const transcript1 = new Uint8Array(G1.F.n8*2*3);
G1.toRprUncompressed(transcript1, 0, proof.A);
G1.toRprUncompressed(transcript1, G1.F.n8*2, proof.B);
G1.toRprUncompressed(transcript1, G1.F.n8*4, proof.C);
const transcript1 = new Uint8Array(zkey.nPublic*n8r + G1.F.n8*2*3);
for (let i=0; i<zkey.nPublic; i++) {
Fr.toRprBE(transcript1, i*n8r, A.slice((i+1)*n8r, (i+2)*n8r));
}
G1.toRprUncompressed(transcript1, zkey.nPublic*n8r + 0, proof.A);
G1.toRprUncompressed(transcript1, zkey.nPublic*n8r + G1.F.n8*2, proof.B);
G1.toRprUncompressed(transcript1, zkey.nPublic*n8r + G1.F.n8*4, proof.C);

ch.beta = hashToFr(transcript1);
if (logger) logger.debug("beta: " + Fr.toString(ch.beta));
Expand Down Expand Up @@ -7295,7 +7311,11 @@ async function plonkVerify(vk_verifier, publicSignals, proof, logger) {
logger.error("Proof is not well constructed");
return false;
}
const challanges = calculateChallanges(curve, proof);
if (publicSignals.length != vk_verifier.nPublic) {
logger.error("Invalid number of public inputs");
return false;
}
const challanges = calculateChallanges(curve, proof, publicSignals);
if (logger) {
logger.debug("beta: " + Fr.toString(challanges.beta, 16));
logger.debug("gamma: " + Fr.toString(challanges.gamma, 16));
Expand Down Expand Up @@ -7415,16 +7435,20 @@ function isWellConstructed(curve, proof) {
return true;
}

function calculateChallanges(curve, proof) {
function calculateChallanges(curve, proof, publicSignals) {
const G1 = curve.G1;
const Fr = curve.Fr;
const n8r = curve.Fr.n8;
const res = {};

const transcript1 = new Uint8Array(G1.F.n8*2*3);
G1.toRprUncompressed(transcript1, 0, proof.A);
G1.toRprUncompressed(transcript1, G1.F.n8*2, proof.B);
G1.toRprUncompressed(transcript1, G1.F.n8*4, proof.C);
const transcript1 = new Uint8Array(publicSignals.length*n8r + G1.F.n8*2*3);
for (let i=0; i<publicSignals.length; i++) {
Fr.toRprBE(transcript1, i*n8r, Fr.e(publicSignals[i]));
}
G1.toRprUncompressed(transcript1, publicSignals.length*n8r + 0, proof.A);
G1.toRprUncompressed(transcript1, publicSignals.length*n8r + G1.F.n8*2, proof.B);
G1.toRprUncompressed(transcript1, publicSignals.length*n8r + G1.F.n8*4, proof.C);

res.beta = hashToFr(curve, transcript1);

const transcript2 = new Uint8Array(n8r);
Expand Down
11 changes: 7 additions & 4 deletions src/plonk_prove.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,13 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger

async function round2() {

const transcript1 = new Uint8Array(G1.F.n8*2*3);
G1.toRprUncompressed(transcript1, 0, proof.A);
G1.toRprUncompressed(transcript1, G1.F.n8*2, proof.B);
G1.toRprUncompressed(transcript1, G1.F.n8*4, proof.C);
const transcript1 = new Uint8Array(zkey.nPublic*n8r + G1.F.n8*2*3);
for (let i=0; i<zkey.nPublic; i++) {
Fr.toRprBE(transcript1, i*n8r, A.slice((i)*n8r, (i+1)*n8r));
}
G1.toRprUncompressed(transcript1, zkey.nPublic*n8r + 0, proof.A);
G1.toRprUncompressed(transcript1, zkey.nPublic*n8r + G1.F.n8*2, proof.B);
G1.toRprUncompressed(transcript1, zkey.nPublic*n8r + G1.F.n8*4, proof.C);

ch.beta = hashToFr(transcript1);
if (logger) logger.debug("beta: " + Fr.toString(ch.beta));
Expand Down
9 changes: 0 additions & 9 deletions src/plonk_setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ import BigArray from "./bigarray.js";

export default async function plonkSetup(r1csName, ptauName, zkeyName, logger) {

if (global.gc) {global.gc();}

await Blake2b.ready();

const {fd: fdPTau, sections: sectionsPTau} = await readBinFile(ptauName, "ptau", 1, 1<<22, 1<<24);
Expand Down Expand Up @@ -319,29 +317,22 @@ export default async function plonkSetup(r1csName, ptauName, zkeyName, logger) {
}
if ((logger)&&(s%1000000 == 0)) logger.debug(`writing ${name} phase2: ${s}/${plonkNVars}`);
}
if (global.gc) {global.gc();}
await startWriteSection(fdZKey, sectionNum);
let S1 = sigma.slice(0, domainSize*n8r);
await writeP4(S1);
if (global.gc) {global.gc();}
let S2 = sigma.slice(domainSize*n8r, domainSize*n8r*2);
await writeP4(S2);
if (global.gc) {global.gc();}
let S3 = sigma.slice(domainSize*n8r*2, domainSize*n8r*3);
await writeP4(S3);
if (global.gc) {global.gc();}
await endWriteSection(fdZKey);

S1 = await Fr.batchFromMontgomery(S1);
S2 = await Fr.batchFromMontgomery(S2);
S3 = await Fr.batchFromMontgomery(S3);

vk.S1= await curve.G1.multiExpAffine(LPoints, S1, logger, "multiexp S1");
if (global.gc) {global.gc();}
vk.S2= await curve.G1.multiExpAffine(LPoints, S2, logger, "multiexp S2");
if (global.gc) {global.gc();}
vk.S3= await curve.G1.multiExpAffine(LPoints, S3, logger, "multiexp S3");
if (global.gc) {global.gc();}

function buildSigma(s, p) {
if (typeof lastAparence[s] === "undefined") {
Expand Down
20 changes: 14 additions & 6 deletions src/plonk_verify.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ export default async function plonkVerify(vk_verifier, publicSignals, proof, log
logger.error("Proof is not well constructed");
return false;
}
const challanges = calculateChallanges(curve, proof);
if (publicSignals.length != vk_verifier.nPublic) {
logger.error("Invalid number of public inputs");
return false;
}
const challanges = calculateChallanges(curve, proof, publicSignals);
if (logger) {
logger.debug("beta: " + Fr.toString(challanges.beta, 16));
logger.debug("gamma: " + Fr.toString(challanges.gamma, 16));
Expand Down Expand Up @@ -162,16 +166,20 @@ function isWellConstructed(curve, proof) {
return true;
}

function calculateChallanges(curve, proof) {
function calculateChallanges(curve, proof, publicSignals) {
const G1 = curve.G1;
const Fr = curve.Fr;
const n8r = curve.Fr.n8;
const res = {};

const transcript1 = new Uint8Array(G1.F.n8*2*3);
G1.toRprUncompressed(transcript1, 0, proof.A);
G1.toRprUncompressed(transcript1, G1.F.n8*2, proof.B);
G1.toRprUncompressed(transcript1, G1.F.n8*4, proof.C);
const transcript1 = new Uint8Array(publicSignals.length*n8r + G1.F.n8*2*3);
for (let i=0; i<publicSignals.length; i++) {
Fr.toRprBE(transcript1, i*n8r, Fr.e(publicSignals[i]));
}
G1.toRprUncompressed(transcript1, publicSignals.length*n8r + 0, proof.A);
G1.toRprUncompressed(transcript1, publicSignals.length*n8r + G1.F.n8*2, proof.B);
G1.toRprUncompressed(transcript1, publicSignals.length*n8r + G1.F.n8*4, proof.C);

res.beta = hashToFr(curve, transcript1);

const transcript2 = new Uint8Array(n8r);
Expand Down
23 changes: 16 additions & 7 deletions templates/verifier_plonk.sol.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,9 @@ contract PlonkVerifier {
<% for (let i=1; i<=Math.max(nPublic, 1); i++) { %>
uint16 constant pEval_l<%=i%> = <%=640+i*32%>;
<% } %>
<% let pLastMem = 672+32*Math.max(nPublic,1) %>


uint16 constant lastMem = <%=672+32*Math.max(nPublic,1)%>;

uint16 constant lastMem = <%=pLastMem%>;

function verifyProof(bytes memory proof, uint[] memory pubSignals) public view returns (bool) {
assembly {
Expand Down Expand Up @@ -199,12 +198,22 @@ contract PlonkVerifier {
// Points are checked in the point operations precompiled smart contracts
}

function calculateChallanges(pProof, pMem) {
function calculateChallanges(pProof, pMem, pPublic) {

let a
let b

b := mod(keccak256(add(pProof, pA), 192), q)

<%for (let i=0; i<nPublic;i++) {%>
mstore( add(pMem, <%=pLastMem + i*32%> ), mload( add( pPublic, <%=i*32 + 32%>)))
<%}%>
mstore( add(pMem, <%=pLastMem + nPublic*32 +0%> ), mload( add( pProof, pA)))
mstore( add(pMem, <%=pLastMem + nPublic*32 +32%> ), mload( add( pProof, add(pA,32))))
mstore( add(pMem, <%=pLastMem + nPublic*32 +64%> ), mload( add( pProof, add(pA,64))))
mstore( add(pMem, <%=pLastMem + nPublic*32 +96%> ), mload( add( pProof, add(pA,96))))
mstore( add(pMem, <%=pLastMem + nPublic*32 +128%> ), mload( add( pProof, add(pA,128))))
mstore( add(pMem, <%=pLastMem + nPublic*32 +160%> ), mload( add( pProof, add(pA,160))))

b := mod(keccak256(add(pMem, lastMem), <%= 192 + 32*nPublic %>), q)
mstore( add(pMem, pBeta), b)
mstore( add(pMem, pGamma), mod(keccak256(add(pMem, pBeta), 32), q))
mstore( add(pMem, pAlpha), mod(keccak256(add(pProof, pZ), 64), q))
Expand Down Expand Up @@ -615,7 +624,7 @@ contract PlonkVerifier {
mstore(0x40, add(pMem, lastMem))

checkInput(proof)
calculateChallanges(proof, pMem)
calculateChallanges(proof, pMem, pubSignals)
calculateLagrange(pMem)
calculatePl(pMem, pubSignals)
calculateT(proof, pMem)
Expand Down
50 changes: 25 additions & 25 deletions test/plonk_circuit/proof.json
Original file line number Diff line number Diff line change
@@ -1,54 +1,54 @@
{
"A": [
"11939839401037308014501661426368356653724850605345253332929657172853812043781",
"16803150087255544989431958662488492904420336924238680701501581437584428607157",
"15917573233407722732062787698951765050036957325370721125210834646525203076389",
"10234794045268909768723861952713815259678638768538486148638400158927236468234",
"1"
],
"B": [
"12217796857989229870486480566571024020165537615492120027996617913635583550919",
"15953050028732489401139070996642159829273127420498389055201687358737110395633",
"6534033380695361734911825473617889658104101245167934289050248436664841578363",
"14061971131648369041603507755410089728742438126668707374914752588236606702754",
"1"
],
"C": [
"2906696582521990272421790638819759482269959041206664482786284127016128717160",
"13202026981472500389768834017524824796942889042108968745956553624097139985303",
"14505892627896587350473010034286107819685493071925324450974954770526434593332",
"6186416458036711799535608999371759388592544992468951288703737883955685292858",
"1"
],
"Z": [
"12963117237509670288018978167117384995558675963765854814463910896579884709481",
"4622289012016200197589549612287854254636168290945719641009001753279825228149",
"12081441476366171431338238830264497598570062548451685935024863321326757767785",
"9387897371969025065284991899948083393556628309133379383594080265474146141157",
"1"
],
"T1": [
"18104357506804140563327524454292715928794326274573109553633239600891197573562",
"538095434184877169430117038240223945215803059446062355137183333593880141605",
"11697295649838930633765261378756086756478619706964809367863062927042238692921",
"14968409908681220375122607622180081440264275996476655054223469087507417759789",
"1"
],
"T2": [
"11026905931134233808041270707862602948406795505689051352903565023828166906250",
"18119786770119651916429915278124137884233023858386753737488502838895847215949",
"2953189016956047791736757973461484048315463397915849932374528729412270696527",
"8620891985757406277592771106070049395916563323571640384543833813728271133486",
"1"
],
"T3": [
"17566889279472128646779664131922958011041076031971155851685601770551415716030",
"9098203299195991935285362173962848018633069009185836024035896571651321000209",
"16223333010830689480143912693604648201451508158843567126275050570081980855643",
"14438863974133388343515803834890541076773695198795082356970685950267401738910",
"1"
],
"eval_a": "18055865061248928277436374209575542340767389401367587042080949450055475826552",
"eval_b": "21850645998014953033835315242107188012141028920551179313126430204177981301827",
"eval_c": "5824117629917668551774989696896451058359923623432918656361263478103100196767",
"eval_s1": "65743854351722680405937613500622654105481480423395233482389298676037124381",
"eval_s2": "403993049457837292639608362612899661597754187086038035508895737334683813284",
"eval_zw": "14169472644142979719809496569719127849776868311673021350864638375395829014729",
"eval_r": "9395413794097544253619189223051084436435081924218993403215287776407899118006",
"eval_a": "14339139182789381237229239915123261853915681686933828385685851702630204504663",
"eval_b": "14868966654115759140239472823375151970328635256589988386102968278787868240414",
"eval_c": "564057494214488102817009147593706678326690684832103817838290432546546599925",
"eval_s1": "19371496695515240161592963759911623294871060124201355865755153108252682382360",
"eval_s2": "2579612056529355211259943592521042166985820548059386261162331074609979969098",
"eval_zw": "19685091872602775677986598924926591283988441651361153034121001539751878867815",
"eval_r": "17019396159933864043409418821108145005876806528173417875530903213264996917828",
"Wxi": [
"3539391490802181190120434708628288229123728841695494613225112420761229267477",
"19988904286663115119238205828592812126968004685055289879546007973679529590700",
"4789447887245439838828293816801085734534480786500369542683260813915807895018",
"5743534347322910212791948378800524709212623490686788228035168007519506810508",
"1"
],
"Wxiw": [
"19317464275069150558817973507256614963505445298046435829549010698677013964612",
"16876609931905898917226763969880049506487107879332614688130170393689647229232",
"19379972490037320589254794886333437175961689166573424007077500138714809349682",
"12523908414418029668596495120104904066342410136497532239942511327769729048404",
"1"
],
"protocol": "plonk",
Expand Down
21 changes: 16 additions & 5 deletions test/plonk_circuit/verifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pragma solidity >=0.7.0 <0.9.0;

contract PlonkVerifier {

uint16 constant n = 8;
uint32 constant n = 8;
uint16 constant nPublic = 2;
uint16 constant nLagrange = 2;

Expand Down Expand Up @@ -105,7 +105,6 @@ contract PlonkVerifier {

uint16 constant lastMem = 736;


function verifyProof(bytes memory proof, uint[] memory pubSignals) public view returns (bool) {
assembly {
/////////
Expand Down Expand Up @@ -201,12 +200,24 @@ contract PlonkVerifier {
// Points are checked in the point operations precompiled smart contracts
}

function calculateChallanges(pProof, pMem) {
function calculateChallanges(pProof, pMem, pPublic) {

let a
let b


mstore( add(pMem, 736 ), mload( add( pPublic, 32)))

mstore( add(pMem, 768 ), mload( add( pPublic, 64)))

mstore( add(pMem, 800 ), mload( add( pProof, pA)))
mstore( add(pMem, 832 ), mload( add( pProof, add(pA,32))))
mstore( add(pMem, 864 ), mload( add( pProof, add(pA,64))))
mstore( add(pMem, 896 ), mload( add( pProof, add(pA,96))))
mstore( add(pMem, 928 ), mload( add( pProof, add(pA,128))))
mstore( add(pMem, 960 ), mload( add( pProof, add(pA,160))))

b := mod(keccak256(add(pProof, pA), 192), q)
b := mod(keccak256(add(pMem, lastMem), 256), q)
mstore( add(pMem, pBeta), b)
mstore( add(pMem, pGamma), mod(keccak256(add(pMem, pBeta), 32), q))
mstore( add(pMem, pAlpha), mod(keccak256(add(pProof, pZ), 64), q))
Expand Down Expand Up @@ -658,7 +669,7 @@ contract PlonkVerifier {
mstore(0x40, add(pMem, lastMem))

checkInput(proof)
calculateChallanges(proof, pMem)
calculateChallanges(proof, pMem, pubSignals)
calculateLagrange(pMem)
calculatePl(pMem, pubSignals)
calculateT(proof, pMem)
Expand Down

0 comments on commit 304c18d

Please sign in to comment.