mirror of https://github.com/vacp2p/research.git
messy but 'the proof is valid' for semaphore, finally
This commit is contained in:
parent
b9ae969427
commit
2395eab71f
|
@ -1,21 +1,27 @@
|
|||
const crypto = require('crypto');
|
||||
var fs = require('fs');
|
||||
const fs = require('fs');
|
||||
const zkSnark = require('snarkjs');
|
||||
const circomlib = require('circomlib');
|
||||
|
||||
const web3Utils = require('web3-utils');
|
||||
|
||||
const ethers = require('ethers');
|
||||
const SMT = require('semaphore-merkle-tree');
|
||||
|
||||
const {stringifyBigInts, unstringifyBigInts} = require("snarkjs/src/stringifybigint.js");
|
||||
//const {stringifyBigInts, unstringifyBigInts} = require("./node_modules/snarkjs/src/stringifybigint.js");
|
||||
const asciiToHex = web3Utils.asciiToHex;
|
||||
|
||||
const bigInt = zkSnark.bigInt;
|
||||
|
||||
const eddsa = circomlib.eddsa;
|
||||
const mimcsponge = circomlib.mimcsponge;
|
||||
|
||||
// Utils
|
||||
|
||||
function pedersenHash(ints) {
|
||||
const p = circomlib.babyJub.unpackPoint(circomlib.pedersenHash.hash(Buffer.concat(
|
||||
ints.map(x => x.leInt2Buff(32))
|
||||
)));
|
||||
return bigInt(p[0]);
|
||||
}
|
||||
|
||||
beBuff2int = function(buff) {
|
||||
let res = bigInt.zero;
|
||||
for (let i=0; i<buff.length; i++) {
|
||||
|
@ -25,6 +31,8 @@ beBuff2int = function(buff) {
|
|||
return res;
|
||||
};
|
||||
|
||||
// XXX: stringifyBigInts etc probably more robust
|
||||
|
||||
// Dealing with JSON BigInt serialization/deserialization
|
||||
function stringifyReplacer(key, value) {
|
||||
if (typeof value === 'bigint') {
|
||||
|
@ -85,12 +93,19 @@ const circuit = new zkSnark.Circuit(circuitDef);
|
|||
// 3. Perform setup - only done once
|
||||
function performSetup(circuit) {
|
||||
const setup = zkSnark.groth.setup(circuit);
|
||||
fs.writeFileSync("build/proving_key.json", serialize(setup.vk_proof), "utf8");
|
||||
fs.writeFileSync("build/verification_key.json", serialize(setup.vk_verifier), "utf8");
|
||||
/// XXX run this again - takes 1h so do at home
|
||||
fs.writeFileSync("myCircuit.vk_proof", JSON.stringify(stringifyBigInts(setup.vk_proof)), "utf8");
|
||||
fs.writeFileSync("myCircuit.vk_verifier", JSON.stringify(stringifyBigInts(setup.vk_verifier)), "utf8");
|
||||
|
||||
// fs.writeFileSync("build/proving_key.json", serialize(setup.vk_proof), "utf8");
|
||||
// fs.writeFileSync("build/verification_key.json", serialize(setup.vk_verifier), "utf8");
|
||||
console.log("Toxic waste:", setup.toxic); // Must be discarded.
|
||||
}
|
||||
// TODO: Conditionally run if file exists
|
||||
// performSetup(circuit);
|
||||
//performSetup(circuit);
|
||||
//console.log("Done, exiting");
|
||||
//process.exit(1);
|
||||
// TODO: run this to get new proving key with stringified etc
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -146,58 +161,163 @@ const pubKey = eddsa.prv2pub(prvKey);
|
|||
// XXX: What are these exactly?
|
||||
let identity_nullifier = loaded_identity.identity_nullifier;
|
||||
let identity_trapdoor = loaded_identity.identity_trapdoor;
|
||||
let identity_commitment = loaded_identity.identity_commitment;
|
||||
|
||||
// identity_path we await from server, glurgh.
|
||||
// XXX: Not an easy place to leave, but that's where I am at
|
||||
// server.js: path_for_element/:el
|
||||
// semaphore.tree.element_index(leaf)
|
||||
// identity tree index, MerkleTree
|
||||
// HERE AM
|
||||
const identity_path_elements = identity_path.path_elements;
|
||||
const identity_path_index = identity_path.path_index;
|
||||
|
||||
assert(eddsa.verifyMiMCSponge(msg, signature, pubKey));
|
||||
// => true
|
||||
// Construct tree
|
||||
const storage = new SMT.storage.MemStorage();
|
||||
const hasher = new SMT.hashers.MimcSpongeHasher();
|
||||
const prefix = 'semaphore';
|
||||
const default_value = '0';
|
||||
const depth = 20; // quite deep?
|
||||
|
||||
// What are the different types of signature fields?
|
||||
//async function foo() {
|
||||
|
||||
// loaded_identity.identity_nullifier?
|
||||
const tree = new SMT.tree.MerkleTree(
|
||||
`${prefix}_id_tree`,
|
||||
storage,
|
||||
hasher,
|
||||
depth,
|
||||
default_value,
|
||||
);
|
||||
|
||||
const inputs = {
|
||||
'identity_pk[0]': pubKey[0],
|
||||
'identity_pk[1]': pubKey[1],
|
||||
'auth_sig_r[0]': signature.R8[0],
|
||||
'auth_sig_r[1]': signature.R8[1],
|
||||
auth_sig_s: signature.S,
|
||||
signal_hash,
|
||||
external_nullifier,
|
||||
identity_nullifier,
|
||||
identity_trapdoor,
|
||||
identity_path_elements,
|
||||
identity_path_index,
|
||||
fake_zero: bigInt(0),
|
||||
// ok, we got the tree, now what?
|
||||
// Add to the tree! we ge that identity commitment
|
||||
// get tree index, etc etc
|
||||
// first have to add to tree
|
||||
// let loaded_identity = generate_identity();
|
||||
|
||||
// semapohore url
|
||||
// server://path_for_element/:identity_commitment OR if exists
|
||||
// server://path/identity.index
|
||||
// 1. How is tree constructed?
|
||||
|
||||
const leaf = identity_commitment; // element
|
||||
|
||||
// tostring?
|
||||
console.log("leaf", leaf);
|
||||
|
||||
// adding identity commitment to tree
|
||||
|
||||
let leaf_index;
|
||||
let path;
|
||||
|
||||
// XXX: Ugly as hell here
|
||||
async function updateTree() {
|
||||
await tree.update(1, leaf);
|
||||
leaf_index = await tree.element_index(leaf);
|
||||
// find path to a index containing identity commitment;
|
||||
path = await tree.path(leaf_index);
|
||||
console.log("***leaf_index", leaf_index);
|
||||
};
|
||||
|
||||
// const w = circuit.calculateWitness(inputs);
|
||||
// assert(circuit.checkWitness(w));
|
||||
// returns promise, we can use .then and go
|
||||
updateTree()
|
||||
.then(() => {
|
||||
console.log("***leaf_index outside", leaf_index);
|
||||
console.log("tree", tree);
|
||||
bar();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log("error", err);
|
||||
});
|
||||
|
||||
// XXX
|
||||
let inputs;
|
||||
let identity_path;
|
||||
|
||||
let witness;
|
||||
let vk_proof;
|
||||
let proof;
|
||||
let publicSignals;
|
||||
|
||||
function bar() {
|
||||
console.log("path", leaf_index);
|
||||
identity_path = path;
|
||||
console.log("identity_path", identity_path);
|
||||
// XXX
|
||||
const identity_path_elements = identity_path.path_elements;
|
||||
console.log("identity_path_elements", identity_path_elements);
|
||||
const identity_path_index = identity_path.path_index;
|
||||
|
||||
assert(eddsa.verifyMiMCSponge(msg, signature, pubKey));
|
||||
// => true
|
||||
|
||||
// What are the different types of signature fields?
|
||||
|
||||
// loaded_identity.identity_nullifier?
|
||||
|
||||
inputs = {
|
||||
'identity_pk[0]': pubKey[0],
|
||||
'identity_pk[1]': pubKey[1],
|
||||
'auth_sig_r[0]': signature.R8[0],
|
||||
'auth_sig_r[1]': signature.R8[1],
|
||||
auth_sig_s: signature.S,
|
||||
// XXX
|
||||
signal_hash,
|
||||
external_nullifier,
|
||||
identity_nullifier,
|
||||
identity_trapdoor,
|
||||
identity_path_elements,
|
||||
identity_path_index,
|
||||
fake_zero: bigInt(0),
|
||||
};
|
||||
|
||||
// So we can define inputs skeleton before
|
||||
|
||||
witness = circuit.calculateWitness(inputs);
|
||||
assert(circuit.checkWitness(witness));
|
||||
|
||||
|
||||
// ok? I assume key is correct
|
||||
//vk_proof = deserialize(fs.readFileSync("build/myCircuit.vk_proof", "utf8"));
|
||||
vk_proof = JSON.parse(fs.readFileSync("build/myCircuit.vk_proof", "utf8"));
|
||||
// XXX: original vs goth?
|
||||
// xxx vk_proof is a hing, whats up witness
|
||||
// unsringifybigints of vk proof loooks...weird tho. like a string.
|
||||
console.log("gen proof");
|
||||
// now it looks OK but smt wrong
|
||||
// compile time
|
||||
// loading
|
||||
let {proof, publicSignals} = zkSnark.groth.genProof(unstringifyBigInts(vk_proof), unstringifyBigInts(witness));
|
||||
// error TypeError: Cannot read property '5' of undefined
|
||||
// gyuess would be it doesn't work.
|
||||
|
||||
|
||||
// a.affine is not a function
|
||||
// https://github.com/iden3/snarkjs/issues/9 err I thought I did this already
|
||||
// zkSnark.groth.genProof(vk_proof, witness); fails
|
||||
//let {proof, publicSignals} = zkSnark.groth.genProof(vk_proof, witness);
|
||||
|
||||
// // 5. Verify proof
|
||||
// XXX dunno if good
|
||||
console.log("before vk verifier");
|
||||
const vk_verifier = JSON.parse(fs.readFileSync("build/myCircuit.vk_verifier", "utf8"));
|
||||
console.log("after vk verifier");
|
||||
|
||||
// if (zkSnark.groth.isValid(vk_verifier, proof, publicSignals)) {
|
||||
// wow works
|
||||
if (zkSnark.groth.isValid(unstringifyBigInts(vk_verifier), unstringifyBigInts(proof), unstringifyBigInts(publicSignals))) {
|
||||
console.log("The proof is valid");
|
||||
} else {
|
||||
console.log("The proof is not valid");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
//// 4. Generate proof
|
||||
// const input = {
|
||||
// "a": "3",
|
||||
// "b": "11"
|
||||
// }
|
||||
// const witness = circuit.calculateWitness(input);
|
||||
// const vk_proof = deserialize(fs.readFileSync("build/proving_key.json", "utf8"));
|
||||
// nice, progress
|
||||
|
||||
// const {proof, publicSignals} = zkSnark.groth.genProof(vk_proof, witness);
|
||||
//const w = circuit.calculateWitness(inputs);
|
||||
|
||||
// // 5. Verify proof
|
||||
// const vk_verifier = deserialize(fs.readFileSync("build/verification_key.json", "utf8"));
|
||||
//};
|
||||
|
||||
// if (zkSnark.groth.isValid(vk_verifier, proof, publicSignals)) {
|
||||
// console.log("The proof is valid");
|
||||
// } else {
|
||||
// console.log("The proof is not valid");
|
||||
// }
|
||||
//foo();
|
||||
|
|
Loading…
Reference in New Issue