More API function tests...
[oweals/gnunet.git] / src / scalarproduct / gnunet-service-scalarproduct_alice.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2013, 2014, 2017 GNUnet e.V.
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19  */
20 /**
21  * @file scalarproduct/gnunet-service-scalarproduct_alice.c
22  * @brief scalarproduct service implementation
23  * @author Christian M. Fuchs
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include <limits.h>
28 #include <gcrypt.h>
29 #include "gnunet_util_lib.h"
30 #include "gnunet_core_service.h"
31 #include "gnunet_cadet_service.h"
32 #include "gnunet_applications.h"
33 #include "gnunet_protocols.h"
34 #include "gnunet_scalarproduct_service.h"
35 #include "gnunet_set_service.h"
36 #include "scalarproduct.h"
37 #include "gnunet-service-scalarproduct.h"
38
39 #define LOG(kind,...) GNUNET_log_from (kind, "scalarproduct-alice", __VA_ARGS__)
40
41 /**
42  * An encrypted element key-value pair.
43  */
44 struct MpiElement
45 {
46   /**
47    * Key used to identify matching pairs of values to multiply.
48    * Points into an existing data structure, to avoid copying
49    * and doubling memory use.
50    */
51   const struct GNUNET_HashCode *key;
52
53   /**
54    * Value represented (a).
55    */
56   gcry_mpi_t value;
57 };
58
59
60 /**
61  * A scalarproduct session which tracks
62  * a request form the client to our final response.
63  */
64 struct AliceServiceSession
65 {
66
67   /**
68    * (hopefully) unique transaction ID
69    */
70   struct GNUNET_HashCode session_id;
71
72   /**
73    * Alice or Bob's peerID
74    */
75   struct GNUNET_PeerIdentity peer;
76
77   /**
78    * The client this request is related to.
79    */
80   struct GNUNET_SERVICE_Client *client;
81
82   /**
83    * The message queue for the client.
84    */
85   struct GNUNET_MQ_Handle *client_mq;
86
87   /**
88    * The message queue for CADET.
89    */
90   struct GNUNET_MQ_Handle *cadet_mq;
91
92   /**
93    * all non-0-value'd elements transmitted to us.
94    * Values are of type `struct GNUNET_SCALARPRODUCT_Element *`
95    */
96   struct GNUNET_CONTAINER_MultiHashMap *intersected_elements;
97
98   /**
99    * Set of elements for which will conduction an intersection.
100    * the resulting elements are then used for computing the scalar product.
101    */
102   struct GNUNET_SET_Handle *intersection_set;
103
104   /**
105    * Set of elements for which will conduction an intersection.
106    * the resulting elements are then used for computing the scalar product.
107    */
108   struct GNUNET_SET_OperationHandle *intersection_op;
109
110   /**
111    * Handle to Alice's Intersection operation listening for Bob
112    */
113   struct GNUNET_SET_ListenHandle *intersection_listen;
114
115   /**
116    * channel-handle associated with our cadet handle
117    */
118   struct GNUNET_CADET_Channel *channel;
119
120   /**
121    * a(Alice), sorted array by key of length @e used_element_count.
122    */
123   struct MpiElement *sorted_elements;
124
125   /**
126    * Bob's permutation p of R
127    */
128   struct GNUNET_CRYPTO_PaillierCiphertext *r;
129
130   /**
131    * Bob's permutation q of R
132    */
133   struct GNUNET_CRYPTO_PaillierCiphertext *r_prime;
134
135   /**
136    * Bob's "s"
137    */
138   struct GNUNET_CRYPTO_PaillierCiphertext s;
139
140   /**
141    * Bob's "s'"
142    */
143   struct GNUNET_CRYPTO_PaillierCiphertext s_prime;
144
145   /**
146    * The computed scalar
147    */
148   gcry_mpi_t product;
149
150   /**
151    * How many elements we were supplied with from the client (total
152    * count before intersection).
153    */
154   uint32_t total;
155
156   /**
157    * How many elements actually are used for the scalar product.
158    * Size of the arrays in @e r and @e r_prime.  Sometimes also
159    * reset to 0 and used as a counter!
160    */
161   uint32_t used_element_count;
162
163   /**
164    * Already transferred elements from client to us.
165    * Less or equal than @e total.
166    */
167   uint32_t client_received_element_count;
168
169   /**
170    * Already transferred elements from Bob to us.
171    * Less or equal than @e total.
172    */
173   uint32_t cadet_received_element_count;
174
175   /**
176    * State of this session.   In
177    * #GNUNET_SCALARPRODUCT_STATUS_ACTIVE while operation is
178    * ongoing, afterwards in #GNUNET_SCALARPRODUCT_STATUS_SUCCESS or
179    * #GNUNET_SCALARPRODUCT_STATUS_FAILURE.
180    */
181   enum GNUNET_SCALARPRODUCT_ResponseStatus status;
182
183   /**
184    * Flag to prevent recursive calls to #destroy_service_session() from
185    * doing harm.
186    */
187   int in_destroy;
188
189 };
190
191
192 /**
193  * GNUnet configuration handle
194  */
195 static const struct GNUNET_CONFIGURATION_Handle *cfg;
196
197 /**
198  * Service's own public key
199  */
200 static struct GNUNET_CRYPTO_PaillierPublicKey my_pubkey;
201
202 /**
203  * Service's own private key
204  */
205 static struct GNUNET_CRYPTO_PaillierPrivateKey my_privkey;
206
207 /**
208  * Service's offset for values that could possibly be negative but are plaintext for encryption.
209  */
210 static gcry_mpi_t my_offset;
211
212 /**
213  * Handle to the CADET service.
214  */
215 static struct GNUNET_CADET_Handle *my_cadet;
216
217
218 /**
219  * Iterator called to free elements.
220  *
221  * @param cls the `struct AliceServiceSession *` (unused)
222  * @param key the key (unused)
223  * @param value value to free
224  * @return #GNUNET_OK (continue to iterate)
225  */
226 static int
227 free_element_cb (void *cls,
228                  const struct GNUNET_HashCode *key,
229                  void *value)
230 {
231   struct GNUNET_SCALARPRODUCT_Element *e = value;
232
233   GNUNET_free (e);
234   return GNUNET_OK;
235 }
236
237
238 /**
239  * Destroy session state, we are done with it.
240  *
241  * @param s the session to free elements from
242  */
243 static void
244 destroy_service_session (struct AliceServiceSession *s)
245 {
246   unsigned int i;
247
248   if (GNUNET_YES == s->in_destroy)
249     return;
250   s->in_destroy = GNUNET_YES;
251   if (NULL != s->client)
252   {
253     struct GNUNET_SERVICE_Client *c = s->client;
254
255     s->client = NULL;
256     GNUNET_SERVICE_client_drop (c);
257   }
258   if (NULL != s->channel)
259   {
260     GNUNET_CADET_channel_destroy (s->channel);
261     s->channel = NULL;
262   }
263   if (NULL != s->intersected_elements)
264   {
265     GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
266                                            &free_element_cb,
267                                            s);
268     GNUNET_CONTAINER_multihashmap_destroy (s->intersected_elements);
269     s->intersected_elements = NULL;
270   }
271   if (NULL != s->intersection_listen)
272   {
273     GNUNET_SET_listen_cancel (s->intersection_listen);
274     s->intersection_listen = NULL;
275   }
276   if (NULL != s->intersection_op)
277   {
278     GNUNET_SET_operation_cancel (s->intersection_op);
279     s->intersection_op = NULL;
280   }
281   if (NULL != s->intersection_set)
282   {
283     GNUNET_SET_destroy (s->intersection_set);
284     s->intersection_set = NULL;
285   }
286   if (NULL != s->sorted_elements)
287   {
288     for (i=0;i<s->used_element_count;i++)
289       gcry_mpi_release (s->sorted_elements[i].value);
290     GNUNET_free (s->sorted_elements);
291     s->sorted_elements = NULL;
292   }
293   if (NULL != s->r)
294   {
295     GNUNET_free (s->r);
296     s->r = NULL;
297   }
298   if (NULL != s->r_prime)
299   {
300     GNUNET_free (s->r_prime);
301     s->r_prime = NULL;
302   }
303   if (NULL != s->product)
304   {
305     gcry_mpi_release (s->product);
306     s->product = NULL;
307   }
308   GNUNET_free (s);
309 }
310
311
312 /**
313  * Notify the client that the session has failed.  A message gets sent
314  * to Alice's client if we encountered any error.
315  *
316  * @param session the associated client session to fail or succeed
317  */
318 static void
319 prepare_client_end_notification (struct AliceServiceSession *session)
320 {
321   struct ClientResponseMessage *msg;
322   struct GNUNET_MQ_Envelope *e;
323
324   if (NULL == session->client_mq)
325     return; /* no client left to be notified */
326   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
327               "Sending session-end notification with status %d to client for session %s\n",
328               session->status,
329               GNUNET_h2s (&session->session_id));
330   e = GNUNET_MQ_msg (msg,
331                      GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT);
332   msg->product_length = htonl (0);
333   msg->status = htonl (session->status);
334   GNUNET_MQ_send (session->client_mq,
335                   e);
336 }
337
338
339 /**
340  * Prepare the final (positive) response we will send to Alice's
341  * client.
342  *
343  * @param s the session associated with our client.
344  */
345 static void
346 transmit_client_response (struct AliceServiceSession *s)
347 {
348   struct ClientResponseMessage *msg;
349   struct GNUNET_MQ_Envelope *e;
350   unsigned char *product_exported = NULL;
351   size_t product_length = 0;
352   int32_t range;
353   gcry_error_t rc;
354   int sign;
355   gcry_mpi_t value;
356
357   if (NULL == s->product)
358   {
359     GNUNET_break (0);
360     prepare_client_end_notification (s);
361     return;
362   }
363   value = gcry_mpi_new (0);
364   sign = gcry_mpi_cmp_ui (s->product, 0);
365   if (0 > sign)
366   {
367     range = -1;
368     gcry_mpi_sub (value,
369                   value,
370                   s->product);
371   }
372   else if (0 < sign)
373   {
374     range = 1;
375     gcry_mpi_add (value, value, s->product);
376   }
377   else
378   {
379     /* result is exactly zero */
380     range = 0;
381   }
382   gcry_mpi_release (s->product);
383   s->product = NULL;
384
385   if ( (0 != range) &&
386        (0 != (rc = gcry_mpi_aprint (GCRYMPI_FMT_STD,
387                                     &product_exported,
388                                     &product_length,
389                                     value))))
390   {
391     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
392               "gcry_mpi_scan",
393               rc);
394     prepare_client_end_notification (s);
395     return;
396   }
397   gcry_mpi_release (value);
398   e = GNUNET_MQ_msg_extra (msg,
399                            product_length,
400                            GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT);
401   msg->status = htonl (GNUNET_SCALARPRODUCT_STATUS_SUCCESS);
402   msg->range = htonl (range);
403   msg->product_length = htonl (product_length);
404   if (NULL != product_exported)
405   {
406     GNUNET_memcpy (&msg[1],
407             product_exported,
408             product_length);
409     GNUNET_free (product_exported);
410   }
411   GNUNET_MQ_send (s->client_mq,
412                   e);
413   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
414               "Sent result to client, session %s has ended!\n",
415               GNUNET_h2s (&s->session_id));
416 }
417
418
419
420 /**
421  * Function called whenever a channel is destroyed.  Should clean up
422  * any associated state.
423  *
424  * It must NOT call #GNUNET_CADET_channel_destroy() on the channel.
425  *
426  * @param cls our `struct AliceServiceSession`
427  * @param channel connection to the other end (henceforth invalid)
428  */
429 static void
430 cb_channel_destruction (void *cls,
431                         const struct GNUNET_CADET_Channel *channel)
432 {
433   struct AliceServiceSession *s = cls;
434
435   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
436               "Peer disconnected, terminating session %s with peer %s\n",
437               GNUNET_h2s (&s->session_id),
438               GNUNET_i2s (&s->peer));
439   if (GNUNET_SCALARPRODUCT_STATUS_ACTIVE == s->status)
440   {
441     /* We didn't get an answer yet, fail with error */
442     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
443     prepare_client_end_notification (s);
444   }
445   s->channel = NULL;
446 }
447
448
449 /**
450  * Computes the square sum over a vector of a given length.
451  *
452  * @param vector the vector to compute over
453  * @param length the length of the vector
454  * @return an MPI value containing the calculated sum, never NULL
455  */
456 static gcry_mpi_t
457 compute_square_sum_mpi_elements (const struct MpiElement *vector,
458                                  uint32_t length)
459 {
460   gcry_mpi_t elem;
461   gcry_mpi_t sum;
462   uint32_t i;
463
464   GNUNET_assert (NULL != (sum = gcry_mpi_new (0)));
465   GNUNET_assert (NULL != (elem = gcry_mpi_new (0)));
466   for (i = 0; i < length; i++)
467   {
468     gcry_mpi_mul (elem, vector[i].value, vector[i].value);
469     gcry_mpi_add (sum, sum, elem);
470   }
471   gcry_mpi_release (elem);
472   return sum;
473 }
474
475
476 /**
477  * Computes the square sum over a vector of a given length.
478  *
479  * @param vector the vector to compute over
480  * @param length the length of the vector
481  * @return an MPI value containing the calculated sum, never NULL
482  */
483 static gcry_mpi_t
484 compute_square_sum (const gcry_mpi_t *vector,
485                     uint32_t length)
486 {
487   gcry_mpi_t elem;
488   gcry_mpi_t sum;
489   uint32_t i;
490
491   GNUNET_assert (NULL != (sum = gcry_mpi_new (0)));
492   GNUNET_assert (NULL != (elem = gcry_mpi_new (0)));
493   for (i = 0; i < length; i++)
494   {
495     gcry_mpi_mul (elem, vector[i], vector[i]);
496     gcry_mpi_add (sum, sum, elem);
497   }
498   gcry_mpi_release (elem);
499   return sum;
500 }
501
502
503 /**
504  * Compute our scalar product, done by Alice
505  *
506  * @param session the session associated with this computation
507  * @return product as MPI, never NULL
508  */
509 static gcry_mpi_t
510 compute_scalar_product (struct AliceServiceSession *session)
511 {
512   uint32_t count;
513   gcry_mpi_t t;
514   gcry_mpi_t u;
515   gcry_mpi_t u_prime;
516   gcry_mpi_t p;
517   gcry_mpi_t p_prime;
518   gcry_mpi_t tmp;
519   gcry_mpi_t r[session->used_element_count];
520   gcry_mpi_t r_prime[session->used_element_count];
521   gcry_mpi_t s;
522   gcry_mpi_t s_prime;
523   unsigned int i;
524
525   count = session->used_element_count;
526   // due to the introduced static offset S, we now also have to remove this
527   // from the E(a_pi)(+)E(-b_pi-r_pi) and E(a_qi)(+)E(-r_qi) twice each,
528   // the result is E((S + a_pi) + (S -b_pi-r_pi)) and E(S + a_qi + S - r_qi)
529   for (i = 0; i < count; i++)
530   {
531     r[i] = gcry_mpi_new (0);
532     GNUNET_CRYPTO_paillier_decrypt (&my_privkey,
533                                     &my_pubkey,
534                                     &session->r[i],
535                                     r[i]);
536     gcry_mpi_sub (r[i],
537                   r[i],
538                   my_offset);
539     gcry_mpi_sub (r[i],
540                   r[i],
541                   my_offset);
542     r_prime[i] = gcry_mpi_new (0);
543     GNUNET_CRYPTO_paillier_decrypt (&my_privkey,
544                                     &my_pubkey,
545                                     &session->r_prime[i],
546                                     r_prime[i]);
547     gcry_mpi_sub (r_prime[i],
548                   r_prime[i],
549                   my_offset);
550     gcry_mpi_sub (r_prime[i],
551                   r_prime[i],
552                   my_offset);
553   }
554
555   // calculate t = sum(ai)
556   t = compute_square_sum_mpi_elements (session->sorted_elements,
557                                        count);
558   // calculate U
559   u = gcry_mpi_new (0);
560   tmp = compute_square_sum (r, count);
561   gcry_mpi_sub (u, u, tmp);
562   gcry_mpi_release (tmp);
563
564   //calculate U'
565   u_prime = gcry_mpi_new (0);
566   tmp = compute_square_sum (r_prime, count);
567   gcry_mpi_sub (u_prime, u_prime, tmp);
568
569   GNUNET_assert (p = gcry_mpi_new (0));
570   GNUNET_assert (p_prime = gcry_mpi_new (0));
571   GNUNET_assert (s = gcry_mpi_new (0));
572   GNUNET_assert (s_prime = gcry_mpi_new (0));
573
574   // compute P
575   GNUNET_CRYPTO_paillier_decrypt (&my_privkey,
576                                   &my_pubkey,
577                                   &session->s,
578                                   s);
579   GNUNET_CRYPTO_paillier_decrypt (&my_privkey,
580                                   &my_pubkey,
581                                   &session->s_prime,
582                                   s_prime);
583
584   // compute P
585   gcry_mpi_add (p, s, t);
586   gcry_mpi_add (p, p, u);
587
588   // compute P'
589   gcry_mpi_add (p_prime, s_prime, t);
590   gcry_mpi_add (p_prime, p_prime, u_prime);
591
592   gcry_mpi_release (t);
593   gcry_mpi_release (u);
594   gcry_mpi_release (u_prime);
595   gcry_mpi_release (s);
596   gcry_mpi_release (s_prime);
597
598   // compute product
599   gcry_mpi_sub (p, p, p_prime);
600   gcry_mpi_release (p_prime);
601   tmp = gcry_mpi_set_ui (tmp, 2);
602   gcry_mpi_div (p, NULL, p, tmp, 0);
603
604   gcry_mpi_release (tmp);
605   for (i = 0; i < count; i++)
606   {
607     gcry_mpi_release (session->sorted_elements[i].value);
608     gcry_mpi_release (r[i]);
609     gcry_mpi_release (r_prime[i]);
610   }
611   GNUNET_free (session->sorted_elements);
612   session->sorted_elements = NULL;
613   GNUNET_free (session->r);
614   session->r = NULL;
615   GNUNET_free (session->r_prime);
616   session->r_prime = NULL;
617
618   return p;
619 }
620
621
622 /**
623  * Check a multipart chunk of a response we got from another service
624  * we wanted to calculate a scalarproduct with.
625  *
626  * @param cls the `struct AliceServiceSession`
627  * @param msg the actual message
628  * @return #GNUNET_OK to keep the connection open,
629  *         #GNUNET_SYSERR to close it (signal serious error)
630  */
631 static int
632 check_bobs_cryptodata_multipart (void *cls,
633                                  const struct BobCryptodataMultipartMessage *msg)
634 {
635   struct AliceServiceSession *s = cls;
636   uint32_t contained;
637   size_t msg_size;
638   size_t required_size;
639
640   msg_size = ntohs (msg->header.size);
641   contained = ntohl (msg->contained_element_count);
642   required_size = sizeof (struct BobCryptodataMultipartMessage)
643     + 2 * contained * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
644   if ( (required_size != msg_size) ||
645        (s->cadet_received_element_count + contained > s->used_element_count) )
646   {
647     GNUNET_break (0);
648     return GNUNET_SYSERR;
649   }
650   return GNUNET_OK;
651 }
652
653 /**
654  * Handle a multipart chunk of a response we got from another service
655  * we wanted to calculate a scalarproduct with.
656  *
657  * @param cls the `struct AliceServiceSession`
658  * @param msg the actual message
659  */
660 static void
661 handle_bobs_cryptodata_multipart (void *cls,
662                                   const struct BobCryptodataMultipartMessage *msg)
663 {
664   struct AliceServiceSession *s = cls;
665   const struct GNUNET_CRYPTO_PaillierCiphertext *payload;
666   size_t i;
667   uint32_t contained;
668
669   contained = ntohl (msg->contained_element_count);
670   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
671               "Received %u additional crypto values from Bob\n",
672               (unsigned int) contained);
673
674   payload = (const struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
675   /* Convert each k[][perm] to its MPI_value */
676   for (i = 0; i < contained; i++)
677   {
678     GNUNET_memcpy (&s->r[s->cadet_received_element_count + i],
679                    &payload[2 * i],
680                    sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
681     GNUNET_memcpy (&s->r_prime[s->cadet_received_element_count + i],
682                    &payload[2 * i],
683                    sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
684   }
685   s->cadet_received_element_count += contained;
686   GNUNET_CADET_receive_done (s->channel);
687   if (s->cadet_received_element_count != s->used_element_count)
688     return; /* more to come */
689
690   s->product = compute_scalar_product (s);
691   transmit_client_response (s);
692 }
693
694
695 /**
696  * Check a response we got from another service we wanted to
697  * calculate a scalarproduct with.
698  *
699  * @param cls our `struct AliceServiceSession`
700  * @param message the actual message
701  * @return #GNUNET_OK to keep the connection open,
702  *         #GNUNET_SYSERR to close it (we are done)
703  */
704 static int
705 check_bobs_cryptodata_message (void *cls,
706                                const struct BobCryptodataMessage *msg)
707 {
708   struct AliceServiceSession *s = cls;
709   uint32_t contained;
710   uint16_t msg_size;
711   size_t required_size;
712
713   msg_size = ntohs (msg->header.size);
714   contained = ntohl (msg->contained_element_count);
715   required_size = sizeof (struct BobCryptodataMessage)
716     + 2 * contained * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)
717     + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
718   if ( (msg_size != required_size) ||
719        (contained > UINT16_MAX) ||
720        (s->used_element_count < contained) )
721   {
722     GNUNET_break_op (0);
723     return GNUNET_SYSERR;
724   }
725   if (NULL == s->sorted_elements)
726   {
727     /* we're not ready yet, how can Bob be? */
728     GNUNET_break_op (0);
729     return GNUNET_SYSERR;
730   }
731   if (s->total != s->client_received_element_count)
732   {
733     /* we're not ready yet, how can Bob be? */
734     GNUNET_break_op (0);
735     return GNUNET_SYSERR;
736   }
737   return GNUNET_OK;
738 }
739
740
741 /**
742  * Handle a response we got from another service we wanted to
743  * calculate a scalarproduct with.
744  *
745  * @param cls our `struct AliceServiceSession`
746  * @param msg the actual message
747  */
748 static void
749 handle_bobs_cryptodata_message (void *cls,
750                                 const struct BobCryptodataMessage *msg)
751 {
752   struct AliceServiceSession *s = cls;
753   const struct GNUNET_CRYPTO_PaillierCiphertext *payload;
754   uint32_t i;
755   uint32_t contained;
756
757   contained = ntohl (msg->contained_element_count);
758   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
759               "Received %u crypto values from Bob\n",
760               (unsigned int) contained);
761   payload = (const struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
762   GNUNET_memcpy (&s->s,
763                  &payload[0],
764                  sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
765   GNUNET_memcpy (&s->s_prime,
766                  &payload[1],
767                  sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
768   payload = &payload[2];
769
770   s->r = GNUNET_new_array (s->used_element_count,
771                            struct GNUNET_CRYPTO_PaillierCiphertext);
772   s->r_prime = GNUNET_new_array (s->used_element_count,
773                                  struct GNUNET_CRYPTO_PaillierCiphertext);
774   for (i = 0; i < contained; i++)
775   {
776     GNUNET_memcpy (&s->r[i],
777                    &payload[2 * i],
778                    sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
779     GNUNET_memcpy (&s->r_prime[i],
780                    &payload[2 * i + 1],
781                    sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
782   }
783   s->cadet_received_element_count = contained;
784   GNUNET_CADET_receive_done (s->channel);
785
786   if (s->cadet_received_element_count != s->used_element_count)
787   {
788     /* More to come */
789     return;
790   }
791   s->product = compute_scalar_product (s);
792   transmit_client_response (s);
793 }
794
795
796 /**
797  * Iterator to copy over messages from the hash map
798  * into an array for sorting.
799  *
800  * @param cls the `struct AliceServiceSession *`
801  * @param key the key (unused)
802  * @param value the `struct GNUNET_SCALARPRODUCT_Element *`
803  */
804 static int
805 copy_element_cb (void *cls,
806                  const struct GNUNET_HashCode *key,
807                  void *value)
808 {
809   struct AliceServiceSession *s = cls;
810   struct GNUNET_SCALARPRODUCT_Element *e = value;
811   gcry_mpi_t mval;
812   int64_t val;
813
814   mval = gcry_mpi_new (0);
815   val = (int64_t) GNUNET_ntohll (e->value);
816   if (0 > val)
817     gcry_mpi_sub_ui (mval, mval, -val);
818   else
819     gcry_mpi_add_ui (mval, mval, val);
820   s->sorted_elements [s->used_element_count].value = mval;
821   s->sorted_elements [s->used_element_count].key = &e->key;
822   s->used_element_count++;
823   return GNUNET_OK;
824 }
825
826
827 /**
828  * Compare two `struct MpiValue`s by key for sorting.
829  *
830  * @param a pointer to first `struct MpiValue *`
831  * @param b pointer to first `struct MpiValue *`
832  * @return -1 for a < b, 0 for a=b, 1 for a > b.
833  */
834 static int
835 element_cmp (const void *a,
836              const void *b)
837 {
838   const struct MpiElement *ma = a;
839   const struct MpiElement *mb = b;
840
841   return GNUNET_CRYPTO_hash_cmp (ma->key,
842                                  mb->key);
843 }
844
845
846 /**
847  * Maximum number of elements we can put into a single cryptodata
848  * message
849  */
850 #define ELEMENT_CAPACITY ((GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE - 1 - sizeof (struct AliceCryptodataMessage)) / sizeof (struct GNUNET_CRYPTO_PaillierCiphertext))
851
852
853 /**
854  * Send the cryptographic data from Alice to Bob.
855  * Does nothing if we already transferred all elements.
856  *
857  * @param s the associated service session
858  */
859 static void
860 send_alices_cryptodata_message (struct AliceServiceSession *s)
861 {
862   struct AliceCryptodataMessage *msg;
863   struct GNUNET_MQ_Envelope *e;
864   struct GNUNET_CRYPTO_PaillierCiphertext *payload;
865   unsigned int i;
866   uint32_t todo_count;
867   gcry_mpi_t a;
868   uint32_t off;
869
870   s->sorted_elements
871     = GNUNET_malloc (GNUNET_CONTAINER_multihashmap_size (s->intersected_elements) *
872                      sizeof (struct MpiElement));
873   s->used_element_count = 0;
874   GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
875                                          &copy_element_cb,
876                                          s);
877   LOG (GNUNET_ERROR_TYPE_DEBUG,
878        "Finished intersection, %d items remain\n",
879        s->used_element_count);
880   qsort (s->sorted_elements,
881          s->used_element_count,
882          sizeof (struct MpiElement),
883          &element_cmp);
884   off = 0;
885   while (off < s->used_element_count)
886   {
887     todo_count = s->used_element_count - off;
888     if (todo_count > ELEMENT_CAPACITY)
889       todo_count = ELEMENT_CAPACITY;
890     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
891                 "Sending %u/%u crypto values to Bob\n",
892                 (unsigned int) todo_count,
893                 (unsigned int) s->used_element_count);
894
895     e = GNUNET_MQ_msg_extra (msg,
896                              todo_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext),
897                              GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA);
898     msg->contained_element_count = htonl (todo_count);
899     payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
900     a = gcry_mpi_new (0);
901     for (i = off; i < off + todo_count; i++)
902     {
903       gcry_mpi_add (a,
904                     s->sorted_elements[i].value,
905                     my_offset);
906       GNUNET_assert (3 ==
907                      GNUNET_CRYPTO_paillier_encrypt (&my_pubkey,
908                                                      a,
909                                                      3,
910                                                      &payload[i - off]));
911     }
912     gcry_mpi_release (a);
913     off += todo_count;
914     GNUNET_MQ_send (s->cadet_mq,
915                     e);
916   }
917 }
918
919
920 /**
921  * Callback for set operation results. Called for each element
922  * that should be removed from the result set, and then once
923  * to indicate that the set intersection operation is done.
924  *
925  * @param cls closure with the `struct AliceServiceSession`
926  * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK
927  * @param status what has happened with the set intersection?
928  */
929 static void
930 cb_intersection_element_removed (void *cls,
931                                  const struct GNUNET_SET_Element *element,
932                                  enum GNUNET_SET_Status status)
933 {
934   struct AliceServiceSession *s = cls;
935   struct GNUNET_SCALARPRODUCT_Element *se;
936
937   switch (status)
938   {
939   case GNUNET_SET_STATUS_OK:
940     /* this element has been removed from the set */
941     se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
942                                             element->data);
943     GNUNET_assert (NULL != se);
944     LOG (GNUNET_ERROR_TYPE_DEBUG,
945          "Intersection removed element with key %s and value %lld\n",
946          GNUNET_h2s (&se->key),
947          (long long) GNUNET_ntohll (se->value));
948     GNUNET_assert (GNUNET_YES ==
949                    GNUNET_CONTAINER_multihashmap_remove (s->intersected_elements,
950                                                          element->data,
951                                                          se));
952     GNUNET_free (se);
953     return;
954   case GNUNET_SET_STATUS_DONE:
955     s->intersection_op = NULL;
956     if (NULL != s->intersection_set)
957     {
958       GNUNET_SET_destroy (s->intersection_set);
959       s->intersection_set = NULL;
960     }
961     send_alices_cryptodata_message (s);
962     return;
963   case GNUNET_SET_STATUS_HALF_DONE:
964     /* unexpected for intersection */
965     GNUNET_break (0);
966     return;
967   case GNUNET_SET_STATUS_FAILURE:
968     /* unhandled status code */
969     LOG (GNUNET_ERROR_TYPE_DEBUG,
970          "Set intersection failed!\n");
971     if (NULL != s->intersection_listen)
972     {
973       GNUNET_SET_listen_cancel (s->intersection_listen);
974       s->intersection_listen = NULL;
975     }
976     s->intersection_op = NULL;
977     if (NULL != s->intersection_set)
978     {
979       GNUNET_SET_destroy (s->intersection_set);
980       s->intersection_set = NULL;
981     }
982     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
983     prepare_client_end_notification (s);
984     return;
985   default:
986     GNUNET_break (0);
987     return;
988   }
989 }
990
991
992 /**
993  * Called when another peer wants to do a set operation with the
994  * local peer. If a listen error occurs, the @a request is NULL.
995  *
996  * @param cls closure with the `struct AliceServiceSession *`
997  * @param other_peer the other peer
998  * @param context_msg message with application specific information from
999  *        the other peer
1000  * @param request request from the other peer (never NULL), use GNUNET_SET_accept()
1001  *        to accept it, otherwise the request will be refused
1002  *        Note that we can't just return value from the listen callback,
1003  *        as it is also necessary to specify the set we want to do the
1004  *        operation with, whith sometimes can be derived from the context
1005  *        message. It's necessary to specify the timeout.
1006  */
1007 static void
1008 cb_intersection_request_alice (void *cls,
1009                                const struct GNUNET_PeerIdentity *other_peer,
1010                                const struct GNUNET_MessageHeader *context_msg,
1011                                struct GNUNET_SET_Request *request)
1012 {
1013   struct AliceServiceSession *s = cls;
1014
1015   if (0 != memcmp (other_peer,
1016                    &s->peer,
1017                    sizeof (struct GNUNET_PeerIdentity)))
1018   {
1019     GNUNET_break_op (0);
1020     return;
1021   }
1022   s->intersection_op
1023     = GNUNET_SET_accept (request,
1024                          GNUNET_SET_RESULT_REMOVED,
1025                          &cb_intersection_element_removed,
1026                          s);
1027   if (NULL == s->intersection_op)
1028   {
1029     GNUNET_break (0);
1030     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
1031     prepare_client_end_notification (s);
1032     return;
1033   }
1034   if (GNUNET_OK !=
1035       GNUNET_SET_commit (s->intersection_op,
1036                          s->intersection_set))
1037   {
1038     GNUNET_break (0);
1039     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
1040     prepare_client_end_notification (s);
1041     return;
1042   }
1043   GNUNET_SET_destroy (s->intersection_set);
1044   s->intersection_set = NULL;
1045   GNUNET_SET_listen_cancel (s->intersection_listen);
1046   s->intersection_listen = NULL;
1047 }
1048
1049
1050 /**
1051  * Our client has finished sending us its multipart message.
1052  *
1053  * @param session the service session context
1054  */
1055 static void
1056 client_request_complete_alice (struct AliceServiceSession *s)
1057 {
1058   struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1059     GNUNET_MQ_hd_var_size (bobs_cryptodata_message,
1060                            GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA,
1061                            struct BobCryptodataMessage,
1062                            s),
1063     GNUNET_MQ_hd_var_size (bobs_cryptodata_multipart,
1064                            GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA_MULTIPART,
1065                            struct BobCryptodataMultipartMessage,
1066                            s),
1067     GNUNET_MQ_handler_end ()
1068   };
1069   struct ServiceRequestMessage *msg;
1070   struct GNUNET_MQ_Envelope *e;
1071
1072   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1073               "Creating new channel for session with key %s.\n",
1074               GNUNET_h2s (&s->session_id));
1075   s->channel
1076     = GNUNET_CADET_channel_creatE (my_cadet,
1077                                    s,
1078                                    &s->peer,
1079                                    &s->session_id,
1080                                    GNUNET_CADET_OPTION_RELIABLE,
1081                                    NULL,
1082                                    &cb_channel_destruction,
1083                                    cadet_handlers);
1084   if (NULL == s->channel)
1085   {
1086     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
1087     prepare_client_end_notification (s);
1088     return;
1089   }
1090   s->cadet_mq = GNUNET_CADET_get_mq (s->channel);
1091   s->intersection_listen
1092     = GNUNET_SET_listen (cfg,
1093                          GNUNET_SET_OPERATION_INTERSECTION,
1094                          &s->session_id,
1095                          &cb_intersection_request_alice,
1096                          s);
1097   if (NULL == s->intersection_listen)
1098   {
1099     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
1100     GNUNET_CADET_channel_destroy (s->channel);
1101     s->channel = NULL;
1102     prepare_client_end_notification (s);
1103     return;
1104   }
1105
1106   e = GNUNET_MQ_msg (msg,
1107                      GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION);
1108   msg->session_id = s->session_id;
1109   msg->public_key = my_pubkey;
1110   GNUNET_MQ_send (s->cadet_mq,
1111                   e);
1112 }
1113
1114
1115 /**
1116  * We're receiving additional set data. Check if
1117  * @a msg is well-formed.
1118  *
1119  * @param cls client identification of the client
1120  * @param msg the actual message
1121  * @return #GNUNET_OK if @a msg is well-formed
1122  */
1123 static int
1124 check_alice_client_message_multipart (void *cls,
1125                                       const struct ComputationBobCryptodataMultipartMessage *msg)
1126 {
1127   struct AliceServiceSession *s = cls;
1128   uint32_t contained_count;
1129   uint16_t msize;
1130
1131   msize = ntohs (msg->header.size);
1132   contained_count = ntohl (msg->element_count_contained);
1133   if ( (msize != (sizeof (struct ComputationBobCryptodataMultipartMessage) +
1134                   contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) ||
1135        (0 == contained_count) ||
1136        (s->total == s->client_received_element_count) ||
1137        (s->total < s->client_received_element_count + contained_count) )
1138   {
1139     GNUNET_break_op (0);
1140     return GNUNET_SYSERR;
1141   }
1142   return GNUNET_OK;
1143 }
1144
1145
1146 /**
1147  * We're receiving additional set data. Add it to our
1148  * set and if we are done, initiate the transaction.
1149  *
1150  * @param cls client identification of the client
1151  * @param msg the actual message
1152  */
1153 static void
1154 handle_alice_client_message_multipart (void *cls,
1155                                        const struct ComputationBobCryptodataMultipartMessage *msg)
1156 {
1157   struct AliceServiceSession *s = cls;
1158   uint32_t contained_count;
1159   const struct GNUNET_SCALARPRODUCT_Element *elements;
1160   struct GNUNET_SET_Element set_elem;
1161   struct GNUNET_SCALARPRODUCT_Element *elem;
1162
1163   contained_count = ntohl (msg->element_count_contained);
1164   s->client_received_element_count += contained_count;
1165   elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1166   for (uint32_t i = 0; i < contained_count; i++)
1167   {
1168     elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
1169     GNUNET_memcpy (elem,
1170                    &elements[i],
1171                    sizeof (struct GNUNET_SCALARPRODUCT_Element));
1172     if (GNUNET_SYSERR ==
1173         GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
1174                                            &elem->key,
1175                                            elem,
1176                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1177     {
1178       GNUNET_break (0);
1179       GNUNET_free (elem);
1180       continue;
1181     }
1182     set_elem.data = &elem->key;
1183     set_elem.size = sizeof (elem->key);
1184     set_elem.element_type = 0;
1185     GNUNET_SET_add_element (s->intersection_set,
1186                             &set_elem,
1187                             NULL, NULL);
1188     s->used_element_count++;
1189   }
1190   GNUNET_SERVICE_client_continue (s->client);
1191   if (s->total != s->client_received_element_count)
1192   {
1193     /* more to come */
1194     return;
1195   }
1196   client_request_complete_alice (s);
1197 }
1198
1199
1200 /**
1201  * Handler for Alice's client request message.
1202  * Check that @a msg is well-formed.
1203  *
1204  * @param cls identification of the client
1205  * @param msg the actual message
1206  * @return #GNUNET_OK if @a msg is well-formed
1207  */
1208 static int
1209 check_alice_client_message (void *cls,
1210                             const struct AliceComputationMessage *msg)
1211 {
1212   struct AliceServiceSession *s = cls;
1213   uint16_t msize;
1214   uint32_t total_count;
1215   uint32_t contained_count;
1216
1217   if (NULL != s->intersected_elements)
1218   {
1219     /* only one concurrent session per client connection allowed,
1220        simplifies logic a lot... */
1221     GNUNET_break (0);
1222     return GNUNET_SYSERR;
1223   }
1224   msize = ntohs (msg->header.size);
1225   total_count = ntohl (msg->element_count_total);
1226   contained_count = ntohl (msg->element_count_contained);
1227   if ( (0 == total_count) ||
1228        (0 == contained_count) ||
1229        (msize != (sizeof (struct AliceComputationMessage) +
1230                   contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) )
1231   {
1232     GNUNET_break_op (0);
1233     return GNUNET_SYSERR;
1234   }
1235   return GNUNET_OK;
1236 }
1237
1238
1239 /**
1240  * Handler for Alice's client request message.
1241  * We are doing request-initiation to compute a scalar product with a peer.
1242  *
1243  * @param cls identification of the client
1244  * @param msg the actual message
1245  */
1246 static void
1247 handle_alice_client_message (void *cls,
1248                              const struct AliceComputationMessage *msg)
1249 {
1250   struct AliceServiceSession *s = cls;
1251   uint32_t contained_count;
1252   uint32_t total_count;
1253   const struct GNUNET_SCALARPRODUCT_Element *elements;
1254   struct GNUNET_SET_Element set_elem;
1255   struct GNUNET_SCALARPRODUCT_Element *elem;
1256
1257   total_count = ntohl (msg->element_count_total);
1258   contained_count = ntohl (msg->element_count_contained);
1259   s->peer = msg->peer;
1260   s->status = GNUNET_SCALARPRODUCT_STATUS_ACTIVE;
1261   s->total = total_count;
1262   s->client_received_element_count = contained_count;
1263   s->session_id = msg->session_key;
1264   elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1265   s->intersected_elements = GNUNET_CONTAINER_multihashmap_create (s->total,
1266                                                                   GNUNET_YES);
1267   s->intersection_set = GNUNET_SET_create (cfg,
1268                                            GNUNET_SET_OPERATION_INTERSECTION);
1269
1270   for (uint32_t i = 0; i < contained_count; i++)
1271   {
1272     if (0 == GNUNET_ntohll (elements[i].value))
1273       continue;
1274     elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
1275     GNUNET_memcpy (elem,
1276             &elements[i],
1277             sizeof (struct GNUNET_SCALARPRODUCT_Element));
1278     if (GNUNET_SYSERR ==
1279         GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
1280                                            &elem->key,
1281                                            elem,
1282                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1283     {
1284       /* element with same key encountered twice! */
1285       GNUNET_break (0);
1286       GNUNET_free (elem);
1287       continue;
1288     }
1289     set_elem.data = &elem->key;
1290     set_elem.size = sizeof (elem->key);
1291     set_elem.element_type = 0;
1292     GNUNET_SET_add_element (s->intersection_set,
1293                             &set_elem,
1294                             NULL, NULL);
1295     s->used_element_count++;
1296   }
1297   GNUNET_SERVICE_client_continue (s->client);
1298   if (s->total != s->client_received_element_count)
1299   {
1300     /* wait for multipart msg */
1301     return;
1302   }
1303   client_request_complete_alice (s);
1304 }
1305
1306
1307 /**
1308  * Task run during shutdown.
1309  *
1310  * @param cls unused
1311  */
1312 static void
1313 shutdown_task (void *cls)
1314 {
1315   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1316               "Shutting down, initiating cleanup.\n");
1317   // FIXME: we have to cut our connections to CADET first!
1318   if (NULL != my_cadet)
1319   {
1320     GNUNET_CADET_disconnect (my_cadet);
1321     my_cadet = NULL;
1322   }
1323 }
1324
1325
1326 /**
1327  * A client connected.
1328  *
1329  * Setup the associated data structure.
1330  *
1331  * @param cls closure, NULL
1332  * @param client identification of the client
1333  * @param mq message queue to communicate with @a client
1334  * @return our `struct AliceServiceSession`
1335  */
1336 static void *
1337 client_connect_cb (void *cls,
1338                    struct GNUNET_SERVICE_Client *client,
1339                    struct GNUNET_MQ_Handle *mq)
1340 {
1341   struct AliceServiceSession *s;
1342
1343   s = GNUNET_new (struct AliceServiceSession);
1344   s->client = client;
1345   s->client_mq = mq;
1346   return s;
1347 }
1348
1349
1350 /**
1351  * A client disconnected.
1352  *
1353  * Remove the associated session(s), release data structures
1354  * and cancel pending outgoing transmissions to the client.
1355  *
1356  * @param cls closure, NULL
1357  * @param client identification of the client
1358  * @param app_cls our `struct AliceServiceSession`
1359  */
1360 static void
1361 client_disconnect_cb (void *cls,
1362                       struct GNUNET_SERVICE_Client *client,
1363                       void *app_cls)
1364 {
1365   struct AliceServiceSession *s = app_cls;
1366
1367   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1368               "Client %p disconnected from us.\n",
1369               client);
1370   s->client = NULL;
1371   s->client_mq = NULL;
1372   destroy_service_session (s);
1373 }
1374
1375
1376 /**
1377  * Initialization of the program and message handlers
1378  *
1379  * @param cls closure
1380  * @param c configuration to use
1381  * @param service the initialized service
1382  */
1383 static void
1384 run (void *cls,
1385      const struct GNUNET_CONFIGURATION_Handle *c,
1386      struct GNUNET_SERVICE_Handle *service)
1387 {
1388   cfg = c;
1389   /*
1390     offset has to be sufficiently small to allow computation of:
1391     m1+m2 mod n == (S + a) + (S + b) mod n,
1392     if we have more complex operations, this factor needs to be lowered */
1393   my_offset = gcry_mpi_new (GNUNET_CRYPTO_PAILLIER_BITS / 3);
1394   gcry_mpi_set_bit (my_offset,
1395                     GNUNET_CRYPTO_PAILLIER_BITS / 3);
1396   GNUNET_CRYPTO_paillier_create (&my_pubkey,
1397                                  &my_privkey);
1398   my_cadet = GNUNET_CADET_connecT (cfg);
1399   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1400                                  NULL);
1401   if (NULL == my_cadet)
1402   {
1403     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1404                 _("Connect to CADET failed\n"));
1405     GNUNET_SCHEDULER_shutdown ();
1406     return;
1407   }
1408 }
1409
1410
1411 /**
1412  * Define "main" method using service macro.
1413  */
1414 GNUNET_SERVICE_MAIN
1415 ("scalarproduct-alice",
1416  GNUNET_SERVICE_OPTION_NONE,
1417  &run,
1418  &client_connect_cb,
1419  &client_disconnect_cb,
1420  NULL,
1421  GNUNET_MQ_hd_var_size (alice_client_message,
1422                         GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE,
1423                         struct AliceComputationMessage,
1424                         NULL),
1425  GNUNET_MQ_hd_var_size (alice_client_message_multipart,
1426                         GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MULTIPART_ALICE,
1427                         struct ComputationBobCryptodataMultipartMessage,
1428                         NULL),
1429  GNUNET_MQ_handler_end ());
1430
1431
1432 /* end of gnunet-service-scalarproduct_alice.c */