diff options
-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 @@ #define TALER_SIGNATURE_WITHDRAW 4 /** - * Signature where the refresh session confirms - * the list of melted coins and requested denominations. + * Signature using a coin key confirming the melting of + * a coin. */ -#define TALER_SIGNATURE_REFRESH_MELT 5 +#define TALER_SIGNATURE_REFRESH_MELT_COIN 5 /** * Signature where the refresh session confirms * the commits. */ -#define TALER_SIGNATURE_REFRESH_COMMIT 6 +#define TALER_SIGNATURE_REFRESH_MELT 6 /** * Signature where the mint (current signing key) - * confirms the list of blind session keys. + * confirms the no-reveal index for cut-and-choose and + * the validity of the melted coins. */ #define TALER_SIGNATURE_REFRESH_MELT_RESPONSE 7 /** - * Signature where the mint (current signing key) - * confirms the no-reveal index for cut-and-choose. - */ -#define TALER_SIGNATURE_REFRESH_COMMIT_RESPONSE 8 - -/** * Signature where coins confirm that they want * to be melted into a certain session. */ @@ -234,18 +229,22 @@ struct TALER_DepositConfirmation /** - * Format of the block signed by the Mint in response to - * a successful "/refresh/melt" request. Hereby the mint - * affirms that all of the coins were successfully melted. + * Message signed by a coin to indicate that the coin should + * be melted. */ -struct RefreshMeltResponseSignatureBody +struct RefreshMeltSignatureBody { /** - * Purpose is #TALER_SIGNATURE_REFRESH_MELT_RESPONSE. + * Purpose is #TALER_SIGNATURE_REFRESH_MELT_COIN. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** + * Which melting operation should the coin become a part of. + */ + struct GNUNET_HashCode melt_hash; + + /** * Signature of the client over the melt request (thereby * indirectly including all of the information the client * sent). @@ -259,30 +258,6 @@ struct RefreshMeltResponseSignatureBody struct GNUNET_CRYPTO_EddsaPublicKey session_key; /** - * Security parameter requested for the commitments. - */ - uint32_t kappa GNUNET_PACKED; - -}; - - -/** - * Message signed by a coin to indicate that the coin should - * be melted. - */ -struct RefreshMeltSignatureBody -{ - /** - * Purpose is #TALER_SIGNATURE_REFRESH_MELT. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Which melting operation should the coin become a part of. - */ - struct GNUNET_HashCode melt_hash; - - /** * How much of the value of the coin should be melted? * This amount includes the fees, so the final amount contributed * to the melt is this value minus the fee for melting the coin. @@ -298,7 +273,7 @@ struct RefreshMeltSignatureBody struct RefreshCommitSignatureBody { /** - * Purpose is #TALER_SIGNATURE_REFRESH_COMMIT. + * Purpose is #TALER_SIGNATURE_REFRESH_MELT. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; @@ -310,10 +285,12 @@ struct RefreshCommitSignatureBody /** - * Message signed by the mint, committing it to a particular - * index to not be revealed during the refresh. + * Format of the block signed by the Mint in response to a successful + * "/refresh/melt" request. Hereby the mint affirms that all of the + * coins were successfully melted. This also commits the mint to a + * particular index to not be revealed during the refresh. */ -struct RefreshCommitResponseSignatureBody +struct RefreshMeltResponseSignatureBody { /** * 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, return GNUNET_SYSERR; } - if (TALER_DB_field_isnull (result, 0, "session_commit_sig")) - session->has_commit_sig = GNUNET_NO; - else - session->has_commit_sig = GNUNET_YES; - session->num_oldcoins = ntohs (session->num_oldcoins); session->num_newcoins = ntohs (session->num_newcoins); session->kappa = ntohs (session->kappa); @@ -1472,28 +1467,6 @@ TALER_MINT_DB_create_refresh_session (PGconn *db_conn, /** - * Update new refresh session with the new state after the - * /refresh/commit operation. - * - * @param db_conn database handle to use - * @param refresh_session_pub public key to use to locate the session - * @param noreveal_index index chosen for the client to not reveal - * @param commit_client_sig signature of the client over its commitment - * @return #GNUNET_YES on success, - * #GNUNET_SYSERR on DB failure - */ -int -TALER_MINT_DB_update_refresh_session (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - uint16_t noreveal_index, - const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig) -{ - // FIXME: implement! - return GNUNET_SYSERR; -} - - -/** * Store the given /refresh/melt request in the database. * * @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 /** * Index (smaller @e kappa) which the mint has chosen to not - * have revealed during cut and choose. Only valid if - * @e has_commit_sig is set to #GNUNET_YES. + * have revealed during cut and choose. */ uint16_t noreveal_index; - /** - * #GNUNET_YES if we have accepted the /refresh/commit and - * thus the @e commit_sig is valid. - */ - int has_commit_sig; - }; @@ -520,24 +513,6 @@ TALER_MINT_DB_create_refresh_session (PGconn *db_conn, /** - * Update new refresh session with the new state after the - * /refresh/commit operation. - * - * @param db_conn database handle to use - * @param refresh_session_pub public key to use to locate the session - * @param noreveal_index index chosen for the client to not reveal - * @param commit_client_sig signature of the client over its commitment - * @return #GNUNET_YES on success, - * #GNUNET_SYSERR on DB failure - */ -int -TALER_MINT_DB_update_refresh_session (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - uint16_t noreveal_index, - const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig); - - -/** * Specification for coin in a /refresh/melt operation. */ 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, { "/refresh/melt", NULL, "text/plain", "Only POST is allowed", 0, &TALER_MINT_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - { "/refresh/commit", MHD_HTTP_METHOD_POST, "application/json", - NULL, 0, - &TALER_MINT_handler_refresh_commit, MHD_HTTP_OK }, - { "/refresh/commit", NULL, "text/plain", - "Only POST is allowed", 0, - &TALER_MINT_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, { "/refresh/reveal", MHD_HTTP_METHOD_POST, "application/json", NULL, 0, &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, if (0 < TALER_amount_cmp (spent, value)) { TALER_MINT_DB_rollback (db_conn); - ret = TALER_MINT_reply_insufficient_funds (connection, + ret = TALER_MINT_reply_deposit_insufficient_funds (connection, tl); TALER_MINT_DB_free_coin_transaction_list (tl); return ret; @@ -435,8 +435,10 @@ refresh_accept_melts (struct MHD_Connection *connection, { struct TALER_MINT_DenomKeyIssue *dki; struct TALER_MINT_DB_TransactionList *tl; - struct TALER_Amount coin_gain; + struct TALER_Amount coin_value; + struct TALER_Amount coin_residual; struct RefreshMelt melt; + int res; dki = &TALER_MINT_get_denom_key (key_state, coin_public_info->denom_pub)->issue; @@ -450,25 +452,30 @@ refresh_accept_melts (struct MHD_Connection *connection, "denom not found")) ? GNUNET_NO : GNUNET_SYSERR; - coin_gain = TALER_amount_ntoh (dki->value); + coin_value = TALER_amount_ntoh (dki->value); tl = TALER_MINT_DB_get_coin_transactions (db_conn, &coin_public_info->coin_pub); /* FIXME: #3636: compute how much value is left with this coin and - compare to `expected_value`! (subtract from "coin_gain") */ - TALER_MINT_DB_free_coin_transaction_list (tl); - + compare to `expected_value`! (subtract from "coin_value") */ + coin_residual = coin_value; /* Refuse to refresh when the coin does not have enough money left to * pay the refreshing fees of the coin. */ - if (TALER_amount_cmp (coin_gain, + if (TALER_amount_cmp (coin_residual, coin_details->melt_amount) < 0) - return (MHD_YES == - TALER_MINT_reply_json_pack (connection, - MHD_HTTP_NOT_FOUND, - "{s:s}", - "error", "depleted")) ? GNUNET_NO : GNUNET_SYSERR; - - + { + res = (MHD_YES == + TALER_MINT_reply_refresh_melt_insufficient_funds (connection, + &coin_public_info->coin_pub, + coin_value, + tl, + coin_details->melt_amount, + coin_residual)) + ? GNUNET_NO : GNUNET_SYSERR; + TALER_MINT_DB_free_coin_transaction_list (tl); + return res; + } + TALER_MINT_DB_free_coin_transaction_list (tl); melt.coin = *coin_public_info; melt.coin_sig = coin_details->melt_sig; @@ -494,6 +501,8 @@ refresh_accept_melts (struct MHD_Connection *connection, * required value left and if so, store that they have been * melted and confirm the melting operation to the client. * + * FIXME: some arguments are redundant here... + * * @param connection the MHD connection to handle * @param melt_hash hash code of the session the coins are melted into * @param refresh_session_pub public key of the refresh session @@ -504,6 +513,15 @@ refresh_accept_melts (struct MHD_Connection *connection, * @param coin_count number of entries in @a coin_public_infos and @a coin_melt_details * @param coin_public_infos information about the coins to melt * @param coin_melt_details signatures and (residual) value of the respective coin should be melted + * @param commit_client_sig signature of the client over this commitment + * @param kappa size of x-dimension of @commit_coin and @commit_link arrays + * @param num_oldcoins size of y-dimension of @commit_link array + * @param num_newcoins size of y-dimension of @commit_coin array + * @param commit_coin 2d array of coin commitments (what the mint is to sign + * once the "/refres/reveal" of cut and choose is done) + * @param commit_link 2d array of coin link commitments (what the mint is + * to return via "/refresh/link" to enable linkage in the + * future) * @return MHD result code */ int @@ -515,13 +533,20 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs, unsigned int coin_count, const struct TALER_CoinPublicInfo *coin_public_infos, - const struct MeltDetails *coin_melt_details) + const struct MeltDetails *coin_melt_details, + const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, + unsigned int kappa, + unsigned int num_oldcoins, + unsigned int num_newcoins, + struct RefreshCommitCoin *const* commit_coin, + struct RefreshCommitLink *const* commit_link) { struct MintKeyState *key_state; struct RefreshSession session; PGconn *db_conn; int res; unsigned int i; + unsigned int j; if (NULL == (db_conn = TALER_MINT_DB_get_connection (GNUNET_NO))) { @@ -540,10 +565,10 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, if (GNUNET_YES == res) { TALER_MINT_DB_rollback (db_conn); - return TALER_MINT_reply_refresh_melt_success (connection, - &session.melt_sig, - refresh_session_pub, - session.kappa); + res = TALER_MINT_reply_refresh_melt_success (connection, + &session.session_hash, + session.noreveal_index); + return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; } if (GNUNET_SYSERR == res) { @@ -586,116 +611,6 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, } } - /* store 'global' session data */ - session.melt_sig = *client_signature; - session.session_hash = *melt_hash; - session.num_oldcoins = coin_count; - session.num_newcoins = num_new_denoms; - session.kappa = KAPPA; - session.noreveal_index = UINT16_MAX; - session.has_commit_sig = GNUNET_NO; - if (GNUNET_OK != - (res = TALER_MINT_DB_create_refresh_session (db_conn, - refresh_session_pub, - &session))) - { - TALER_MINT_DB_rollback (db_conn); - return TALER_MINT_reply_internal_db_error (connection); - } - - if (GNUNET_OK != - TALER_MINT_DB_commit (db_conn)) - { - LOG_WARNING ("/refresh/melt transaction commit failed\n"); - return TALER_MINT_reply_commit_error (connection); - } - return TALER_MINT_reply_refresh_melt_success (connection, - client_signature, - refresh_session_pub, - session.kappa); -} - - -/** - * Execute a "/refresh/commit". The client is committing to @a kappa - * sets of transfer keys, and linkage information for a refresh - * operation. Confirm that the commit matches the melts of an - * existing @a refresh_session_pub, store the refresh session commit - * data and then return the client a challenge specifying which of the - * @a kappa sets of private transfer keys should not be revealed. - * - * @param connection the MHD connection to handle - * @param refresh_session public key of the session - * @param commit_client_sig signature of the client over this commitment - * @param kappa size of x-dimension of @commit_coin and @commit_link arrays - * @param num_oldcoins size of y-dimension of @commit_link array - * @param num_newcoins size of y-dimension of @commit_coin array - * @param commit_coin 2d array of coin commitments (what the mint is to sign - * once the "/refres/reveal" of cut and choose is done) - * @param commit_link 2d array of coin link commitments (what the mint is - * to return via "/refresh/link" to enable linkage in the - * future) - * @return MHD result code - */ -int -TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, - unsigned int kappa, - unsigned int num_oldcoins, - unsigned int num_newcoins, - struct RefreshCommitCoin *const*commit_coin, - struct RefreshCommitLink *const*commit_link) - -{ - PGconn *db_conn; - struct RefreshSession refresh_session; - unsigned int i; - unsigned int j; - int res; - - if (NULL == (db_conn = TALER_MINT_DB_get_connection (GNUNET_NO))) - { - GNUNET_break (0); - return TALER_MINT_reply_internal_db_error (connection); - } - - if (GNUNET_OK != - TALER_MINT_DB_transaction (db_conn)) - { - GNUNET_break (0); - return TALER_MINT_reply_internal_db_error (connection); - } - res = TALER_MINT_DB_get_refresh_session (db_conn, - refresh_session_pub, - &refresh_session); - if (GNUNET_SYSERR == res) - { - TALER_MINT_DB_rollback (db_conn); - return TALER_MINT_reply_internal_db_error (connection); - } - if (GNUNET_NO == res) - { - TALER_MINT_DB_rollback (db_conn); - return TALER_MINT_reply_arg_invalid (connection, - "session_pub"); - } - if ( (refresh_session.kappa != kappa) || - (refresh_session.num_newcoins != num_newcoins) || - (refresh_session.num_oldcoins != num_oldcoins) ) - { - TALER_MINT_DB_rollback (db_conn); - return TALER_MINT_reply_arg_invalid (connection, - "dimensions"); - } - if (GNUNET_YES == refresh_session.has_commit_sig) - { - TALER_MINT_DB_rollback (db_conn); - res = TALER_MINT_reply_refresh_commit_success (connection, - &refresh_session.session_hash, - refresh_session.noreveal_index); - return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; - } for (i = 0; i < kappa; i++) { for (j = 0; j < num_newcoins; j++) @@ -729,31 +644,36 @@ TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection, } } - refresh_session.noreveal_index - = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, - refresh_session.kappa); + /* store 'global' session data */ + session.melt_sig = *client_signature; + session.session_hash = *melt_hash; + session.num_oldcoins = coin_count; + session.num_newcoins = num_new_denoms; + session.kappa = KAPPA; // FIXME... + session.noreveal_index + = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, + session.kappa); if (GNUNET_OK != - (res = TALER_MINT_DB_update_refresh_session (db_conn, + (res = TALER_MINT_DB_create_refresh_session (db_conn, refresh_session_pub, - refresh_session.noreveal_index, - commit_client_sig))) + &session))) { TALER_MINT_DB_rollback (db_conn); return TALER_MINT_reply_internal_db_error (connection); } + if (GNUNET_OK != TALER_MINT_DB_commit (db_conn)) { - LOG_WARNING ("/refresh/commit transaction commit failed\n"); + LOG_WARNING ("/refresh/melt transaction commit failed\n"); return TALER_MINT_reply_commit_error (connection); } - - return TALER_MINT_reply_refresh_commit_success (connection, - &refresh_session.session_hash, - refresh_session.noreveal_index); + return TALER_MINT_reply_refresh_melt_success (connection, + &session.session_hash, + session.noreveal_index); } @@ -1061,15 +981,6 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, return TALER_MINT_reply_internal_db_error (connection); } - if ( (refresh_session.noreveal_index >= refresh_session.kappa) || - (GNUNET_NO == refresh_session.has_commit_sig) ) - { - GNUNET_break (UINT16_MAX == refresh_session.noreveal_index); - GNUNET_break (GNUNET_NO == refresh_session.has_commit_sig); - return TALER_MINT_reply_external_error (connection, - "/refresh/commit must be executed first"); - } - melts = GNUNET_malloc (refresh_session.num_oldcoins * sizeof (struct RefreshMelt)); 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 * required value left and if so, store that they have been * melted and confirm the melting operation to the client. * + * FIXME: some arguments are redundant here... + * * @param connection the MHD connection to handle * @param melt_hash hash code of the session the coins are melted into * @param refresh_session_pub public key of the refresh session @@ -117,30 +119,6 @@ struct MeltDetails * @param coin_count number of entries in @a coin_public_infos and @ a coin_melt_details * @param coin_public_infos information about the coins to melt * @param coin_melt_details signatures and (residual) value of the respective coin should be melted - * @return MHD result code - */ -int -TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, - const struct GNUNET_HashCode *melt_hash, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - const struct GNUNET_CRYPTO_EddsaSignature *client_signature, - unsigned int num_new_denoms, - struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs, - unsigned int coin_count, - const struct TALER_CoinPublicInfo *coin_public_infos, - const struct MeltDetails *coin_melt_details); - - -/** - * Execute a "/refresh/commit". The client is committing to @a kappa - * sets of transfer keys, and linkage information for a refresh - * operation. Confirm that the commit matches the melts of an - * existing @a refresh_session_pub, store the refresh session commit - * data and then return the client a challenge specifying which of the - * @a kappa sets of private transfer keys should not be revealed. - * - * @param connection the MHD connection to handle - * @param refresh_session public key of the session * @param commit_client_sig signature of the client over this commitment * @param kappa size of x-dimension of @commit_coin and @commit_link arrays * @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, */ // FIXME: see #3635. int -TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, - unsigned int kappa, - unsigned int num_oldcoins, - unsigned int num_newcoins, - struct RefreshCommitCoin *const* commit_coin, - struct RefreshCommitLink *const* commit_link); +TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, + const struct GNUNET_HashCode *melt_hash, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + const struct GNUNET_CRYPTO_EddsaSignature *client_signature, + unsigned int num_new_denoms, + struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs, + unsigned int coin_count, + const struct TALER_CoinPublicInfo *coin_public_infos, + const struct MeltDetails *coin_melt_details, + const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, + unsigned int kappa, + unsigned int num_oldcoins, + unsigned int num_newcoins, + struct RefreshCommitCoin *const* commit_coin, + struct RefreshCommitLink *const* commit_link); /** 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, * @param coin_public_infos array with @a coin_count entries about the coins * @param coin_melt_details array with @a coin_count entries with melting details * @param melt_sig_json signature affirming the overall melt operation + * @param commit_client_sig signature of the client over this commitment + * @param kappa size of x-dimension of @commit_coin and @commit_link arrays + * @param num_oldcoins size of y-dimension of @commit_coin array + * @param num_newcoins size of y-dimension of @commit_link array + * @param commit_coin 2d array of coin commitments (what the mint is to sign + * once the "/refres/reveal" of cut and choose is done) + * @param commit_link 2d array of coin link commitments (what the mint is + * to return via "/refresh/link" to enable linkage in the + * future) * @return MHD result code */ static int @@ -161,7 +170,14 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, unsigned int coin_count, struct TALER_CoinPublicInfo *coin_public_infos, const struct MeltDetails *coin_melt_details, - const json_t *melt_sig_json) + const json_t *melt_sig_json, + const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, + unsigned int kappa, + unsigned int num_oldcoins, + unsigned int num_newcoins, + struct RefreshCommitCoin *const* commit_coin, + struct RefreshCommitLink *const* commit_link) + { int res; unsigned int i; @@ -256,7 +272,13 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, denom_pubs, coin_count, coin_public_infos, - coin_melt_details); + coin_melt_details, + NULL /* FIXME: 3635! */, + kappa, + num_oldcoins, + num_newcoins, + commit_coin, + commit_link); } @@ -364,6 +386,58 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection, /** + * Release memory from the @a commit_coin array. + * + * @param commit_coin array to release + * @param kappa size of 1st dimension + * @param num_new_coins size of 2nd dimension + */ +static void +free_commit_coins (struct RefreshCommitCoin **commit_coin, + unsigned int kappa, + unsigned int num_new_coins) +{ + unsigned int i; + unsigned int j; + + for (i=0;i<kappa;i++) + { + if (NULL == commit_coin[i]) + break; + for (j=0;j<num_new_coins;j++) + { + GNUNET_free_non_null (commit_coin[i][j].coin_ev); + GNUNET_free_non_null (commit_coin[i][j].refresh_link); + } + GNUNET_free (commit_coin[i]); + } +} + + +/** + * Release memory from the @a commit_link array. + * + * @param commit_coin array to release + * @param kappa size of 1st dimension + * @param num_old_coins size of 2nd dimension + */ +static void +free_commit_links (struct RefreshCommitLink **commit_link, + unsigned int kappa, + unsigned int num_old_coins) +{ + unsigned int i; + + for (i=0;i<kappa;i++) + { + if (NULL == commit_link[i]) + break; + GNUNET_free (commit_link[i]); + } +} + + +/** * Handle a "/refresh/melt" request after the first parsing has happened. * We now need to validate the coins being melted and the session signature * 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, * @param new_denoms array of denomination keys * @param melt_coins array of coins to melt * @param melt_sig_json signature affirming the melt operation + * @param commit_signature signature over the commit + * @param kappa security parameter for cut and choose + * @param num_oldcoins number of coins that are being melted + * @param transfer_pubs @a kappa-dimensional array of @a num_oldcoins transfer keys + * @param secret_encs @a kappa-dimensional array of @a num_oldcoins secrets + * @param num_newcoins number of coins that the refresh will generate + * @param coin_envs @a kappa-dimensional array of @a num_newcoins envelopes to sign + * @param link_encs @a kappa-dimensional array of @a num_newcoins encrypted links * @return MHD result code */ static int @@ -382,7 +464,16 @@ handle_refresh_melt_json (struct MHD_Connection *connection, const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, const json_t *new_denoms, const json_t *melt_coins, - const json_t *melt_sig_json) + const json_t *melt_sig_json, + const json_t *commit_signature, + unsigned int kappa, + unsigned int num_oldcoins, + const json_t *transfer_pubs, + const json_t *secret_encs, + unsigned int num_newcoins, + const json_t *coin_evs, + const json_t *link_encs) + { int res; unsigned int i; @@ -392,6 +483,11 @@ handle_refresh_melt_json (struct MHD_Connection *connection, struct TALER_CoinPublicInfo *coin_public_infos; struct MeltDetails *coin_melt_details; unsigned int coin_count; + struct GNUNET_HashCode commit_hash; + struct GNUNET_HashContext *hash_context; + struct RefreshCommitSignatureBody body; + struct RefreshCommitCoin *commit_coin[kappa]; + struct RefreshCommitLink *commit_link[kappa]; num_new_denoms = json_array_size (new_denoms); denom_pubs = GNUNET_malloc (num_new_denoms * @@ -441,180 +537,6 @@ handle_refresh_melt_json (struct MHD_Connection *connection, } } - res = handle_refresh_melt_binary (connection, - refresh_session_pub, - num_new_denoms, - denom_pubs, - coin_count, - coin_public_infos, - coin_melt_details, - melt_sig_json); - for (j=0;j<coin_count;j++) - { - GNUNET_CRYPTO_rsa_public_key_free (coin_public_infos[j].denom_pub); - GNUNET_CRYPTO_rsa_signature_free (coin_public_infos[j].denom_sig); - } - GNUNET_free (coin_public_infos); - for (j=0;j<num_new_denoms;j++) - { - GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j]); - } - GNUNET_free (coin_melt_details); - GNUNET_free (denom_pubs); - return res; -} - - -/** - * Handle a "/refresh/melt" request. Parses the request into the JSON - * components and then hands things of to #handle_referesh_melt_json() - * to validate the melted coins, the signature and execute the melt - * using TALER_MINT_db_execute_refresh_melt(). - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[IN|OUT] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data - * @return MHD result code - */ -int -TALER_MINT_handler_refresh_melt (struct RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) -{ - json_t *root; - json_t *new_denoms; - json_t *melt_coins; - json_t *melt_sig_json; - struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub; - int res; - struct GNUNET_MINT_ParseFieldSpec spec[] = { - TALER_MINT_PARSE_FIXED ("session_pub", &refresh_session_pub), - TALER_MINT_PARSE_ARRAY ("new_denoms", &new_denoms), - TALER_MINT_PARSE_ARRAY ("melt_coins", &melt_coins), - TALER_MINT_PARSE_ARRAY ("melt_signature", &melt_sig_json), - TALER_MINT_PARSE_END - }; - - res = TALER_MINT_parse_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &root); - if (GNUNET_SYSERR == res) - return MHD_NO; - if ( (GNUNET_NO == res) || (NULL == root) ) - return MHD_YES; - - res = TALER_MINT_parse_json_data (connection, - root, - spec); - json_decref (root); - if (GNUNET_OK != res) - return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; - res = handle_refresh_melt_json (connection, - &refresh_session_pub, - new_denoms, - melt_coins, - melt_sig_json); - TALER_MINT_release_parsed_data (spec); - return res; -} - - -/** - * Release memory from the @a commit_coin array. - * - * @param commit_coin array to release - * @param kappa size of 1st dimension - * @param num_new_coins size of 2nd dimension - */ -static void -free_commit_coins (struct RefreshCommitCoin **commit_coin, - unsigned int kappa, - unsigned int num_new_coins) -{ - unsigned int i; - unsigned int j; - - for (i=0;i<kappa;i++) - { - if (NULL == commit_coin[i]) - break; - for (j=0;j<num_new_coins;j++) - { - GNUNET_free_non_null (commit_coin[i][j].coin_ev); - GNUNET_free_non_null (commit_coin[i][j].refresh_link); - } - GNUNET_free (commit_coin[i]); - } -} - - -/** - * Release memory from the @a commit_link array. - * - * @param commit_coin array to release - * @param kappa size of 1st dimension - * @param num_old_coins size of 2nd dimension - */ -static void -free_commit_links (struct RefreshCommitLink **commit_link, - unsigned int kappa, - unsigned int num_old_coins) -{ - unsigned int i; - - for (i=0;i<kappa;i++) - { - if (NULL == commit_link[i]) - break; - GNUNET_free (commit_link[i]); - } -} - - - -/** - * Handle a "/refresh/commit" request. We have the individual JSON - * arrays, now we need to parse their contents and verify the - * commit signature. Then we can commit the data to the database. - * - * @param connection the MHD connection to handle - * @param refresh_session_pub public key of the refresh session - * @param commit_signature signature over the commit - * @param kappa security parameter for cut and choose - * @param num_oldcoins number of coins that are being melted - * @param transfer_pubs @a kappa-dimensional array of @a num_oldcoins transfer keys - * @param secret_encs @a kappa-dimensional array of @a num_oldcoins secrets - * @param num_newcoins number of coins that the refresh will generate - * @param coin_envs @a kappa-dimensional array of @a num_newcoins envelopes to sign - * @param link_encs @a kappa-dimensional array of @a num_newcoins encrypted links - * @return MHD result code - */ -static int -handle_refresh_commit_json (struct MHD_Connection *connection, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - const json_t *commit_signature, - unsigned int kappa, - unsigned int num_oldcoins, - const json_t *transfer_pubs, - const json_t *secret_encs, - unsigned int num_newcoins, - const json_t *coin_evs, - const json_t *link_encs) -{ - struct GNUNET_HashCode commit_hash; - struct GNUNET_HashContext *hash_context; - struct RefreshCommitSignatureBody body; - struct RefreshCommitCoin *commit_coin[kappa]; - struct RefreshCommitLink *commit_link[kappa]; - unsigned int i; - unsigned int j; - int res; /* parse JSON arrays into 2d binary arrays and hash everything together for the signature check */ @@ -721,7 +643,7 @@ handle_refresh_commit_json (struct MHD_Connection *connection, GNUNET_CRYPTO_hash_context_finish (hash_context, &commit_hash); /* verify commit signature */ - body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_COMMIT); + body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT); body.purpose.size = htonl (sizeof (struct RefreshCommitSignatureBody)); body.commit_hash = commit_hash; @@ -738,29 +660,43 @@ handle_refresh_commit_json (struct MHD_Connection *connection, /* execute commit */ /* FIXME: we must also store the signature! (#3635) */ - res = TALER_MINT_db_execute_refresh_commit (connection, - refresh_session_pub, - NULL /* FIXME: 3635! */, - kappa, - num_oldcoins, - num_newcoins, - commit_coin, - commit_link); + res = handle_refresh_melt_binary (connection, + refresh_session_pub, + num_new_denoms, + denom_pubs, + coin_count, + coin_public_infos, + coin_melt_details, + melt_sig_json, + NULL /* FIXME: 3635! */, + kappa, + num_oldcoins, + num_newcoins, + commit_coin, + commit_link); free_commit_coins (commit_coin, kappa, num_newcoins); free_commit_links (commit_link, kappa, num_oldcoins); - + for (j=0;j<coin_count;j++) + { + GNUNET_CRYPTO_rsa_public_key_free (coin_public_infos[j].denom_pub); + GNUNET_CRYPTO_rsa_signature_free (coin_public_infos[j].denom_sig); + } + GNUNET_free (coin_public_infos); + for (j=0;j<num_new_denoms;j++) + { + GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j]); + } + GNUNET_free (coin_melt_details); + GNUNET_free (denom_pubs); return res; } /** - * Handle a "/refresh/commit" request. Parses the top-level JSON to - * determine the dimensions of the problem and then handles handing - * off to #handle_refresh_commit_json() to parse the details of the - * JSON arguments. Once the signature has been verified, the - * commit data is written to the database via - * #TALER_MINT_db_execute_refresh_commit() and the reveal parameter - * is then returned to the client. + * Handle a "/refresh/melt" request. Parses the request into the JSON + * components and then hands things of to #handle_referesh_melt_json() + * to validate the melted coins, the signature and execute the melt + * using TALER_MINT_db_execute_refresh_melt(). * * @param rh context of the handler * @param connection the MHD connection to handle @@ -768,28 +704,34 @@ handle_refresh_commit_json (struct MHD_Connection *connection, * @param upload_data upload data * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data * @return MHD result code - */ + */ int -TALER_MINT_handler_refresh_commit (struct RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) +TALER_MINT_handler_refresh_melt (struct RequestHandler *rh, + struct MHD_Connection *connection, + void **connection_cls, + const char *upload_data, + size_t *upload_data_size) { - struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub; - int res; - unsigned int kappa; - unsigned int num_oldcoins; - unsigned int num_newcoins; json_t *root; + json_t *new_denoms; + json_t *melt_coins; + json_t *melt_sig_json; json_t *coin_evs; json_t *link_encs; json_t *transfer_pubs; json_t *secret_encs; - json_t *coin_detail; json_t *commit_sig_json; + unsigned int kappa; + unsigned int num_oldcoins; + unsigned int num_newcoins; + json_t *coin_detail; + struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub; + int res; struct GNUNET_MINT_ParseFieldSpec spec[] = { TALER_MINT_PARSE_FIXED ("session_pub", &refresh_session_pub), + TALER_MINT_PARSE_ARRAY ("new_denoms", &new_denoms), + TALER_MINT_PARSE_ARRAY ("melt_coins", &melt_coins), + TALER_MINT_PARSE_ARRAY ("melt_signature", &melt_sig_json), TALER_MINT_PARSE_ARRAY ("coin_evs", &coin_evs), TALER_MINT_PARSE_ARRAY ("link_encs", &link_encs), TALER_MINT_PARSE_ARRAY ("transfer_pubs", &transfer_pubs), @@ -852,16 +794,21 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh, return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; } num_oldcoins = json_array_size (coin_detail); - res = handle_refresh_commit_json (connection, - &refresh_session_pub, - commit_sig_json, - kappa, - num_oldcoins, - transfer_pubs, - secret_encs, - num_newcoins, - coin_evs, - link_encs); + + res = handle_refresh_melt_json (connection, + &refresh_session_pub, + new_denoms, + melt_coins, + melt_sig_json, + commit_sig_json, + kappa, + num_oldcoins, + transfer_pubs, + secret_encs, + num_newcoins, + coin_evs, + link_encs); + TALER_MINT_release_parsed_data (spec); return res; } @@ -931,7 +878,7 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, /** * Handle a "/refresh/reveal" request. This time, the client reveals * the private transfer keys except for the cut-and-choose value - * returned from "/refresh/commit". This function parses the revealed + * returned from "/refresh/melt". This function parses the revealed * keys and secrets and ultimately passes everything to * #TALER_MINT_db_execute_refresh_reveal() which will verify that the * 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, /** - * Handle a "/refresh/commit" request. Parses the top-level JSON to - * determine the dimensions of the problem and then handles handing - * off to #handle_refresh_commit_json() to parse the details of the - * JSON arguments. Once the signature has been verified, the - * commit data is written to the database via - * #TALER_MINT_db_execute_refresh_commit() and the cut-and-choose value - * is then returned to the client. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[IN|OUT] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data - * @return MHD result code - */ -int -TALER_MINT_handler_refresh_commit (struct RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); - - -/** * Handle a "/refresh/reveal" request. This time, the client reveals * the private transfer keys except for the cut-and-choose value * 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, return ret; } - /** - * Send proof that a /deposit, /refresh/melt or /lock request is - * invalid to client. This function will create a message with all of - * the operations affecting the coin that demonstrate that the coin - * has insufficient value. + * Compile the transaction history of a coin into a JSON object. * - * @param connection connection to the client - * @param tl transaction list to use to build reply - * @return MHD result code + * @param tl transaction history to JSON-ify + * @return json representation of the @a rh */ -int -TALER_MINT_reply_insufficient_funds (struct MHD_Connection *connection, - const struct TALER_MINT_DB_TransactionList *tl) +static json_t * +compile_transaction_history (const struct TALER_MINT_DB_TransactionList *tl) { - const struct TALER_MINT_DB_TransactionList *pos; - int ret; - json_t *history; json_t *transaction; const char *type; struct TALER_Amount value; + json_t *history; + const struct TALER_MINT_DB_TransactionList *pos; history = json_array (); for (pos = tl; NULL != pos; pos = pos->next) @@ -392,13 +385,31 @@ TALER_MINT_reply_insufficient_funds (struct MHD_Connection *connection, "amount", TALER_JSON_from_amount (value), "signature", transaction)); } + return history; +} - ret = TALER_MINT_reply_json_pack (connection, - MHD_HTTP_FORBIDDEN, - "{s:s, s:o}", - "error", "insufficient funds", - "history", history); - return ret; + +/** + * Send proof that a /withdraw request is invalid to client. This + * function will create a message with all of the operations affecting + * the coin that demonstrate that the coin has insufficient value. + * + * @param connection connection to the client + * @param tl transaction list to use to build reply + * @return MHD result code + */ +int +TALER_MINT_reply_deposit_insufficient_funds (struct MHD_Connection *connection, + const struct TALER_MINT_DB_TransactionList *tl) +{ + json_t *history; + + history = compile_transaction_history (tl); + return TALER_MINT_reply_json_pack (connection, + MHD_HTTP_FORBIDDEN, + "{s:s, s:o}", + "error", "insufficient funds", + "history", history); } @@ -589,47 +600,46 @@ TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection, /** - * Send a response for "/refresh/melt". Essentially we sign - * over the client's signature and public key, thereby - * demonstrating that we accepted all of the client's coins. + * Send a response for a failed "/refresh/melt" request. The + * transaction history of the given coin demonstrates that the + * @a residual value of the coin is below the @a requested + * contribution of the coin for the melt. Thus, the mint + * refuses the melt operation. * * @param connection the connection to send the response to - * @param signature the client's signature over the melt request - * @param session_pub the refresh session public key. - * @param kappa security parameter to use for cut and choose + * @param coin_pub public key of the coin + * @param coin_value original value of the coin + * @param tl transaction history for the coin + * @param requested how much this coin was supposed to contribute + * @param residual remaining value of the coin (after subtracting @a tl) * @return a MHD result code */ int -TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, - const struct GNUNET_CRYPTO_EddsaSignature *signature, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - unsigned int kappa) +TALER_MINT_reply_refresh_melt_insufficient_funds (struct MHD_Connection *connection, + const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, + struct TALER_Amount coin_value, + struct TALER_MINT_DB_TransactionList *tl, + struct TALER_Amount requested, + struct TALER_Amount residual) { - int ret; - struct RefreshMeltResponseSignatureBody body; - struct GNUNET_CRYPTO_EddsaSignature sig; - json_t *sig_json; + json_t *history; - body.purpose.size = htonl (sizeof (struct RefreshMeltResponseSignatureBody)); - body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_RESPONSE); - body.melt_client_signature = *signature; - body.session_key = *session_pub; - body.kappa = htonl (kappa); - TALER_MINT_keys_sign (&body.purpose, - &sig); - sig_json = TALER_JSON_from_eddsa_sig (&body.purpose, &sig); - ret = TALER_MINT_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o, s:i}", - "signature", sig_json, - "kappa", (int) kappa); - json_decref (sig_json); - return ret; + history = compile_transaction_history (tl); + return TALER_MINT_reply_json_pack (connection, + MHD_HTTP_NOT_FOUND, + "{s:s, s:o, s:o, s:o, s:o, s:o}", + "error", "insufficient funds", + "coin-pub", TALER_JSON_from_data (coin_pub, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)), + "original-value", TALER_JSON_from_amount (coin_value), + "residual-value", TALER_JSON_from_amount (residual), + "requested-value", TALER_JSON_from_amount (requested), + "history", history); } /** - * Send a response to a "/refresh/commit" request. + * Send a response to a "/refresh/melt" request. * * @param connection the connection to send the response to * @param session_hash hash of the refresh session @@ -637,17 +647,17 @@ TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, * @return a MHD status code */ int -TALER_MINT_reply_refresh_commit_success (struct MHD_Connection *connection, - const struct GNUNET_HashCode *session_hash, - uint16_t noreveal_index) +TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, + const struct GNUNET_HashCode *session_hash, + uint16_t noreveal_index) { - struct RefreshCommitResponseSignatureBody body; + struct RefreshMeltResponseSignatureBody body; struct GNUNET_CRYPTO_EddsaSignature sig; json_t *sig_json; int ret; - body.purpose.size = htonl (sizeof (struct RefreshCommitResponseSignatureBody)); - body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_COMMIT_RESPONSE); + body.purpose.size = htonl (sizeof (struct RefreshMeltResponseSignatureBody)); + body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_RESPONSE); body.session_hash = *session_hash; body.noreveal_index = htons (noreveal_index); 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, /** - * Send proof that a /deposit, /refresh/melt or /lock request is - * invalid to client. This function will create a message with all of - * the operations affecting the coin that demonstrate that the coin - * has insufficient value. + * Send proof that a /deposit request is invalid to client. This + * function will create a message with all of the operations affecting + * the coin that demonstrate that the coin has insufficient value. * * @param connection connection to the client * @param tl transaction list to use to build reply * @return MHD result code */ int -TALER_MINT_reply_insufficient_funds (struct MHD_Connection *connection, - const struct TALER_MINT_DB_TransactionList *tl); +TALER_MINT_reply_deposit_insufficient_funds (struct MHD_Connection *connection, + const struct TALER_MINT_DB_TransactionList *tl); /** @@ -247,7 +246,7 @@ TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection, /** - * Send a response to a "/refresh/commit" request. + * Send a confirmation response to a "/refresh/melt" request. * * @param connection the connection to send the response to * @param session_hash hash of the refresh session @@ -255,27 +254,33 @@ TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection, * @return a MHD status code */ int -TALER_MINT_reply_refresh_commit_success (struct MHD_Connection *connection, - const struct GNUNET_HashCode *session_hash, - uint16_t noreveal_index); +TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, + const struct GNUNET_HashCode *session_hash, + uint16_t noreveal_index); /** - * Send a response for "/refresh/melt". Essentially we sign - * over the client's signature and public key, thereby - * demonstrating that we accepted all of the client's coins. + * Send a response for a failed "/refresh/melt" request. The + * transaction history of the given coin demonstrates that the + * @a residual value of the coin is below the @a requested + * contribution of the coin for the melt. Thus, the mint + * refuses the melt operation. * * @param connection the connection to send the response to - * @param signature the client's signature over the melt request - * @param session_pub the refresh session public key. - * @param kappa security parameter to use for cut and choose + * @param coin_pub public key of the coin + * @param coin_value original value of the coin + * @param tl transaction history for the coin + * @param requested how much this coin was supposed to contribute + * @param residual remaining value of the coin (after subtracting @a tl) * @return a MHD result code */ int -TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, - const struct GNUNET_CRYPTO_EddsaSignature *signature, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - unsigned int kappa); +TALER_MINT_reply_refresh_melt_insufficient_funds (struct MHD_Connection *connection, + const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, + struct TALER_Amount coin_value, + struct TALER_MINT_DB_TransactionList *tl, + struct TALER_Amount requested, + struct TALER_Amount residual); /** |