From 8f9a45e853d9759f04a5f4fe9aa0146ed3f3fb17 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Sun, 19 Apr 2020 20:05:26 +0200 Subject: [PATCH] towards less variance --- src/include/gnunet_revocation_service.h | 89 +++++++-- src/revocation/gnunet-revocation.c | 137 ++++++-------- src/revocation/gnunet-service-revocation.c | 16 +- src/revocation/plugin_block_revocation.c | 16 +- src/revocation/revocation.h | 24 +-- src/revocation/revocation_api.c | 198 +++++++++++++++++---- 6 files changed, 310 insertions(+), 170 deletions(-) diff --git a/src/include/gnunet_revocation_service.h b/src/include/gnunet_revocation_service.h index 1e1abb787..775da01ac 100644 --- a/src/include/gnunet_revocation_service.h +++ b/src/include/gnunet_revocation_service.h @@ -50,6 +50,47 @@ extern "C" */ #define GNUNET_REVOCATION_VERSION 0x00000000 +/** + * The proof-of-work narrowing factor. + * The number of PoWs that are calculates as part of revocation. + */ +#define POW_COUNT 32 + +struct GNUNET_REVOCATION_Pow +{ + /** + * The timestamp of the revocation + */ + struct GNUNET_TIME_AbsoluteNBO timestamp; + + /** + * The TTL of this revocation (purely informational) + */ + uint64_t ttl; + + /** + * The PoWs + */ + uint64_t pow[POW_COUNT]; + + /** + * The signature + */ + struct GNUNET_CRYPTO_EcdsaSignature signature; + + /** + * The signature purpose + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * The revoked public key + */ + struct GNUNET_CRYPTO_EcdsaPublicKey key; +}; + +struct GNUNET_REVOCATION_PowCalculationHandle; + /** * Handle for the key revocation query. */ @@ -116,10 +157,7 @@ struct GNUNET_REVOCATION_Handle; */ struct GNUNET_REVOCATION_Handle * GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_CRYPTO_EcdsaPublicKey *key, - const struct GNUNET_CRYPTO_EcdsaSignature *sig, - const struct GNUNET_TIME_Absolute *ts, - uint64_t pow, + const struct GNUNET_REVOCATION_Pow *pow, GNUNET_REVOCATION_Callback func, void *func_cls); @@ -143,12 +181,42 @@ GNUNET_REVOCATION_revoke_cancel (struct GNUNET_REVOCATION_Handle *h); * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not */ int -GNUNET_REVOCATION_check_pow (const struct GNUNET_CRYPTO_EcdsaPublicKey *key, - const struct GNUNET_TIME_Absolute *ts, - uint64_t pow, +GNUNET_REVOCATION_check_pow (const struct GNUNET_REVOCATION_Pow *pow, unsigned int matching_bits); +struct GNUNET_REVOCATION_PowCalculationHandle* +GNUNET_REVOCATION_pow_init (const struct GNUNET_CRYPTO_EcdsaPublicKey *key, + int epochs, + unsigned int difficulty); + + +/** + * Calculate a key revocation valid for broadcasting for a number + * of epochs. + * + * @param pc handle to the PoW, initially called with NULL. + * @param epochs number of epochs for which the revocation must be valid. + * @param pow current pow value to try + * @param difficulty current base difficulty to achieve + * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not + */ +int +GNUNET_REVOCATION_pow_round (struct GNUNET_REVOCATION_PowCalculationHandle *pc); + + +const struct GNUNET_REVOCATION_Pow* +GNUNET_REVOCATION_pow_get (const struct + GNUNET_REVOCATION_PowCalculationHandle *pc); + + +void +GNUNET_REVOCATION_pow_cleanup (struct + GNUNET_REVOCATION_PowCalculationHandle *pc); + + + + /** * Create a revocation signature. * @@ -156,9 +224,10 @@ GNUNET_REVOCATION_check_pow (const struct GNUNET_CRYPTO_EcdsaPublicKey *key, * @param sig where to write the revocation signature */ void -GNUNET_REVOCATION_sign_revocation (const struct - GNUNET_CRYPTO_EcdsaPrivateKey *key, - struct GNUNET_CRYPTO_EcdsaSignature *sig); +GNUNET_REVOCATION_sign_revocation (struct + GNUNET_REVOCATION_Pow *pow, + const struct + GNUNET_CRYPTO_EcdsaPrivateKey *key); #if 0 /* keep Emacsens' auto-indent happy */ diff --git a/src/revocation/gnunet-revocation.c b/src/revocation/gnunet-revocation.c index 42ec71d16..2d83da8b6 100644 --- a/src/revocation/gnunet-revocation.c +++ b/src/revocation/gnunet-revocation.c @@ -218,16 +218,12 @@ struct RevocationData * Perform the revocation. */ static void -perform_revocation (const struct RevocationData *rd) +perform_revocation (const struct GNUNET_REVOCATION_Pow *pow) { struct GNUNET_TIME_Absolute ts; - ts = GNUNET_TIME_absolute_ntoh (rd->ts); h = GNUNET_REVOCATION_revoke (cfg, - &rd->key, - &rd->sig, - &ts, - rd->pow, + pow, &print_revocation_result, NULL); } @@ -240,13 +236,13 @@ perform_revocation (const struct RevocationData *rd) * @param rd data to sync */ static void -sync_rd (const struct RevocationData *rd) +sync_pow (const struct GNUNET_REVOCATION_Pow *pow) { if ((NULL != filename) && - (sizeof(struct RevocationData) == + (sizeof(struct GNUNET_REVOCATION_Pow) == GNUNET_DISK_fn_write (filename, - &rd, - sizeof(rd), + &pow, + sizeof(pow), GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE))) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", filename); @@ -261,15 +257,14 @@ sync_rd (const struct RevocationData *rd) static void calculate_pow_shutdown (void *cls) { - struct RevocationData *rd = cls; + struct GNUNET_REVOCATION_PowCalculationHandle *ph = cls; if (NULL != pow_task) { GNUNET_SCHEDULER_cancel (pow_task); pow_task = NULL; } - sync_rd (rd); - GNUNET_free (rd); + GNUNET_REVOCATION_pow_cleanup (ph); } @@ -281,40 +276,27 @@ calculate_pow_shutdown (void *cls) static void calculate_pow (void *cls) { - struct RevocationData *rd = cls; - struct GNUNET_TIME_Absolute ts = GNUNET_TIME_absolute_ntoh (rd->ts); + struct GNUNET_REVOCATION_PowCalculationHandle *ph = cls; /* store temporary results */ pow_task = NULL; - if (0 == (rd->pow % 128)) - sync_rd (rd); - /* display progress estimate */ - if ((0 == ((1 << matching_bits) / 100 / 50)) || - (0 == (rd->pow % ((1 << matching_bits) / 100 / 50)))) - fprintf (stderr, "%s", "."); - if ((0 != rd->pow) && ((0 == ((1 << matching_bits) / 100)) || - (0 == (rd->pow % ((1 << matching_bits) / 100))))) - fprintf (stderr, - " - @ %3u%% (estimate)\n", - (unsigned int) (rd->pow * 100) / (1 << matching_bits)); + //if (0 == (rd->pow % 128)) + // sync_rd (rd); /* actually do POW calculation */ - rd->pow++; - if (GNUNET_OK == GNUNET_REVOCATION_check_pow (&rd->key, - &ts, - rd->pow, - (unsigned int) matching_bits)) + if (GNUNET_OK == GNUNET_REVOCATION_pow_round (ph)) { + const struct GNUNET_REVOCATION_Pow *pow = GNUNET_REVOCATION_pow_get (ph); if ((NULL != filename) && - (sizeof(struct RevocationData) != + (sizeof(struct GNUNET_REVOCATION_Pow) != GNUNET_DISK_fn_write (filename, - rd, - sizeof(struct RevocationData), + pow, + sizeof(struct GNUNET_REVOCATION_Pow), GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE))) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", filename); if (perform) { - perform_revocation (rd); + perform_revocation (pow); } else { @@ -327,7 +309,7 @@ calculate_pow (void *cls) } return; } - pow_task = GNUNET_SCHEDULER_add_now (&calculate_pow, rd); + pow_task = GNUNET_SCHEDULER_add_now (&calculate_pow, ph); } @@ -340,9 +322,8 @@ calculate_pow (void *cls) static void ego_callback (void *cls, const struct GNUNET_IDENTITY_Ego *ego) { - struct RevocationData *rd; + struct GNUNET_REVOCATION_Pow *pow; struct GNUNET_CRYPTO_EcdsaPublicKey key; - struct GNUNET_TIME_Absolute ts; el = NULL; if (NULL == ego) @@ -352,49 +333,49 @@ ego_callback (void *cls, const struct GNUNET_IDENTITY_Ego *ego) return; } GNUNET_IDENTITY_ego_get_public_key (ego, &key); - rd = GNUNET_new (struct RevocationData); + pow = GNUNET_new (struct GNUNET_REVOCATION_Pow); if ((NULL != filename) && (GNUNET_YES == GNUNET_DISK_file_test (filename)) && - (sizeof(struct RevocationData) == - GNUNET_DISK_fn_read (filename, rd, sizeof(struct RevocationData)))) + (sizeof(struct GNUNET_REVOCATION_Pow) == + GNUNET_DISK_fn_read (filename, pow, sizeof(struct + GNUNET_REVOCATION_Pow)))) { - if (0 != GNUNET_memcmp (&rd->key, &key)) + if (0 != GNUNET_memcmp (&pow->key, &key)) { fprintf (stderr, _ ("Error: revocation certificate in `%s' is not for `%s'\n"), filename, revoke_ego); - GNUNET_free (rd); + GNUNET_free (pow); return; } - } - else - { - GNUNET_REVOCATION_sign_revocation (GNUNET_IDENTITY_ego_get_private_key ( - ego), - &rd->sig); - rd->key = key; - rd->ts = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); - } - ts = GNUNET_TIME_absolute_ntoh (rd->ts); - if (GNUNET_YES == - GNUNET_REVOCATION_check_pow (&key, - &ts, - rd->pow, - (unsigned int) matching_bits)) - { - fprintf (stderr, "%s", _ ("Revocation certificate ready\n")); - if (perform) - perform_revocation (rd); - else - GNUNET_SCHEDULER_shutdown (); - GNUNET_free (rd); + if (GNUNET_YES == + GNUNET_REVOCATION_check_pow (pow, + (unsigned int) matching_bits)) + { + fprintf (stderr, "%s", _ ("Revocation certificate ready\n")); + if (perform) + perform_revocation (pow); + else + GNUNET_SCHEDULER_shutdown (); + GNUNET_free (pow); + return; + } + fprintf (stderr, + _ ("Error: revocation certificate in `%s' invalid\n"), + filename); + GNUNET_free (pow); return; } fprintf (stderr, "%s", _ ("Revocation certificate not ready, calculating proof of work\n")); - pow_task = GNUNET_SCHEDULER_add_now (&calculate_pow, rd); - GNUNET_SCHEDULER_add_shutdown (&calculate_pow_shutdown, rd); + GNUNET_free (pow); + struct GNUNET_REVOCATION_PowCalculationHandle *ph; + ph = GNUNET_REVOCATION_pow_init (&key, + 1, /* Epochs */ + matching_bits); + pow_task = GNUNET_SCHEDULER_add_now (&calculate_pow, ph); + GNUNET_SCHEDULER_add_shutdown (&calculate_pow_shutdown, ph); } @@ -413,8 +394,7 @@ run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c) { struct GNUNET_CRYPTO_EcdsaPublicKey pk; - struct RevocationData rd; - struct GNUNET_TIME_Absolute ts; + struct GNUNET_REVOCATION_Pow pow; cfg = c; if (NULL != test_ego) @@ -463,7 +443,7 @@ run (void *cls, } if ((NULL != filename) && (perform)) { - if (sizeof(rd) != GNUNET_DISK_fn_read (filename, &rd, sizeof(rd))) + if (sizeof(pow) != GNUNET_DISK_fn_read (filename, &pow, sizeof(pow))) { fprintf (stderr, _ ("Failed to read revocation certificate from `%s'\n"), @@ -471,21 +451,20 @@ run (void *cls, return; } GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); - ts = GNUNET_TIME_absolute_ntoh (rd.ts); if (GNUNET_YES != - GNUNET_REVOCATION_check_pow (&rd.key, - &ts, - rd.pow, + GNUNET_REVOCATION_check_pow (&pow, (unsigned int) matching_bits)) { - struct RevocationData *cp = GNUNET_new (struct RevocationData); + struct GNUNET_REVOCATION_PowCalculationHandle *ph; + ph = GNUNET_REVOCATION_pow_init (&pk, + 1, /* Epochs */ + matching_bits); - *cp = rd; - pow_task = GNUNET_SCHEDULER_add_now (&calculate_pow, cp); - GNUNET_SCHEDULER_add_shutdown (&calculate_pow_shutdown, cp); + pow_task = GNUNET_SCHEDULER_add_now (&calculate_pow, ph); + GNUNET_SCHEDULER_add_shutdown (&calculate_pow_shutdown, ph); return; } - perform_revocation (&rd); + perform_revocation (&pow); return; } fprintf (stderr, "%s", _ ("No action specified. Nothing to do.\n")); diff --git a/src/revocation/gnunet-service-revocation.c b/src/revocation/gnunet-service-revocation.c index ff75faa2c..420cb392f 100644 --- a/src/revocation/gnunet-service-revocation.c +++ b/src/revocation/gnunet-service-revocation.c @@ -167,12 +167,8 @@ new_peer_entry (const struct GNUNET_PeerIdentity *peer) static int verify_revoke_message (const struct RevokeMessage *rm) { - struct GNUNET_TIME_Absolute ts; - ts = GNUNET_TIME_absolute_ntoh (rm->ts); if (GNUNET_YES != - GNUNET_REVOCATION_check_pow (&rm->public_key, - &ts, - rm->proof_of_work, + GNUNET_REVOCATION_check_pow (&rm->proof_of_work, (unsigned int) revocation_work_required)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -182,9 +178,9 @@ verify_revoke_message (const struct RevokeMessage *rm) } if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify_ (GNUNET_SIGNATURE_PURPOSE_REVOCATION, - &rm->purpose, - &rm->signature, - &rm->public_key)) + &rm->proof_of_work.purpose, + &rm->proof_of_work.signature, + &rm->proof_of_work.key)) { GNUNET_break_op (0); return GNUNET_NO; @@ -311,7 +307,7 @@ publicize_rm (const struct RevokeMessage *rm) struct GNUNET_HashCode hc; struct GNUNET_SET_Element e; - GNUNET_CRYPTO_hash (&rm->public_key, + GNUNET_CRYPTO_hash (&rm->proof_of_work.key, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey), &hc); if (GNUNET_YES == @@ -896,7 +892,7 @@ run (void *cls, return; } GNUNET_break (0 == ntohl (rm->reserved)); - GNUNET_CRYPTO_hash (&rm->public_key, + GNUNET_CRYPTO_hash (&rm->proof_of_work.key, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey), &hc); GNUNET_break (GNUNET_OK == diff --git a/src/revocation/plugin_block_revocation.c b/src/revocation/plugin_block_revocation.c index 57234fa36..a57a933c3 100644 --- a/src/revocation/plugin_block_revocation.c +++ b/src/revocation/plugin_block_revocation.c @@ -134,7 +134,6 @@ block_plugin_revocation_evaluate (void *cls, struct InternalContext *ic = cls; struct GNUNET_HashCode chash; const struct RevokeMessage *rm = reply_block; - struct GNUNET_TIME_Absolute ts; if (NULL == reply_block) return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; @@ -143,11 +142,8 @@ block_plugin_revocation_evaluate (void *cls, GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } - ts = GNUNET_TIME_absolute_ntoh (rm->ts); if (GNUNET_YES != - GNUNET_REVOCATION_check_pow (&rm->public_key, - &ts, - rm->proof_of_work, + GNUNET_REVOCATION_check_pow (&rm->proof_of_work, ic->matching_bits)) { GNUNET_break_op (0); @@ -155,14 +151,14 @@ block_plugin_revocation_evaluate (void *cls, } if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify_ (GNUNET_SIGNATURE_PURPOSE_REVOCATION, - &rm->purpose, - &rm->signature, - &rm->public_key)) + &rm->proof_of_work.purpose, + &rm->proof_of_work.signature, + &rm->proof_of_work.key)) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } - GNUNET_CRYPTO_hash (&rm->public_key, + GNUNET_CRYPTO_hash (&rm->proof_of_work.key, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey), &chash); if (GNUNET_YES == @@ -198,7 +194,7 @@ block_plugin_revocation_get_key (void *cls, GNUNET_break_op (0); return GNUNET_SYSERR; } - GNUNET_CRYPTO_hash (&rm->public_key, + GNUNET_CRYPTO_hash (&rm->proof_of_work.key, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey), key); return GNUNET_OK; diff --git a/src/revocation/revocation.h b/src/revocation/revocation.h index d7b9cc139..b2769da0e 100644 --- a/src/revocation/revocation.h +++ b/src/revocation/revocation.h @@ -27,6 +27,7 @@ #define REVOCATION_H #include "gnunet_util_lib.h" +#include "gnunet_revocation_service.h" GNUNET_NETWORK_STRUCT_BEGIN @@ -91,28 +92,7 @@ struct RevokeMessage /** * Number that causes a hash collision with the @e public_key. */ - uint64_t proof_of_work GNUNET_PACKED; - - /** - * Timestamp - */ - struct GNUNET_TIME_AbsoluteNBO ts; - - /** - * Signature confirming revocation. - */ - struct GNUNET_CRYPTO_EcdsaSignature signature; - - /** - * Must have purpose #GNUNET_SIGNATURE_PURPOSE_REVOCATION, - * size expands over the public key. (@deprecated) - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Key to revoke. - */ - struct GNUNET_CRYPTO_EcdsaPublicKey public_key; + struct GNUNET_REVOCATION_Pow proof_of_work GNUNET_PACKED; }; 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 void *func_cls; }; +struct BestPow +{ + uint64_t pow; + unsigned int bits; +}; + +struct GNUNET_REVOCATION_PowCalculationHandle +{ + struct BestPow best[POW_COUNT]; + struct GNUNET_REVOCATION_Pow pow; + uint64_t current_pow; + unsigned int epochs; + unsigned int difficulty; + int valid; +}; /** * Generic error handler, called with the appropriate @@ -246,10 +261,7 @@ handle_revocation_response (void *cls, */ struct GNUNET_REVOCATION_Handle * GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_CRYPTO_EcdsaPublicKey *key, - const struct GNUNET_CRYPTO_EcdsaSignature *sig, - const struct GNUNET_TIME_Absolute *ts, - uint64_t pow, + const struct GNUNET_REVOCATION_Pow *pow, GNUNET_REVOCATION_Callback func, void *func_cls) { @@ -272,9 +284,7 @@ GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg, "WORKBITS", &matching_bits)) && (GNUNET_YES != - GNUNET_REVOCATION_check_pow (key, - ts, - pow, + GNUNET_REVOCATION_check_pow (pow, (unsigned int) matching_bits))) { GNUNET_break (0); @@ -297,12 +307,7 @@ GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg, env = GNUNET_MQ_msg (rm, GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE); rm->reserved = htonl (0); - rm->proof_of_work = pow; - rm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_REVOCATION); - rm->purpose.size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) - + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)); - rm->public_key = *key; - rm->signature = *sig; + rm->proof_of_work = *pow; GNUNET_MQ_send (h->mq, env); return h; @@ -344,6 +349,23 @@ count_leading_zeroes (const struct GNUNET_HashCode *hash) } +/** + * Calculate the average zeros in the pows. + * + * @param ph the PowHandle + * @return the average number of zeroes. + */ +static unsigned int +calculate_score (const struct GNUNET_REVOCATION_PowCalculationHandle *ph) +{ + double sum = 0.0; + for (unsigned int j = 0; jbest[j].bits; + double avg = sum / POW_COUNT; + return avg; +} + + /** * Check if the given proof-of-work value * would be acceptable for revoking the given key. @@ -355,32 +377,133 @@ count_leading_zeroes (const struct GNUNET_HashCode *hash) * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not */ int -GNUNET_REVOCATION_check_pow (const struct GNUNET_CRYPTO_EcdsaPublicKey *key, - const struct GNUNET_TIME_Absolute *ts, - uint64_t pow, - unsigned int matching_bits) +GNUNET_REVOCATION_check_pow (const struct GNUNET_REVOCATION_Pow *pow, + unsigned int difficulty) +{ + char buf[sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey) + + sizeof (uint64_t) + + sizeof (uint64_t)] GNUNET_ALIGN; + struct GNUNET_HashCode result; + unsigned int score = 0; + unsigned int tmp_score = 0; + unsigned int epochs; + uint64_t pow_val; + + GNUNET_memcpy (&buf[sizeof(uint64_t)], + &pow->timestamp, + sizeof (uint64_t)); + GNUNET_memcpy (&buf[sizeof(uint64_t) * 2], + &pow->key, + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)); + for (unsigned int i = 0; i < POW_COUNT; i++) + { + pow_val = GNUNET_ntohll (pow->pow[i]); + GNUNET_memcpy (buf, &pow_val, sizeof(uint64_t)); + GNUNET_CRYPTO_pow_hash ("gnunet-revocation-proof-of-work", + buf, + sizeof(buf), + &result); + tmp_score = count_leading_zeroes (&result); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Score %u (#%u)\n", + tmp_score, i); + score += tmp_score; + + } + score = score / POW_COUNT; + if (score < difficulty) + return GNUNET_NO; + // TODO verfiy signature? + epochs = score - difficulty + 1; + // TODO verify expiration + return GNUNET_YES; +} + + +struct GNUNET_REVOCATION_PowCalculationHandle* +GNUNET_REVOCATION_pow_init (const struct GNUNET_CRYPTO_EcdsaPublicKey *key, + int epochs, + unsigned int difficulty) +{ + struct GNUNET_REVOCATION_PowCalculationHandle*pc; + struct GNUNET_TIME_Absolute ts = GNUNET_TIME_absolute_get(); + + pc = GNUNET_new (struct GNUNET_REVOCATION_PowCalculationHandle); + pc->pow.key = *key; + pc->pow.timestamp = GNUNET_TIME_absolute_hton(ts); + pc->current_pow = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, + UINT64_MAX); + pc->difficulty = difficulty; + pc->epochs = epochs; + return pc; +} + + +/** + * Calculate a key revocation valid for broadcasting for a number + * of epochs. + * + * @param pc handle to the PoW, initially called with NULL. + * @param epochs number of epochs for which the revocation must be valid. + * @param pow current pow value to try + * @param difficulty current base difficulty to achieve + * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not + */ +int +GNUNET_REVOCATION_pow_round (struct GNUNET_REVOCATION_PowCalculationHandle *pc) { char buf[sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey) - + sizeof(pow) - + sizeof (struct GNUNET_TIME_AbsoluteNBO)] GNUNET_ALIGN; + + sizeof (uint64_t) + + sizeof (uint64_t)] GNUNET_ALIGN; struct GNUNET_HashCode result; - struct GNUNET_TIME_AbsoluteNBO ts_nbo; + unsigned int zeros; - ts_nbo = GNUNET_TIME_absolute_hton (*ts); + pc->current_pow++; - GNUNET_memcpy (buf, &pow, sizeof(pow)); - GNUNET_memcpy (&buf[sizeof(pow)], - &ts_nbo, - sizeof (struct GNUNET_TIME_AbsoluteNBO)); - GNUNET_memcpy (&buf[sizeof(pow) + sizeof (struct GNUNET_TIME_AbsoluteNBO)], - key, + GNUNET_memcpy (buf, &pc->current_pow, sizeof(uint64_t)); + GNUNET_memcpy (&buf[sizeof(uint64_t)], + &pc->pow.timestamp, + sizeof (uint64_t)); + GNUNET_memcpy (&buf[sizeof(uint64_t) * 2], + &pc->pow.key, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)); GNUNET_CRYPTO_pow_hash ("gnunet-revocation-proof-of-work", buf, sizeof(buf), &result); - return (count_leading_zeroes (&result) >= - matching_bits) ? GNUNET_YES : GNUNET_NO; + zeros = count_leading_zeroes (&result); + for (unsigned int i = 0; i < POW_COUNT; i++) + { + if (pc->best[i].bits < zeros) + { + pc->best[i].bits = zeros; + pc->best[i].pow = pc->current_pow; + pc->pow.pow[i] = GNUNET_htonll (pc->current_pow); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "New best score %u (#%u)\n", + zeros, i); + break; + } + } + return calculate_score (pc) >= pc->difficulty + pc->epochs ? GNUNET_YES : + GNUNET_NO; +} + + +const struct GNUNET_REVOCATION_Pow* +GNUNET_REVOCATION_pow_get (const struct + GNUNET_REVOCATION_PowCalculationHandle *pc) +{ + return calculate_score (pc) >= pc->difficulty + pc->epochs ? &pc->pow : + NULL; +} + + +void +GNUNET_REVOCATION_pow_cleanup (struct + GNUNET_REVOCATION_PowCalculationHandle *pc) +{ + GNUNET_free (pc); } @@ -391,20 +514,17 @@ GNUNET_REVOCATION_check_pow (const struct GNUNET_CRYPTO_EcdsaPublicKey *key, * @param sig where to write the revocation signature */ void -GNUNET_REVOCATION_sign_revocation (const struct - GNUNET_CRYPTO_EcdsaPrivateKey *key, - struct GNUNET_CRYPTO_EcdsaSignature *sig) +GNUNET_REVOCATION_sign_revocation (struct GNUNET_REVOCATION_Pow *pow, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *key) { - struct RevokeMessage rm; - - rm.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_REVOCATION); - rm.purpose.size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) + pow->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_REVOCATION); + pow->purpose.size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)); - GNUNET_CRYPTO_ecdsa_key_get_public (key, &rm.public_key); + GNUNET_CRYPTO_ecdsa_key_get_public (key, &pow->key); GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_sign_ (key, - &rm.purpose, - sig)); + &pow->purpose, + &pow->signature)); } -- 2.25.1