/ src / tests / update-poc.c
update-poc.c
  1  #include <stdio.h>
  2  #include <string.h>
  3  #include <stdint.h>
  4  #include "../dkg-vss.h"
  5  #include "../utils.h"
  6  #include "../mpmult.h"
  7  #include "../toprf.h"
  8  
  9  static uint8_t dkg_vss_verify_commitments(const uint8_t n,
 10                                            const uint8_t self,
 11                                            const uint8_t commitments[n][n][crypto_core_ristretto255_BYTES],
 12                                            const TOPRF_Share shares[n][2],
 13                                            uint8_t complaints[n]) {
 14    uint8_t complaints_len=0;
 15    for(uint8_t i=1;i<=n;i++) {
 16      if(i==self) continue;
 17  
 18      if(0!=dkg_vss_verify_commitment(commitments[i-1][self-1], shares[i-1])) {
 19        // complain about P_i
 20        fprintf(stderr, "\x1b[0;31mfailed to verify contribs of P_%d in stage 1\x1b[0m\n", i);
 21        complaints[complaints_len++]=i;
 22        //return 1;
 23      } else {
 24  #ifdef UNIT_TEST
 25        if(liboprf_debug) fprintf(stderr, "\x1b[0;32mP_%d stage 1 correct!\x1b[0m\n", i);
 26  #endif // UNIT_TEST
 27      }
 28    }
 29    return complaints_len;
 30  }
 31  
 32  int dkg_vss(const uint8_t n, const uint8_t t,
 33              TOPRF_Share final_shares[n][2],
 34              uint8_t commitments[n][crypto_core_ristretto255_BYTES]) {
 35    uint8_t dealer_commitments[n][n][crypto_core_ristretto255_BYTES];
 36    TOPRF_Share shares[n][n][2];
 37  
 38    for(int i=0;i<n;i++) {
 39      if(dkg_vss_share(n, t, NULL, dealer_commitments[i], shares[i], NULL)) {
 40        return 1;
 41      }
 42      //broadcast dealer_commitments
 43    }
 44  
 45    // each Pi sends s_ij, and s'_ij to Pj
 46    // basically we are transposing here the shares matrix above
 47    TOPRF_Share sent_shares[n][2];
 48  
 49    for(int i=0;i<n;i++) {
 50      for(int j=0;j<n;j++) {
 51        memcpy(&sent_shares[j][0], &shares[j][i][0], sizeof(TOPRF_Share));
 52        memcpy(&sent_shares[j][1], &shares[j][i][1], sizeof(TOPRF_Share));
 53      }
 54  
 55      uint8_t complaints[n];
 56      memset(complaints, 0, sizeof complaints);
 57      uint8_t complaints_len=dkg_vss_verify_commitments(n,i+1,dealer_commitments,sent_shares,complaints);
 58      if(complaints_len>0) {
 59        // todo accused dealer P_i publishes α_i, ρ_i such that A_i = 𝓗(α_i,ρ_i)
 60        // if dealer P_i fails, disqualify them.
 61        // otherwise the accuser sets their shares to α_i, ρ_i
 62        return 1;
 63      }
 64      // todo handle complaints, build qual set
 65      uint8_t qual[n+1];
 66      for(int i=0;i<n;i++) qual[i]=i+1; //everyone qualifies
 67      qual[n]=0;
 68      final_shares[i][0].index=i+1;
 69      final_shares[i][1].index=i+1;
 70      // finalize dkg
 71      if(0!=dkg_vss_finish(n,qual,sent_shares,i+1,final_shares[i], commitments[i])) return 1;
 72    }
 73    return 0;
 74  }
 75  
 76  int ft_mult(const uint8_t n, const uint8_t t,
 77              const TOPRF_Share alpha_shares[n][2], const uint8_t A_i[n][crypto_core_ristretto255_BYTES],
 78              const TOPRF_Share beta_shares[n][2], const uint8_t B_i[n][crypto_core_ristretto255_BYTES],
 79              TOPRF_Share r_shares[n][2]) {
 80    fprintf(stderr, "start ft_mult\n");
 81  
 82    if(t<2) return 1;
 83    const uint8_t dealers = (t-1)*2 + 1;
 84    if(n<dealers) return 1;
 85  
 86    // pubic inputs, for i:=0..n
 87    // 𝓐_i = 𝓗(α_i,ρ_i) = g^(α_i)*h^(ρ_i)
 88    // 𝓑_i = 𝓗(β_i,σ_i) = g^(β_i)*h^(σ_i)
 89  
 90    // we assume the VSPS property has been checked on the commitments
 91    if(0!=toprf_mpc_vsps_check(t-1, A_i)) return 1;
 92    if(0!=toprf_mpc_vsps_check(t-1, B_i)) return 1;
 93    fprintf(stderr, "[0] vsps(A_i) & vsps(B_i) ok\n");
 94  
 95    // step 1. Each player P_i shares λ_iα_iβ_i, using VSS
 96    uint8_t indexes[dealers];
 97    for(unsigned i=0;i<dealers;i++) indexes[i]=i+1;
 98  
 99    // λ_i is row 1 of inv VDM matrix
100    uint8_t lambdas[dealers][dealers][crypto_core_ristretto255_SCALARBYTES];
101    invertedVDMmatrix(dealers, indexes, lambdas);
102  
103    TOPRF_Share ci_shares[dealers][n][2];
104    uint8_t ci_commitments[dealers][n][crypto_core_ristretto255_BYTES];
105    uint8_t ci_commitments0[dealers][crypto_core_ristretto255_BYTES];
106    uint8_t ci_tau[dealers][crypto_core_ristretto255_SCALARBYTES];
107    for(unsigned i=0;i<dealers;i++) {
108      // c_ij = 𝑓_αβ,i(j), where 𝑓_αβ,i is a random polynomials of degree t, such that 𝑓_αβ,i(0) = λ_iα_iβ_i
109      // τ_ij = u_i(j), where u_i(j) is a random polynomials of degree t
110  
111      uint8_t lambda_ai_bi[crypto_scalarmult_ristretto255_SCALARBYTES];
112      crypto_core_ristretto255_scalar_mul(lambda_ai_bi, alpha_shares[i][0].value, beta_shares[i][0].value);
113      crypto_core_ristretto255_scalar_mul(lambda_ai_bi, lambda_ai_bi, lambdas[0][i]);
114      if(0!=dkg_vss_share(n,t,lambda_ai_bi, ci_commitments[i], ci_shares[i], ci_tau[i])) return 1;
115      // c_i0 for the sake of the ZK proof is g^λab * h^t
116      if(0!=dkg_vss_commit(lambda_ai_bi, ci_tau[i], ci_commitments0[i])) return 1;
117  
118      // send ci_shares[j] to P_j
119      // broadcast ci_commitments
120    }
121    fprintf(stderr, "[1] calculated shares and commitments of a*b\n");
122  
123    // step 2. P_i proves in zk that 𝓒_i0 is a commitment of the product λ_iα_iβ_i.
124    // As per Appendix F: ZK Proof for multiplication of committed values from GRR98
125    // step 2.1 all P_j generate a challenge share, and broadcast a commitment to it
126    uint8_t zk_challenge_shares[n][2][crypto_scalarmult_ristretto255_SCALARBYTES];
127    uint8_t zk_challenge_commitments[n][crypto_scalarmult_ristretto255_BYTES];
128    for(unsigned i=0;i<n;i++) {
129      crypto_core_ristretto255_scalar_random(zk_challenge_shares[i][0]);
130      crypto_core_ristretto255_scalar_random(zk_challenge_shares[i][1]);
131      if(0!=dkg_vss_commit(zk_challenge_shares[i][0], zk_challenge_shares[i][1], zk_challenge_commitments[i])) return 1;
132    }
133    // every P_j broadcasts their  zk_challenge_commitment[i]
134    fprintf(stderr, "[2.1] broadcast e_i commitment share\n");
135  
136    // step 2.2 P_i chooses d, s, x, s_1, s_2 ∈ Z_q. Sends to the verifier the messages:
137    //  M   = g^d * h^s,
138    //  M_1 = g^x * h^s_1,
139    //  M_2 = B^x * h^s_2
140    uint8_t d[dealers][crypto_scalarmult_ristretto255_SCALARBYTES];
141    uint8_t s[dealers][crypto_scalarmult_ristretto255_SCALARBYTES];
142    uint8_t x[dealers][crypto_scalarmult_ristretto255_SCALARBYTES];
143    uint8_t s_1[dealers][crypto_scalarmult_ristretto255_SCALARBYTES];
144    uint8_t s_2[dealers][crypto_scalarmult_ristretto255_SCALARBYTES];
145    uint8_t zk_commitments[dealers][3][crypto_scalarmult_ristretto255_SCALARBYTES];
146    for(unsigned i=0;i<dealers;i++) {
147      crypto_core_ristretto255_scalar_random(d[i]);
148      crypto_core_ristretto255_scalar_random(s[i]);
149      crypto_core_ristretto255_scalar_random(x[i]);
150      crypto_core_ristretto255_scalar_random(s_1[i]);
151      crypto_core_ristretto255_scalar_random(s_2[i]);
152      //  M   = g^d * h^s,
153      if(0!=dkg_vss_commit(d[i],s[i], zk_commitments[i][0])) return 1;
154      //  M_1 = g^x * h^s_1,
155      if(0!=dkg_vss_commit(x[i],s_1[i], zk_commitments[i][1])) return 1;
156      //  M_2 = B^x * h^s_2
157      uint8_t tmp[crypto_scalarmult_ristretto255_BYTES];
158      if(crypto_scalarmult_ristretto255(tmp, x[i], B_i[i])) return 1;
159      if(crypto_scalarmult_ristretto255(zk_commitments[i][2], s_2[i], H)) return 1;
160      crypto_core_ristretto255_add(zk_commitments[i][2], zk_commitments[i][2], tmp);
161    }
162    fprintf(stderr, "[2.2] broadcast M, M_1 and M_2\n");
163  
164    // step 2.3. P_j broadcasts  e_j,r_j
165    fprintf(stderr, "[2.3] broadcast e_j, r_j\n");
166  
167    // step 2.4. P_i verifies the commitment from 0. against e:
168    uint8_t y[dealers][crypto_scalarmult_ristretto255_SCALARBYTES];
169    uint8_t w[dealers][crypto_scalarmult_ristretto255_SCALARBYTES];
170    uint8_t z[dealers][crypto_scalarmult_ristretto255_SCALARBYTES];
171    uint8_t w_1[dealers][crypto_scalarmult_ristretto255_SCALARBYTES];
172    uint8_t w_2[dealers][crypto_scalarmult_ristretto255_SCALARBYTES];
173    for(unsigned i=0;i<dealers;i++) {
174      // P_i verifies commitments for e_j,r_j
175      // P_i computes e'_i:
176      //  e'_i = Σ e_j
177      //       j!=i
178      uint8_t e_i[crypto_scalarmult_ristretto255_SCALARBYTES]={0};
179      uint8_t zk_challenge_commitment[crypto_scalarmult_ristretto255_BYTES];
180      for(unsigned j=0;j<n;j++) {
181        if(j==i) continue;
182        if(0!=dkg_vss_commit(zk_challenge_shares[j][0], zk_challenge_shares[j][1], zk_challenge_commitment)) return 1;
183        if(memcmp(zk_challenge_commitment, zk_challenge_commitments[j], crypto_scalarmult_ristretto255_BYTES)!=0) return 1;
184  
185        crypto_core_ristretto255_scalar_add(e_i, e_i, zk_challenge_shares[j][0]);
186      }
187  
188      // P_i replies with the following values:
189      // y   = d + e'_iβ,
190      crypto_core_ristretto255_scalar_mul(y[i], e_i, beta_shares[i][0].value);
191      crypto_core_ristretto255_scalar_add(y[i], y[i], d[i]);
192      // w   = s + e'_iσ
193      crypto_core_ristretto255_scalar_mul(w[i], e_i, beta_shares[i][1].value);
194      crypto_core_ristretto255_scalar_add(w[i], w[i], s[i]);
195      // z   = x + e'_iα
196      crypto_core_ristretto255_scalar_mul(z[i], e_i, alpha_shares[i][0].value);
197      crypto_core_ristretto255_scalar_mul(z[i], z[i], lambdas[0][i]);
198      crypto_core_ristretto255_scalar_add(z[i], z[i], x[i]);
199      // w_1 = s_1 + e'_iρ
200      crypto_core_ristretto255_scalar_mul(w_1[i], e_i, alpha_shares[i][1].value);
201      crypto_core_ristretto255_scalar_mul(w_1[i], w_1[i], lambdas[0][i]);
202      crypto_core_ristretto255_scalar_add(w_1[i], w_1[i], s_1[i]);
203      // w_2 = s_2 + e'_i(τ - σα)
204      crypto_core_ristretto255_scalar_mul(w_2[i], beta_shares[i][1].value, alpha_shares[i][0].value);
205      crypto_core_ristretto255_scalar_mul(w_2[i], w_2[i], lambdas[0][i]);
206      crypto_core_ristretto255_scalar_sub(w_2[i], ci_tau[i], w_2[i]);
207      crypto_core_ristretto255_scalar_mul(w_2[i], e_i, w_2[i]);
208      crypto_core_ristretto255_scalar_add(w_2[i], w_2[i], s_2[i]);
209    }
210    fprintf(stderr, "[2.4] calculate proof of a*b\n");
211  
212    // step 2.5. P_j checks zk proof
213    for(unsigned j=0;j<n;j++) {
214      // for each P_i zk proof
215      for(unsigned i=0;i<dealers;i++) {
216        //  P_j computes e'_i:
217        //    e'_i = Σ e_j
218        //         j!=i
219        uint8_t e_i[crypto_scalarmult_ristretto255_SCALARBYTES]={0};
220        for(unsigned k=0;k<n;k++) {
221          if(k==i) continue;
222          crypto_core_ristretto255_scalar_add(e_i, e_i, zk_challenge_shares[k][0]);
223        }
224  
225        uint8_t v0[crypto_scalarmult_ristretto255_BYTES];
226        uint8_t v1[crypto_scalarmult_ristretto255_BYTES];
227        //   g^y * h^w   == M * B^e'_i
228        if(0!=dkg_vss_commit(y[i], w[i], v0)) return 1;
229  
230        if(crypto_scalarmult_ristretto255(v1, e_i, B_i[i])) return 1;
231        crypto_core_ristretto255_add(v1, zk_commitments[i][0], v1);
232        if(memcmp(v1, v0, crypto_scalarmult_ristretto255_BYTES)!=0) return 1;
233  
234        //   g^z * h^w_1 == M_1 * A^e'_i
235        if(0!=dkg_vss_commit(z[i], w_1[i], v0)) return 1;
236  
237        if(crypto_scalarmult_ristretto255(v1, e_i, A_i[i])) return 1;
238        if(crypto_scalarmult_ristretto255(v1, lambdas[0][i], v1)) return 1;
239        crypto_core_ristretto255_add(v1, zk_commitments[i][1], v1);
240        if(memcmp(v1, v0, crypto_scalarmult_ristretto255_BYTES)!=0) return 1;
241  
242        //   B^z * h^w_2 == M_2 * C^e'_i
243        if(crypto_scalarmult_ristretto255(v0, z[i], B_i[i])) return 1;
244        // we abuse v1 as a temp storage, v1 = h^w_2
245        if(crypto_scalarmult_ristretto255(v1, w_2[i], H)) return 1;
246        crypto_core_ristretto255_add(v0, v0, v1);
247  
248        if(crypto_scalarmult_ristretto255(v1, e_i, ci_commitments0[i])) return 1;
249        crypto_core_ristretto255_add(v1, zk_commitments[i][2], v1);
250        if(memcmp(v1, v0, crypto_scalarmult_ristretto255_BYTES)!=0) return 1;
251      }
252    }
253    fprintf(stderr, "[2.5] verified proof of a*b\n");
254  
255    uint8_t C_i[n][crypto_scalarmult_ristretto255_BYTES];
256    for(unsigned i=0;i<n;i++) {
257      // step 3. P_i computes:
258      //      2t+1
259      //  γ_i = Σ c_ji
260      //       j=1
261      //  which is a share of γ = αβ, via random polynomial of degree t and
262      //      2t+1
263      //  τ_i = Σ τ_ji
264      //       j=1
265      memcpy(&r_shares[i][0], &ci_shares[0][i][0], TOPRF_Share_BYTES);
266      memcpy(&r_shares[i][1], &ci_shares[0][i][1], TOPRF_Share_BYTES);
267      for(unsigned j=1;j<dealers;j++) {
268        crypto_core_ristretto255_scalar_add(r_shares[i][0].value, r_shares[i][0].value, ci_shares[j][i][0].value);
269        crypto_core_ristretto255_scalar_add(r_shares[i][1].value, r_shares[i][1].value, ci_shares[j][i][1].value);
270      }
271  
272      // step 4. P_i computes and broadcasts
273      //    𝓒_i = 𝓗(γ_i, τ_i)
274      //        = g^(γ_i)*h^(τ_i)
275      //
276      //        2t+1
277      //        = Π 𝓒_ji
278      //         j=1
279      if(0!=dkg_vss_commit(r_shares[i][0].value, r_shares[i][1].value, C_i[i])) return 1;
280      // use this below to calculate all commitments for the other peers
281      uint8_t Cx_i[crypto_scalarmult_ristretto255_BYTES];
282      memcpy(Cx_i,ci_commitments[0][i], crypto_scalarmult_ristretto255_BYTES);
283      for(unsigned j=1;j<dealers;j++) {
284        crypto_core_ristretto255_add(Cx_i, Cx_i, ci_commitments[j][i]);
285      }
286      if(memcmp(Cx_i, C_i[i], sizeof Cx_i) != 0) return 1;
287    }
288    fprintf(stderr, "[3&4] calculated final shares of a*b and their commitments\n");
289  
290    for(unsigned i=0;i<n;i++) {
291      // step 5. players run a VSPS Check on 𝓒_i, i:=1..n,
292      // if the test succeeds:
293      // Secret information of P_i: share γ_i
294      // Public information: 𝓒_i, for i:=1..n
295      // protocol terminates successfully
296  
297      // TODO remove me, we are forcing step 6 here for development!
298      if(0==toprf_mpc_vsps_check(t-1, C_i)) {
299        fprintf(stderr, "vsps checks out for C_i\n");
300        //return 0;
301      }
302  
303      // If the test fails STOP and run MULT from step 2.
304    }
305    fprintf(stderr, "[5] failed vsps check for C_i\n");
306  
307    // step 6. only if 5. fails, as per Mult algorithm from fig. 3. step 2
308    // Players run a VSPS Check on P_i's sharing. If a sharing fails the test
309    // then expose the secret through the VSS reconstruction.
310    for(unsigned i=0;i<n;i++) {
311      // each P_i VSPS checks P_j (i!=j) sharing
312      for(unsigned j=0;j<dealers;j++) {
313        if(j==i) continue;
314        if(0!=toprf_mpc_vsps_check(t-1, ci_commitments[j])) {
315          // expose the secret of P_j through vss reconstruction
316          fprintf(stderr, "vsps for peer %d failed\n", j);
317        }
318      }
319    }
320    fprintf(stderr, "[6] VSPS check on P_i sharing\n");
321  
322    for(unsigned i=0;i<n;i++) { // todo possibly needs adjustment due to usage of reconstructed values.
323      // step 7. P_i computes:
324      //      2t+1
325      //  γ_i = Σ c_ji
326      //       j=1
327      //  which is a share of γ = αβ, via random polynomial of degree t and
328      //      2t+1
329      //  τ_i = Σ τ_ji
330      //       j=1
331      memcpy(&r_shares[i][0], &ci_shares[0][i][0], TOPRF_Share_BYTES);
332      memcpy(&r_shares[i][1], &ci_shares[0][i][1], TOPRF_Share_BYTES);
333      for(unsigned j=1;j<dealers;j++) {
334        crypto_core_ristretto255_scalar_add(r_shares[i][0].value, r_shares[i][0].value, ci_shares[j][i][0].value);
335        crypto_core_ristretto255_scalar_add(r_shares[i][1].value, r_shares[i][1].value, ci_shares[j][i][1].value);
336      }
337  
338      // step 8. P_i computes and broadcasts
339      //    𝓒_i = 𝓗(γ_i, τ_i)
340      //        = g^(γ_i)*h^(τ_i)
341      //
342      //        2t+1
343      //        = Π 𝓒_ji
344      //         j=1
345      if(0!=dkg_vss_commit(r_shares[i][0].value, r_shares[i][1].value, C_i[i])) return 1;
346      // use this below to calculate all commitments for the other peers
347      uint8_t Cx_i[crypto_scalarmult_ristretto255_BYTES];
348      memcpy(Cx_i,ci_commitments[0][i], crypto_scalarmult_ristretto255_BYTES);
349      for(unsigned j=1;j<dealers;j++) {
350        crypto_core_ristretto255_add(Cx_i, Cx_i, ci_commitments[j][i]);
351      }
352      if(memcmp(Cx_i, C_i[i], sizeof Cx_i) != 0) return 1;
353    }
354    fprintf(stderr, "[7&8] calculated final shares of a*b and their commitments\n");
355  
356    return 0;
357  }
358  
359  int test_mul() {
360    liboprf_log_file = stderr;
361    liboprf_debug = 0;
362  
363    uint8_t n=5, t=2;
364    TOPRF_Share kc_shares[n][2];
365    uint8_t kc_commitments[n][crypto_core_ristretto255_BYTES];
366    // generate kc, the original old key, we are gonna update
367    if(0!=dkg_vss(n,t,kc_shares, kc_commitments)) return 1;
368  
369    uint8_t kc[crypto_scalarmult_ristretto255_SCALARBYTES];
370    dkg_vss_reconstruct(t, 0, n, kc_shares, kc_commitments, kc, NULL);
371    liboprf_debug=1; dump(kc, sizeof kc, "kc ");liboprf_debug=0;
372  
373    // step 2. generate ρ
374    TOPRF_Share p_shares[n][2];
375    uint8_t p_commitments[n][crypto_core_ristretto255_BYTES];
376    // generate kc, the original old key, we are gonna update
377    if(0!=dkg_vss(n,t,p_shares, p_commitments)) return 1;
378  
379    uint8_t p[crypto_scalarmult_ristretto255_SCALARBYTES];
380    dkg_vss_reconstruct(t, 0, n, p_shares, p_commitments, p, NULL);
381    liboprf_debug=1; dump(p, sizeof p, "p  ");liboprf_debug=0;
382  
383    // 3. execute the FT-Mult protocol, to calculate FT-Mult(kc, ρ), generating sharings of r.
384    TOPRF_Share r_shares[n][2];
385    if(0!=ft_mult(n, t, kc_shares, kc_commitments, p_shares, p_commitments, r_shares)) return 1;
386  
387    uint8_t r[crypto_scalarmult_ristretto255_SCALARBYTES];
388    dkg_vss_reconstruct(t, 0, n, r_shares, NULL, r, NULL);
389    liboprf_debug=1;dump(r, sizeof r, "r  ");liboprf_debug=0;
390  
391    uint8_t tmp[crypto_scalarmult_ristretto255_SCALARBYTES];
392    crypto_core_ristretto255_scalar_mul(tmp, p, kc);
393    liboprf_debug=1;dump(tmp, sizeof tmp, "pkc");liboprf_debug=0;
394  
395    fprintf(stderr, "\e[0;32mtest_mul checks out!\e[0m\n");
396    return 0;
397  }
398  
399  int main(void) {
400    if(0!=test_mul()) return 1;
401  
402    liboprf_log_file = stderr;
403    liboprf_debug = 0;
404  
405    uint8_t n=5, t=2;
406    TOPRF_Share kc_shares[n][2];
407    uint8_t kc_commitments[n][crypto_core_ristretto255_BYTES];
408    // generate kc, the original old key, we are gonna update
409    if(0!=dkg_vss(n,t,kc_shares, kc_commitments)) return 1;
410    uint8_t kc[crypto_scalarmult_ristretto255_SCALARBYTES];
411    uint8_t kc1[crypto_scalarmult_ristretto255_SCALARBYTES];
412    uint8_t p[crypto_scalarmult_ristretto255_SCALARBYTES];
413    dkg_vss_reconstruct(t, 0, n, kc_shares, kc_commitments, kc, NULL);
414    liboprf_debug=1; dump(kc, sizeof kc, "kc ");liboprf_debug=0;
415  
416    // precondition 2
417  
418    // long-term signing keys known by everyone
419    uint8_t lt_pks[n+1][crypto_sign_PUBLICKEYBYTES];
420    // only known by corresponding peer
421    uint8_t lt_sks[n+1][crypto_sign_SECRETKEYBYTES];
422    for(uint8_t i=0;i<n+1;i++) {
423        crypto_sign_keypair(lt_pks[i], lt_sks[i]);
424    }
425  
426    // precondition 3
427    if(n<2*t+1) return 3;
428  
429    // step 1. generate kc'
430    TOPRF_Share kc1_shares[n][2];
431    uint8_t kc1_commitments[n][crypto_core_ristretto255_BYTES];
432    if(0!=dkg_vss(n,t,kc1_shares, kc1_commitments)) return 1;
433    dkg_vss_reconstruct(t, 0, n, kc1_shares, kc1_commitments, kc1, NULL);
434    liboprf_debug=1; dump(kc1, sizeof kc1, "kc1");liboprf_debug=0;
435  
436    // step 2. generate ρ
437    TOPRF_Share p_shares[n][2];
438    uint8_t p_commitments[n][crypto_core_ristretto255_BYTES];
439    if(0!=dkg_vss(n,t,p_shares, p_commitments)) return 1;
440    dkg_vss_reconstruct(t, 0, n, p_shares, p_commitments, p, NULL);
441    liboprf_debug=1; dump(p, sizeof p, "p  ");liboprf_debug=0;
442  
443    // 3. execute the FT-Mult protocol, to calculate FT-Mult(kc, ρ), generating sharings of r.
444    TOPRF_Share r_shares[n][2];
445    if(0!=ft_mult(n, t, kc_shares, kc_commitments, p_shares, p_commitments, r_shares)) return 1;
446  
447    // 4. execute the FT-Mult protocol, to calculate FT-Mult(kc`, ρ), generating sharings of r'.
448    TOPRF_Share r1_shares[n][2];
449    if(0!=ft_mult(n, t, kc1_shares, kc1_commitments, p_shares, p_commitments, r1_shares)) return 1;
450  
451    // 5. parties send their r and r` shares to the STP
452  
453    // 6. STP reconstructs r = ρ·kc and r′ = ρ·kc′ and computes ∆= r/r′.
454  
455    uint8_t tmp[crypto_scalarmult_ristretto255_SCALARBYTES];
456    crypto_core_ristretto255_scalar_mul(tmp, p, kc);
457    liboprf_debug=1;dump(tmp, sizeof tmp, "pkc");liboprf_debug=0;
458    crypto_core_ristretto255_scalar_mul(tmp, p, kc1);
459    liboprf_debug=1;dump(tmp, sizeof tmp, "pkc");liboprf_debug=0;
460  
461    uint8_t r[crypto_scalarmult_ristretto255_SCALARBYTES];
462    uint8_t r1[crypto_scalarmult_ristretto255_SCALARBYTES];
463    dkg_vss_reconstruct(t, 0, n, r_shares, NULL, r, NULL);
464    liboprf_debug=1;dump(r, sizeof r, "r  ");liboprf_debug=0;
465    dkg_vss_reconstruct(t, 0, n, r1_shares, NULL, r1, NULL);
466    liboprf_debug=1;dump(r1, sizeof r1, "r1 ");liboprf_debug=0;
467    uint8_t r1inv[crypto_scalarmult_ristretto255_SCALARBYTES];
468    if(0!=crypto_core_ristretto255_scalar_invert(r1inv, r1)) return 1;
469    uint8_t delta[crypto_scalarmult_ristretto255_SCALARBYTES];
470    crypto_core_ristretto255_scalar_mul(delta, r, r1inv);
471  
472    // check if delta is equal kc/kc'
473    dkg_vss_reconstruct(t, 0, n, kc_shares, kc_commitments, tmp, NULL);
474    if(memcmp(tmp,kc,sizeof tmp)!=0) {
475      liboprf_debug=1; dump(tmp, sizeof tmp, "kc ");liboprf_debug=0;
476      return 1;
477    }
478    dkg_vss_reconstruct(t, 0, n, kc1_shares, kc1_commitments, tmp, NULL);
479    if(memcmp(tmp,kc1,sizeof tmp)!=0) {
480      liboprf_debug=1; dump(kc1, sizeof kc1, "kc1");liboprf_debug=0;
481      return 1;
482    }
483    uint8_t kc1inv[crypto_scalarmult_ristretto255_SCALARBYTES];
484    if(0!=crypto_core_ristretto255_scalar_invert(kc1inv, kc1)) return 1;
485    uint8_t deltakc[crypto_scalarmult_ristretto255_SCALARBYTES];
486    crypto_core_ristretto255_scalar_mul(deltakc, kc, kc1inv);
487    if(memcmp(delta, deltakc, sizeof delta)!=0) {
488      liboprf_debug=1;
489      dump(delta,  sizeof delta, "delta  ");
490      dump(deltakc,sizeof delta, "deltakc");
491    } else {
492      liboprf_debug=1;dump(delta, sizeof delta, "delta");liboprf_debug=0;
493    }
494  
495    // 7. parties delete their r and r` shares and replace their kc share with their kc` share.
496  
497    fprintf(stderr, "\e[0;32meverything correct!\e[0m\n");
498    return 0;
499  }