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    // external inputs at each folding step
 21    signal input external_inputs[num_felts+2+2];
 22    signal phrase[num_felts]; // secret phrase, if first iteration
 23    for (var i=0; i<num_felts; i++) {
 24        phrase[i] <== external_inputs[i];
 25    }
 26    signal usernames[2]; // prev username, current username
 27    usernames[0]<==external_inputs[num_felts];
 28    usernames[1]<==external_inputs[num_felts+1];
 29    signal auth_secrets[2]; // prev degree's user secret, current degree's user secret
 30    auth_secrets[0]<==external_inputs[num_felts+2];
 31    auth_secrets[1]<==external_inputs[num_felts+3];
 32
 33    // name inputs from step_in
 34    signal degrees_of_separation <== ivc_input[0];
 35    signal given_phrase_hash <== ivc_input[1];
 36    signal given_degree_secret_hash <== ivc_input[2];
 37    signal is_chaff_step <== ivc_input[3];
 38
 39    // determine whether degrees of separation from secret is zero
 40    component is_degree_zero = IsZero();
 41    is_degree_zero.in <== degrees_of_separation;
 42
 43    // compute poseidon hash of secret
 44    // same as the word essentially
 45    component phrase_hasher = Poseidon(num_felts);
 46    phrase_hasher.inputs <== phrase;
 47    
 48    // mux between computed hash and previous iteration's hash to get phrase hash to use
 49    // if degrees of separation = 0 use computed hash, else use hash from previous step
 50    component phrase_mux = Mux1();
 51    phrase_mux.c[0] <== given_phrase_hash;
 52    phrase_mux.c[1] <== phrase_hasher.out;
 53    phrase_mux.s <== is_degree_zero.out;
 54
 55    // compute hash of given degree secret
 56    // H(H(preimage), username, auth_secret[0])
 57    // where preimage is muxed depending on whether degree N is 1 or > 1
 58    component degree_secret_hasher = Poseidon(3);
 59    degree_secret_hasher.inputs[0] <== phrase_mux.out;
 60    degree_secret_hasher.inputs[1] <== usernames[0];
 61    degree_secret_hasher.inputs[2] <== auth_secrets[0];
 62
 63    // compare computed degree secret hash to prev degree secret hash
 64    component degree_secret_hash_match = IsEqual();
 65    degree_secret_hash_match.in[0] <== degree_secret_hasher.out;
 66    degree_secret_hash_match.in[1] <== given_degree_secret_hash;
 67
 68    // create boolean that is true if either is true:
 69    //  - given degree secret hash matches computed hash
 70    //  - is a chaff step
 71    component degree_secret_match_or_chaff = OR();
 72    degree_secret_match_or_chaff.a <== degree_secret_hash_match.out;
 73    degree_secret_match_or_chaff.b <== is_chaff_step;
 74
 75    // create boolean that is muxes according to:
 76    //  - if degrees of separation = 0, always true (no check needed)
 77    //  - if degree of separation > 0, return output of degree_secret_match_or_chaff
 78    component degree_secret_satisfied_mux = Mux1();
 79    degree_secret_satisfied_mux.c[0] <== degree_secret_match_or_chaff.out;
 80    degree_secret_satisfied_mux.c[1] <== 1;
 81    degree_secret_satisfied_mux.s <== is_degree_zero.out;
 82
 83    // constrain degree_secret_satisfied_mux to be true
 84    degree_secret_satisfied_mux.out === 1;
 85
 86    // compute the next username hash
 87    component next_degree_secret_hash = Poseidon(3);
 88    next_degree_secret_hash.inputs[0] <== phrase_mux.out;
 89    next_degree_secret_hash.inputs[1] <== usernames[1];
 90    next_degree_secret_hash.inputs[2] <== auth_secrets[1];
 91
 92    // mux step_out signal according to whether or not this is a chaff step
 93    component chaff_mux = ChaffMux();
 94    chaff_mux.degrees_of_separation <== degrees_of_separation;
 95    chaff_mux.given_phrase_hash <== given_phrase_hash;
 96    chaff_mux.given_degree_secret_hash <== given_degree_secret_hash;
 97    chaff_mux.is_chaff_step <== is_chaff_step;
 98    chaff_mux.computed_phrase_hash <== phrase_mux.out;
 99    chaff_mux.computed_degree_secret_hash <== next_degree_secret_hash.out;
100
101    // wire output signals
102    ivc_output <== chaff_mux.out;
103}
104
105component main { public [ivc_input] } = grapevine(6);