arnaucube
arnaucube/grapevine-sonobePublic Self-hosted repository
grapevine-sonobe/circom/grapevine.circom
circom/grapevine.circomRaw
 1pragma circom 2.1.6;
 2
 3include "node_modules/circomlib/circuits/poseidon.circom";
 4include "node_modules/circomlib/circuits/mux1.circom";
 5include "node_modules/circomlib/circuits/comparators.circom";
 6include "node_modules/circomlib/circuits/gates.circom";
 7include "./templates/chaff.circom";
 8
 9template grapevine(num_felts) {  
10
11    // in_out schema
12    // 0: degrees of separation
13    // 1: secret hash from previous step
14    // 2: hash of username + secret hash from previous step
15    // 3: chaff
16
17    signal input ivc_input[4];
18    signal output ivc_output[4];
19
20    // private inputs
21    signal input phrase[num_felts]; // secret phrase, if first iteration
22    signal input usernames[2]; // prev username, current username
23    signal input auth_secrets[2]; // prev degree's user secret, current degree's user secret
24
25    // name inputs from step_in
26    signal degrees_of_separation <== ivc_input[0];
27    signal given_phrase_hash <== ivc_input[1];
28    signal given_degree_secret_hash <== ivc_input[2];
29    signal is_chaff_step <== ivc_input[3];
30
31    // determine whether degrees of separation from secret is zero
32    component is_degree_zero = IsZero();
33    is_degree_zero.in <== degrees_of_separation;
34
35    // compute poseidon hash of secret
36    // same as the word essentially
37    component phrase_hasher = Poseidon(num_felts);
38    phrase_hasher.inputs <== phrase;
39    
40    // mux between computed hash and previous iteration's hash to get phrase hash to use
41    // if degrees of separation = 0 use computed hash, else use hash from previous step
42    component phrase_mux = Mux1();
43    phrase_mux.c[0] <== given_phrase_hash;
44    phrase_mux.c[1] <== phrase_hasher.out;
45    phrase_mux.s <== is_degree_zero.out;
46
47    // compute hash of given degree secret
48    // H(H(preimage), username, auth_secret[0])
49    // where preimage is muxed depending on whether degree N is 1 or > 1
50    component degree_secret_hasher = Poseidon(3);
51    degree_secret_hasher.inputs[0] <== phrase_mux.out;
52    degree_secret_hasher.inputs[1] <== usernames[0];
53    degree_secret_hasher.inputs[2] <== auth_secrets[0];
54
55    // compare computed degree secret hash to prev degree secret hash
56    component degree_secret_hash_match = IsEqual();
57    degree_secret_hash_match.in[0] <== degree_secret_hasher.out;
58    degree_secret_hash_match.in[1] <== given_degree_secret_hash;
59
60    // create boolean that is true if either is true:
61    //  - given degree secret hash matches computed hash
62    //  - is a chaff step
63    component degree_secret_match_or_chaff = OR();
64    degree_secret_match_or_chaff.a <== degree_secret_hash_match.out;
65    degree_secret_match_or_chaff.b <== is_chaff_step;
66
67    // create boolean that is muxes according to:
68    //  - if degrees of separation = 0, always true (no check needed)
69    //  - if degree of separation > 0, return output of degree_secret_match_or_chaff
70    component degree_secret_satisfied_mux = Mux1();
71    degree_secret_satisfied_mux.c[0] <== degree_secret_match_or_chaff.out;
72    degree_secret_satisfied_mux.c[1] <== 1;
73    degree_secret_satisfied_mux.s <== is_degree_zero.out;
74
75    // constrain degree_secret_satisfied_mux to be true
76    degree_secret_satisfied_mux.out === 1;
77
78    // compute the next username hash
79    component next_degree_secret_hash = Poseidon(3);
80    next_degree_secret_hash.inputs[0] <== phrase_mux.out;
81    next_degree_secret_hash.inputs[1] <== usernames[1];
82    next_degree_secret_hash.inputs[2] <== auth_secrets[1];
83
84    // mux step_out signal according to whether or not this is a chaff step
85    component chaff_mux = ChaffMux();
86    chaff_mux.degrees_of_separation <== degrees_of_separation;
87    chaff_mux.given_phrase_hash <== given_phrase_hash;
88    chaff_mux.given_degree_secret_hash <== given_degree_secret_hash;
89    chaff_mux.is_chaff_step <== is_chaff_step;
90    chaff_mux.computed_phrase_hash <== phrase_mux.out;
91    chaff_mux.computed_degree_secret_hash <== next_degree_secret_hash.out;
92
93    // wire output signals
94    ivc_output <== chaff_mux.out;
95}
96
97component main { public [ivc_input] } = grapevine(6);