diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-03-10 16:15:14 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-03-10 16:15:14 +0100 |
commit | c2c8646a83c07662e1246f768c23e71c687ddcb0 (patch) | |
tree | 3ea5a96e43fda20b9ecb10485bbc05b0749eff33 | |
parent | 07f18f16601cc4757c0c2658ad501497b07cebee (diff) | |
download | exchange-c2c8646a83c07662e1246f768c23e71c687ddcb0.tar.gz exchange-c2c8646a83c07662e1246f768c23e71c687ddcb0.zip |
combining /mint/melt and /mint/commit
-rw-r--r-- | src/include/taler_signatures.h | 65 | ||||
-rw-r--r-- | src/mint/mint_db.c | 27 | ||||
-rw-r--r-- | src/mint/mint_db.h | 27 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd.c | 6 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_db.c | 209 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_db.h | 49 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_refresh.c | 381 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_refresh.h | 24 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_responses.c | 122 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_responses.h | 45 |
10 files changed, 354 insertions, 601 deletions
diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index bf39c0aba..9e3068a78 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h | |||
@@ -56,30 +56,25 @@ | |||
56 | #define TALER_SIGNATURE_WITHDRAW 4 | 56 | #define TALER_SIGNATURE_WITHDRAW 4 |
57 | 57 | ||
58 | /** | 58 | /** |
59 | * Signature where the refresh session confirms | 59 | * Signature using a coin key confirming the melting of |
60 | * the list of melted coins and requested denominations. | 60 | * a coin. |
61 | */ | 61 | */ |
62 | #define TALER_SIGNATURE_REFRESH_MELT 5 | 62 | #define TALER_SIGNATURE_REFRESH_MELT_COIN 5 |
63 | 63 | ||
64 | /** | 64 | /** |
65 | * Signature where the refresh session confirms | 65 | * Signature where the refresh session confirms |
66 | * the commits. | 66 | * the commits. |
67 | */ | 67 | */ |
68 | #define TALER_SIGNATURE_REFRESH_COMMIT 6 | 68 | #define TALER_SIGNATURE_REFRESH_MELT 6 |
69 | 69 | ||
70 | /** | 70 | /** |
71 | * Signature where the mint (current signing key) | 71 | * Signature where the mint (current signing key) |
72 | * confirms the list of blind session keys. | 72 | * confirms the no-reveal index for cut-and-choose and |
73 | * the validity of the melted coins. | ||
73 | */ | 74 | */ |
74 | #define TALER_SIGNATURE_REFRESH_MELT_RESPONSE 7 | 75 | #define TALER_SIGNATURE_REFRESH_MELT_RESPONSE 7 |
75 | 76 | ||
76 | /** | 77 | /** |
77 | * Signature where the mint (current signing key) | ||
78 | * confirms the no-reveal index for cut-and-choose. | ||
79 | */ | ||
80 | #define TALER_SIGNATURE_REFRESH_COMMIT_RESPONSE 8 | ||
81 | |||
82 | /** | ||
83 | * Signature where coins confirm that they want | 78 | * Signature where coins confirm that they want |
84 | * to be melted into a certain session. | 79 | * to be melted into a certain session. |
85 | */ | 80 | */ |
@@ -234,18 +229,22 @@ struct TALER_DepositConfirmation | |||
234 | 229 | ||
235 | 230 | ||
236 | /** | 231 | /** |
237 | * Format of the block signed by the Mint in response to | 232 | * Message signed by a coin to indicate that the coin should |
238 | * a successful "/refresh/melt" request. Hereby the mint | 233 | * be melted. |
239 | * affirms that all of the coins were successfully melted. | ||
240 | */ | 234 | */ |
241 | struct RefreshMeltResponseSignatureBody | 235 | struct RefreshMeltSignatureBody |
242 | { | 236 | { |
243 | /** | 237 | /** |
244 | * Purpose is #TALER_SIGNATURE_REFRESH_MELT_RESPONSE. | 238 | * Purpose is #TALER_SIGNATURE_REFRESH_MELT_COIN. |
245 | */ | 239 | */ |
246 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; | 240 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; |
247 | 241 | ||
248 | /** | 242 | /** |
243 | * Which melting operation should the coin become a part of. | ||
244 | */ | ||
245 | struct GNUNET_HashCode melt_hash; | ||
246 | |||
247 | /** | ||
249 | * Signature of the client over the melt request (thereby | 248 | * Signature of the client over the melt request (thereby |
250 | * indirectly including all of the information the client | 249 | * indirectly including all of the information the client |
251 | * sent). | 250 | * sent). |
@@ -259,30 +258,6 @@ struct RefreshMeltResponseSignatureBody | |||
259 | struct GNUNET_CRYPTO_EddsaPublicKey session_key; | 258 | struct GNUNET_CRYPTO_EddsaPublicKey session_key; |
260 | 259 | ||
261 | /** | 260 | /** |
262 | * Security parameter requested for the commitments. | ||
263 | */ | ||
264 | uint32_t kappa GNUNET_PACKED; | ||
265 | |||
266 | }; | ||
267 | |||
268 | |||
269 | /** | ||
270 | * Message signed by a coin to indicate that the coin should | ||
271 | * be melted. | ||
272 | */ | ||
273 | struct RefreshMeltSignatureBody | ||
274 | { | ||
275 | /** | ||
276 | * Purpose is #TALER_SIGNATURE_REFRESH_MELT. | ||
277 | */ | ||
278 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; | ||
279 | |||
280 | /** | ||
281 | * Which melting operation should the coin become a part of. | ||
282 | */ | ||
283 | struct GNUNET_HashCode melt_hash; | ||
284 | |||
285 | /** | ||
286 | * How much of the value of the coin should be melted? | 261 | * How much of the value of the coin should be melted? |
287 | * This amount includes the fees, so the final amount contributed | 262 | * This amount includes the fees, so the final amount contributed |
288 | * to the melt is this value minus the fee for melting the coin. | 263 | * to the melt is this value minus the fee for melting the coin. |
@@ -298,7 +273,7 @@ struct RefreshMeltSignatureBody | |||
298 | struct RefreshCommitSignatureBody | 273 | struct RefreshCommitSignatureBody |
299 | { | 274 | { |
300 | /** | 275 | /** |
301 | * Purpose is #TALER_SIGNATURE_REFRESH_COMMIT. | 276 | * Purpose is #TALER_SIGNATURE_REFRESH_MELT. |
302 | */ | 277 | */ |
303 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; | 278 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; |
304 | 279 | ||
@@ -310,10 +285,12 @@ struct RefreshCommitSignatureBody | |||
310 | 285 | ||
311 | 286 | ||
312 | /** | 287 | /** |
313 | * Message signed by the mint, committing it to a particular | 288 | * Format of the block signed by the Mint in response to a successful |
314 | * index to not be revealed during the refresh. | 289 | * "/refresh/melt" request. Hereby the mint affirms that all of the |
290 | * coins were successfully melted. This also commits the mint to a | ||
291 | * particular index to not be revealed during the refresh. | ||
315 | */ | 292 | */ |
316 | struct RefreshCommitResponseSignatureBody | 293 | struct RefreshMeltResponseSignatureBody |
317 | { | 294 | { |
318 | /** | 295 | /** |
319 | * Purpose is #TALER_SIGNATURE_REFRESH_MELT_RESPONSE. | 296 | * Purpose is #TALER_SIGNATURE_REFRESH_MELT_RESPONSE. |
diff --git a/src/mint/mint_db.c b/src/mint/mint_db.c index 53d35b33d..848f9e045 100644 --- a/src/mint/mint_db.c +++ b/src/mint/mint_db.c | |||
@@ -1417,11 +1417,6 @@ TALER_MINT_DB_get_refresh_session (PGconn *db_conn, | |||
1417 | return GNUNET_SYSERR; | 1417 | return GNUNET_SYSERR; |
1418 | } | 1418 | } |
1419 | 1419 | ||
1420 | if (TALER_DB_field_isnull (result, 0, "session_commit_sig")) | ||
1421 | session->has_commit_sig = GNUNET_NO; | ||
1422 | else | ||
1423 | session->has_commit_sig = GNUNET_YES; | ||
1424 | |||
1425 | session->num_oldcoins = ntohs (session->num_oldcoins); | 1420 | session->num_oldcoins = ntohs (session->num_oldcoins); |
1426 | session->num_newcoins = ntohs (session->num_newcoins); | 1421 | session->num_newcoins = ntohs (session->num_newcoins); |
1427 | session->kappa = ntohs (session->kappa); | 1422 | session->kappa = ntohs (session->kappa); |
@@ -1472,28 +1467,6 @@ TALER_MINT_DB_create_refresh_session (PGconn *db_conn, | |||
1472 | 1467 | ||
1473 | 1468 | ||
1474 | /** | 1469 | /** |
1475 | * Update new refresh session with the new state after the | ||
1476 | * /refresh/commit operation. | ||
1477 | * | ||
1478 | * @param db_conn database handle to use | ||
1479 | * @param refresh_session_pub public key to use to locate the session | ||
1480 | * @param noreveal_index index chosen for the client to not reveal | ||
1481 | * @param commit_client_sig signature of the client over its commitment | ||
1482 | * @return #GNUNET_YES on success, | ||
1483 | * #GNUNET_SYSERR on DB failure | ||
1484 | */ | ||
1485 | int | ||
1486 | TALER_MINT_DB_update_refresh_session (PGconn *db_conn, | ||
1487 | const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, | ||
1488 | uint16_t noreveal_index, | ||
1489 | const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig) | ||
1490 | { | ||
1491 | // FIXME: implement! | ||
1492 | return GNUNET_SYSERR; | ||
1493 | } | ||
1494 | |||
1495 | |||
1496 | /** | ||
1497 | * Store the given /refresh/melt request in the database. | 1470 | * Store the given /refresh/melt request in the database. |
1498 | * | 1471 | * |
1499 | * @param db_conn database connection | 1472 | * @param db_conn database connection |
diff --git a/src/mint/mint_db.h b/src/mint/mint_db.h index 403e1f394..9818172af 100644 --- a/src/mint/mint_db.h +++ b/src/mint/mint_db.h | |||
@@ -474,17 +474,10 @@ struct RefreshSession | |||
474 | 474 | ||
475 | /** | 475 | /** |
476 | * Index (smaller @e kappa) which the mint has chosen to not | 476 | * Index (smaller @e kappa) which the mint has chosen to not |
477 | * have revealed during cut and choose. Only valid if | 477 | * have revealed during cut and choose. |
478 | * @e has_commit_sig is set to #GNUNET_YES. | ||
479 | */ | 478 | */ |
480 | uint16_t noreveal_index; | 479 | uint16_t noreveal_index; |
481 | 480 | ||
482 | /** | ||
483 | * #GNUNET_YES if we have accepted the /refresh/commit and | ||
484 | * thus the @e commit_sig is valid. | ||
485 | */ | ||
486 | int has_commit_sig; | ||
487 | |||
488 | }; | 481 | }; |
489 | 482 | ||
490 | 483 | ||
@@ -520,24 +513,6 @@ TALER_MINT_DB_create_refresh_session (PGconn *db_conn, | |||
520 | 513 | ||
521 | 514 | ||
522 | /** | 515 | /** |
523 | * Update new refresh session with the new state after the | ||
524 | * /refresh/commit operation. | ||
525 | * | ||
526 | * @param db_conn database handle to use | ||
527 | * @param refresh_session_pub public key to use to locate the session | ||
528 | * @param noreveal_index index chosen for the client to not reveal | ||
529 | * @param commit_client_sig signature of the client over its commitment | ||
530 | * @return #GNUNET_YES on success, | ||
531 | * #GNUNET_SYSERR on DB failure | ||
532 | */ | ||
533 | int | ||
534 | TALER_MINT_DB_update_refresh_session (PGconn *db_conn, | ||
535 | const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, | ||
536 | uint16_t noreveal_index, | ||
537 | const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig); | ||
538 | |||
539 | |||
540 | /** | ||
541 | * Specification for coin in a /refresh/melt operation. | 516 | * Specification for coin in a /refresh/melt operation. |
542 | */ | 517 | */ |
543 | struct RefreshMelt | 518 | struct RefreshMelt |
diff --git a/src/mint/taler-mint-httpd.c b/src/mint/taler-mint-httpd.c index 281f58f1b..3b1512ff1 100644 --- a/src/mint/taler-mint-httpd.c +++ b/src/mint/taler-mint-httpd.c | |||
@@ -152,12 +152,6 @@ handle_mhd_request (void *cls, | |||
152 | { "/refresh/melt", NULL, "text/plain", | 152 | { "/refresh/melt", NULL, "text/plain", |
153 | "Only POST is allowed", 0, | 153 | "Only POST is allowed", 0, |
154 | &TALER_MINT_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, | 154 | &TALER_MINT_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, |
155 | { "/refresh/commit", MHD_HTTP_METHOD_POST, "application/json", | ||
156 | NULL, 0, | ||
157 | &TALER_MINT_handler_refresh_commit, MHD_HTTP_OK }, | ||
158 | { "/refresh/commit", NULL, "text/plain", | ||
159 | "Only POST is allowed", 0, | ||
160 | &TALER_MINT_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, | ||
161 | { "/refresh/reveal", MHD_HTTP_METHOD_POST, "application/json", | 155 | { "/refresh/reveal", MHD_HTTP_METHOD_POST, "application/json", |
162 | NULL, 0, | 156 | NULL, 0, |
163 | &TALER_MINT_handler_refresh_melt, MHD_HTTP_OK }, | 157 | &TALER_MINT_handler_refresh_melt, MHD_HTTP_OK }, |
diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index d9a172a40..4423433b8 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c | |||
@@ -151,7 +151,7 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, | |||
151 | if (0 < TALER_amount_cmp (spent, value)) | 151 | if (0 < TALER_amount_cmp (spent, value)) |
152 | { | 152 | { |
153 | TALER_MINT_DB_rollback (db_conn); | 153 | TALER_MINT_DB_rollback (db_conn); |
154 | ret = TALER_MINT_reply_insufficient_funds (connection, | 154 | ret = TALER_MINT_reply_deposit_insufficient_funds (connection, |
155 | tl); | 155 | tl); |
156 | TALER_MINT_DB_free_coin_transaction_list (tl); | 156 | TALER_MINT_DB_free_coin_transaction_list (tl); |
157 | return ret; | 157 | return ret; |
@@ -435,8 +435,10 @@ refresh_accept_melts (struct MHD_Connection *connection, | |||
435 | { | 435 | { |
436 | struct TALER_MINT_DenomKeyIssue *dki; | 436 | struct TALER_MINT_DenomKeyIssue *dki; |
437 | struct TALER_MINT_DB_TransactionList *tl; | 437 | struct TALER_MINT_DB_TransactionList *tl; |
438 | struct TALER_Amount coin_gain; | 438 | struct TALER_Amount coin_value; |
439 | struct TALER_Amount coin_residual; | ||
439 | struct RefreshMelt melt; | 440 | struct RefreshMelt melt; |
441 | int res; | ||
440 | 442 | ||
441 | dki = &TALER_MINT_get_denom_key (key_state, | 443 | dki = &TALER_MINT_get_denom_key (key_state, |
442 | coin_public_info->denom_pub)->issue; | 444 | coin_public_info->denom_pub)->issue; |
@@ -450,25 +452,30 @@ refresh_accept_melts (struct MHD_Connection *connection, | |||
450 | "denom not found")) | 452 | "denom not found")) |
451 | ? GNUNET_NO : GNUNET_SYSERR; | 453 | ? GNUNET_NO : GNUNET_SYSERR; |
452 | 454 | ||
453 | coin_gain = TALER_amount_ntoh (dki->value); | 455 | coin_value = TALER_amount_ntoh (dki->value); |
454 | tl = TALER_MINT_DB_get_coin_transactions (db_conn, | 456 | tl = TALER_MINT_DB_get_coin_transactions (db_conn, |
455 | &coin_public_info->coin_pub); | 457 | &coin_public_info->coin_pub); |
456 | /* FIXME: #3636: compute how much value is left with this coin and | 458 | /* FIXME: #3636: compute how much value is left with this coin and |
457 | compare to `expected_value`! (subtract from "coin_gain") */ | 459 | compare to `expected_value`! (subtract from "coin_value") */ |
458 | TALER_MINT_DB_free_coin_transaction_list (tl); | 460 | coin_residual = coin_value; |
459 | |||
460 | /* Refuse to refresh when the coin does not have enough money left to | 461 | /* Refuse to refresh when the coin does not have enough money left to |
461 | * pay the refreshing fees of the coin. */ | 462 | * pay the refreshing fees of the coin. */ |
462 | 463 | ||
463 | if (TALER_amount_cmp (coin_gain, | 464 | if (TALER_amount_cmp (coin_residual, |
464 | coin_details->melt_amount) < 0) | 465 | coin_details->melt_amount) < 0) |
465 | return (MHD_YES == | 466 | { |
466 | TALER_MINT_reply_json_pack (connection, | 467 | res = (MHD_YES == |
467 | MHD_HTTP_NOT_FOUND, | 468 | TALER_MINT_reply_refresh_melt_insufficient_funds (connection, |
468 | "{s:s}", | 469 | &coin_public_info->coin_pub, |
469 | "error", "depleted")) ? GNUNET_NO : GNUNET_SYSERR; | 470 | coin_value, |
470 | 471 | tl, | |
471 | 472 | coin_details->melt_amount, | |
473 | coin_residual)) | ||
474 | ? GNUNET_NO : GNUNET_SYSERR; | ||
475 | TALER_MINT_DB_free_coin_transaction_list (tl); | ||
476 | return res; | ||
477 | } | ||
478 | TALER_MINT_DB_free_coin_transaction_list (tl); | ||
472 | 479 | ||
473 | melt.coin = *coin_public_info; | 480 | melt.coin = *coin_public_info; |
474 | melt.coin_sig = coin_details->melt_sig; | 481 | melt.coin_sig = coin_details->melt_sig; |
@@ -494,6 +501,8 @@ refresh_accept_melts (struct MHD_Connection *connection, | |||
494 | * required value left and if so, store that they have been | 501 | * required value left and if so, store that they have been |
495 | * melted and confirm the melting operation to the client. | 502 | * melted and confirm the melting operation to the client. |
496 | * | 503 | * |
504 | * FIXME: some arguments are redundant here... | ||
505 | * | ||
497 | * @param connection the MHD connection to handle | 506 | * @param connection the MHD connection to handle |
498 | * @param melt_hash hash code of the session the coins are melted into | 507 | * @param melt_hash hash code of the session the coins are melted into |
499 | * @param refresh_session_pub public key of the refresh session | 508 | * @param refresh_session_pub public key of the refresh session |
@@ -504,6 +513,15 @@ refresh_accept_melts (struct MHD_Connection *connection, | |||
504 | * @param coin_count number of entries in @a coin_public_infos and @a coin_melt_details | 513 | * @param coin_count number of entries in @a coin_public_infos and @a coin_melt_details |
505 | * @param coin_public_infos information about the coins to melt | 514 | * @param coin_public_infos information about the coins to melt |
506 | * @param coin_melt_details signatures and (residual) value of the respective coin should be melted | 515 | * @param coin_melt_details signatures and (residual) value of the respective coin should be melted |
516 | * @param commit_client_sig signature of the client over this commitment | ||
517 | * @param kappa size of x-dimension of @commit_coin and @commit_link arrays | ||
518 | * @param num_oldcoins size of y-dimension of @commit_link array | ||
519 | * @param num_newcoins size of y-dimension of @commit_coin array | ||
520 | * @param commit_coin 2d array of coin commitments (what the mint is to sign | ||
521 | * once the "/refres/reveal" of cut and choose is done) | ||
522 | * @param commit_link 2d array of coin link commitments (what the mint is | ||
523 | * to return via "/refresh/link" to enable linkage in the | ||
524 | * future) | ||
507 | * @return MHD result code | 525 | * @return MHD result code |
508 | */ | 526 | */ |
509 | int | 527 | int |
@@ -515,13 +533,20 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, | |||
515 | struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs, | 533 | struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs, |
516 | unsigned int coin_count, | 534 | unsigned int coin_count, |
517 | const struct TALER_CoinPublicInfo *coin_public_infos, | 535 | const struct TALER_CoinPublicInfo *coin_public_infos, |
518 | const struct MeltDetails *coin_melt_details) | 536 | const struct MeltDetails *coin_melt_details, |
537 | const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, | ||
538 | unsigned int kappa, | ||
539 | unsigned int num_oldcoins, | ||
540 | unsigned int num_newcoins, | ||
541 | struct RefreshCommitCoin *const* commit_coin, | ||
542 | struct RefreshCommitLink *const* commit_link) | ||
519 | { | 543 | { |
520 | struct MintKeyState *key_state; | 544 | struct MintKeyState *key_state; |
521 | struct RefreshSession session; | 545 | struct RefreshSession session; |
522 | PGconn *db_conn; | 546 | PGconn *db_conn; |
523 | int res; | 547 | int res; |
524 | unsigned int i; | 548 | unsigned int i; |
549 | unsigned int j; | ||
525 | 550 | ||
526 | if (NULL == (db_conn = TALER_MINT_DB_get_connection (GNUNET_NO))) | 551 | if (NULL == (db_conn = TALER_MINT_DB_get_connection (GNUNET_NO))) |
527 | { | 552 | { |
@@ -540,10 +565,10 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, | |||
540 | if (GNUNET_YES == res) | 565 | if (GNUNET_YES == res) |
541 | { | 566 | { |
542 | TALER_MINT_DB_rollback (db_conn); | 567 | TALER_MINT_DB_rollback (db_conn); |
543 | return TALER_MINT_reply_refresh_melt_success (connection, | 568 | res = TALER_MINT_reply_refresh_melt_success (connection, |
544 | &session.melt_sig, | 569 | &session.session_hash, |
545 | refresh_session_pub, | 570 | session.noreveal_index); |
546 | session.kappa); | 571 | return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; |
547 | } | 572 | } |
548 | if (GNUNET_SYSERR == res) | 573 | if (GNUNET_SYSERR == res) |
549 | { | 574 | { |
@@ -586,116 +611,6 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, | |||
586 | } | 611 | } |
587 | } | 612 | } |
588 | 613 | ||
589 | /* store 'global' session data */ | ||
590 | session.melt_sig = *client_signature; | ||
591 | session.session_hash = *melt_hash; | ||
592 | session.num_oldcoins = coin_count; | ||
593 | session.num_newcoins = num_new_denoms; | ||
594 | session.kappa = KAPPA; | ||
595 | session.noreveal_index = UINT16_MAX; | ||
596 | session.has_commit_sig = GNUNET_NO; | ||
597 | if (GNUNET_OK != | ||
598 | (res = TALER_MINT_DB_create_refresh_session (db_conn, | ||
599 | refresh_session_pub, | ||
600 | &session))) | ||
601 | { | ||
602 | TALER_MINT_DB_rollback (db_conn); | ||
603 | return TALER_MINT_reply_internal_db_error (connection); | ||
604 | } | ||
605 | |||
606 | if (GNUNET_OK != | ||
607 | TALER_MINT_DB_commit (db_conn)) | ||
608 | { | ||
609 | LOG_WARNING ("/refresh/melt transaction commit failed\n"); | ||
610 | return TALER_MINT_reply_commit_error (connection); | ||
611 | } | ||
612 | return TALER_MINT_reply_refresh_melt_success (connection, | ||
613 | client_signature, | ||
614 | refresh_session_pub, | ||
615 | session.kappa); | ||
616 | } | ||
617 | |||
618 | |||
619 | /** | ||
620 | * Execute a "/refresh/commit". The client is committing to @a kappa | ||
621 | * sets of transfer keys, and linkage information for a refresh | ||
622 | * operation. Confirm that the commit matches the melts of an | ||
623 | * existing @a refresh_session_pub, store the refresh session commit | ||
624 | * data and then return the client a challenge specifying which of the | ||
625 | * @a kappa sets of private transfer keys should not be revealed. | ||
626 | * | ||
627 | * @param connection the MHD connection to handle | ||
628 | * @param refresh_session public key of the session | ||
629 | * @param commit_client_sig signature of the client over this commitment | ||
630 | * @param kappa size of x-dimension of @commit_coin and @commit_link arrays | ||
631 | * @param num_oldcoins size of y-dimension of @commit_link array | ||
632 | * @param num_newcoins size of y-dimension of @commit_coin array | ||
633 | * @param commit_coin 2d array of coin commitments (what the mint is to sign | ||
634 | * once the "/refres/reveal" of cut and choose is done) | ||
635 | * @param commit_link 2d array of coin link commitments (what the mint is | ||
636 | * to return via "/refresh/link" to enable linkage in the | ||
637 | * future) | ||
638 | * @return MHD result code | ||
639 | */ | ||
640 | int | ||
641 | TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection, | ||
642 | const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, | ||
643 | const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, | ||
644 | unsigned int kappa, | ||
645 | unsigned int num_oldcoins, | ||
646 | unsigned int num_newcoins, | ||
647 | struct RefreshCommitCoin *const*commit_coin, | ||
648 | struct RefreshCommitLink *const*commit_link) | ||
649 | |||
650 | { | ||
651 | PGconn *db_conn; | ||
652 | struct RefreshSession refresh_session; | ||
653 | unsigned int i; | ||
654 | unsigned int j; | ||
655 | int res; | ||
656 | |||
657 | if (NULL == (db_conn = TALER_MINT_DB_get_connection (GNUNET_NO))) | ||
658 | { | ||
659 | GNUNET_break (0); | ||
660 | return TALER_MINT_reply_internal_db_error (connection); | ||
661 | } | ||
662 | |||
663 | if (GNUNET_OK != | ||
664 | TALER_MINT_DB_transaction (db_conn)) | ||
665 | { | ||
666 | GNUNET_break (0); | ||
667 | return TALER_MINT_reply_internal_db_error (connection); | ||
668 | } | ||
669 | res = TALER_MINT_DB_get_refresh_session (db_conn, | ||
670 | refresh_session_pub, | ||
671 | &refresh_session); | ||
672 | if (GNUNET_SYSERR == res) | ||
673 | { | ||
674 | TALER_MINT_DB_rollback (db_conn); | ||
675 | return TALER_MINT_reply_internal_db_error (connection); | ||
676 | } | ||
677 | if (GNUNET_NO == res) | ||
678 | { | ||
679 | TALER_MINT_DB_rollback (db_conn); | ||
680 | return TALER_MINT_reply_arg_invalid (connection, | ||
681 | "session_pub"); | ||
682 | } | ||
683 | if ( (refresh_session.kappa != kappa) || | ||
684 | (refresh_session.num_newcoins != num_newcoins) || | ||
685 | (refresh_session.num_oldcoins != num_oldcoins) ) | ||
686 | { | ||
687 | TALER_MINT_DB_rollback (db_conn); | ||
688 | return TALER_MINT_reply_arg_invalid (connection, | ||
689 | "dimensions"); | ||
690 | } | ||
691 | if (GNUNET_YES == refresh_session.has_commit_sig) | ||
692 | { | ||
693 | TALER_MINT_DB_rollback (db_conn); | ||
694 | res = TALER_MINT_reply_refresh_commit_success (connection, | ||
695 | &refresh_session.session_hash, | ||
696 | refresh_session.noreveal_index); | ||
697 | return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; | ||
698 | } | ||
699 | for (i = 0; i < kappa; i++) | 614 | for (i = 0; i < kappa; i++) |
700 | { | 615 | { |
701 | for (j = 0; j < num_newcoins; j++) | 616 | for (j = 0; j < num_newcoins; j++) |
@@ -729,31 +644,36 @@ TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection, | |||
729 | } | 644 | } |
730 | } | 645 | } |
731 | 646 | ||
732 | refresh_session.noreveal_index | ||
733 | = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, | ||
734 | refresh_session.kappa); | ||
735 | 647 | ||
648 | /* store 'global' session data */ | ||
649 | session.melt_sig = *client_signature; | ||
650 | session.session_hash = *melt_hash; | ||
651 | session.num_oldcoins = coin_count; | ||
652 | session.num_newcoins = num_new_denoms; | ||
653 | session.kappa = KAPPA; // FIXME... | ||
654 | session.noreveal_index | ||
655 | = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, | ||
656 | session.kappa); | ||
736 | if (GNUNET_OK != | 657 | if (GNUNET_OK != |
737 | (res = TALER_MINT_DB_update_refresh_session (db_conn, | 658 | (res = TALER_MINT_DB_create_refresh_session (db_conn, |
738 | refresh_session_pub, | 659 | refresh_session_pub, |
739 | refresh_session.noreveal_index, | 660 | &session))) |
740 | commit_client_sig))) | ||
741 | { | 661 | { |
742 | TALER_MINT_DB_rollback (db_conn); | 662 | TALER_MINT_DB_rollback (db_conn); |
743 | return TALER_MINT_reply_internal_db_error (connection); | 663 | return TALER_MINT_reply_internal_db_error (connection); |
744 | } | 664 | } |
745 | 665 | ||
746 | 666 | ||
667 | |||
747 | if (GNUNET_OK != | 668 | if (GNUNET_OK != |
748 | TALER_MINT_DB_commit (db_conn)) | 669 | TALER_MINT_DB_commit (db_conn)) |
749 | { | 670 | { |
750 | LOG_WARNING ("/refresh/commit transaction commit failed\n"); | 671 | LOG_WARNING ("/refresh/melt transaction commit failed\n"); |
751 | return TALER_MINT_reply_commit_error (connection); | 672 | return TALER_MINT_reply_commit_error (connection); |
752 | } | 673 | } |
753 | 674 | return TALER_MINT_reply_refresh_melt_success (connection, | |
754 | return TALER_MINT_reply_refresh_commit_success (connection, | 675 | &session.session_hash, |
755 | &refresh_session.session_hash, | 676 | session.noreveal_index); |
756 | refresh_session.noreveal_index); | ||
757 | } | 677 | } |
758 | 678 | ||
759 | 679 | ||
@@ -1061,15 +981,6 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, | |||
1061 | return TALER_MINT_reply_internal_db_error (connection); | 981 | return TALER_MINT_reply_internal_db_error (connection); |
1062 | } | 982 | } |
1063 | 983 | ||
1064 | if ( (refresh_session.noreveal_index >= refresh_session.kappa) || | ||
1065 | (GNUNET_NO == refresh_session.has_commit_sig) ) | ||
1066 | { | ||
1067 | GNUNET_break (UINT16_MAX == refresh_session.noreveal_index); | ||
1068 | GNUNET_break (GNUNET_NO == refresh_session.has_commit_sig); | ||
1069 | return TALER_MINT_reply_external_error (connection, | ||
1070 | "/refresh/commit must be executed first"); | ||
1071 | } | ||
1072 | |||
1073 | melts = GNUNET_malloc (refresh_session.num_oldcoins * | 984 | melts = GNUNET_malloc (refresh_session.num_oldcoins * |
1074 | sizeof (struct RefreshMelt)); | 985 | sizeof (struct RefreshMelt)); |
1075 | for (j=0;j<refresh_session.num_oldcoins;j++) | 986 | for (j=0;j<refresh_session.num_oldcoins;j++) |
diff --git a/src/mint/taler-mint-httpd_db.h b/src/mint/taler-mint-httpd_db.h index dcd5e6fa0..2a26de9b4 100644 --- a/src/mint/taler-mint-httpd_db.h +++ b/src/mint/taler-mint-httpd_db.h | |||
@@ -107,6 +107,8 @@ struct MeltDetails | |||
107 | * required value left and if so, store that they have been | 107 | * required value left and if so, store that they have been |
108 | * melted and confirm the melting operation to the client. | 108 | * melted and confirm the melting operation to the client. |
109 | * | 109 | * |
110 | * FIXME: some arguments are redundant here... | ||
111 | * | ||
110 | * @param connection the MHD connection to handle | 112 | * @param connection the MHD connection to handle |
111 | * @param melt_hash hash code of the session the coins are melted into | 113 | * @param melt_hash hash code of the session the coins are melted into |
112 | * @param refresh_session_pub public key of the refresh session | 114 | * @param refresh_session_pub public key of the refresh session |
@@ -117,30 +119,6 @@ struct MeltDetails | |||
117 | * @param coin_count number of entries in @a coin_public_infos and @ a coin_melt_details | 119 | * @param coin_count number of entries in @a coin_public_infos and @ a coin_melt_details |
118 | * @param coin_public_infos information about the coins to melt | 120 | * @param coin_public_infos information about the coins to melt |
119 | * @param coin_melt_details signatures and (residual) value of the respective coin should be melted | 121 | * @param coin_melt_details signatures and (residual) value of the respective coin should be melted |
120 | * @return MHD result code | ||
121 | */ | ||
122 | int | ||
123 | TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, | ||
124 | const struct GNUNET_HashCode *melt_hash, | ||
125 | const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, | ||
126 | const struct GNUNET_CRYPTO_EddsaSignature *client_signature, | ||
127 | unsigned int num_new_denoms, | ||
128 | struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs, | ||
129 | unsigned int coin_count, | ||
130 | const struct TALER_CoinPublicInfo *coin_public_infos, | ||
131 | const struct MeltDetails *coin_melt_details); | ||
132 | |||
133 | |||
134 | /** | ||
135 | * Execute a "/refresh/commit". The client is committing to @a kappa | ||
136 | * sets of transfer keys, and linkage information for a refresh | ||
137 | * operation. Confirm that the commit matches the melts of an | ||
138 | * existing @a refresh_session_pub, store the refresh session commit | ||
139 | * data and then return the client a challenge specifying which of the | ||
140 | * @a kappa sets of private transfer keys should not be revealed. | ||
141 | * | ||
142 | * @param connection the MHD connection to handle | ||
143 | * @param refresh_session public key of the session | ||
144 | * @param commit_client_sig signature of the client over this commitment | 122 | * @param commit_client_sig signature of the client over this commitment |
145 | * @param kappa size of x-dimension of @commit_coin and @commit_link arrays | 123 | * @param kappa size of x-dimension of @commit_coin and @commit_link arrays |
146 | * @param num_oldcoins size of y-dimension of @commit_coin array | 124 | * @param num_oldcoins size of y-dimension of @commit_coin array |
@@ -154,14 +132,21 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, | |||
154 | */ | 132 | */ |
155 | // FIXME: see #3635. | 133 | // FIXME: see #3635. |
156 | int | 134 | int |
157 | TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection, | 135 | TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, |
158 | const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, | 136 | const struct GNUNET_HashCode *melt_hash, |
159 | const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, | 137 | const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, |
160 | unsigned int kappa, | 138 | const struct GNUNET_CRYPTO_EddsaSignature *client_signature, |
161 | unsigned int num_oldcoins, | 139 | unsigned int num_new_denoms, |
162 | unsigned int num_newcoins, | 140 | struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs, |
163 | struct RefreshCommitCoin *const* commit_coin, | 141 | unsigned int coin_count, |
164 | struct RefreshCommitLink *const* commit_link); | 142 | const struct TALER_CoinPublicInfo *coin_public_infos, |
143 | const struct MeltDetails *coin_melt_details, | ||
144 | const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, | ||
145 | unsigned int kappa, | ||
146 | unsigned int num_oldcoins, | ||
147 | unsigned int num_newcoins, | ||
148 | struct RefreshCommitCoin *const* commit_coin, | ||
149 | struct RefreshCommitLink *const* commit_link); | ||
165 | 150 | ||
166 | 151 | ||
167 | /** | 152 | /** |
diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index cfb3ba0f5..d7b670749 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c | |||
@@ -151,6 +151,15 @@ request_json_check_signature (struct MHD_Connection *connection, | |||
151 | * @param coin_public_infos array with @a coin_count entries about the coins | 151 | * @param coin_public_infos array with @a coin_count entries about the coins |
152 | * @param coin_melt_details array with @a coin_count entries with melting details | 152 | * @param coin_melt_details array with @a coin_count entries with melting details |
153 | * @param melt_sig_json signature affirming the overall melt operation | 153 | * @param melt_sig_json signature affirming the overall melt operation |
154 | * @param commit_client_sig signature of the client over this commitment | ||
155 | * @param kappa size of x-dimension of @commit_coin and @commit_link arrays | ||
156 | * @param num_oldcoins size of y-dimension of @commit_coin array | ||
157 | * @param num_newcoins size of y-dimension of @commit_link array | ||
158 | * @param commit_coin 2d array of coin commitments (what the mint is to sign | ||
159 | * once the "/refres/reveal" of cut and choose is done) | ||
160 | * @param commit_link 2d array of coin link commitments (what the mint is | ||
161 | * to return via "/refresh/link" to enable linkage in the | ||
162 | * future) | ||
154 | * @return MHD result code | 163 | * @return MHD result code |
155 | */ | 164 | */ |
156 | static int | 165 | static int |
@@ -161,7 +170,14 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, | |||
161 | unsigned int coin_count, | 170 | unsigned int coin_count, |
162 | struct TALER_CoinPublicInfo *coin_public_infos, | 171 | struct TALER_CoinPublicInfo *coin_public_infos, |
163 | const struct MeltDetails *coin_melt_details, | 172 | const struct MeltDetails *coin_melt_details, |
164 | const json_t *melt_sig_json) | 173 | const json_t *melt_sig_json, |
174 | const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, | ||
175 | unsigned int kappa, | ||
176 | unsigned int num_oldcoins, | ||
177 | unsigned int num_newcoins, | ||
178 | struct RefreshCommitCoin *const* commit_coin, | ||
179 | struct RefreshCommitLink *const* commit_link) | ||
180 | |||
165 | { | 181 | { |
166 | int res; | 182 | int res; |
167 | unsigned int i; | 183 | unsigned int i; |
@@ -256,7 +272,13 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, | |||
256 | denom_pubs, | 272 | denom_pubs, |
257 | coin_count, | 273 | coin_count, |
258 | coin_public_infos, | 274 | coin_public_infos, |
259 | coin_melt_details); | 275 | coin_melt_details, |
276 | NULL /* FIXME: 3635! */, | ||
277 | kappa, | ||
278 | num_oldcoins, | ||
279 | num_newcoins, | ||
280 | commit_coin, | ||
281 | commit_link); | ||
260 | } | 282 | } |
261 | 283 | ||
262 | 284 | ||
@@ -364,6 +386,58 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection, | |||
364 | 386 | ||
365 | 387 | ||
366 | /** | 388 | /** |
389 | * Release memory from the @a commit_coin array. | ||
390 | * | ||
391 | * @param commit_coin array to release | ||
392 | * @param kappa size of 1st dimension | ||
393 | * @param num_new_coins size of 2nd dimension | ||
394 | */ | ||
395 | static void | ||
396 | free_commit_coins (struct RefreshCommitCoin **commit_coin, | ||
397 | unsigned int kappa, | ||
398 | unsigned int num_new_coins) | ||
399 | { | ||
400 | unsigned int i; | ||
401 | unsigned int j; | ||
402 | |||
403 | for (i=0;i<kappa;i++) | ||
404 | { | ||
405 | if (NULL == commit_coin[i]) | ||
406 | break; | ||
407 | for (j=0;j<num_new_coins;j++) | ||
408 | { | ||
409 | GNUNET_free_non_null (commit_coin[i][j].coin_ev); | ||
410 | GNUNET_free_non_null (commit_coin[i][j].refresh_link); | ||
411 | } | ||
412 | GNUNET_free (commit_coin[i]); | ||
413 | } | ||
414 | } | ||
415 | |||
416 | |||
417 | /** | ||
418 | * Release memory from the @a commit_link array. | ||
419 | * | ||
420 | * @param commit_coin array to release | ||
421 | * @param kappa size of 1st dimension | ||
422 | * @param num_old_coins size of 2nd dimension | ||
423 | */ | ||
424 | static void | ||
425 | free_commit_links (struct RefreshCommitLink **commit_link, | ||
426 | unsigned int kappa, | ||
427 | unsigned int num_old_coins) | ||
428 | { | ||
429 | unsigned int i; | ||
430 | |||
431 | for (i=0;i<kappa;i++) | ||
432 | { | ||
433 | if (NULL == commit_link[i]) | ||
434 | break; | ||
435 | GNUNET_free (commit_link[i]); | ||
436 | } | ||
437 | } | ||
438 | |||
439 | |||
440 | /** | ||
367 | * Handle a "/refresh/melt" request after the first parsing has happened. | 441 | * Handle a "/refresh/melt" request after the first parsing has happened. |
368 | * We now need to validate the coins being melted and the session signature | 442 | * We now need to validate the coins being melted and the session signature |
369 | * and then hand things of to execute the melt operation. This function | 443 | * and then hand things of to execute the melt operation. This function |
@@ -375,6 +449,14 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection, | |||
375 | * @param new_denoms array of denomination keys | 449 | * @param new_denoms array of denomination keys |
376 | * @param melt_coins array of coins to melt | 450 | * @param melt_coins array of coins to melt |
377 | * @param melt_sig_json signature affirming the melt operation | 451 | * @param melt_sig_json signature affirming the melt operation |
452 | * @param commit_signature signature over the commit | ||
453 | * @param kappa security parameter for cut and choose | ||
454 | * @param num_oldcoins number of coins that are being melted | ||
455 | * @param transfer_pubs @a kappa-dimensional array of @a num_oldcoins transfer keys | ||
456 | * @param secret_encs @a kappa-dimensional array of @a num_oldcoins secrets | ||
457 | * @param num_newcoins number of coins that the refresh will generate | ||
458 | * @param coin_envs @a kappa-dimensional array of @a num_newcoins envelopes to sign | ||
459 | * @param link_encs @a kappa-dimensional array of @a num_newcoins encrypted links | ||
378 | * @return MHD result code | 460 | * @return MHD result code |
379 | */ | 461 | */ |
380 | static int | 462 | static int |
@@ -382,7 +464,16 @@ handle_refresh_melt_json (struct MHD_Connection *connection, | |||
382 | const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, | 464 | const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, |
383 | const json_t *new_denoms, | 465 | const json_t *new_denoms, |
384 | const json_t *melt_coins, | 466 | const json_t *melt_coins, |
385 | const json_t *melt_sig_json) | 467 | const json_t *melt_sig_json, |
468 | const json_t *commit_signature, | ||
469 | unsigned int kappa, | ||
470 | unsigned int num_oldcoins, | ||
471 | const json_t *transfer_pubs, | ||
472 | const json_t *secret_encs, | ||
473 | unsigned int num_newcoins, | ||
474 | const json_t *coin_evs, | ||
475 | const json_t *link_encs) | ||
476 | |||
386 | { | 477 | { |
387 | int res; | 478 | int res; |
388 | unsigned int i; | 479 | unsigned int i; |
@@ -392,6 +483,11 @@ handle_refresh_melt_json (struct MHD_Connection *connection, | |||
392 | struct TALER_CoinPublicInfo *coin_public_infos; | 483 | struct TALER_CoinPublicInfo *coin_public_infos; |
393 | struct MeltDetails *coin_melt_details; | 484 | struct MeltDetails *coin_melt_details; |
394 | unsigned int coin_count; | 485 | unsigned int coin_count; |
486 | struct GNUNET_HashCode commit_hash; | ||
487 | struct GNUNET_HashContext *hash_context; | ||
488 | struct RefreshCommitSignatureBody body; | ||
489 | struct RefreshCommitCoin *commit_coin[kappa]; | ||
490 | struct RefreshCommitLink *commit_link[kappa]; | ||
395 | 491 | ||
396 | num_new_denoms = json_array_size (new_denoms); | 492 | num_new_denoms = json_array_size (new_denoms); |
397 | denom_pubs = GNUNET_malloc (num_new_denoms * | 493 | denom_pubs = GNUNET_malloc (num_new_denoms * |
@@ -441,180 +537,6 @@ handle_refresh_melt_json (struct MHD_Connection *connection, | |||
441 | } | 537 | } |
442 | } | 538 | } |
443 | 539 | ||
444 | res = handle_refresh_melt_binary (connection, | ||
445 | refresh_session_pub, | ||
446 | num_new_denoms, | ||
447 | denom_pubs, | ||
448 | coin_count, | ||
449 | coin_public_infos, | ||
450 | coin_melt_details, | ||
451 | melt_sig_json); | ||
452 | for (j=0;j<coin_count;j++) | ||
453 | { | ||
454 | GNUNET_CRYPTO_rsa_public_key_free (coin_public_infos[j].denom_pub); | ||
455 | GNUNET_CRYPTO_rsa_signature_free (coin_public_infos[j].denom_sig); | ||
456 | } | ||
457 | GNUNET_free (coin_public_infos); | ||
458 | for (j=0;j<num_new_denoms;j++) | ||
459 | { | ||
460 | GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j]); | ||
461 | } | ||
462 | GNUNET_free (coin_melt_details); | ||
463 | GNUNET_free (denom_pubs); | ||
464 | return res; | ||
465 | } | ||
466 | |||
467 | |||
468 | /** | ||
469 | * Handle a "/refresh/melt" request. Parses the request into the JSON | ||
470 | * components and then hands things of to #handle_referesh_melt_json() | ||
471 | * to validate the melted coins, the signature and execute the melt | ||
472 | * using TALER_MINT_db_execute_refresh_melt(). | ||
473 | * | ||
474 | * @param rh context of the handler | ||
475 | * @param connection the MHD connection to handle | ||
476 | * @param[IN|OUT] connection_cls the connection's closure (can be updated) | ||
477 | * @param upload_data upload data | ||
478 | * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data | ||
479 | * @return MHD result code | ||
480 | */ | ||
481 | int | ||
482 | TALER_MINT_handler_refresh_melt (struct RequestHandler *rh, | ||
483 | struct MHD_Connection *connection, | ||
484 | void **connection_cls, | ||
485 | const char *upload_data, | ||
486 | size_t *upload_data_size) | ||
487 | { | ||
488 | json_t *root; | ||
489 | json_t *new_denoms; | ||
490 | json_t *melt_coins; | ||
491 | json_t *melt_sig_json; | ||
492 | struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub; | ||
493 | int res; | ||
494 | struct GNUNET_MINT_ParseFieldSpec spec[] = { | ||
495 | TALER_MINT_PARSE_FIXED ("session_pub", &refresh_session_pub), | ||
496 | TALER_MINT_PARSE_ARRAY ("new_denoms", &new_denoms), | ||
497 | TALER_MINT_PARSE_ARRAY ("melt_coins", &melt_coins), | ||
498 | TALER_MINT_PARSE_ARRAY ("melt_signature", &melt_sig_json), | ||
499 | TALER_MINT_PARSE_END | ||
500 | }; | ||
501 | |||
502 | res = TALER_MINT_parse_post_json (connection, | ||
503 | connection_cls, | ||
504 | upload_data, | ||
505 | upload_data_size, | ||
506 | &root); | ||
507 | if (GNUNET_SYSERR == res) | ||
508 | return MHD_NO; | ||
509 | if ( (GNUNET_NO == res) || (NULL == root) ) | ||
510 | return MHD_YES; | ||
511 | |||
512 | res = TALER_MINT_parse_json_data (connection, | ||
513 | root, | ||
514 | spec); | ||
515 | json_decref (root); | ||
516 | if (GNUNET_OK != res) | ||
517 | return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; | ||
518 | res = handle_refresh_melt_json (connection, | ||
519 | &refresh_session_pub, | ||
520 | new_denoms, | ||
521 | melt_coins, | ||
522 | melt_sig_json); | ||
523 | TALER_MINT_release_parsed_data (spec); | ||
524 | return res; | ||
525 | } | ||
526 | |||
527 | |||
528 | /** | ||
529 | * Release memory from the @a commit_coin array. | ||
530 | * | ||
531 | * @param commit_coin array to release | ||
532 | * @param kappa size of 1st dimension | ||
533 | * @param num_new_coins size of 2nd dimension | ||
534 | */ | ||
535 | static void | ||
536 | free_commit_coins (struct RefreshCommitCoin **commit_coin, | ||
537 | unsigned int kappa, | ||
538 | unsigned int num_new_coins) | ||
539 | { | ||
540 | unsigned int i; | ||
541 | unsigned int j; | ||
542 | |||
543 | for (i=0;i<kappa;i++) | ||
544 | { | ||
545 | if (NULL == commit_coin[i]) | ||
546 | break; | ||
547 | for (j=0;j<num_new_coins;j++) | ||
548 | { | ||
549 | GNUNET_free_non_null (commit_coin[i][j].coin_ev); | ||
550 | GNUNET_free_non_null (commit_coin[i][j].refresh_link); | ||
551 | } | ||
552 | GNUNET_free (commit_coin[i]); | ||
553 | } | ||
554 | } | ||
555 | |||
556 | |||
557 | /** | ||
558 | * Release memory from the @a commit_link array. | ||
559 | * | ||
560 | * @param commit_coin array to release | ||
561 | * @param kappa size of 1st dimension | ||
562 | * @param num_old_coins size of 2nd dimension | ||
563 | */ | ||
564 | static void | ||
565 | free_commit_links (struct RefreshCommitLink **commit_link, | ||
566 | unsigned int kappa, | ||
567 | unsigned int num_old_coins) | ||
568 | { | ||
569 | unsigned int i; | ||
570 | |||
571 | for (i=0;i<kappa;i++) | ||
572 | { | ||
573 | if (NULL == commit_link[i]) | ||
574 | break; | ||
575 | GNUNET_free (commit_link[i]); | ||
576 | } | ||
577 | } | ||
578 | |||
579 | |||
580 | |||
581 | /** | ||
582 | * Handle a "/refresh/commit" request. We have the individual JSON | ||
583 | * arrays, now we need to parse their contents and verify the | ||
584 | * commit signature. Then we can commit the data to the database. | ||
585 | * | ||
586 | * @param connection the MHD connection to handle | ||
587 | * @param refresh_session_pub public key of the refresh session | ||
588 | * @param commit_signature signature over the commit | ||
589 | * @param kappa security parameter for cut and choose | ||
590 | * @param num_oldcoins number of coins that are being melted | ||
591 | * @param transfer_pubs @a kappa-dimensional array of @a num_oldcoins transfer keys | ||
592 | * @param secret_encs @a kappa-dimensional array of @a num_oldcoins secrets | ||
593 | * @param num_newcoins number of coins that the refresh will generate | ||
594 | * @param coin_envs @a kappa-dimensional array of @a num_newcoins envelopes to sign | ||
595 | * @param link_encs @a kappa-dimensional array of @a num_newcoins encrypted links | ||
596 | * @return MHD result code | ||
597 | */ | ||
598 | static int | ||
599 | handle_refresh_commit_json (struct MHD_Connection *connection, | ||
600 | const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, | ||
601 | const json_t *commit_signature, | ||
602 | unsigned int kappa, | ||
603 | unsigned int num_oldcoins, | ||
604 | const json_t *transfer_pubs, | ||
605 | const json_t *secret_encs, | ||
606 | unsigned int num_newcoins, | ||
607 | const json_t *coin_evs, | ||
608 | const json_t *link_encs) | ||
609 | { | ||
610 | struct GNUNET_HashCode commit_hash; | ||
611 | struct GNUNET_HashContext *hash_context; | ||
612 | struct RefreshCommitSignatureBody body; | ||
613 | struct RefreshCommitCoin *commit_coin[kappa]; | ||
614 | struct RefreshCommitLink *commit_link[kappa]; | ||
615 | unsigned int i; | ||
616 | unsigned int j; | ||
617 | int res; | ||
618 | 540 | ||
619 | /* parse JSON arrays into 2d binary arrays and hash everything | 541 | /* parse JSON arrays into 2d binary arrays and hash everything |
620 | together for the signature check */ | 542 | together for the signature check */ |
@@ -721,7 +643,7 @@ handle_refresh_commit_json (struct MHD_Connection *connection, | |||
721 | GNUNET_CRYPTO_hash_context_finish (hash_context, &commit_hash); | 643 | GNUNET_CRYPTO_hash_context_finish (hash_context, &commit_hash); |
722 | 644 | ||
723 | /* verify commit signature */ | 645 | /* verify commit signature */ |
724 | body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_COMMIT); | 646 | body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT); |
725 | body.purpose.size = htonl (sizeof (struct RefreshCommitSignatureBody)); | 647 | body.purpose.size = htonl (sizeof (struct RefreshCommitSignatureBody)); |
726 | body.commit_hash = commit_hash; | 648 | body.commit_hash = commit_hash; |
727 | 649 | ||
@@ -738,29 +660,43 @@ handle_refresh_commit_json (struct MHD_Connection *connection, | |||
738 | 660 | ||
739 | /* execute commit */ | 661 | /* execute commit */ |
740 | /* FIXME: we must also store the signature! (#3635) */ | 662 | /* FIXME: we must also store the signature! (#3635) */ |
741 | res = TALER_MINT_db_execute_refresh_commit (connection, | 663 | res = handle_refresh_melt_binary (connection, |
742 | refresh_session_pub, | 664 | refresh_session_pub, |
743 | NULL /* FIXME: 3635! */, | 665 | num_new_denoms, |
744 | kappa, | 666 | denom_pubs, |
745 | num_oldcoins, | 667 | coin_count, |
746 | num_newcoins, | 668 | coin_public_infos, |
747 | commit_coin, | 669 | coin_melt_details, |
748 | commit_link); | 670 | melt_sig_json, |
671 | NULL /* FIXME: 3635! */, | ||
672 | kappa, | ||
673 | num_oldcoins, | ||
674 | num_newcoins, | ||
675 | commit_coin, | ||
676 | commit_link); | ||
749 | free_commit_coins (commit_coin, kappa, num_newcoins); | 677 | free_commit_coins (commit_coin, kappa, num_newcoins); |
750 | free_commit_links (commit_link, kappa, num_oldcoins); | 678 | free_commit_links (commit_link, kappa, num_oldcoins); |
751 | 679 | for (j=0;j<coin_count;j++) | |
680 | { | ||
681 | GNUNET_CRYPTO_rsa_public_key_free (coin_public_infos[j].denom_pub); | ||
682 | GNUNET_CRYPTO_rsa_signature_free (coin_public_infos[j].denom_sig); | ||
683 | } | ||
684 | GNUNET_free (coin_public_infos); | ||
685 | for (j=0;j<num_new_denoms;j++) | ||
686 | { | ||
687 | GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j]); | ||
688 | } | ||
689 | GNUNET_free (coin_melt_details); | ||
690 | GNUNET_free (denom_pubs); | ||
752 | return res; | 691 | return res; |
753 | } | 692 | } |
754 | 693 | ||
755 | 694 | ||
756 | /** | 695 | /** |
757 | * Handle a "/refresh/commit" request. Parses the top-level JSON to | 696 | * Handle a "/refresh/melt" request. Parses the request into the JSON |
758 | * determine the dimensions of the problem and then handles handing | 697 | * components and then hands things of to #handle_referesh_melt_json() |
759 | * off to #handle_refresh_commit_json() to parse the details of the | 698 | * to validate the melted coins, the signature and execute the melt |
760 | * JSON arguments. Once the signature has been verified, the | 699 | * using TALER_MINT_db_execute_refresh_melt(). |
761 | * commit data is written to the database via | ||
762 | * #TALER_MINT_db_execute_refresh_commit() and the reveal parameter | ||
763 | * is then returned to the client. | ||
764 | * | 700 | * |
765 | * @param rh context of the handler | 701 | * @param rh context of the handler |
766 | * @param connection the MHD connection to handle | 702 | * @param connection the MHD connection to handle |
@@ -768,28 +704,34 @@ handle_refresh_commit_json (struct MHD_Connection *connection, | |||
768 | * @param upload_data upload data | 704 | * @param upload_data upload data |
769 | * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data | 705 | * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data |
770 | * @return MHD result code | 706 | * @return MHD result code |
771 | */ | 707 | */ |
772 | int | 708 | int |
773 | TALER_MINT_handler_refresh_commit (struct RequestHandler *rh, | 709 | TALER_MINT_handler_refresh_melt (struct RequestHandler *rh, |
774 | struct MHD_Connection *connection, | 710 | struct MHD_Connection *connection, |
775 | void **connection_cls, | 711 | void **connection_cls, |
776 | const char *upload_data, | 712 | const char *upload_data, |
777 | size_t *upload_data_size) | 713 | size_t *upload_data_size) |
778 | { | 714 | { |
779 | struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub; | ||
780 | int res; | ||
781 | unsigned int kappa; | ||
782 | unsigned int num_oldcoins; | ||
783 | unsigned int num_newcoins; | ||
784 | json_t *root; | 715 | json_t *root; |
716 | json_t *new_denoms; | ||
717 | json_t *melt_coins; | ||
718 | json_t *melt_sig_json; | ||
785 | json_t *coin_evs; | 719 | json_t *coin_evs; |
786 | json_t *link_encs; | 720 | json_t *link_encs; |
787 | json_t *transfer_pubs; | 721 | json_t *transfer_pubs; |
788 | json_t *secret_encs; | 722 | json_t *secret_encs; |
789 | json_t *coin_detail; | ||
790 | json_t *commit_sig_json; | 723 | json_t *commit_sig_json; |
724 | unsigned int kappa; | ||
725 | unsigned int num_oldcoins; | ||
726 | unsigned int num_newcoins; | ||
727 | json_t *coin_detail; | ||
728 | struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub; | ||
729 | int res; | ||
791 | struct GNUNET_MINT_ParseFieldSpec spec[] = { | 730 | struct GNUNET_MINT_ParseFieldSpec spec[] = { |
792 | TALER_MINT_PARSE_FIXED ("session_pub", &refresh_session_pub), | 731 | TALER_MINT_PARSE_FIXED ("session_pub", &refresh_session_pub), |
732 | TALER_MINT_PARSE_ARRAY ("new_denoms", &new_denoms), | ||
733 | TALER_MINT_PARSE_ARRAY ("melt_coins", &melt_coins), | ||
734 | TALER_MINT_PARSE_ARRAY ("melt_signature", &melt_sig_json), | ||
793 | TALER_MINT_PARSE_ARRAY ("coin_evs", &coin_evs), | 735 | TALER_MINT_PARSE_ARRAY ("coin_evs", &coin_evs), |
794 | TALER_MINT_PARSE_ARRAY ("link_encs", &link_encs), | 736 | TALER_MINT_PARSE_ARRAY ("link_encs", &link_encs), |
795 | TALER_MINT_PARSE_ARRAY ("transfer_pubs", &transfer_pubs), | 737 | TALER_MINT_PARSE_ARRAY ("transfer_pubs", &transfer_pubs), |
@@ -852,16 +794,21 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh, | |||
852 | return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; | 794 | return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; |
853 | } | 795 | } |
854 | num_oldcoins = json_array_size (coin_detail); | 796 | num_oldcoins = json_array_size (coin_detail); |
855 | res = handle_refresh_commit_json (connection, | 797 | |
856 | &refresh_session_pub, | 798 | res = handle_refresh_melt_json (connection, |
857 | commit_sig_json, | 799 | &refresh_session_pub, |
858 | kappa, | 800 | new_denoms, |
859 | num_oldcoins, | 801 | melt_coins, |
860 | transfer_pubs, | 802 | melt_sig_json, |
861 | secret_encs, | 803 | commit_sig_json, |
862 | num_newcoins, | 804 | kappa, |
863 | coin_evs, | 805 | num_oldcoins, |
864 | link_encs); | 806 | transfer_pubs, |
807 | secret_encs, | ||
808 | num_newcoins, | ||
809 | coin_evs, | ||
810 | link_encs); | ||
811 | |||
865 | TALER_MINT_release_parsed_data (spec); | 812 | TALER_MINT_release_parsed_data (spec); |
866 | return res; | 813 | return res; |
867 | } | 814 | } |
@@ -931,7 +878,7 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, | |||
931 | /** | 878 | /** |
932 | * Handle a "/refresh/reveal" request. This time, the client reveals | 879 | * Handle a "/refresh/reveal" request. This time, the client reveals |
933 | * the private transfer keys except for the cut-and-choose value | 880 | * the private transfer keys except for the cut-and-choose value |
934 | * returned from "/refresh/commit". This function parses the revealed | 881 | * returned from "/refresh/melt". This function parses the revealed |
935 | * keys and secrets and ultimately passes everything to | 882 | * keys and secrets and ultimately passes everything to |
936 | * #TALER_MINT_db_execute_refresh_reveal() which will verify that the | 883 | * #TALER_MINT_db_execute_refresh_reveal() which will verify that the |
937 | * revealed information is valid then returns the signed refreshed | 884 | * revealed information is valid then returns the signed refreshed |
diff --git a/src/mint/taler-mint-httpd_refresh.h b/src/mint/taler-mint-httpd_refresh.h index 80bad6c5c..c1f69e1de 100644 --- a/src/mint/taler-mint-httpd_refresh.h +++ b/src/mint/taler-mint-httpd_refresh.h | |||
@@ -50,30 +50,6 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh, | |||
50 | 50 | ||
51 | 51 | ||
52 | /** | 52 | /** |
53 | * Handle a "/refresh/commit" request. Parses the top-level JSON to | ||
54 | * determine the dimensions of the problem and then handles handing | ||
55 | * off to #handle_refresh_commit_json() to parse the details of the | ||
56 | * JSON arguments. Once the signature has been verified, the | ||
57 | * commit data is written to the database via | ||
58 | * #TALER_MINT_db_execute_refresh_commit() and the cut-and-choose value | ||
59 | * is then returned to the client. | ||
60 | * | ||
61 | * @param rh context of the handler | ||
62 | * @param connection the MHD connection to handle | ||
63 | * @param[IN|OUT] connection_cls the connection's closure (can be updated) | ||
64 | * @param upload_data upload data | ||
65 | * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data | ||
66 | * @return MHD result code | ||
67 | */ | ||
68 | int | ||
69 | TALER_MINT_handler_refresh_commit (struct RequestHandler *rh, | ||
70 | struct MHD_Connection *connection, | ||
71 | void **connection_cls, | ||
72 | const char *upload_data, | ||
73 | size_t *upload_data_size); | ||
74 | |||
75 | |||
76 | /** | ||
77 | * Handle a "/refresh/reveal" request. This time, the client reveals | 53 | * Handle a "/refresh/reveal" request. This time, the client reveals |
78 | * the private transfer keys except for the cut-and-choose value | 54 | * the private transfer keys except for the cut-and-choose value |
79 | * returned from "/refresh/commit". This function parses the revealed | 55 | * returned from "/refresh/commit". This function parses the revealed |
diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index 21e208115..83c81e800 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c | |||
@@ -315,27 +315,20 @@ TALER_MINT_reply_deposit_success (struct MHD_Connection *connection, | |||
315 | return ret; | 315 | return ret; |
316 | } | 316 | } |
317 | 317 | ||
318 | |||
319 | /** | 318 | /** |
320 | * Send proof that a /deposit, /refresh/melt or /lock request is | 319 | * Compile the transaction history of a coin into a JSON object. |
321 | * invalid to client. This function will create a message with all of | ||
322 | * the operations affecting the coin that demonstrate that the coin | ||
323 | * has insufficient value. | ||
324 | * | 320 | * |
325 | * @param connection connection to the client | 321 | * @param tl transaction history to JSON-ify |
326 | * @param tl transaction list to use to build reply | 322 | * @return json representation of the @a rh |
327 | * @return MHD result code | ||
328 | */ | 323 | */ |
329 | int | 324 | static json_t * |
330 | TALER_MINT_reply_insufficient_funds (struct MHD_Connection *connection, | 325 | compile_transaction_history (const struct TALER_MINT_DB_TransactionList *tl) |
331 | const struct TALER_MINT_DB_TransactionList *tl) | ||
332 | { | 326 | { |
333 | const struct TALER_MINT_DB_TransactionList *pos; | ||
334 | int ret; | ||
335 | json_t *history; | ||
336 | json_t *transaction; | 327 | json_t *transaction; |
337 | const char *type; | 328 | const char *type; |
338 | struct TALER_Amount value; | 329 | struct TALER_Amount value; |
330 | json_t *history; | ||
331 | const struct TALER_MINT_DB_TransactionList *pos; | ||
339 | 332 | ||
340 | history = json_array (); | 333 | history = json_array (); |
341 | for (pos = tl; NULL != pos; pos = pos->next) | 334 | for (pos = tl; NULL != pos; pos = pos->next) |
@@ -392,13 +385,31 @@ TALER_MINT_reply_insufficient_funds (struct MHD_Connection *connection, | |||
392 | "amount", TALER_JSON_from_amount (value), | 385 | "amount", TALER_JSON_from_amount (value), |
393 | "signature", transaction)); | 386 | "signature", transaction)); |
394 | } | 387 | } |
388 | return history; | ||
389 | } | ||
395 | 390 | ||
396 | ret = TALER_MINT_reply_json_pack (connection, | 391 | |
397 | MHD_HTTP_FORBIDDEN, | 392 | /** |
398 | "{s:s, s:o}", | 393 | * Send proof that a /withdraw request is invalid to client. This |
399 | "error", "insufficient funds", | 394 | * function will create a message with all of the operations affecting |
400 | "history", history); | 395 | * the coin that demonstrate that the coin has insufficient value. |
401 | return ret; | 396 | * |
397 | * @param connection connection to the client | ||
398 | * @param tl transaction list to use to build reply | ||
399 | * @return MHD result code | ||
400 | */ | ||
401 | int | ||
402 | TALER_MINT_reply_deposit_insufficient_funds (struct MHD_Connection *connection, | ||
403 | const struct TALER_MINT_DB_TransactionList *tl) | ||
404 | { | ||
405 | json_t *history; | ||
406 | |||
407 | history = compile_transaction_history (tl); | ||
408 | return TALER_MINT_reply_json_pack (connection, | ||
409 | MHD_HTTP_FORBIDDEN, | ||
410 | "{s:s, s:o}", | ||
411 | "error", "insufficient funds", | ||
412 | "history", history); | ||
402 | } | 413 | } |
403 | 414 | ||
404 | 415 | ||
@@ -589,47 +600,46 @@ TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection, | |||
589 | 600 | ||
590 | 601 | ||
591 | /** | 602 | /** |
592 | * Send a response for "/refresh/melt". Essentially we sign | 603 | * Send a response for a failed "/refresh/melt" request. The |
593 | * over the client's signature and public key, thereby | 604 | * transaction history of the given coin demonstrates that the |
594 | * demonstrating that we accepted all of the client's coins. | 605 | * @a residual value of the coin is below the @a requested |
606 | * contribution of the coin for the melt. Thus, the mint | ||
607 | * refuses the melt operation. | ||
595 | * | 608 | * |
596 | * @param connection the connection to send the response to | 609 | * @param connection the connection to send the response to |
597 | * @param signature the client's signature over the melt request | 610 | * @param coin_pub public key of the coin |
598 | * @param session_pub the refresh session public key. | 611 | * @param coin_value original value of the coin |
599 | * @param kappa security parameter to use for cut and choose | 612 | * @param tl transaction history for the coin |
613 | * @param requested how much this coin was supposed to contribute | ||
614 | * @param residual remaining value of the coin (after subtracting @a tl) | ||
600 | * @return a MHD result code | 615 | * @return a MHD result code |
601 | */ | 616 | */ |
602 | int | 617 | int |
603 | TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, | 618 | TALER_MINT_reply_refresh_melt_insufficient_funds (struct MHD_Connection *connection, |
604 | const struct GNUNET_CRYPTO_EddsaSignature *signature, | 619 | const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, |
605 | const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, | 620 | struct TALER_Amount coin_value, |
606 | unsigned int kappa) | 621 | struct TALER_MINT_DB_TransactionList *tl, |
622 | struct TALER_Amount requested, | ||
623 | struct TALER_Amount residual) | ||
607 | { | 624 | { |
608 | int ret; | 625 | json_t *history; |
609 | struct RefreshMeltResponseSignatureBody body; | ||
610 | struct GNUNET_CRYPTO_EddsaSignature sig; | ||
611 | json_t *sig_json; | ||
612 | 626 | ||
613 | body.purpose.size = htonl (sizeof (struct RefreshMeltResponseSignatureBody)); | 627 | history = compile_transaction_history (tl); |
614 | body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_RESPONSE); | 628 | return TALER_MINT_reply_json_pack (connection, |
615 | body.melt_client_signature = *signature; | 629 | MHD_HTTP_NOT_FOUND, |
616 | body.session_key = *session_pub; | 630 | "{s:s, s:o, s:o, s:o, s:o, s:o}", |
617 | body.kappa = htonl (kappa); | 631 | "error", "insufficient funds", |
618 | TALER_MINT_keys_sign (&body.purpose, | 632 | "coin-pub", TALER_JSON_from_data (coin_pub, |
619 | &sig); | 633 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)), |
620 | sig_json = TALER_JSON_from_eddsa_sig (&body.purpose, &sig); | 634 | "original-value", TALER_JSON_from_amount (coin_value), |
621 | ret = TALER_MINT_reply_json_pack (connection, | 635 | "residual-value", TALER_JSON_from_amount (residual), |
622 | MHD_HTTP_OK, | 636 | "requested-value", TALER_JSON_from_amount (requested), |
623 | "{s:o, s:i}", | 637 | "history", history); |
624 | "signature", sig_json, | ||
625 | "kappa", (int) kappa); | ||
626 | json_decref (sig_json); | ||
627 | return ret; | ||
628 | } | 638 | } |
629 | 639 | ||
630 | 640 | ||
631 | /** | 641 | /** |
632 | * Send a response to a "/refresh/commit" request. | 642 | * Send a response to a "/refresh/melt" request. |
633 | * | 643 | * |
634 | * @param connection the connection to send the response to | 644 | * @param connection the connection to send the response to |
635 | * @param session_hash hash of the refresh session | 645 | * @param session_hash hash of the refresh session |
@@ -637,17 +647,17 @@ TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, | |||
637 | * @return a MHD status code | 647 | * @return a MHD status code |
638 | */ | 648 | */ |
639 | int | 649 | int |
640 | TALER_MINT_reply_refresh_commit_success (struct MHD_Connection *connection, | 650 | TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, |
641 | const struct GNUNET_HashCode *session_hash, | 651 | const struct GNUNET_HashCode *session_hash, |
642 | uint16_t noreveal_index) | 652 | uint16_t noreveal_index) |
643 | { | 653 | { |
644 | struct RefreshCommitResponseSignatureBody body; | 654 | struct RefreshMeltResponseSignatureBody body; |
645 | struct GNUNET_CRYPTO_EddsaSignature sig; | 655 | struct GNUNET_CRYPTO_EddsaSignature sig; |
646 | json_t *sig_json; | 656 | json_t *sig_json; |
647 | int ret; | 657 | int ret; |
648 | 658 | ||
649 | body.purpose.size = htonl (sizeof (struct RefreshCommitResponseSignatureBody)); | 659 | body.purpose.size = htonl (sizeof (struct RefreshMeltResponseSignatureBody)); |
650 | body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_COMMIT_RESPONSE); | 660 | body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_RESPONSE); |
651 | body.session_hash = *session_hash; | 661 | body.session_hash = *session_hash; |
652 | body.noreveal_index = htons (noreveal_index); | 662 | body.noreveal_index = htons (noreveal_index); |
653 | TALER_MINT_keys_sign (&body.purpose, | 663 | TALER_MINT_keys_sign (&body.purpose, |
diff --git a/src/mint/taler-mint-httpd_responses.h b/src/mint/taler-mint-httpd_responses.h index abfb4318c..7d0824c88 100644 --- a/src/mint/taler-mint-httpd_responses.h +++ b/src/mint/taler-mint-httpd_responses.h | |||
@@ -194,18 +194,17 @@ TALER_MINT_reply_deposit_success (struct MHD_Connection *connection, | |||
194 | 194 | ||
195 | 195 | ||
196 | /** | 196 | /** |
197 | * Send proof that a /deposit, /refresh/melt or /lock request is | 197 | * Send proof that a /deposit request is invalid to client. This |
198 | * invalid to client. This function will create a message with all of | 198 | * function will create a message with all of the operations affecting |
199 | * the operations affecting the coin that demonstrate that the coin | 199 | * the coin that demonstrate that the coin has insufficient value. |
200 | * has insufficient value. | ||
201 | * | 200 | * |
202 | * @param connection connection to the client | 201 | * @param connection connection to the client |
203 | * @param tl transaction list to use to build reply | 202 | * @param tl transaction list to use to build reply |
204 | * @return MHD result code | 203 | * @return MHD result code |
205 | */ | 204 | */ |
206 | int | 205 | int |
207 | TALER_MINT_reply_insufficient_funds (struct MHD_Connection *connection, | 206 | TALER_MINT_reply_deposit_insufficient_funds (struct MHD_Connection *connection, |
208 | const struct TALER_MINT_DB_TransactionList *tl); | 207 | const struct TALER_MINT_DB_TransactionList *tl); |
209 | 208 | ||
210 | 209 | ||
211 | /** | 210 | /** |
@@ -247,7 +246,7 @@ TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection, | |||
247 | 246 | ||
248 | 247 | ||
249 | /** | 248 | /** |
250 | * Send a response to a "/refresh/commit" request. | 249 | * Send a confirmation response to a "/refresh/melt" request. |
251 | * | 250 | * |
252 | * @param connection the connection to send the response to | 251 | * @param connection the connection to send the response to |
253 | * @param session_hash hash of the refresh session | 252 | * @param session_hash hash of the refresh session |
@@ -255,27 +254,33 @@ TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection, | |||
255 | * @return a MHD status code | 254 | * @return a MHD status code |
256 | */ | 255 | */ |
257 | int | 256 | int |
258 | TALER_MINT_reply_refresh_commit_success (struct MHD_Connection *connection, | 257 | TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, |
259 | const struct GNUNET_HashCode *session_hash, | 258 | const struct GNUNET_HashCode *session_hash, |
260 | uint16_t noreveal_index); | 259 | uint16_t noreveal_index); |
261 | 260 | ||
262 | 261 | ||
263 | /** | 262 | /** |
264 | * Send a response for "/refresh/melt". Essentially we sign | 263 | * Send a response for a failed "/refresh/melt" request. The |
265 | * over the client's signature and public key, thereby | 264 | * transaction history of the given coin demonstrates that the |
266 | * demonstrating that we accepted all of the client's coins. | 265 | * @a residual value of the coin is below the @a requested |
266 | * contribution of the coin for the melt. Thus, the mint | ||
267 | * refuses the melt operation. | ||
267 | * | 268 | * |
268 | * @param connection the connection to send the response to | 269 | * @param connection the connection to send the response to |
269 | * @param signature the client's signature over the melt request | 270 | * @param coin_pub public key of the coin |
270 | * @param session_pub the refresh session public key. | 271 | * @param coin_value original value of the coin |
271 | * @param kappa security parameter to use for cut and choose | 272 | * @param tl transaction history for the coin |
273 | * @param requested how much this coin was supposed to contribute | ||
274 | * @param residual remaining value of the coin (after subtracting @a tl) | ||
272 | * @return a MHD result code | 275 | * @return a MHD result code |
273 | */ | 276 | */ |
274 | int | 277 | int |
275 | TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, | 278 | TALER_MINT_reply_refresh_melt_insufficient_funds (struct MHD_Connection *connection, |
276 | const struct GNUNET_CRYPTO_EddsaSignature *signature, | 279 | const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, |
277 | const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, | 280 | struct TALER_Amount coin_value, |
278 | unsigned int kappa); | 281 | struct TALER_MINT_DB_TransactionList *tl, |
282 | struct TALER_Amount requested, | ||
283 | struct TALER_Amount residual); | ||
279 | 284 | ||
280 | 285 | ||
281 | /** | 286 | /** |