diff --git a/test_brandt.c b/test_brandt.c index ee53a0d..8a27748 100644 --- a/test_brandt.c +++ b/test_brandt.c @@ -28,6 +28,7 @@ #include "crypto.h" #include "util.h" +#define MIN(A, B) ((A) < (B) ? (A) : (B)) struct msg { uint16_t sender; @@ -55,26 +56,73 @@ static struct testcase tcase; static struct BRANDT_Result * expected_outcome (uint16_t i) { + struct BRANDT_Result *ret = NULL; int32_t highest_bidder = -1; int32_t highest_bid = -1; - struct BRANDT_Result *ret; + int32_t mpf_highest_bidder; + int32_t mpf_highest_bid; + int32_t prev_mpf_highest_bidder = -1; + uint16_t winners = MIN (tcase.m, tcase.n); + uint16_t cur_winner = 0; - for (uint16_t h = 0; h < tcase.n; h++) + if (0 == tcase.m) { - if (tcase.bids[h] > highest_bid) - { - highest_bid = tcase.bids[h]; - highest_bidder = h; - } + for (uint16_t h = 0; h < tcase.n; h++) + if (tcase.bids[h] > highest_bid) + highest_bid = tcase.bids[highest_bidder = h]; + + if (!tcase.outcome_public && !(i == highest_bidder || i == tcase.n)) + return NULL; + + ret = GNUNET_new (struct BRANDT_Result); + ret->bidder = highest_bidder; + ret->price = highest_bid; + ret->status = BRANDT_bidder_won; + return ret; } - if (!tcase.outcome_public && !(i == highest_bidder || i == tcase.n)) - return NULL; + /* find M+1st highest bidder to determine selling price */ + for (uint16_t m = 0; m <= MIN (tcase.m, tcase.n - 1); m++) + { + for (uint16_t h = 0; h < tcase.n; h++) + { + mpf_highest_bidder = -1; + mpf_highest_bid = -1; + if (tcase.bids[h] > mpf_highest_bid && + (-1 == prev_mpf_highest_bidder || + tcase.bids[h] < tcase.bids[prev_mpf_highest_bidder] || + h > prev_mpf_highest_bidder)) + mpf_highest_bid = tcase.bids[mpf_highest_bidder = h]; + } + prev_mpf_highest_bidder = mpf_highest_bidder; + } - ret = GNUNET_new (struct BRANDT_Result); - ret->bidder = highest_bidder; - ret->price = highest_bid; - ret->status = BRANDT_bidder_won; + /* for simplicity always locate the big block if we need to report at + * least one winner. with private outcome for losing bidders or winners + * only none or one element will be used respectively. */ + if (tcase.outcome_public || i == tcase.n || + tcase.bids[i] > mpf_highest_bid || + (tcase.bids[i] == mpf_highest_bid && i < mpf_highest_bidder)) + ret = GNUNET_new_array (winners, struct BRANDT_Result); + + /* report winners */ + 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.outcome_public || i == h || i == tcase.n)) /* needs report */ + { + if (cur_winner >= winners) + { + weprintf ("got too many winners"); + _exit (1); + } + ret[cur_winner].bidder = h; + ret[cur_winner].price = mpf_highest_bid; + ret[cur_winner].status = BRANDT_bidder_won; + cur_winner++; + } + } return ret; }