sensor: pow benchmarking
[oweals/gnunet.git] / src / sensor / perf_pow_sign.c
1   /*
2    * This file is part of GNUnet.
3    * (C)
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., 59 Temple Place - Suite 330,
18    * Boston, MA 02111-1307, USA.
19    */
20 /**
21  * @file sensor/perf_pow_sign.c
22  * @brief Print the average time required to generate pow for each matching bits
23  */
24 #include <inttypes.h>
25 #include "platform.h"
26 #include "gnunet_util_lib.h"
27 #include "gnunet_sensor_util_lib.h"
28 #include "gnunet_testbed_service.h"
29 #include "gnunet_signatures.h"
30
31 /**
32  * Number of peers to start for the test
33  */
34 #define NUM_PEERS 1
35
36 /**
37  * Size of the message exchanged
38  */
39 #define MSG_SIZE 1024
40
41 /**
42  * How many matching bits to start with
43  */
44 #define MATCHING_BITS_START 1
45
46 /**
47  * How many matching bits to end with
48  */
49 #define MATCHING_BITS_END 50
50
51 /**
52  * How many readings per matching bits value
53  */
54 #define ITERATIONS 10
55
56 /**
57  * Test name
58  */
59 static const char *testname = "test_pow_sign";
60
61 /**
62  * Name of GNUNET config file used in this test
63  */
64 static const char *cfg_filename = "test_pow_sign.conf";
65
66 /**
67  * Status of the test to be returned by main()
68  */
69 static int ok = 1;
70
71 /**
72  * Task used to shutdown / expire the test
73  */
74 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
75
76 /**
77  * Message to be exchanged
78  */
79 static char msg[MSG_SIZE];
80
81 /**
82  * Private key of sending peer
83  */
84 static struct GNUNET_CRYPTO_EddsaPrivateKey *private_key;
85
86 /**
87  * Public key of sending peer
88  */
89 static struct GNUNET_CRYPTO_EddsaPublicKey *public_key;
90
91 /**
92  * The current matching bits being evaluated
93  */
94 static int current_matching_bits;
95
96 /**
97  * How many iterations performed for this matching bits value
98  */
99 static int performed_iterations;
100
101 /**
102  * Total duration of all iterations
103  */
104 static struct GNUNET_TIME_Relative total_duration;
105
106 /**
107  * Task creating pow block
108  */
109 struct GNUNET_SENSOR_crypto_pow_context *pow_task;
110
111
112 /**
113  * Start a new pow calculation
114  */
115 static void
116 pow_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
117
118
119 /**
120  * Shutdown task
121  *
122  * @param cls Closure (unused)
123  * @param tc Task context (unused)
124  */
125 static void
126 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
127 {
128   if (NULL != pow_task)
129   {
130     GNUNET_SENSOR_crypto_pow_sign_cancel (pow_task);
131     pow_task = NULL;
132   }
133   if (NULL != private_key)
134   {
135     GNUNET_free (private_key);
136     private_key = NULL;
137   }
138   if (NULL != public_key)
139   {
140     GNUNET_free (public_key);
141     public_key = NULL;
142   }
143   GNUNET_SCHEDULER_shutdown ();
144 }
145
146
147 static void
148 pow_cb (void *cls, struct GNUNET_SENSOR_crypto_pow_block *block)
149 {
150   struct GNUNET_TIME_Absolute end_time;
151   struct GNUNET_TIME_Relative duration;
152
153   pow_task = NULL;
154   end_time = GNUNET_TIME_absolute_get();
155   duration = GNUNET_TIME_absolute_get_difference (block->timestamp, end_time);
156   printf(".");
157   performed_iterations++;
158   total_duration = GNUNET_TIME_relative_add (total_duration, duration);
159   if (ITERATIONS == performed_iterations)
160   {
161     total_duration = GNUNET_TIME_relative_divide (total_duration, ITERATIONS);
162     printf ("Matching bits %d: %s\n", current_matching_bits,
163              GNUNET_STRINGS_relative_time_to_string(total_duration, GNUNET_NO));
164     total_duration = GNUNET_TIME_UNIT_ZERO;
165     performed_iterations = 0;
166     if (MATCHING_BITS_END == current_matching_bits)
167     {
168       ok = 0;
169       GNUNET_SCHEDULER_cancel (shutdown_task);
170       GNUNET_SCHEDULER_add_now (do_shutdown, NULL);
171       return;
172     }
173     current_matching_bits ++;
174   }
175   GNUNET_SCHEDULER_add_now (&pow_start, NULL);
176 }
177
178
179 /**
180  * Start a new pow calculation
181  */
182 static void
183 pow_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
184 {
185   struct GNUNET_TIME_Absolute timestamp;
186
187   timestamp = GNUNET_TIME_absolute_get ();
188   pow_task = GNUNET_SENSOR_crypto_pow_sign (msg, MSG_SIZE, &timestamp, public_key,
189                                  private_key, current_matching_bits, &pow_cb, NULL);
190 }
191
192
193 /**
194  * Callback to be called when the requested peer information is available
195  *
196  * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
197  * @param op the operation this callback corresponds to
198  * @param pinfo the result; will be NULL if the operation has failed
199  * @param emsg error message if the operation has failed; will be NULL if the
200  *          operation is successfull
201  */
202 static void
203 peer_info_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op,
204               const struct GNUNET_TESTBED_PeerInformation *pinfo,
205               const char *emsg)
206 {
207   /* generate random data block */
208   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, msg, MSG_SIZE);
209   /* get private and public keys */
210   private_key =
211       GNUNET_CRYPTO_eddsa_key_create_from_configuration (pinfo->result.cfg);
212   GNUNET_assert (NULL != private_key);
213   public_key = GNUNET_new (struct GNUNET_CRYPTO_EddsaPublicKey);
214   GNUNET_CRYPTO_eddsa_key_get_public (private_key, public_key);
215   current_matching_bits = MATCHING_BITS_START;
216   performed_iterations = 0;
217   total_duration = GNUNET_TIME_UNIT_ZERO;
218   GNUNET_TESTBED_operation_done (op);
219   GNUNET_SCHEDULER_add_now (&pow_start, NULL);
220 }
221
222
223 /**
224  * Signature of a main function for a testcase.
225  *
226  * @param cls closure
227  * @param h the run handle
228  * @param num_peers number of peers in 'peers'
229  * @param peers handle to peers run in the testbed.  NULL upon timeout (see
230  *          GNUNET_TESTBED_test_run()).
231  * @param links_succeeded the number of overlay link connection attempts that
232  *          succeeded
233  * @param links_failed the number of overlay link connection attempts that
234  *          failed
235  * @see GNUNET_TESTBED_test_run()
236  */
237 static void
238 test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h,
239              unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers,
240              unsigned int links_succeeded, unsigned int links_failed)
241 {
242   GNUNET_assert (NUM_PEERS == num_peers);
243   GNUNET_assert (0 == links_failed);
244   shutdown_task =
245     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL);
246   GNUNET_TESTBED_peer_get_information (peers[0],
247                                        GNUNET_TESTBED_PIT_CONFIGURATION,
248                                        &peer_info_cb, peers[0]);
249 }
250
251
252 int
253 main (int argc, char *argv[])
254 {
255   GNUNET_log_setup (testname, "INFO", NULL);
256   if (GNUNET_OK ==
257       GNUNET_TESTBED_test_run (testname, cfg_filename, NUM_PEERS, 0, NULL, NULL,
258                                &test_master, NULL))
259     return ok;
260   return 1;
261 }