diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-11-19 19:46:30 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-11-19 19:46:30 +0000 |
commit | f93a17240ae3e809ff6ef84af917c600306df3ff (patch) | |
tree | 830fa595e5e6218c5285b8b3fc249bded2ac1bb9 /src/revocation | |
parent | 332160659373044ac0c2a15a799a55cf7d113ee9 (diff) | |
download | gnunet-f93a17240ae3e809ff6ef84af917c600306df3ff.tar.gz gnunet-f93a17240ae3e809ff6ef84af917c600306df3ff.zip |
-implementing revocation set union
Diffstat (limited to 'src/revocation')
-rw-r--r-- | src/revocation/gnunet-service-revocation.c | 229 |
1 files changed, 213 insertions, 16 deletions
diff --git a/src/revocation/gnunet-service-revocation.c b/src/revocation/gnunet-service-revocation.c index 5a7170de6..11f3fab77 100644 --- a/src/revocation/gnunet-service-revocation.c +++ b/src/revocation/gnunet-service-revocation.c | |||
@@ -31,7 +31,6 @@ | |||
31 | * peers that connect. | 31 | * peers that connect. |
32 | * | 32 | * |
33 | * TODO: | 33 | * TODO: |
34 | * - handle p2p connect (trigger SET union, #3057) | ||
35 | * - optimization: avoid sending revocation back to peer that we got it from; | 34 | * - optimization: avoid sending revocation back to peer that we got it from; |
36 | * - optimization: have randomized delay in sending revocations to other peers | 35 | * - optimization: have randomized delay in sending revocations to other peers |
37 | * to make it rare to traverse each link twice (NSE-style) | 36 | * to make it rare to traverse each link twice (NSE-style) |
@@ -66,6 +65,16 @@ struct PeerEntry | |||
66 | */ | 65 | */ |
67 | struct GNUNET_PeerIdentity id; | 66 | struct GNUNET_PeerIdentity id; |
68 | 67 | ||
68 | /** | ||
69 | * Tasked used to trigger the set union operation. | ||
70 | */ | ||
71 | GNUNET_SCHEDULER_TaskIdentifier transmit_task; | ||
72 | |||
73 | /** | ||
74 | * Handle to active set union operation (over revocation sets). | ||
75 | */ | ||
76 | struct GNUNET_SET_OperationHandle *so; | ||
77 | |||
69 | }; | 78 | }; |
70 | 79 | ||
71 | 80 | ||
@@ -121,10 +130,22 @@ static struct GNUNET_SERVER_NotificationContext *nc; | |||
121 | static struct GNUNET_DISK_FileHandle *revocation_db; | 130 | static struct GNUNET_DISK_FileHandle *revocation_db; |
122 | 131 | ||
123 | /** | 132 | /** |
133 | * Handle for us listening to incoming revocation set union requests. | ||
134 | */ | ||
135 | static struct GNUNET_SET_ListenHandle *revocation_union_listen_handle; | ||
136 | |||
137 | /** | ||
124 | * Amount of work required (W-bit collisions) for REVOCATION proofs, in collision-bits. | 138 | * Amount of work required (W-bit collisions) for REVOCATION proofs, in collision-bits. |
125 | */ | 139 | */ |
126 | static unsigned long long revocation_work_required; | 140 | static unsigned long long revocation_work_required; |
127 | 141 | ||
142 | /** | ||
143 | * Our application ID for set union operations. Must be the | ||
144 | * same for all (compatible) peers. | ||
145 | */ | ||
146 | static struct GNUNET_HashCode revocation_set_union_app_id; | ||
147 | |||
148 | |||
128 | 149 | ||
129 | /** | 150 | /** |
130 | * An revoke message has been received, check that it is well-formed. | 151 | * An revoke message has been received, check that it is well-formed. |
@@ -360,6 +381,105 @@ handle_p2p_revoke_message (void *cls, | |||
360 | } | 381 | } |
361 | 382 | ||
362 | 383 | ||
384 | |||
385 | /** | ||
386 | * Callback for set operation results. Called for each element in the | ||
387 | * result set. Each element contains a revocation, which we should | ||
388 | * validate and then add to our revocation list (and set). | ||
389 | * | ||
390 | * @param cls closure | ||
391 | * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK | ||
392 | * @param status see `enum GNUNET_SET_Status` | ||
393 | */ | ||
394 | static void | ||
395 | add_revocation (void *cls, | ||
396 | const struct GNUNET_SET_Element *element, | ||
397 | enum GNUNET_SET_Status status) | ||
398 | { | ||
399 | struct PeerEntry *peer_entry = cls; | ||
400 | const struct RevokeMessage *rm; | ||
401 | |||
402 | switch (status) | ||
403 | { | ||
404 | case GNUNET_SET_STATUS_OK: | ||
405 | if (element->size != sizeof (struct RevokeMessage)) | ||
406 | { | ||
407 | GNUNET_break_op (0); | ||
408 | return; | ||
409 | } | ||
410 | if (0 != element->type) | ||
411 | { | ||
412 | GNUNET_STATISTICS_update (stats, | ||
413 | "# unsupported revocations received via set union", | ||
414 | 1, GNUNET_NO); | ||
415 | return; | ||
416 | } | ||
417 | rm = element->data; | ||
418 | (void) handle_p2p_revoke_message (NULL, | ||
419 | &peer_entry->id, | ||
420 | &rm->header); | ||
421 | GNUNET_STATISTICS_update (stats, | ||
422 | "# revocation messages received via set union", | ||
423 | 1, GNUNET_NO); | ||
424 | break; | ||
425 | case GNUNET_SET_STATUS_TIMEOUT: | ||
426 | case GNUNET_SET_STATUS_FAILURE: | ||
427 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
428 | _("Error computing revocation set union with %s\n"), | ||
429 | GNUNET_i2s (&peer_entry->id)); | ||
430 | peer_entry->so = NULL; | ||
431 | GNUNET_STATISTICS_update (stats, "# revocation set unions failed", | ||
432 | 1, GNUNET_NO); | ||
433 | break; | ||
434 | case GNUNET_SET_STATUS_HALF_DONE: | ||
435 | break; | ||
436 | case GNUNET_SET_STATUS_DONE: | ||
437 | peer_entry->so = NULL; | ||
438 | GNUNET_STATISTICS_update (stats, "# revocation set unions completed", | ||
439 | 1, GNUNET_NO); | ||
440 | break; | ||
441 | default: | ||
442 | GNUNET_break (0); | ||
443 | break; | ||
444 | } | ||
445 | } | ||
446 | |||
447 | |||
448 | /** | ||
449 | * The timeout for performing the set union has expired, | ||
450 | * run the set operation on the revocation certificates. | ||
451 | * | ||
452 | * @param cls NULL | ||
453 | * @param tc scheduler context (unused) | ||
454 | */ | ||
455 | static void | ||
456 | transmit_task_cb (void *cls, | ||
457 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
458 | { | ||
459 | struct PeerEntry *peer_entry = cls; | ||
460 | uint16_t salt; | ||
461 | |||
462 | salt = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
463 | UINT16_MAX); | ||
464 | peer_entry->transmit_task = GNUNET_SCHEDULER_NO_TASK; | ||
465 | peer_entry->so = GNUNET_SET_prepare (&peer_entry->id, | ||
466 | &revocation_set_union_app_id, | ||
467 | NULL, salt, | ||
468 | GNUNET_SET_RESULT_ADDED, | ||
469 | &add_revocation, | ||
470 | peer_entry); | ||
471 | if (GNUNET_OK != | ||
472 | GNUNET_SET_commit (peer_entry->so, | ||
473 | revocation_set)) | ||
474 | { | ||
475 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
476 | _("SET service crashed, terminating revocation service\n")); | ||
477 | GNUNET_SCHEDULER_shutdown (); | ||
478 | return; | ||
479 | } | ||
480 | } | ||
481 | |||
482 | |||
363 | /** | 483 | /** |
364 | * Method called whenever a peer connects. Sets up the PeerEntry and | 484 | * Method called whenever a peer connects. Sets up the PeerEntry and |
365 | * schedules the initial revocation set exchange with this peer. | 485 | * schedules the initial revocation set exchange with this peer. |
@@ -372,22 +492,38 @@ handle_core_connect (void *cls, | |||
372 | const struct GNUNET_PeerIdentity *peer) | 492 | const struct GNUNET_PeerIdentity *peer) |
373 | { | 493 | { |
374 | struct PeerEntry *peer_entry; | 494 | struct PeerEntry *peer_entry; |
495 | struct GNUNET_HashCode my_hash; | ||
496 | struct GNUNET_HashCode peer_hash; | ||
375 | 497 | ||
376 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s' connected to us\n", | 498 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
499 | "Peer `%s' connected to us\n", | ||
377 | GNUNET_i2s (peer)); | 500 | GNUNET_i2s (peer)); |
378 | peer_entry = GNUNET_new (struct PeerEntry); | 501 | peer_entry = GNUNET_CONTAINER_multipeermap_get (peers, |
379 | peer_entry->id = *peer; | 502 | peer); |
503 | if (NULL == peer_entry) | ||
504 | { | ||
505 | peer_entry = GNUNET_new (struct PeerEntry); | ||
506 | peer_entry->id = *peer; | ||
507 | GNUNET_assert (GNUNET_OK == | ||
508 | GNUNET_CONTAINER_multipeermap_put (peers, peer, | ||
509 | peer_entry, | ||
510 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
511 | } | ||
512 | else | ||
513 | { | ||
514 | GNUNET_assert (NULL == peer_entry->mq); | ||
515 | } | ||
380 | peer_entry->mq = GNUNET_CORE_mq_create (core_api, peer); | 516 | peer_entry->mq = GNUNET_CORE_mq_create (core_api, peer); |
381 | GNUNET_assert (GNUNET_OK == | 517 | GNUNET_CRYPTO_hash (&my_identity, sizeof (my_identity), &my_hash); |
382 | GNUNET_CONTAINER_multipeermap_put (peers, peer, | 518 | GNUNET_CRYPTO_hash (peer, sizeof (*peer), &peer_hash); |
383 | peer_entry, | 519 | if (0 < GNUNET_CRYPTO_hash_cmp (&my_hash, |
384 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | 520 | &peer_hash)) |
385 | // GNUNET_break (0); // FIXME: implement revocation set union on connect! | 521 | { |
386 | #if 0 | 522 | peer_entry->transmit_task = |
387 | peer_entry->transmit_task = | 523 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, |
388 | GNUNET_SCHEDULER_add_delayed (get_transmit_delay (-1), &transmit_task_cb, | 524 | &transmit_task_cb, |
389 | peer_entry); | 525 | peer_entry); |
390 | #endif | 526 | } |
391 | GNUNET_STATISTICS_update (stats, "# peers connected", 1, GNUNET_NO); | 527 | GNUNET_STATISTICS_update (stats, "# peers connected", 1, GNUNET_NO); |
392 | } | 528 | } |
393 | 529 | ||
@@ -418,13 +554,16 @@ handle_core_disconnect (void *cls, | |||
418 | GNUNET_CONTAINER_multipeermap_remove (peers, peer, | 554 | GNUNET_CONTAINER_multipeermap_remove (peers, peer, |
419 | pos)); | 555 | pos)); |
420 | GNUNET_MQ_destroy (pos->mq); | 556 | GNUNET_MQ_destroy (pos->mq); |
421 | #if 0 | ||
422 | if (pos->transmit_task != GNUNET_SCHEDULER_NO_TASK) | 557 | if (pos->transmit_task != GNUNET_SCHEDULER_NO_TASK) |
423 | { | 558 | { |
424 | GNUNET_SCHEDULER_cancel (pos->transmit_task); | 559 | GNUNET_SCHEDULER_cancel (pos->transmit_task); |
425 | pos->transmit_task = GNUNET_SCHEDULER_NO_TASK; | 560 | pos->transmit_task = GNUNET_SCHEDULER_NO_TASK; |
426 | } | 561 | } |
427 | #endif | 562 | if (NULL != pos->so) |
563 | { | ||
564 | GNUNET_SET_operation_cancel (pos->so); | ||
565 | pos->so = NULL; | ||
566 | } | ||
428 | GNUNET_free (pos); | 567 | GNUNET_free (pos); |
429 | GNUNET_STATISTICS_update (stats, "# peers connected", -1, GNUNET_NO); | 568 | GNUNET_STATISTICS_update (stats, "# peers connected", -1, GNUNET_NO); |
430 | } | 569 | } |
@@ -463,6 +602,11 @@ shutdown_task (void *cls, | |||
463 | GNUNET_SET_destroy (revocation_set); | 602 | GNUNET_SET_destroy (revocation_set); |
464 | revocation_set = NULL; | 603 | revocation_set = NULL; |
465 | } | 604 | } |
605 | if (NULL != revocation_union_listen_handle) | ||
606 | { | ||
607 | GNUNET_SET_listen_cancel (revocation_union_listen_handle); | ||
608 | revocation_union_listen_handle = NULL; | ||
609 | } | ||
466 | if (NULL != core_api) | 610 | if (NULL != core_api) |
467 | { | 611 | { |
468 | GNUNET_CORE_disconnect (core_api); | 612 | GNUNET_CORE_disconnect (core_api); |
@@ -517,6 +661,52 @@ core_init (void *cls, | |||
517 | 661 | ||
518 | 662 | ||
519 | /** | 663 | /** |
664 | * Called when another peer wants to do a set operation with the | ||
665 | * local peer. If a listen error occurs, the 'request' is NULL. | ||
666 | * | ||
667 | * @param cls closure | ||
668 | * @param other_peer the other peer | ||
669 | * @param context_msg message with application specific information from | ||
670 | * the other peer | ||
671 | * @param request request from the other peer (never NULL), use GNUNET_SET_accept() | ||
672 | * to accept it, otherwise the request will be refused | ||
673 | * Note that we can't just return value from the listen callback, | ||
674 | * as it is also necessary to specify the set we want to do the | ||
675 | * operation with, whith sometimes can be derived from the context | ||
676 | * message. It's necessary to specify the timeout. | ||
677 | */ | ||
678 | static void | ||
679 | handle_revocation_union_request (void *cls, | ||
680 | const struct GNUNET_PeerIdentity *other_peer, | ||
681 | const struct GNUNET_MessageHeader *context_msg, | ||
682 | struct GNUNET_SET_Request *request) | ||
683 | { | ||
684 | struct PeerEntry *peer_entry; | ||
685 | |||
686 | if (NULL == request) | ||
687 | { | ||
688 | GNUNET_break (0); | ||
689 | return; | ||
690 | } | ||
691 | peer_entry = GNUNET_CONTAINER_multipeermap_get (peers, | ||
692 | other_peer); | ||
693 | if (NULL == peer_entry) | ||
694 | { | ||
695 | peer_entry = GNUNET_new (struct PeerEntry); | ||
696 | peer_entry->id = *other_peer; | ||
697 | GNUNET_assert (GNUNET_OK == | ||
698 | GNUNET_CONTAINER_multipeermap_put (peers, other_peer, | ||
699 | peer_entry, | ||
700 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
701 | } | ||
702 | peer_entry->so = GNUNET_SET_accept (request, | ||
703 | GNUNET_SET_RESULT_ADDED, | ||
704 | &add_revocation, | ||
705 | peer_entry); | ||
706 | } | ||
707 | |||
708 | |||
709 | /** | ||
520 | * Handle network size estimate clients. | 710 | * Handle network size estimate clients. |
521 | * | 711 | * |
522 | * @param cls closure | 712 | * @param cls closure |
@@ -584,7 +774,11 @@ run (void *cls, | |||
584 | } | 774 | } |
585 | revocation_set = GNUNET_SET_create (cfg, | 775 | revocation_set = GNUNET_SET_create (cfg, |
586 | GNUNET_SET_OPERATION_UNION); | 776 | GNUNET_SET_OPERATION_UNION); |
587 | 777 | revocation_union_listen_handle = GNUNET_SET_listen (cfg, | |
778 | GNUNET_SET_OPERATION_UNION, | ||
779 | &revocation_set_union_app_id, | ||
780 | &handle_revocation_union_request, | ||
781 | NULL); | ||
588 | revocation_db = GNUNET_DISK_file_open (fn, | 782 | revocation_db = GNUNET_DISK_file_open (fn, |
589 | GNUNET_DISK_OPEN_READWRITE | | 783 | GNUNET_DISK_OPEN_READWRITE | |
590 | GNUNET_DISK_OPEN_CREATE, | 784 | GNUNET_DISK_OPEN_CREATE, |
@@ -667,6 +861,9 @@ int | |||
667 | main (int argc, | 861 | main (int argc, |
668 | char *const *argv) | 862 | char *const *argv) |
669 | { | 863 | { |
864 | GNUNET_CRYPTO_hash ("revocation-set-union-application-id", | ||
865 | strlen ("revocation-set-union-application-id"), | ||
866 | &revocation_set_union_app_id); | ||
670 | return (GNUNET_OK == | 867 | return (GNUNET_OK == |
671 | GNUNET_SERVICE_run (argc, argv, "revocation", GNUNET_SERVICE_OPTION_NONE, | 868 | GNUNET_SERVICE_run (argc, argv, "revocation", GNUNET_SERVICE_OPTION_NONE, |
672 | &run, NULL)) ? 0 : 1; | 869 | &run, NULL)) ? 0 : 1; |