diff options
Diffstat (limited to 'test_brandt.c')
-rw-r--r-- | test_brandt.c | 494 |
1 files changed, 431 insertions, 63 deletions
diff --git a/test_brandt.c b/test_brandt.c index afc178a..0a25569 100644 --- a/test_brandt.c +++ b/test_brandt.c @@ -23,6 +23,8 @@ #include "platform.h" #include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_json_lib.h> +#include <jansson.h> #include "brandt.h" #include "crypto.h" @@ -30,41 +32,52 @@ #define MIN(A, B) ((A) < (B) ? (A) : (B)) -struct msg { +struct msg +{ uint16_t sender; uint16_t receiver; void *buf; - size_t buf_len; + size_t buf_len; }; -struct testcase { - uint16_t n; - uint16_t k; +struct testcase +{ + uint16_t n; + uint16_t k; uint16_t *bids; - uint16_t m; - uint16_t outcome_public; - uint16_t ret; + uint16_t m; + uint16_t outcome_public; + uint16_t ret; struct BRANDT_Auction **ad; uint16_t *id; uint16_t *result_called; + + /* key material for signatures */ + struct GNUNET_CRYPTO_EddsaPrivateKey *prv; + struct GNUNET_CRYPTO_EddsaPublicKey *pub; + + struct msg **tr; /* transcript of the messages */ + size_t tr_idx; + struct BRANDT_Auction *rad; /* auction for replay */ + struct BRANDT_Result *res; /* result for transcript */ + size_t res_len; }; -static struct testcase tcase; +static struct testcase tcase; static struct GNUNET_CRYPTO_EccDlogContext *edc; - static struct BRANDT_Result * expected_outcome (uint16_t i, uint16_t *rlen) { struct BRANDT_Result *ret = NULL; - int32_t highest_bidder = -1; - int32_t highest_bid = -1; - int32_t mpf_highest_bidder; - int32_t mpf_highest_bid = -1; - int32_t prev_mpf_highest_bidder = -1; - uint16_t winners = MIN (tcase.m, tcase.n); - uint16_t cur_winner = 0; + int32_t highest_bidder = -1; + int32_t highest_bid = -1; + int32_t mpf_highest_bidder; + int32_t mpf_highest_bid = -1; + int32_t prev_mpf_highest_bidder = -1; + uint16_t winners = MIN (tcase.m, tcase.n); + uint16_t cur_winner = 0; *rlen = 0; @@ -145,7 +158,7 @@ expected_outcome (uint16_t i, uint16_t *rlen) for (uint16_t h = 0; h < tcase.n; h++) { if (((tcase.bids[h] == mpf_highest_bid && h < mpf_highest_bidder) || - tcase.bids[h] > mpf_highest_bid) && /* h is a winner */ + tcase.bids[h] > mpf_highest_bid) && /* h is a winner */ (tcase.outcome_public || i == h || i == tcase.n)) /* needs report */ { if (cur_winner >= winners) @@ -167,7 +180,7 @@ expected_outcome (uint16_t i, uint16_t *rlen) static void bidder_start (void *arg) { - uint16_t i = *(uint16_t *)arg; + uint16_t i = *(uint16_t *) arg; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "starting bidder %d\n", i); BRANDT_bidder_start (tcase.ad[i], i, tcase.n); @@ -177,12 +190,26 @@ bidder_start (void *arg) static void transfer_message (void *arg) { - struct msg *m = (struct msg *)arg; - struct msg_head *h = (struct msg_head *)m->buf; + struct msg *m = (struct msg *) arg; + struct msg_head *h = (struct msg_head *) m->buf; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "xfer msg %d %p from %d to %d\n", ntohl (h->msg_type), arg, m->sender, m->receiver); + + /** keep a transcript as the seller **/ + if (tcase.n == m->receiver) + { + struct msg *m2 = GNUNET_new (struct msg); + + m2->sender = m->sender; + m2->buf_len = m->buf_len; + m2->buf = GNUNET_malloc (m->buf_len); + GNUNET_memcpy (m2->buf, m->buf, m->buf_len); + tcase.tr[tcase.tr_idx++] = m2; + } + BRANDT_got_message (tcase.ad[m->receiver], m->sender, m->buf, m->buf_len); + GNUNET_free (m->buf); GNUNET_free (m); } @@ -191,7 +218,7 @@ transfer_message (void *arg) static uint16_t cb_start (void *auction_closure) { - uint16_t *s = (uint16_t *)auction_closure; + uint16_t *s = (uint16_t *) auction_closure; if (tcase.n != *s) { @@ -210,9 +237,9 @@ cb_start (void *auction_closure) static int cb_broadcast (void *auction_closure, const void *msg, - size_t msg_len) + size_t msg_len) { - uint16_t *s = (uint16_t *)auction_closure; + uint16_t *s = (uint16_t *) auction_closure; struct msg *m; for (uint16_t i = 0; i <= tcase.n; i++) @@ -234,9 +261,9 @@ cb_broadcast (void *auction_closure, static int cb_unicast (void *auction_closure, const void *msg, - size_t msg_len) + size_t msg_len) { - uint16_t *s = (uint16_t *)auction_closure; + uint16_t *s = (uint16_t *) auction_closure; struct msg *m; m = GNUNET_new (struct msg); @@ -254,10 +281,10 @@ cb_unicast (void *auction_closure, static void cb_result (void *auction_closure, struct BRANDT_Result results[], - uint16_t results_len) + uint16_t results_len) { - uint16_t *s = (uint16_t *)auction_closure; - uint16_t mustlen = -1; + uint16_t *s = (uint16_t *) auction_closure; + uint16_t mustlen = -1; struct BRANDT_Result *must = expected_outcome (*s, &mustlen); if (mustlen != results_len) @@ -277,7 +304,7 @@ cb_result (void *auction_closure, { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "expected result is: %p\n", - (void *)must); + (void *) must); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "computed result is: (nil) (by agent %d)\n", *s); @@ -288,18 +315,20 @@ cb_result (void *auction_closure, for (uint16_t i = 0; i < results_len; i++) { GNUNET_log ( - GNUNET_ERROR_TYPE_INFO, - "expected result is: bidder %d got status %d with price %d\n", - must[i].bidder, - must[i].status, - must[i].price); + GNUNET_ERROR_TYPE_INFO, + "[%s] expected result is: bidder %d got status %d with price %d\n", + tcase.n == *s ? "seller" : "bidder", + must[i].bidder, + must[i].status, + must[i].price); GNUNET_log ( - GNUNET_ERROR_TYPE_INFO, - "computed result is: bidder %d got status %d with price %d (by agent %d)\n", - results[i].bidder, - results[i].status, - results[i].price, - *s); + GNUNET_ERROR_TYPE_INFO, + "[%s] computed result is: bidder %d got status %d with price %d (by agent %d)\n", + tcase.n == *s ? "seller" : "bidder", + results[i].bidder, + results[i].status, + results[i].price, + *s); if (NULL == must || must[i].bidder != results[i].bidder || @@ -308,6 +337,17 @@ cb_result (void *auction_closure, tcase.ret = 1; } + if (*s == tcase.n) + { + /* save the results of the seller */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Saving results, len %d\n", + results_len); + tcase.res = results; + tcase.res_len = results_len; + } + + quit: tcase.result_called[*s] = 1; if (must) @@ -329,9 +369,9 @@ run_auction (void *arg) &desc_len, GNUNET_TIME_absolute_get (), GNUNET_TIME_UNIT_MINUTES, - tcase.k, /* number of prizes */ - tcase.m, /* m */ - tcase.outcome_public, /* outcome public */ + tcase.k, /* number of prizes */ + tcase.m, /* m */ + tcase.outcome_public, /* outcome public */ tcase.outcome_public ? edc : NULL); if (!tcase.ad[tcase.n]) { @@ -375,6 +415,304 @@ run_auction (void *arg) } +static void +tr_result (void *auction_closure, + struct BRANDT_Result results[], + uint16_t results_len) +{ + uint16_t *s = (uint16_t *) auction_closure; + uint16_t mustlen = -1; + struct BRANDT_Result *must = expected_outcome (*s, &mustlen); + + if (mustlen != results_len) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "expected result len is: %d\n", + mustlen); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "computed result len is: %d (by seller)\n", + results_len); + tcase.ret = 1; + goto quit; + } + + if (0 == results_len && NULL != must) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "expected result is: %p\n", + (void *) must); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "computed result is: (nil) (by seller)\n"); + + tcase.ret = 1; + } + + for (uint16_t i = 0; i < results_len; i++) + { + GNUNET_log ( + GNUNET_ERROR_TYPE_INFO, + "REPLAY [seller] expected result is: bidder %d got status %d with price %d\n", + must[i].bidder, + must[i].status, + must[i].price); + GNUNET_log ( + GNUNET_ERROR_TYPE_INFO, + "REPLAY [seller] computed result is: bidder %d got status %d with price %d\n", + results[i].bidder, + results[i].status, + results[i].price); + + if (NULL == must || + must[i].bidder != results[i].bidder || + must[i].status != results[i].status || + must[i].price != results[i].price) + tcase.ret = 1; + } + +quit: + tcase.result_called[*s] = 1; + if (must) + GNUNET_free (must); +} + + +static uint16_t +tr_start (void *auction_closure) +{ + void + resend (void *x) + { + size_t i = (size_t) x; + struct msg *m = tcase.tr[i]; + if (NULL == m) + { + dprintf (2, "REPLAY skipping empty msg no. %ld\n", i); + return; + } + dprintf (2, "REPLAY sent msg no. %ld\n", i); + BRANDT_got_message (tcase.rad, m->sender, m->buf, m->buf_len); + } + + + dprintf (2, "REPLAY start replay auction\n"); + for (size_t i = 0; i < 4 * tcase.n; i++) + GNUNET_SCHEDULER_add_now (&resend, (void *) i); + + return tcase.n; +} + + +struct some_sig { + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + struct GNUNET_HashCode hc GNUNET_PACKED; +}; + +static void +print_transcript (uint32_t highestprice) +{ + struct BRANDT_Auction *ad = tcase.ad[tcase.n]; + json_t *root; + json_t *auction; + json_t *prices; + json_t *bidders; + json_t *sigs; + json_t *transcript; + json_t *winners; + struct GNUNET_HashCode hc; + struct some_sig p = { .purpose.size = htonl(sizeof(struct some_sig)) }; + char price[256]; + + prices = json_array (); + GNUNET_assert (prices); + + for (size_t p = 0; p < tcase.k; p++) + { + sprintf(price, "EUR:%d", highestprice--); + GNUNET_assert ( + -1 != json_array_append_new ( + prices, + json_string(price))); + } + + auction = json_pack ("{s:{s:o}, s:{s:o}, s:i, s:b, s:o, s:s, s:s}", + "time_start", "t_s", json_integer (ad->time_start.abs_value_us / 1000LL), + "time_round", "d_us", json_integer (ad->time_round.rel_value_us), + "type", ad->m, + "public", ad->outcome_public == 0 ? json_false () : json_true (), + "prices", prices, + "payto", "payto://some/iban", + "pubkey", GNUNET_CRYPTO_eddsa_public_key_to_string ( + &tcase.pub[tcase.n])); + GNUNET_assert (auction); + + bidders = json_array (); + GNUNET_assert (bidders); + + for (size_t b = 0; b < tcase.n; b++) + { + char *ps = GNUNET_CRYPTO_eddsa_public_key_to_string (&tcase.pub[b]); + GNUNET_assert (-1 != + json_array_append_new (bidders, + json_string (ps))); + } + + // Add signatures form each bidder for the auction. + sigs = json_array (); + GNUNET_assert (sigs); + { + char *auc_js = json_dumps(auction, JSON_COMPACT); + GNUNET_CRYPTO_hash(auc_js, + strlen(auc_js), + &hc); + + p.purpose.purpose = htonl(23); + p.hc = hc; + + for (size_t b = 0; b < tcase.n; b++) + { + struct GNUNET_CRYPTO_EddsaSignature sig; + GNUNET_CRYPTO_eddsa_sign(&tcase.prv[b], + &p, + &sig); + GNUNET_assert (-1 != + json_array_append_new ( + sigs, + GNUNET_JSON_from_data_auto(&sig))); + } + } + + transcript = json_array (); + GNUNET_assert (transcript); + + for (size_t i = 0; i < 4 * tcase.n; i++) + { + json_t *entry; + struct msg *msg = tcase.tr[i]; + struct GNUNET_CRYPTO_EddsaSignature sig; + + if (NULL == msg) + { + GNUNET_log(GNUNET_ERROR_TYPE_INFO, + "skipping NULL msg[%ld]\n", i); + continue; + } + + GNUNET_assert (msg); + + GNUNET_CRYPTO_hash(msg->buf, msg->buf_len, &hc); + + p.purpose.purpose = htonl(42); + p.hc = hc; + + GNUNET_CRYPTO_eddsa_sign ( + &tcase.prv[msg->sender], + &p, + &sig); + + + entry = json_pack ("{s:i, s:o, s:o}", + "bidder", msg->sender, + "msg", GNUNET_JSON_from_data (msg->buf, msg->buf_len), + "sig", GNUNET_JSON_from_data_auto(&sig)); + + GNUNET_assert (entry); + GNUNET_assert (-1 != + json_array_append_new (transcript, + entry)); + + } + + winners = json_array(); + GNUNET_assert (winners); + + // add the winner(s) + { + for (uint16_t i = 0; i < tcase.res_len ; i++) + { + json_t *res = json_pack("{s:i, s:i, s:o*}", + "bidder", + tcase.res[i].bidder, + "price_idx", + tcase.res[i].price, + "price", + json_array_get(prices, tcase.res[i].price)); + GNUNET_assert(res); + GNUNET_assert(-1 != + json_array_append_new(winners, res)); + + } + } + + + root = json_pack ("{s:o, s:o, s:o, s:o, s:o}", + "auction", auction, + "bidders", bidders, + "signatures", sigs, + "transcript", transcript, + "winners", winners); + + GNUNET_assert (root); + + // Add signature of seller to H(auction, bidders, signatures, transscript, result) + { + struct GNUNET_CRYPTO_EddsaSignature sig; + char *root_js = json_dumps(root, JSON_COMPACT); + + GNUNET_CRYPTO_hash(root_js, + strlen(root_js), + &hc); + + p.purpose.purpose = htonl(815); + p.hc = hc; + + GNUNET_CRYPTO_eddsa_sign(&tcase.prv[tcase.n], + &p, + &sig); + GNUNET_assert ( -1 != + json_object_set_new ( + root, + "sig", + GNUNET_JSON_from_data_auto(&sig))); + } + + printf ("%s\n", json_dumps (root, JSON_INDENT (2))); + + json_decref (root); +} + +static void +replay_transcript (void *arg) +{ + void *desc; + size_t desc_len; + static struct GNUNET_CRYPTO_EccDlogContext *redc; + + print_transcript(96); + redc = GNUNET_CRYPTO_ecc_dlog_prepare (1024, 16); + + dprintf (2,"REPLAY, calling BRANDT_new...\n"); + tcase.rad = BRANDT_new (&tr_result, + NULL, + &tr_start, + &tcase.id[tcase.n], + &desc, + &desc_len, + tcase.ad[tcase.n]->time_start, + tcase.ad[tcase.n]->time_round, + tcase.k, /* number of prizes */ + tcase.m, /* m */ + tcase.outcome_public, /* outcome public */ + tcase.outcome_public ? redc : NULL); + if (!tcase.rad) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "REPLAY BRANDT_new() failed.\n"); + _exit (1); + } +} + + + + /** * Test a specific auction setup. * @@ -400,6 +738,8 @@ test_auction (uint16_t n, tcase.m = m; tcase.outcome_public = outcome_public; tcase.ret = 0; + tcase.res = NULL; + tcase.res_len = 0; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "######################################\n"); @@ -413,9 +753,19 @@ test_auction (uint16_t n, "######################################\n"); tcase.ad = GNUNET_new_array (tcase.n + 1, struct BRANDT_Auction *); tcase.id = GNUNET_new_array (tcase.n + 1, uint16_t); + tcase.prv = GNUNET_new_array (tcase.n + 1, struct + GNUNET_CRYPTO_EddsaPrivateKey); + tcase.pub = GNUNET_new_array (tcase.n + 1, struct + GNUNET_CRYPTO_EddsaPublicKey); for (uint16_t i = 0; i <= tcase.n; i++) + { tcase.id[i] = i; + GNUNET_CRYPTO_eddsa_key_create (&tcase.prv[i]); + GNUNET_CRYPTO_eddsa_key_get_public (&tcase.prv[i], &tcase.pub[i]); + } tcase.result_called = GNUNET_new_array (tcase.n + 1, uint16_t); + tcase.tr = GNUNET_new_array (4 * tcase.n, struct msg *); /* transcript, one message per bidder per round */ + GNUNET_SCHEDULER_run (&run_auction, NULL); @@ -431,9 +781,19 @@ test_auction (uint16_t n, } } + GNUNET_SCHEDULER_run (&replay_transcript, NULL); + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "DONE testing auction\n"); + + + tcase.tr_idx = 0; + GNUNET_free (tcase.tr); GNUNET_free (tcase.ad); GNUNET_free (tcase.id); GNUNET_free (tcase.result_called); + GNUNET_free (tcase.prv); + GNUNET_free (tcase.pub); return tcase.ret; } @@ -444,31 +804,39 @@ main (int argc, char *argv[]) { int ret = 0; - if (GNUNET_OK != GNUNET_log_setup ("test_brandt", "WARNING", NULL)) + if (GNUNET_OK != GNUNET_log_setup ("test_brandt", "INFO", NULL)) return 1; edc = GNUNET_CRYPTO_ecc_dlog_prepare (1024, 16); BRANDT_init (); ret |= 0 || - // zero bidders - test_auction (0, 2, NULL, 0, 0) || - test_auction (0, 2, NULL, 0, 1) || - test_auction (0, 2, NULL, 1, 0) || - test_auction (0, 2, NULL, 2, 0) || - - // too few bidders => outcome is lowest possible price - test_auction (1, 2, (uint16_t[]) { 1 }, 1, 0) || - test_auction (1, 2, (uint16_t[]) { 0 }, 2, 0) || - test_auction (2, 2, (uint16_t[]) { 1, 0 }, 2, 0) || - test_auction (2, 2, (uint16_t[]) { 1, 0 }, 1, 0) || - test_auction (3, 2, (uint16_t[]) { 0, 0, 1 }, 2, 0) || - - // general checks of all four algorithms - test_auction (3, 2, (uint16_t[]) { 0, 1, 1 }, 0, 0) || - test_auction (3, 2, (uint16_t[]) { 0, 1, 1 }, 0, 1) || - test_auction (3, 2, (uint16_t[]) { 0, 1, 1 }, 2, 0) || - test_auction (3, 2, (uint16_t[]) { 0, 1, 1 }, 2, 1) || + /* + // zero bidders + test_auction (0, 2, NULL, 0, 0) || + test_auction (0, 2, NULL, 0, 1) || + test_auction (0, 2, NULL, 1, 0) || + test_auction (0, 2, NULL, 2, 0) || + + // too few bidders => outcome is lowest possible price + test_auction (1, 2, (uint16_t[]) { 1 }, 1, 0) || + test_auction (1, 2, (uint16_t[]) { 0 }, 2, 0) || + test_auction (2, 2, (uint16_t[]) { 1, 0 }, 2, 0) || + test_auction (2, 2, (uint16_t[]) { 1, 0 }, 1, 0) || + test_auction (3, 2, (uint16_t[]) { 0, 0, 1 }, 2, 0) || + + // general checks of all four algorithms + test_auction (3, 2, (uint16_t[]) { 0, 1, 1 }, 0, 0) || + test_auction (3, 2, (uint16_t[]) { 0, 1, 1 }, 0, 1) || + */ + // test_auction (3, 5, (uint16_t[]) { 4, 3, 1 }, 0, 1) || + // test_auction (3, 5, (uint16_t[]) { 1, 2, 3 }, 0, 1) || + test_auction (3, 5, (uint16_t[]) { 1, 2, 3 }, 0, 1) || + test_auction (5, 6, (uint16_t[]) {5,4,2,1,0,3}, 1, 1) || + // test_auction (5, 6, (uint16_t[]) {5,4,2,1,0,3}, 1, 0) || + test_auction (10, 3, (uint16_t[]) {1,2,0,1,1,0,1,0,1,0}, 0, 1) || + test_auction (10, 6, (uint16_t[]) {3,4,5,2,1,0,1,2,3,4}, 2, 1) || + // test_auction (10, 3, (uint16_t[]) {1,2,0,1,1,0,1,0,1,0}, 1, 0) || 0; GNUNET_CRYPTO_ecc_dlog_release (edc); |