aboutsummaryrefslogtreecommitdiff
path: root/src/revocation/revocation_api.c
diff options
context:
space:
mode:
authorSchanzenbach, Martin <mschanzenbach@posteo.de>2020-04-19 20:05:26 +0200
committerSchanzenbach, Martin <mschanzenbach@posteo.de>2020-04-19 20:05:26 +0200
commit8f9a45e853d9759f04a5f4fe9aa0146ed3f3fb17 (patch)
treeb9ef6928b2fdb8647a8c7d3e0f6d316198b51d48 /src/revocation/revocation_api.c
parenteb6b547e243144f27749811c15b6cce90e03aaa7 (diff)
downloadgnunet-8f9a45e853d9759f04a5f4fe9aa0146ed3f3fb17.tar.gz
gnunet-8f9a45e853d9759f04a5f4fe9aa0146ed3f3fb17.zip
towards less variance
Diffstat (limited to 'src/revocation/revocation_api.c')
-rw-r--r--src/revocation/revocation_api.c198
1 files changed, 159 insertions, 39 deletions
diff --git a/src/revocation/revocation_api.c b/src/revocation/revocation_api.c
index c9bb2543a..6510f9583 100644
--- a/src/revocation/revocation_api.c
+++ b/src/revocation/revocation_api.c
@@ -51,6 +51,21 @@ struct GNUNET_REVOCATION_Query
51 void *func_cls; 51 void *func_cls;
52}; 52};
53 53
54struct BestPow
55{
56 uint64_t pow;
57 unsigned int bits;
58};
59
60struct GNUNET_REVOCATION_PowCalculationHandle
61{
62 struct BestPow best[POW_COUNT];
63 struct GNUNET_REVOCATION_Pow pow;
64 uint64_t current_pow;
65 unsigned int epochs;
66 unsigned int difficulty;
67 int valid;
68};
54 69
55/** 70/**
56 * Generic error handler, called with the appropriate 71 * Generic error handler, called with the appropriate
@@ -246,10 +261,7 @@ handle_revocation_response (void *cls,
246 */ 261 */
247struct GNUNET_REVOCATION_Handle * 262struct GNUNET_REVOCATION_Handle *
248GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg, 263GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg,
249 const struct GNUNET_CRYPTO_EcdsaPublicKey *key, 264 const struct GNUNET_REVOCATION_Pow *pow,
250 const struct GNUNET_CRYPTO_EcdsaSignature *sig,
251 const struct GNUNET_TIME_Absolute *ts,
252 uint64_t pow,
253 GNUNET_REVOCATION_Callback func, 265 GNUNET_REVOCATION_Callback func,
254 void *func_cls) 266 void *func_cls)
255{ 267{
@@ -272,9 +284,7 @@ GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg,
272 "WORKBITS", 284 "WORKBITS",
273 &matching_bits)) && 285 &matching_bits)) &&
274 (GNUNET_YES != 286 (GNUNET_YES !=
275 GNUNET_REVOCATION_check_pow (key, 287 GNUNET_REVOCATION_check_pow (pow,
276 ts,
277 pow,
278 (unsigned int) matching_bits))) 288 (unsigned int) matching_bits)))
279 { 289 {
280 GNUNET_break (0); 290 GNUNET_break (0);
@@ -297,12 +307,7 @@ GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg,
297 env = GNUNET_MQ_msg (rm, 307 env = GNUNET_MQ_msg (rm,
298 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE); 308 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE);
299 rm->reserved = htonl (0); 309 rm->reserved = htonl (0);
300 rm->proof_of_work = pow; 310 rm->proof_of_work = *pow;
301 rm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_REVOCATION);
302 rm->purpose.size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
303 + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
304 rm->public_key = *key;
305 rm->signature = *sig;
306 GNUNET_MQ_send (h->mq, 311 GNUNET_MQ_send (h->mq,
307 env); 312 env);
308 return h; 313 return h;
@@ -345,6 +350,23 @@ count_leading_zeroes (const struct GNUNET_HashCode *hash)
345 350
346 351
347/** 352/**
353 * Calculate the average zeros in the pows.
354 *
355 * @param ph the PowHandle
356 * @return the average number of zeroes.
357 */
358static unsigned int
359calculate_score (const struct GNUNET_REVOCATION_PowCalculationHandle *ph)
360{
361 double sum = 0.0;
362 for (unsigned int j = 0; j<POW_COUNT; j++)
363 sum += ph->best[j].bits;
364 double avg = sum / POW_COUNT;
365 return avg;
366}
367
368
369/**
348 * Check if the given proof-of-work value 370 * Check if the given proof-of-work value
349 * would be acceptable for revoking the given key. 371 * would be acceptable for revoking the given key.
350 * 372 *
@@ -355,32 +377,133 @@ count_leading_zeroes (const struct GNUNET_HashCode *hash)
355 * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not 377 * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not
356 */ 378 */
357int 379int
358GNUNET_REVOCATION_check_pow (const struct GNUNET_CRYPTO_EcdsaPublicKey *key, 380GNUNET_REVOCATION_check_pow (const struct GNUNET_REVOCATION_Pow *pow,
359 const struct GNUNET_TIME_Absolute *ts, 381 unsigned int difficulty)
360 uint64_t pow, 382{
361 unsigned int matching_bits) 383 char buf[sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)
384 + sizeof (uint64_t)
385 + sizeof (uint64_t)] GNUNET_ALIGN;
386 struct GNUNET_HashCode result;
387 unsigned int score = 0;
388 unsigned int tmp_score = 0;
389 unsigned int epochs;
390 uint64_t pow_val;
391
392 GNUNET_memcpy (&buf[sizeof(uint64_t)],
393 &pow->timestamp,
394 sizeof (uint64_t));
395 GNUNET_memcpy (&buf[sizeof(uint64_t) * 2],
396 &pow->key,
397 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
398 for (unsigned int i = 0; i < POW_COUNT; i++)
399 {
400 pow_val = GNUNET_ntohll (pow->pow[i]);
401 GNUNET_memcpy (buf, &pow_val, sizeof(uint64_t));
402 GNUNET_CRYPTO_pow_hash ("gnunet-revocation-proof-of-work",
403 buf,
404 sizeof(buf),
405 &result);
406 tmp_score = count_leading_zeroes (&result);
407 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
408 "Score %u (#%u)\n",
409 tmp_score, i);
410 score += tmp_score;
411
412 }
413 score = score / POW_COUNT;
414 if (score < difficulty)
415 return GNUNET_NO;
416 // TODO verfiy signature?
417 epochs = score - difficulty + 1;
418 // TODO verify expiration
419 return GNUNET_YES;
420}
421
422
423struct GNUNET_REVOCATION_PowCalculationHandle*
424GNUNET_REVOCATION_pow_init (const struct GNUNET_CRYPTO_EcdsaPublicKey *key,
425 int epochs,
426 unsigned int difficulty)
427{
428 struct GNUNET_REVOCATION_PowCalculationHandle*pc;
429 struct GNUNET_TIME_Absolute ts = GNUNET_TIME_absolute_get();
430
431 pc = GNUNET_new (struct GNUNET_REVOCATION_PowCalculationHandle);
432 pc->pow.key = *key;
433 pc->pow.timestamp = GNUNET_TIME_absolute_hton(ts);
434 pc->current_pow = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
435 UINT64_MAX);
436 pc->difficulty = difficulty;
437 pc->epochs = epochs;
438 return pc;
439}
440
441
442/**
443 * Calculate a key revocation valid for broadcasting for a number
444 * of epochs.
445 *
446 * @param pc handle to the PoW, initially called with NULL.
447 * @param epochs number of epochs for which the revocation must be valid.
448 * @param pow current pow value to try
449 * @param difficulty current base difficulty to achieve
450 * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not
451 */
452int
453GNUNET_REVOCATION_pow_round (struct GNUNET_REVOCATION_PowCalculationHandle *pc)
362{ 454{
363 char buf[sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey) 455 char buf[sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)
364 + sizeof(pow) 456 + sizeof (uint64_t)
365 + sizeof (struct GNUNET_TIME_AbsoluteNBO)] GNUNET_ALIGN; 457 + sizeof (uint64_t)] GNUNET_ALIGN;
366 struct GNUNET_HashCode result; 458 struct GNUNET_HashCode result;
367 struct GNUNET_TIME_AbsoluteNBO ts_nbo; 459 unsigned int zeros;
368 460
369 ts_nbo = GNUNET_TIME_absolute_hton (*ts); 461 pc->current_pow++;
370 462
371 GNUNET_memcpy (buf, &pow, sizeof(pow)); 463 GNUNET_memcpy (buf, &pc->current_pow, sizeof(uint64_t));
372 GNUNET_memcpy (&buf[sizeof(pow)], 464 GNUNET_memcpy (&buf[sizeof(uint64_t)],
373 &ts_nbo, 465 &pc->pow.timestamp,
374 sizeof (struct GNUNET_TIME_AbsoluteNBO)); 466 sizeof (uint64_t));
375 GNUNET_memcpy (&buf[sizeof(pow) + sizeof (struct GNUNET_TIME_AbsoluteNBO)], 467 GNUNET_memcpy (&buf[sizeof(uint64_t) * 2],
376 key, 468 &pc->pow.key,
377 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)); 469 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
378 GNUNET_CRYPTO_pow_hash ("gnunet-revocation-proof-of-work", 470 GNUNET_CRYPTO_pow_hash ("gnunet-revocation-proof-of-work",
379 buf, 471 buf,
380 sizeof(buf), 472 sizeof(buf),
381 &result); 473 &result);
382 return (count_leading_zeroes (&result) >= 474 zeros = count_leading_zeroes (&result);
383 matching_bits) ? GNUNET_YES : GNUNET_NO; 475 for (unsigned int i = 0; i < POW_COUNT; i++)
476 {
477 if (pc->best[i].bits < zeros)
478 {
479 pc->best[i].bits = zeros;
480 pc->best[i].pow = pc->current_pow;
481 pc->pow.pow[i] = GNUNET_htonll (pc->current_pow);
482 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
483 "New best score %u (#%u)\n",
484 zeros, i);
485 break;
486 }
487 }
488 return calculate_score (pc) >= pc->difficulty + pc->epochs ? GNUNET_YES :
489 GNUNET_NO;
490}
491
492
493const struct GNUNET_REVOCATION_Pow*
494GNUNET_REVOCATION_pow_get (const struct
495 GNUNET_REVOCATION_PowCalculationHandle *pc)
496{
497 return calculate_score (pc) >= pc->difficulty + pc->epochs ? &pc->pow :
498 NULL;
499}
500
501
502void
503GNUNET_REVOCATION_pow_cleanup (struct
504 GNUNET_REVOCATION_PowCalculationHandle *pc)
505{
506 GNUNET_free (pc);
384} 507}
385 508
386 509
@@ -391,20 +514,17 @@ GNUNET_REVOCATION_check_pow (const struct GNUNET_CRYPTO_EcdsaPublicKey *key,
391 * @param sig where to write the revocation signature 514 * @param sig where to write the revocation signature
392 */ 515 */
393void 516void
394GNUNET_REVOCATION_sign_revocation (const struct 517GNUNET_REVOCATION_sign_revocation (struct GNUNET_REVOCATION_Pow *pow,
395 GNUNET_CRYPTO_EcdsaPrivateKey *key, 518 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key)
396 struct GNUNET_CRYPTO_EcdsaSignature *sig)
397{ 519{
398 struct RevokeMessage rm; 520 pow->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_REVOCATION);
399 521 pow->purpose.size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
400 rm.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_REVOCATION);
401 rm.purpose.size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
402 + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)); 522 + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
403 GNUNET_CRYPTO_ecdsa_key_get_public (key, &rm.public_key); 523 GNUNET_CRYPTO_ecdsa_key_get_public (key, &pow->key);
404 GNUNET_assert (GNUNET_OK == 524 GNUNET_assert (GNUNET_OK ==
405 GNUNET_CRYPTO_ecdsa_sign_ (key, 525 GNUNET_CRYPTO_ecdsa_sign_ (key,
406 &rm.purpose, 526 &pow->purpose,
407 sig)); 527 &pow->signature));
408} 528}
409 529
410 530