2 This file is part of GNUnet.
3 Copyright (C) 2014 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
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 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
21 * @file util/gnunet-scrypt.c
22 * @brief tool to manipulate SCRYPT proofs of work.
26 #include "gnunet_util_lib.h"
30 * Amount of work required (W-bit collisions) for NSE proofs, in collision-bits.
32 static unsigned long long nse_work_required;
35 * Interval between proof find runs.
37 static struct GNUNET_TIME_Relative proof_find_delay;
39 static struct GNUNET_CRYPTO_EddsaPublicKey pub;
41 static uint64_t proof;
43 static struct GNUNET_SCHEDULER_Task *proof_task;
45 static const struct GNUNET_CONFIGURATION_Handle *cfg;
53 * Write our current proof to disk.
58 shutdown_task (void *cls)
61 if (sizeof(proof) != GNUNET_DISK_fn_write (pwfn,
64 GNUNET_DISK_PERM_USER_READ
65 | GNUNET_DISK_PERM_USER_WRITE))
66 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "write", pwfn);
71 * Count the leading zeroes in hash.
73 * @param hash to count leading zeros in
74 * @return the number of leading zero bits.
77 count_leading_zeroes (const struct GNUNET_HashCode *hash)
79 unsigned int hash_count;
82 while (0 == GNUNET_CRYPTO_hash_get_bit (hash, hash_count))
89 * Find our proof of work.
91 * @param cls closure (unused)
92 * @param tc task context
95 find_proof (void *cls)
99 char buf[sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)
100 + sizeof(uint64_t)] GNUNET_ALIGN;
101 struct GNUNET_HashCode result;
103 struct GNUNET_TIME_Absolute timestamp;
104 struct GNUNET_TIME_Relative elapsed;
107 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
108 "Got Proof of Work %llu\n",
109 (unsigned long long) proof);
111 GNUNET_memcpy (&buf[sizeof(uint64_t)],
113 sizeof(struct GNUNET_CRYPTO_EddsaPublicKey));
116 timestamp = GNUNET_TIME_absolute_get ();
117 while ((counter != UINT64_MAX) && (i < ROUND_SIZE))
119 GNUNET_memcpy (buf, &counter, sizeof(uint64_t));
120 GNUNET_CRYPTO_pow_hash ("gnunet-nse-proof-of-work",
124 if (nse_work_required <= count_leading_zeroes (&result))
128 "Proof of work found: %llu!\n",
129 (unsigned long long) proof);
130 GNUNET_SCHEDULER_shutdown ();
136 elapsed = GNUNET_TIME_absolute_get_duration (timestamp);
137 elapsed = GNUNET_TIME_relative_divide (elapsed, ROUND_SIZE);
138 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
139 "Current: %llu [%s/proof]\n",
140 (unsigned long long) counter,
141 GNUNET_STRINGS_relative_time_to_string (elapsed, 0));
142 if (proof / (100 * ROUND_SIZE) < counter / (100 * ROUND_SIZE))
144 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
145 "Testing proofs currently at %llu\n",
146 (unsigned long long) counter);
147 /* remember progress every 100 rounds */
149 shutdown_task (NULL);
156 GNUNET_SCHEDULER_add_delayed_with_priority (proof_find_delay,
157 GNUNET_SCHEDULER_PRIORITY_IDLE,
164 * Main function that will be run by the scheduler.
167 * @param args remaining command-line arguments
168 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
169 * @param cfg configuration
175 const struct GNUNET_CONFIGURATION_Handle *config)
177 struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
184 /* load proof of work */
187 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg,
192 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "NSE", "PROOFFILE");
193 GNUNET_SCHEDULER_shutdown ();
197 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Proof of Work file: %s\n", pwfn);
198 if ((GNUNET_YES != GNUNET_DISK_file_test (pwfn)) ||
199 (sizeof(proof) != GNUNET_DISK_fn_read (pwfn, &proof, sizeof(proof))))
202 /* load private key */
205 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg,
210 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
216 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Private Key file: %s\n", pkfn);
217 if (NULL == (pk = GNUNET_CRYPTO_eddsa_key_create_from_file (pkfn)))
219 fprintf (stderr, _ ("Loading hostkey from `%s' failed.\n"), pkfn);
224 GNUNET_CRYPTO_eddsa_key_get_public (pk, &pub);
226 pids = GNUNET_CRYPTO_eddsa_public_key_to_string (&pub);
227 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer ID: %s\n", pids);
230 /* get target bit amount */
231 if (0 == nse_work_required)
233 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg,
238 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "NSE", "WORKBITS");
239 GNUNET_SCHEDULER_shutdown ();
242 if (nse_work_required >= sizeof(struct GNUNET_HashCode) * 8)
244 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
247 _ ("Value is too large.\n"));
248 GNUNET_SCHEDULER_shutdown ();
251 else if (0 == nse_work_required)
253 GNUNET_SCHEDULER_shutdown ();
257 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Bits: %llu\n", nse_work_required);
259 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
260 "Delay between tries: %s\n",
261 GNUNET_STRINGS_relative_time_to_string (proof_find_delay, 1));
263 GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE,
266 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
271 * Program to manipulate ECC key files.
273 * @param argc number of arguments from the command line
274 * @param argv command line arguments
275 * @return 0 ok, 1 on error
278 main (int argc, char *const *argv)
280 struct GNUNET_GETOPT_CommandLineOption options[] =
281 { GNUNET_GETOPT_option_ulong (
285 gettext_noop ("number of bits to require for the proof of work"),
287 GNUNET_GETOPT_option_filename (
291 gettext_noop ("file with private key, otherwise default is used"),
293 GNUNET_GETOPT_option_filename (
297 gettext_noop ("file with proof of work, otherwise default is used"),
299 GNUNET_GETOPT_option_relative_time ('t',
303 "time to wait between calculations"),
305 GNUNET_GETOPT_OPTION_END };
308 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
313 GNUNET_PROGRAM_run (argc,
315 "gnunet-scrypt [OPTIONS] prooffile",
316 gettext_noop ("Manipulate GNUnet proof of work files"),
322 GNUNET_free ((void *) argv);
323 GNUNET_free_non_null (pwfn);
328 /* end of gnunet-scrypt.c */