research/zksnarks/semaphore/snark/semaphore-base.circom

183 lines
5.1 KiB
Plaintext

include "../node_modules/circomlib/circuits/pedersen.circom";
include "../node_modules/circomlib/circuits/mimcsponge.circom";
include "../node_modules/circomlib/circuits/bitify.circom";
include "../node_modules/circomlib/circuits/eddsamimcsponge.circom";
include "./blake2s/blake2s.circom";
template HashLeftRight(n_rounds) {
signal input left;
signal input right;
signal output hash;
component hasher = MiMCSponge(2, n_rounds, 1);
left ==> hasher.ins[0];
right ==> hasher.ins[1];
hasher.k <== 0;
hash <== hasher.outs[0];
}
template Selector() {
signal input input_elem;
signal input path_elem;
signal input path_index;
signal output left;
signal output right;
signal left_selector_1;
signal left_selector_2;
signal right_selector_1;
signal right_selector_2;
path_index * (1-path_index) === 0
left_selector_1 <== (1 - path_index)*input_elem;
left_selector_2 <== (path_index)*path_elem;
right_selector_1 <== (path_index)*input_elem;
right_selector_2 <== (1 - path_index)*path_elem;
left <== left_selector_1 + left_selector_2;
right <== right_selector_1 + right_selector_2;
}
template Semaphore(jubjub_field_size, n_levels, n_rounds) {
// BEGIN signals
signal input signal_hash;
signal input external_nullifier;
signal private input fake_zero;
fake_zero === 0;
// mimc vector commitment
signal private input identity_pk[2];
signal private input identity_nullifier;
signal private input identity_trapdoor;
signal private input identity_path_elements[n_levels];
signal private input identity_path_index[n_levels];
// signature on (external nullifier, signal_hash) with identity_pk
signal private input auth_sig_r[2];
signal private input auth_sig_s;
// get a prime subgroup element derived from identity_pk
component dbl1 = BabyDbl();
dbl1.x <== identity_pk[0];
dbl1.y <== identity_pk[1];
component dbl2 = BabyDbl();
dbl2.x <== dbl1.xout;
dbl2.y <== dbl1.yout;
component dbl3 = BabyDbl();
dbl3.x <== dbl2.xout;
dbl3.y <== dbl2.yout;
// mimc hash
signal output root;
signal output nullifiers_hash;
// END signals
component identity_nullifier_bits = Num2Bits(248);
identity_nullifier_bits.in <== identity_nullifier;
component identity_trapdoor_bits = Num2Bits(248);
identity_trapdoor_bits.in <== identity_trapdoor;
component identity_pk_0_bits = Num2Bits_strict();
identity_pk_0_bits.in <== dbl3.xout;
component identity_commitment = Pedersen(3*256);
// BEGIN identity commitment
for (var i = 0; i < 256; i++) {
if (i < 254) {
identity_commitment.in[i] <== identity_pk_0_bits.out[i];
} else {
identity_commitment.in[i] <== 0;
}
if (i < 248) {
identity_commitment.in[i + 256] <== identity_nullifier_bits.out[i];
identity_commitment.in[i + 2*256] <== identity_trapdoor_bits.out[i];
} else {
identity_commitment.in[i + 256] <== 0;
identity_commitment.in[i + 2*256] <== 0;
}
}
// END identity commitment
// BEGIN tree
component selectors[n_levels];
component hashers[n_levels];
for (var i = 0; i < n_levels; i++) {
selectors[i] = Selector();
hashers[i] = HashLeftRight(n_rounds);
identity_path_index[i] ==> selectors[i].path_index;
identity_path_elements[i] ==> selectors[i].path_elem;
selectors[i].left ==> hashers[i].left;
selectors[i].right ==> hashers[i].right;
}
identity_commitment.out[0] ==> selectors[0].input_elem;
for (var i = 1; i < n_levels; i++) {
hashers[i-1].hash ==> selectors[i].input_elem;
}
root <== hashers[n_levels - 1].hash;
// END tree
// BEGIN nullifiers
component external_nullifier_bits = Num2Bits(232);
external_nullifier_bits.in <== external_nullifier;
component nullifiers_hasher = Blake2s(512, 0);
for (var i = 0; i < 248; i++) {
nullifiers_hasher.in_bits[i] <== identity_nullifier_bits.out[i];
}
for (var i = 0; i < 232; i++) {
nullifiers_hasher.in_bits[248 + i] <== external_nullifier_bits.out[i];
}
for (var i = 0; i < n_levels; i++) {
nullifiers_hasher.in_bits[248 + 232 + i] <== identity_path_index[i];
}
for (var i = (248 + 232 + n_levels); i < 512; i++) {
nullifiers_hasher.in_bits[i] <== 0;
}
component nullifiers_hash_num = Bits2Num(253);
for (var i = 0; i < 253; i++) {
nullifiers_hash_num.in[i] <== nullifiers_hasher.out[i];
}
nullifiers_hash <== nullifiers_hash_num.out;
// END nullifiers
// BEGIN verify sig
component msg_hasher = MiMCSponge(2, n_rounds, 1);
msg_hasher.ins[0] <== external_nullifier;
msg_hasher.ins[1] <== signal_hash;
msg_hasher.k <== 0;
component sig_verifier = EdDSAMiMCSpongeVerifier();
(1 - fake_zero) ==> sig_verifier.enabled;
identity_pk[0] ==> sig_verifier.Ax;
identity_pk[1] ==> sig_verifier.Ay;
auth_sig_r[0] ==> sig_verifier.R8x;
auth_sig_r[1] ==> sig_verifier.R8y;
auth_sig_s ==> sig_verifier.S;
msg_hasher.outs[0] ==> sig_verifier.M;
// END verify sig
}