diff options
-rw-r--r-- | contrib/defaults.conf | 1 | ||||
-rw-r--r-- | src/nse/gnunet-service-nse.c | 138 |
2 files changed, 120 insertions, 19 deletions
diff --git a/contrib/defaults.conf b/contrib/defaults.conf index 7a072f1d3..639c30f6a 100644 --- a/contrib/defaults.conf +++ b/contrib/defaults.conf | |||
@@ -431,6 +431,7 @@ ACCEPT_FROM6 = ::1; | |||
431 | UNIXPATH = /tmp/test-nse-service-nse.unix | 431 | UNIXPATH = /tmp/test-nse-service-nse.unix |
432 | UNIX_MATCH_UID = YES | 432 | UNIX_MATCH_UID = YES |
433 | UNIX_MATCH_GID = YES | 433 | UNIX_MATCH_GID = YES |
434 | PROOFFILE = $SERVICEHOME/.nse-proof | ||
434 | 435 | ||
435 | 436 | ||
436 | [vpn] | 437 | [vpn] |
diff --git a/src/nse/gnunet-service-nse.c b/src/nse/gnunet-service-nse.c index c690eb1e2..066ba3463 100644 --- a/src/nse/gnunet-service-nse.c +++ b/src/nse/gnunet-service-nse.c | |||
@@ -34,9 +34,6 @@ | |||
34 | * those peer from sending their messages at a later duration. So | 34 | * those peer from sending their messages at a later duration. So |
35 | * every peer should receive the same nearest peer message, and from | 35 | * every peer should receive the same nearest peer message, and from |
36 | * this can calculate the expected number of peers in the network. | 36 | * this can calculate the expected number of peers in the network. |
37 | * | ||
38 | * TODO: | ||
39 | * - generate proof-of-work asynchronously, store it on disk & load it back | ||
40 | */ | 37 | */ |
41 | #include "platform.h" | 38 | #include "platform.h" |
42 | #include "gnunet_util_lib.h" | 39 | #include "gnunet_util_lib.h" |
@@ -73,6 +70,11 @@ | |||
73 | */ | 70 | */ |
74 | #define GNUNET_NSE_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) | 71 | #define GNUNET_NSE_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) |
75 | 72 | ||
73 | /** | ||
74 | * Interval between proof find runs. | ||
75 | */ | ||
76 | #define PROOF_FIND_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 50) | ||
77 | |||
76 | 78 | ||
77 | /** | 79 | /** |
78 | * Per-peer information. | 80 | * Per-peer information. |
@@ -223,6 +225,11 @@ static unsigned int estimate_count; | |||
223 | static GNUNET_SCHEDULER_TaskIdentifier flood_task; | 225 | static GNUNET_SCHEDULER_TaskIdentifier flood_task; |
224 | 226 | ||
225 | /** | 227 | /** |
228 | * Task scheduled to compute our proof. | ||
229 | */ | ||
230 | static GNUNET_SCHEDULER_TaskIdentifier proof_task; | ||
231 | |||
232 | /** | ||
226 | * Notification context, simplifies client broadcasts. | 233 | * Notification context, simplifies client broadcasts. |
227 | */ | 234 | */ |
228 | static struct GNUNET_SERVER_NotificationContext *nc; | 235 | static struct GNUNET_SERVER_NotificationContext *nc; |
@@ -484,6 +491,24 @@ transmit_ready (void *cls, size_t size, void *buf) | |||
484 | &transmit_task, | 491 | &transmit_task, |
485 | peer_entry); | 492 | peer_entry); |
486 | } | 493 | } |
494 | if ( (ntohl (size_estimate_messages[idx].hop_count) == 0) && | ||
495 | (GNUNET_SCHEDULER_NO_TASK != proof_task) ) | ||
496 | { | ||
497 | GNUNET_STATISTICS_update (stats, | ||
498 | "# flood messages not generated (no proof yet)", | ||
499 | 1, | ||
500 | GNUNET_NO); | ||
501 | return 0; | ||
502 | } | ||
503 | if (ntohl (size_estimate_messages[idx].hop_count) == 0) | ||
504 | GNUNET_STATISTICS_update (stats, | ||
505 | "# flood messages started", | ||
506 | 1, | ||
507 | GNUNET_NO); | ||
508 | GNUNET_STATISTICS_update (stats, | ||
509 | "# flood messages transmitted", | ||
510 | 1, | ||
511 | GNUNET_NO); | ||
487 | memcpy (buf, | 512 | memcpy (buf, |
488 | &size_estimate_messages[idx], | 513 | &size_estimate_messages[idx], |
489 | sizeof (struct GNUNET_NSE_FloodMessage)); | 514 | sizeof (struct GNUNET_NSE_FloodMessage)); |
@@ -705,35 +730,74 @@ check_proof_of_work(const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey, | |||
705 | 730 | ||
706 | 731 | ||
707 | /** | 732 | /** |
708 | * Given a public key, find an integer such that the hash of the key | 733 | * Write our current proof to disk. |
709 | * concatenated with the integer has NSE_WORK_REQUIRED leading 0 | 734 | */ |
710 | * bits. FIXME: this is a synchronous function... bad | 735 | static void |
736 | write_proof () | ||
737 | { | ||
738 | char *proof; | ||
739 | |||
740 | if (GNUNET_OK != | ||
741 | GNUNET_CONFIGURATION_get_value_filename (cfg, | ||
742 | "NSE", "PROOFFILE", | ||
743 | &proof)) | ||
744 | return; | ||
745 | if (sizeof (my_proof) != | ||
746 | GNUNET_DISK_fn_write (proof, | ||
747 | &my_proof, | ||
748 | sizeof (my_proof), | ||
749 | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)) | ||
750 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | ||
751 | "write", | ||
752 | proof); | ||
753 | GNUNET_free (proof); | ||
754 | |||
755 | } | ||
756 | |||
757 | |||
758 | /** | ||
759 | * Find our proof of work. | ||
711 | * | 760 | * |
712 | * @param pkey the public key | 761 | * @param cls closure (unused) |
713 | * @return 64 bit number that satisfies the requirements | 762 | * @param tc task context |
714 | */ | 763 | */ |
715 | static uint64_t | 764 | static void |
716 | find_proof_of_work(const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey) | 765 | find_proof (void *cls, |
766 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
717 | { | 767 | { |
768 | #define ROUND_SIZE 10 | ||
718 | uint64_t counter; | 769 | uint64_t counter; |
719 | char buf[sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + sizeof(uint64_t)]; | 770 | char buf[sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + sizeof(uint64_t)]; |
720 | GNUNET_HashCode result; | 771 | GNUNET_HashCode result; |
772 | unsigned int i; | ||
721 | 773 | ||
774 | proof_task = GNUNET_SCHEDULER_NO_TASK; | ||
722 | memcpy (&buf[sizeof(uint64_t)], | 775 | memcpy (&buf[sizeof(uint64_t)], |
723 | pkey, | 776 | &my_public_key, |
724 | sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); | 777 | sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); |
725 | counter = 0; | 778 | i = 0; |
726 | while (counter != UINT64_MAX) | 779 | counter = my_proof; |
780 | while ( (counter != UINT64_MAX) && (i < ROUND_SIZE) ) | ||
727 | { | 781 | { |
728 | memcpy (buf, | 782 | memcpy (buf, |
729 | &counter, | 783 | &counter, |
730 | sizeof(uint64_t)); | 784 | sizeof(uint64_t)); |
731 | GNUNET_CRYPTO_hash (buf, sizeof (buf), &result); | 785 | GNUNET_CRYPTO_hash (buf, sizeof (buf), &result); |
732 | if (NSE_WORK_REQUIRED <= count_leading_zeroes(&result)) | 786 | if (NSE_WORK_REQUIRED <= count_leading_zeroes(&result)) |
733 | break; | 787 | { |
788 | my_proof = counter; | ||
789 | write_proof (); | ||
790 | return; | ||
791 | } | ||
734 | counter++; | 792 | counter++; |
793 | i++; | ||
735 | } | 794 | } |
736 | return counter; | 795 | my_proof = counter; |
796 | if (0 == (my_proof % 100 * ROUND_SIZE)) | ||
797 | write_proof (); /* remember progress every 100 rounds */ | ||
798 | proof_task = GNUNET_SCHEDULER_add_delayed (PROOF_FIND_DELAY, | ||
799 | &find_proof, | ||
800 | NULL); | ||
737 | } | 801 | } |
738 | 802 | ||
739 | 803 | ||
@@ -1011,6 +1075,12 @@ shutdown_task(void *cls, | |||
1011 | GNUNET_SCHEDULER_cancel (flood_task); | 1075 | GNUNET_SCHEDULER_cancel (flood_task); |
1012 | flood_task = GNUNET_SCHEDULER_NO_TASK; | 1076 | flood_task = GNUNET_SCHEDULER_NO_TASK; |
1013 | } | 1077 | } |
1078 | if (proof_task != GNUNET_SCHEDULER_NO_TASK) | ||
1079 | { | ||
1080 | GNUNET_SCHEDULER_cancel (proof_task); | ||
1081 | proof_task = GNUNET_SCHEDULER_NO_TASK; | ||
1082 | write_proof (); /* remember progress */ | ||
1083 | } | ||
1014 | if (nc != NULL) | 1084 | if (nc != NULL) |
1015 | { | 1085 | { |
1016 | GNUNET_SERVER_notification_context_destroy (nc); | 1086 | GNUNET_SERVER_notification_context_destroy (nc); |
@@ -1031,6 +1101,11 @@ shutdown_task(void *cls, | |||
1031 | GNUNET_CONTAINER_multihashmap_destroy (peers); | 1101 | GNUNET_CONTAINER_multihashmap_destroy (peers); |
1032 | peers = NULL; | 1102 | peers = NULL; |
1033 | } | 1103 | } |
1104 | if (my_private_key != NULL) | ||
1105 | { | ||
1106 | GNUNET_CRYPTO_rsa_key_free (my_private_key); | ||
1107 | my_private_key = NULL; | ||
1108 | } | ||
1034 | } | 1109 | } |
1035 | 1110 | ||
1036 | 1111 | ||
@@ -1060,9 +1135,7 @@ core_init (void *cls, struct GNUNET_CORE_Handle *server, | |||
1060 | GNUNET_SCHEDULER_shutdown (); | 1135 | GNUNET_SCHEDULER_shutdown (); |
1061 | return; | 1136 | return; |
1062 | } | 1137 | } |
1063 | my_identity = *identity; | 1138 | GNUNET_assert (0 == memcmp (&my_identity, identity, sizeof (struct GNUNET_PeerIdentity))); |
1064 | my_public_key = *publicKey; | ||
1065 | |||
1066 | now = GNUNET_TIME_absolute_get (); | 1139 | now = GNUNET_TIME_absolute_get (); |
1067 | current_timestamp.abs_value = (now.abs_value / GNUNET_NSE_INTERVAL.rel_value) * GNUNET_NSE_INTERVAL.rel_value; | 1140 | current_timestamp.abs_value = (now.abs_value / GNUNET_NSE_INTERVAL.rel_value) * GNUNET_NSE_INTERVAL.rel_value; |
1068 | next_timestamp.abs_value = current_timestamp.abs_value + GNUNET_NSE_INTERVAL.rel_value; | 1141 | next_timestamp.abs_value = current_timestamp.abs_value + GNUNET_NSE_INTERVAL.rel_value; |
@@ -1077,7 +1150,6 @@ core_init (void *cls, struct GNUNET_CORE_Handle *server, | |||
1077 | flood_task | 1150 | flood_task |
1078 | = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (next_timestamp), | 1151 | = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (next_timestamp), |
1079 | &update_flood_message, NULL); | 1152 | &update_flood_message, NULL); |
1080 | my_proof = find_proof_of_work (&my_public_key); | ||
1081 | } | 1153 | } |
1082 | 1154 | ||
1083 | 1155 | ||
@@ -1093,6 +1165,7 @@ run(void *cls, struct GNUNET_SERVER_Handle *server, | |||
1093 | const struct GNUNET_CONFIGURATION_Handle *c) | 1165 | const struct GNUNET_CONFIGURATION_Handle *c) |
1094 | { | 1166 | { |
1095 | char *keyfile; | 1167 | char *keyfile; |
1168 | char *proof; | ||
1096 | 1169 | ||
1097 | static const struct GNUNET_SERVER_MessageHandler handlers[] = | 1170 | static const struct GNUNET_SERVER_MessageHandler handlers[] = |
1098 | { | 1171 | { |
@@ -1124,6 +1197,33 @@ run(void *cls, struct GNUNET_SERVER_Handle *server, | |||
1124 | GNUNET_SCHEDULER_shutdown (); | 1197 | GNUNET_SCHEDULER_shutdown (); |
1125 | return; | 1198 | return; |
1126 | } | 1199 | } |
1200 | GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key); | ||
1201 | GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key), &my_identity.hashPubKey); | ||
1202 | if (GNUNET_OK != | ||
1203 | GNUNET_CONFIGURATION_get_value_filename (cfg, | ||
1204 | "NSE", "PROOFFILE", | ||
1205 | &proof)) | ||
1206 | { | ||
1207 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1208 | _ ("NSE service is lacking key configuration settings. Exiting.\n")); | ||
1209 | if (my_private_key != NULL) | ||
1210 | { | ||
1211 | GNUNET_CRYPTO_rsa_key_free (my_private_key); | ||
1212 | my_private_key = NULL; | ||
1213 | } | ||
1214 | GNUNET_SCHEDULER_shutdown (); | ||
1215 | return; | ||
1216 | } | ||
1217 | if (sizeof (my_proof) != | ||
1218 | GNUNET_DISK_fn_read (proof, | ||
1219 | &my_proof, | ||
1220 | sizeof (my_proof))) | ||
1221 | my_proof = 0; | ||
1222 | GNUNET_free (proof); | ||
1223 | proof_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, | ||
1224 | &find_proof, | ||
1225 | NULL); | ||
1226 | |||
1127 | peers = GNUNET_CONTAINER_multihashmap_create (128); | 1227 | peers = GNUNET_CONTAINER_multihashmap_create (128); |
1128 | GNUNET_SERVER_add_handlers (server, handlers); | 1228 | GNUNET_SERVER_add_handlers (server, handlers); |
1129 | nc = GNUNET_SERVER_notification_context_create (server, 1); | 1229 | nc = GNUNET_SERVER_notification_context_create (server, 1); |