semaphore early wip

This commit is contained in:
Oskar Thoren
2019-10-30 17:53:50 +08:00
parent 6c0a41152d
commit fbc5c98a49
3 changed files with 1332 additions and 0 deletions

View File

@@ -4,4 +4,31 @@ Based on https://github.com/kobigurk/semaphore but only focusing on the core cir
See https://github.com/iden3/snarkjs for a quick start.
According to https://github.com/kobigurk/semaphore#zksnark-statement:
```
The statement assures that given public inputs:
signal_hash
external_nullifier
root
nullifiers_hash
and private inputs:
identity_pk
identity_nullifier
identity_trapdoor
identity_path_elements
identity_path_index
auth_sig_r
auth_sig_s
the following conditions hold:
The commitment of the identity structure (identity_pk, identity_nullifier, identity_trapdoor) exists in the identity tree with the root root, using the path (identity_path_elements, identity_path_index). This ensures that the user was added to the system at some point in the past.
nullifiers_hash is uniquely derived from external_nullifier, identity_nullifier and identity_path_index. This ensures a user cannot broadcast a signal with the same external_nullifier more than once.
The message (external_nullifier, signal_hash) is signed by the secret key corresponding to identity_pk, having the signature (auth_sig_r, auth_sig_s). This ensures that a state of the contract having a specific external_nullifier, ensuring no double-signaling.
```
So we need to setup these identity_* and auth_* inputs.

1234
zksnarks/semaphore/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,71 @@
var fs = require('fs');
const zkSnark = require('snarkjs');
// Utils
// Dealing with JSON BigInt serialization/deserialization
function stringifyReplacer(key, value) {
if (typeof value === 'bigint') {
return value.toString() + 'n';
} else {
return value;
}
}
function parseReviver(key, value) {
if (typeof value === 'string' && /^\d+n$/.test(value)) {
return BigInt(value.slice(0, -1));
}
return value;
}
function serialize(value) {
return JSON.stringify(value, stringifyReplacer);
}
function deserialize(json_str) {
return JSON.parse(json_str, parseReviver);
}
// Using Groth
// 1. Compile circuit with circom:
// circom snark/circuit.circom -o build/circuit.json
const circuitDef = deserialize(fs.readFileSync("build/circuit.json", "utf-8"));
const circuit = new zkSnark.Circuit(circuitDef);
// 2. Inspect circuit with e.g.:
// circuits.nConstraints
// 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");
console.log("Toxic waste:", setup.toxic); // Must be discarded.
}
// TODO: Conditionally run if file exists
// performSetup(circuit);
// XXX: Here at the moment, the inputs are wrong (obviously)
// Calculate witness? I know roughly: client/semaphore.js, construct all inputs and to the checkWitness etc. Has logic for proofs and so on.
// 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"));
const {proof, publicSignals} = zkSnark.groth.genProof(vk_proof, witness);
// 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");
}