mirror of
https://github.com/vacp2p/research.git
synced 2025-02-24 12:18:06 +00:00
183 lines
5.1 KiB
Plaintext
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
|
|
}
|