diff options
author | Schanzenbach, Martin <mschanzenbach@posteo.de> | 2020-04-19 20:05:26 +0200 |
---|---|---|
committer | Schanzenbach, Martin <mschanzenbach@posteo.de> | 2020-04-19 20:05:26 +0200 |
commit | 8f9a45e853d9759f04a5f4fe9aa0146ed3f3fb17 (patch) | |
tree | b9ef6928b2fdb8647a8c7d3e0f6d316198b51d48 /src/revocation/revocation_api.c | |
parent | eb6b547e243144f27749811c15b6cce90e03aaa7 (diff) | |
download | gnunet-8f9a45e853d9759f04a5f4fe9aa0146ed3f3fb17.tar.gz gnunet-8f9a45e853d9759f04a5f4fe9aa0146ed3f3fb17.zip |
towards less variance
Diffstat (limited to 'src/revocation/revocation_api.c')
-rw-r--r-- | src/revocation/revocation_api.c | 198 |
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 | ||
54 | struct BestPow | ||
55 | { | ||
56 | uint64_t pow; | ||
57 | unsigned int bits; | ||
58 | }; | ||
59 | |||
60 | struct 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 | */ |
247 | struct GNUNET_REVOCATION_Handle * | 262 | struct GNUNET_REVOCATION_Handle * |
248 | GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg, | 263 | GNUNET_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 | */ | ||
358 | static unsigned int | ||
359 | calculate_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 | */ |
357 | int | 379 | int |
358 | GNUNET_REVOCATION_check_pow (const struct GNUNET_CRYPTO_EcdsaPublicKey *key, | 380 | GNUNET_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 | |||
423 | struct GNUNET_REVOCATION_PowCalculationHandle* | ||
424 | GNUNET_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 | */ | ||
452 | int | ||
453 | GNUNET_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 | |||
493 | const struct GNUNET_REVOCATION_Pow* | ||
494 | GNUNET_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 | |||
502 | void | ||
503 | GNUNET_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 | */ |
393 | void | 516 | void |
394 | GNUNET_REVOCATION_sign_revocation (const struct | 517 | GNUNET_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 | ||