Nodejsとsanrkjsを使用してゼロ知識証明を生成し、検証します.
30883 ワード
Merkle Treeパス証明を例に、nodejsとsanrkjsを使用してゼロ知識証明を生成し、ローカル検証を行います.
バージョン#バージョン#
ソースコード
genKeypair.js setup、pkとvkを生成
index.jsはproofを生成し、ローカル検証を行う
verify.solとインタラクティブにチェーン上で検証する部分も追加できます.
完全なコードは私のgithubの上に置いてあります.
あった問題 Cannot read property’prime’of undefined解決:compile()の2番目のパラメータは{} と書く Circuit is not a constructor解決:古いバージョンのcircomとsnarkjsを変更し、circomのindex.jsをmodule.exports.compiler=require(./src/compiler.js)に変更します. WebAssembly.Memory():could not allocate memory解決:コンピュータのメモリが足りないはずです.サーバーに変えてok を実行します. index.js実行中にverifyが通過し、コマンドラインverifyを使用して失敗しました.proof.json出力フォーマットが と書き間違えました.
リファレンス
https://www.jianshu.com/p/45ef81cc77b9 https://github.com/kendricktan/hello-world-zk-dapp
バージョン#バージョン#
"circom": "0.0.35",
"circomlib": "0.0.20",
"snarkjs": "0.1.20"
ソースコード
genKeypair.js setup、pkとvkを生成
const { compiler } = require("circom");
const { Circuit, groth ,stringifyBigInts } = require("snarkjs");
const path = require("path");
const fs = require("fs");
const genKeypair = async () => {
console.log("start....");
console.log("Get circtui definition....");
const circuitDef = await compiler(
path.join(__dirname, "./withdraw.circom"),{}
);
const circuit = new Circuit(circuitDef);
console.log("Setup....");
const {vk_proof,vk_verifier} = groth.setup(circuit);
//save pk,vk file
fs.writeFileSync("proving_key.json", JSON.stringify(stringifyBigInts(vk_proof)), 'utf8');
fs.writeFileSync("verification_key.json", JSON.stringify(stringifyBigInts(vk_verifier)), 'utf8');
console.log("finish....");
process.exit(0);
};
genKeypair();
index.jsはproofを生成し、ローカル検証を行う
const { binarifyWitness } = require("./utils/binarify");
const bigInt = require("big-integer");
const { compiler } = require("circom");
const { Circuit, groth ,stringifyBigInts ,unstringifyBigInts} = require("snarkjs");
const path = require("path");
const fs = require("fs");
const SNARK_FIELD_SIZE = bigInt(
"21888242871839275222246405745257275088548364400416034343698204186575808495617"
);
//read input
const fileData = fs.readFileSync('input.json');
const inputObj = JSON.parse(fileData);
const root = bigInt(inputObj.root);
const nullifierHash = bigInt(inputObj.nullifierHash);
const secret = bigInt(inputObj.secret);
const paths2_root = [
bigInt(inputObj.paths2_root[0]),
bigInt(inputObj.paths2_root[1]),
bigInt(inputObj.paths2_root[2])
];
const paths2_root_pos = bigInt(inputObj.paths2_root_pos);
const provingKey = require("./proving_key.json");
const verifyingKey = require("./verification_key.json");
//gen wintness proof
const generateProofAndVerify = async circuitInputs => {
console.log("Get circtui definition....");
const circuitDef = await compiler(
path.join(__dirname, "./withdraw.circom"),{}
);
const circuit = new Circuit(circuitDef);
console.log("loading pk,vk....");
const vk_proof = unstringifyBigInts(provingKey);
const vk_verifier = unstringifyBigInts(verifyingKey);
console.log("Generating witness....");
const witness = circuit.calculateWitness(stringifyBigInts(circuitInputs));
//save witness file
const witnessString = witness.map(x => x.toString());
fs.writeFileSync("witness.json",JSON.stringify(witnessString));
console.log("Generating proof and publicSignals....");
const {proof,publicSignals} = await groth.genProof(vk_proof,witness);
//save proof file
const proofJson = JSON.stringify({
pi_a: stringifyBigInts(proof.pi_a).slice(0, 3),
pi_b: stringifyBigInts(proof.pi_b).slice(0, 3),
pi_c: stringifyBigInts(proof.pi_c).slice(0, 3),
protocol: "groth"
});
fs.writeFileSync("proof.json", proofJson);
//save public file
console.log("Generating public.json....");
const pS = publicSignals.map(x => bigInt(x));
const publicInputs = pS.map(x => x.mod(SNARK_FIELD_SIZE).toString());
console.log("Generating public.json....");
const publicJson = [
publicInputs[0],publicInputs[1]
];
fs.writeFileSync("public.json", JSON.stringify(publicJson));
console.log("Check isValid....");
const isValid = groth.isValid(vk_verifier,proof,publicSignals);
console.log(`Passed local zk-snark verification: ${isValid}`);
console.log("Generating solidityProof....");
const solidityProof = {
a: stringifyBigInts(proof.pi_a).slice(0, 2),
b: stringifyBigInts(proof.pi_b).slice(0, 2),
c: stringifyBigInts(proof.pi_c).slice(0, 2),
inputs: publicInputs
};
//save solidityProof file
fs.writeFileSync("solidityProof.json", JSON.stringify(solidityProof));
//// Submit to smart contract
//const solidityIsValid = await zkIdentityContract.isInGroup(
// solidityProof.a,
// solidityProof.b,
// solidityProof.c,
// solidityProof.inputs
//);
//console.log(`Verified user is in group (via solidity): ${solidityIsValid}`);
};
const main = async () => {
console.log("zkp start....");
await generateProofAndVerify({
root: root,
nullifierHash: nullifierHash,
secret: secret,
paths2_root: paths2_root,
paths2_root_pos: paths2_root_pos
});
console.log("zkp finish....");
process.exit(0);
};
main();
verify.solとインタラクティブにチェーン上で検証する部分も追加できます.
完全なコードは私のgithubの上に置いてあります.
あった問題
リファレンス
https://www.jianshu.com/p/45ef81cc77b9 https://github.com/kendricktan/hello-world-zk-dapp