diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-01-30 15:34:01 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-01-30 15:34:01 +0100 |
commit | 1102b7dace09012087ca38d143788e5ae74ae2c5 (patch) | |
tree | 75eb2300f90807d613a5c47035838ea38fa820f4 | |
parent | 29ee8a41a46136f0aa23a27b073dd368b0b4c62a (diff) |
working on /refresh/melt operation
-rw-r--r-- | src/mint/mint_db.c | 259 | ||||
-rw-r--r-- | src/mint/mint_db.h | 80 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_db.c | 245 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_db.h | 24 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_refresh.c | 33 |
5 files changed, 304 insertions, 337 deletions
diff --git a/src/mint/mint_db.c b/src/mint/mint_db.c index 9a35ddbd4..57a1014b7 100644 --- a/src/mint/mint_db.c +++ b/src/mint/mint_db.c @@ -494,51 +494,6 @@ TALER_MINT_DB_prepare (PGconn *db_conn) } -/** - * Insert a refresh order into the database. - */ -int -TALER_MINT_DB_insert_refresh_order (PGconn *db_conn, - uint16_t newcoin_index, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub) -{ - uint16_t newcoin_index_nbo = htons (newcoin_index); - char *buf; - size_t buf_size; - PGresult *result; - - buf_size = GNUNET_CRYPTO_rsa_public_key_encode (denom_pub, - &buf); - - { - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (&newcoin_index_nbo), - TALER_DB_QUERY_PARAM_PTR (session_pub), - TALER_DB_QUERY_PARAM_PTR_SIZED (buf, buf_size), - TALER_DB_QUERY_PARAM_END - }; - result = TALER_DB_exec_prepared (db_conn, - "insert_refresh_order", - params); - } - GNUNET_free (buf); - if (PGRES_COMMAND_OK != PQresultStatus (result)) - { - break_db_err (result); - PQclear (result); - return GNUNET_SYSERR; - } - if (0 != strcmp ("1", PQcmdTuples (result))) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - PQclear (result); - return GNUNET_OK; -} - - int TALER_MINT_DB_set_commit_signature (PGconn *db_conn, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, @@ -578,55 +533,6 @@ TALER_MINT_DB_set_reveal_ok (PGconn *db_conn, } -struct GNUNET_CRYPTO_rsa_PublicKey * -TALER_MINT_DB_get_refresh_order (PGconn *db_conn, - uint16_t newcoin_index, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub) - -{ - char *buf; - size_t buf_size; - struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; - uint16_t newcoin_index_nbo = htons (newcoin_index); - - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(session_pub), - TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo), - TALER_DB_QUERY_PARAM_END - }; - - PGresult *result = TALER_DB_exec_prepared (db_conn, "get_refresh_order", params); - - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - break_db_err (result); - PQclear (result); - return NULL; - } - - if (0 == PQntuples (result)) - { - PQclear (result); - /* FIXME: may want to distinguish between different error cases! */ - return NULL; - } - GNUNET_assert (1 == PQntuples (result)); - struct TALER_DB_ResultSpec rs[] = { - TALER_DB_RESULT_SPEC_VAR ("denom_pub", &buf, &buf_size), - TALER_DB_RESULT_SPEC_END - }; - if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0)) - { - PQclear (result); - GNUNET_break (0); - return NULL; - } - PQclear (result); - denom_pub = GNUNET_CRYPTO_rsa_public_key_decode (buf, buf_size); - GNUNET_free (buf); - return denom_pub; -} - int TALER_MINT_DB_insert_refresh_collectable (PGconn *db_conn, @@ -1480,61 +1386,23 @@ TALER_MINT_DB_update_refresh_session (PGconn *db_conn, /** - * Test if the given /refresh/melt request is known to us. - * - * @param db_conn database connection - * @param melt melt operation - * @return #GNUNET_YES if known, - * #GNUENT_NO if not, - * #GNUNET_SYSERR on internal error - */ -int -TALER_MINT_DB_have_refresh_melt (PGconn *db_conn, - const struct RefreshMelt *melt) -{ - // FIXME: check logic! - uint16_t oldcoin_index_nbo = htons (melt->oldcoin_index); - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(&melt->session_pub), - TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo), - TALER_DB_QUERY_PARAM_END - }; - - PGresult *result = TALER_DB_exec_prepared (db_conn, - "get_refresh_melt", - params); - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - break_db_err (result); - PQclear (result); - return GNUNET_SYSERR; - } - - if (0 == PQntuples (result)) - { - PQclear (result); - return GNUNET_NO; - } - GNUNET_break (1 == PQntuples (result)); - PQclear (result); - return GNUNET_YES; -} - - -/** * Store the given /refresh/melt request in the database. * * @param db_conn database connection + * @param session session key of the melt operation + * @param oldcoin_index index of the coin to store * @param melt melt operation * @return #GNUNET_OK on success * #GNUNET_SYSERR on internal error */ int TALER_MINT_DB_insert_refresh_melt (PGconn *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *session, + uint16_t oldcoin_index, const struct RefreshMelt *melt) { // FIXME: check logic! - uint16_t oldcoin_index_nbo = htons (melt->oldcoin_index); + uint16_t oldcoin_index_nbo = htons (oldcoin_index); char *buf; size_t buf_size; PGresult *result; @@ -1543,7 +1411,7 @@ TALER_MINT_DB_insert_refresh_melt (PGconn *db_conn, &buf); { struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(&melt->session_pub), + TALER_DB_QUERY_PARAM_PTR(session), TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo), TALER_DB_QUERY_PARAM_PTR(&melt->coin.coin_pub), TALER_DB_QUERY_PARAM_PTR_SIZED(buf, buf_size), @@ -1586,6 +1454,121 @@ TALER_MINT_DB_get_refresh_melt (PGconn *db_conn, /** + * Store in the database which coin(s) we want to create + * in a given refresh operation. + * + * @param db_conn database connection + * @param session_pub refresh session key + * @param newcoin_index index of the coin to generate + * @param denom_pub denomination of the coin to create + * @return #GNUNET_OK on success + * #GNUNET_SYSERR on internal error + */ +int +TALER_MINT_DB_insert_refresh_order (PGconn *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + uint16_t newcoin_index, + const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub) +{ + // FIXME: check logic + uint16_t newcoin_index_nbo = htons (newcoin_index); + char *buf; + size_t buf_size; + PGresult *result; + + buf_size = GNUNET_CRYPTO_rsa_public_key_encode (denom_pub, + &buf); + + { + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR (&newcoin_index_nbo), + TALER_DB_QUERY_PARAM_PTR (session_pub), + TALER_DB_QUERY_PARAM_PTR_SIZED (buf, buf_size), + TALER_DB_QUERY_PARAM_END + }; + result = TALER_DB_exec_prepared (db_conn, + "insert_refresh_order", + params); + } + GNUNET_free (buf); + if (PGRES_COMMAND_OK != PQresultStatus (result)) + { + break_db_err (result); + PQclear (result); + return GNUNET_SYSERR; + } + if (0 != strcmp ("1", PQcmdTuples (result))) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + PQclear (result); + return GNUNET_OK; +} + + +/** + * Lookup in the database the @a newcoin_index coin that we want to + * create in the given refresh operation. + * + * @param db_conn database connection + * @param session_pub refresh session key + * @param newcoin_index index of the coin to generate + * @param denom_pub denomination of the coin to create + * @return NULL on error (not found or internal error) + */ +struct GNUNET_CRYPTO_rsa_PublicKey * +TALER_MINT_DB_get_refresh_order (PGconn *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + uint16_t newcoin_index) +{ + // FIXME: check logic + char *buf; + size_t buf_size; + struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; + uint16_t newcoin_index_nbo = htons (newcoin_index); + + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR(session_pub), + TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo), + TALER_DB_QUERY_PARAM_END + }; + + PGresult *result = TALER_DB_exec_prepared (db_conn, "get_refresh_order", params); + + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + break_db_err (result); + PQclear (result); + return NULL; + } + + if (0 == PQntuples (result)) + { + PQclear (result); + /* FIXME: may want to distinguish between different error cases! */ + return NULL; + } + GNUNET_assert (1 == PQntuples (result)); + struct TALER_DB_ResultSpec rs[] = { + TALER_DB_RESULT_SPEC_VAR ("denom_pub", &buf, &buf_size), + TALER_DB_RESULT_SPEC_END + }; + if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0)) + { + PQclear (result); + GNUNET_break (0); + return NULL; + } + PQclear (result); + denom_pub = GNUNET_CRYPTO_rsa_public_key_decode (buf, buf_size); + GNUNET_free (buf); + return denom_pub; +} + + + +/** * Store information about the commitment of the * given coin for the given refresh session in the database. * diff --git a/src/mint/mint_db.h b/src/mint/mint_db.h index 0c0288ab2..ec9947bc2 100644 --- a/src/mint/mint_db.h +++ b/src/mint/mint_db.h @@ -35,19 +35,6 @@ int TALER_MINT_DB_prepare (PGconn *db_conn); -int -TALER_MINT_DB_insert_refresh_order (PGconn *db_conn, - uint16_t newcoin_index, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub); - - - -struct GNUNET_CRYPTO_rsa_PublicKey * -TALER_MINT_DB_get_refresh_order (PGconn *db_conn, - uint16_t newcoin_index, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub); - int TALER_MINT_DB_insert_refresh_collectable (PGconn *db_conn, @@ -520,6 +507,8 @@ TALER_MINT_DB_update_refresh_session (PGconn *db_conn, /** * Specification for coin in a /refresh/melt operation. + * FIXME: same as `struct MeltDetails`, and not by accident! + * We should merge the structs! */ struct RefreshMelt /* FIXME: name to make it clearer this is about ONE coin! */ { @@ -529,11 +518,6 @@ struct RefreshMelt /* FIXME: name to make it clearer this is about ONE coin! */ struct TALER_CoinPublicInfo coin; /** - * Public key of the melting session. - */ - struct GNUNET_CRYPTO_EddsaPublicKey session_pub; - - /** * Signature over the melting operation. */ struct GNUNET_CRYPTO_EcdsaSignature coin_sig; @@ -543,41 +527,27 @@ struct RefreshMelt /* FIXME: name to make it clearer this is about ONE coin! */ */ struct TALER_Amount amount; - /** - * What is the index of this coin in the melting session? - */ - uint16_t oldcoin_index; - }; /** - * Test if the given /refresh/melt request is known to us. - * - * @param db_conn database connection - * @param melt melt operation - * @return #GNUNET_YES if known, - * #GNUENT_NO if not, - * #GNUNET_SYSERR on internal error - */ -int -TALER_MINT_DB_have_refresh_melt (PGconn *db_conn, - const struct RefreshMelt *melt); - - -/** * Store the given /refresh/melt request in the database. * * @param db_conn database connection - * @param melt melt operation + * @param session session key of the melt operation + * @param oldcoin_index index of the coin to store + * @param melt coin melt operation details to store * @return #GNUNET_OK on success * #GNUNET_SYSERR on internal error */ int TALER_MINT_DB_insert_refresh_melt (PGconn *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *session, + uint16_t oldcoin_index, const struct RefreshMelt *melt); + /** * Get information about melted coin details from the database. * @@ -596,6 +566,40 @@ TALER_MINT_DB_get_refresh_melt (PGconn *db_conn, /** + * Store in the database which coin(s) we want to create + * in a given refresh operation. + * + * @param db_conn database connection + * @param session_pub refresh session key + * @param newcoin_index index of the coin to generate + * @param denom_pub denomination of the coin to create + * @return #GNUNET_OK on success + * #GNUNET_SYSERR on internal error + */ +int +TALER_MINT_DB_insert_refresh_order (PGconn *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + uint16_t newcoin_index, + const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub); + + +/** + * Lookup in the database the @a newcoin_index coin that we want to + * create in the given refresh operation. + * + * @param db_conn database connection + * @param session_pub refresh session key + * @param newcoin_index index of the coin to generate + * @param denom_pub denomination of the coin to create + * @return NULL on error (not found or internal error) + */ +struct GNUNET_CRYPTO_rsa_PublicKey * +TALER_MINT_DB_get_refresh_order (PGconn *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + uint16_t newcoin_index); + + +/** * We have as many `struct RefreshCommitCoin` as there are new * coins being created by the refresh (for each of the kappa * sets). These are the coins we ask the mint to sign if the diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 0da207747..39a0bffdd 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -420,50 +420,6 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, } - - - -/** - * Insert all requested denominations into the DB, and compute the - * required cost of the denominations, including fees. - * - * @param connection the connection to send an error response to - * @param db_conn the database connection - * @param key_state the mint's key state to use - * @param session_pub the refresh session public key - * @param denom_pubs_count number of entries in @a denom_pubs - * @param denom_pubs array of public keys for the refresh - * @return FIXME! - */ -static int -refresh_accept_denoms (struct MHD_Connection *connection, - PGconn *db_conn, - const struct MintKeyState *key_state, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - unsigned int denom_pubs_count, - struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs) -{ - unsigned int i; - int res; - - for (i = 0; i < denom_pubs_count; i++) - { - /* Insert the requested coin into the DB, so we'll know later - * what denomination the request had */ - - if (GNUNET_OK != - (res = TALER_MINT_DB_insert_refresh_order (db_conn, - i, - session_pub, - denom_pubs[i]))) - return res; // ??? - } - return GNUNET_OK; -} - - - - /** * Parse coin melt requests from a JSON object and write them to * the database. @@ -472,9 +428,9 @@ refresh_accept_denoms (struct MHD_Connection *connection, * @param db_conn the database connection * @param key_state the mint's key state * @param session_pub the refresh session's public key - * @param coin_count number of coins in @a coin_public_infos to melt - * @param coin_public_infos the coins to melt - * @param r_melt_balance[OUT] FIXME (#3636: check earlier, pass expected value IN, not OUT!) + * @param coin_public_info the coin to melt + * @param coin_details details about the coin being melted + * @param oldcoin_index what is the number assigned to this coin * @return #GNUNET_OK on success, * #GNUNET_NO if an error message was generated, * #GNUNET_SYSERR on internal errors (no response generated) @@ -484,69 +440,58 @@ refresh_accept_melts (struct MHD_Connection *connection, PGconn *db_conn, const struct MintKeyState *key_state, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - unsigned int coin_count, - const struct TALER_CoinPublicInfo *coin_public_infos, - struct TALER_Amount *r_melt_balance) + const struct TALER_CoinPublicInfo *coin_public_info, + const struct MeltDetails *coin_details, + uint16_t oldcoin_index) { - size_t i; + struct TALER_MINT_DenomKeyIssue *dki; + struct TALER_MINT_DB_TransactionList *tl; + struct TALER_Amount coin_gain; + struct RefreshMelt melt; - memset (r_melt_balance, 0, sizeof (struct TALER_Amount)); + dki = &TALER_MINT_get_denom_key (key_state, + coin_public_info->denom_pub)->issue; - for (i = 0; i < coin_count; i++) - { - struct TALER_MINT_DenomKeyIssue *dki; - struct TALER_MINT_DB_TransactionList *tl; - // money the customer gets by melting the current coin - struct TALER_Amount coin_gain; - struct RefreshMelt melt; + if (NULL == dki) + return (MHD_YES == + TALER_MINT_reply_json_pack (connection, + MHD_HTTP_NOT_FOUND, + "{s:s}", + "error", + "denom not found")) + ? GNUNET_NO : GNUNET_SYSERR; + + coin_gain = 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); - dki = &TALER_MINT_get_denom_key (key_state, - coin_public_infos[i].denom_pub)->issue; + /* Refuse to refresh when the coin does not have enough money left to + * pay the refreshing fees of the coin. */ - if (NULL == dki) - return (MHD_YES == - TALER_MINT_reply_json_pack (connection, - MHD_HTTP_NOT_FOUND, - "{s:s}", - "error", - "denom not found")) - ? GNUNET_NO : GNUNET_SYSERR; - - coin_gain = TALER_amount_ntoh (dki->value); - tl = TALER_MINT_DB_get_coin_transactions (db_conn, - &coin_public_infos[i].coin_pub); - /* FIXME: compute how much value is left with this coin! */ - TALER_MINT_DB_free_coin_transaction_list (tl); + if (TALER_amount_cmp (coin_gain, + 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; - melt.coin = coin_public_infos[i]; - melt.session_pub = *session_pub; - // melt.coin_sig = FIXME; - // melt.amount = FIXME; - melt.oldcoin_index = i; - if (GNUNET_OK != - TALER_MINT_DB_insert_refresh_melt (db_conn, - &melt)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - - - /* 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, - TALER_amount_ntoh (dki->fee_refresh)) < 0) - return (MHD_YES == - TALER_MINT_reply_json_pack (connection, - MHD_HTTP_NOT_FOUND, - "{s:s}", - "error", "depleted")) ? GNUNET_NO : GNUNET_SYSERR; - coin_gain = TALER_amount_subtract (coin_gain, - TALER_amount_ntoh (dki->fee_refresh)); - *r_melt_balance = TALER_amount_add (*r_melt_balance, - coin_gain); + melt.coin = *coin_public_info; + melt.coin_sig = coin_details->melt_sig; + melt.amount = coin_details->melt_amount; + if (GNUNET_OK != + TALER_MINT_DB_insert_refresh_melt (db_conn, + session_pub, + oldcoin_index, + &melt)) + { + GNUNET_break (0); + return GNUNET_SYSERR; } return GNUNET_OK; } @@ -565,8 +510,9 @@ refresh_accept_melts (struct MHD_Connection *connection, * over the melting request * @param num_new_denoms number of entries in @a denom_pubs * @param denum_pubs public keys of the coins we want to withdraw in the end - * @param coin_count number of entries in @a coin_public_infos + * @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 @@ -576,13 +522,14 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, 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 TALER_CoinPublicInfo *coin_public_infos, + const struct MeltDetails *coin_melt_details) { - struct TALER_Amount melt_balance; struct MintKeyState *key_state; struct RefreshSession session; PGconn *db_conn; int res; + unsigned int i; if (NULL == (db_conn = TALER_MINT_DB_get_connection ())) { @@ -612,6 +559,41 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, return TALER_MINT_reply_internal_db_error (connection); } + /* Melt old coins and check that they had enough residual value */ + key_state = TALER_MINT_key_state_acquire (); + for (i=0;i<coin_count;i++) + { + if (GNUNET_OK != + (res = refresh_accept_melts (connection, + db_conn, + key_state, + refresh_session_pub, + &coin_public_infos[i], + &coin_melt_details[i], + i))) + { + TALER_MINT_key_state_release (key_state); + TALER_MINT_DB_rollback (db_conn); + return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; + } + } + TALER_MINT_key_state_release (key_state); + + /* store requested new denominations */ + for (i=0;i<num_new_denoms;i++) + { + if (GNUNET_OK != + TALER_MINT_DB_insert_refresh_order (db_conn, + refresh_session_pub, + i, + denom_pubs[i])) + { + TALER_MINT_DB_rollback (db_conn); + return TALER_MINT_reply_internal_db_error (connection); + } + } + + /* store 'global' session data */ session.melt_sig = *client_signature; session.num_oldcoins = coin_count; session.num_newcoins = num_new_denoms; @@ -627,61 +609,16 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, return TALER_MINT_reply_internal_db_error (connection); } - /* The next two operations must see the same key state, - * thus we acquire it here. */ - - key_state = TALER_MINT_key_state_acquire (); - if (GNUNET_OK != - (res = refresh_accept_denoms (connection, db_conn, key_state, - refresh_session_pub, - num_new_denoms, - denom_pubs))) - { - TALER_MINT_key_state_release (key_state); - TALER_MINT_DB_rollback (db_conn); - return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; - } - - /* Write old coins to db and sum their value */ - if (GNUNET_OK != - (res = refresh_accept_melts (connection, db_conn, key_state, - refresh_session_pub, - coin_count, - coin_public_infos, - &melt_balance))) - { - TALER_MINT_key_state_release (key_state); - TALER_MINT_DB_rollback (db_conn); - return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; - } - - TALER_MINT_key_state_release (key_state); - - - /* Request is only ok if cost of requested coins - * does not exceed value of melted coins. */ - if (GNUNET_OK != TALER_MINT_DB_commit (db_conn)) { LOG_WARNING ("/refresh/melt transaction commit failed\n"); return TALER_MINT_reply_commit_error (connection); } - if (GNUNET_OK != - (res = TALER_MINT_DB_get_refresh_session (db_conn, - refresh_session_pub, - &session))) - { - // FIXME: send internal error - GNUNET_break (0); - return MHD_NO; - } return TALER_MINT_reply_refresh_melt_success (connection, client_signature, refresh_session_pub, session.kappa); - - } @@ -1042,8 +979,8 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, GNUNET_CRYPTO_ecdsa_key_get_public (&link_data->coin_priv, &coin_pub); denom_pub = TALER_MINT_DB_get_refresh_order (db_conn, - j, - refresh_session_pub); + refresh_session_pub, + j); if (NULL == denom_pub) { GNUNET_break (0); @@ -1110,7 +1047,9 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, // FIXME: return error code! return MHD_NO; } - denom_pub = TALER_MINT_DB_get_refresh_order (db_conn, j, refresh_session_pub); + denom_pub = TALER_MINT_DB_get_refresh_order (db_conn, + refresh_session_pub, + j); if (NULL == denom_pub) { GNUNET_break (0); diff --git a/src/mint/taler-mint-httpd_db.h b/src/mint/taler-mint-httpd_db.h index d2566cf7c..e34139868 100644 --- a/src/mint/taler-mint-httpd_db.h +++ b/src/mint/taler-mint-httpd_db.h @@ -80,6 +80,24 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, const struct GNUNET_CRYPTO_EddsaSignature *signature); +/** + * Details about a melt operation of an individual coin. + */ +struct MeltDetails +{ + /** + * Signature allowing the melt (using + * a `struct RefreshMeltConfirmSignRequestBody`) to sign over. + */ + struct GNUNET_CRYPTO_EcdsaSignature melt_sig; + + /** + * How much of the coin's value did the client allow to be melted? + * (FIXME: are the fees included here!?) + */ + struct TALER_Amount melt_amount; +}; + /** * Execute a "/refresh/melt". We have been given a list of valid @@ -94,8 +112,9 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, * over the melting request * @param num_new_denoms number of entries in @a denom_pubs * @param denum_pubs array of public denomination keys for the refresh (?) - * @param coin_count number of entries in @a coin_public_infos + * @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 @@ -105,7 +124,8 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, 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 TALER_CoinPublicInfo *coin_public_infos, + const struct MeltDetails *coin_melt_details); /** diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index e9222be27..f4cff6537 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -145,9 +145,12 @@ request_json_check_signature (struct MHD_Connection *connection, * * @param connection the MHD connection to handle * @param refresh_session_pub public key of the melt operation - * @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 num_new_denoms number of coins to be created + * @param denom_pubs array of @a num_new_denoms keys + * @param coin_count number of coins to be melted + * @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 * @return MHD result code */ static int @@ -157,6 +160,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs, unsigned int coin_count, struct TALER_CoinPublicInfo *coin_public_infos, + const struct MeltDetails *coin_melt_details, const json_t *melt_sig_json) { int res; @@ -248,7 +252,8 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, num_new_denoms, denom_pubs, coin_count, - coin_public_infos); + coin_public_infos, + coin_melt_details); } @@ -264,6 +269,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, * @param session_pub public key of the session the coin is melted into * @param coin_info the JSON object to extract the coin info from * @param r_public_info[OUT] set to the coin's public information + * @param r_melt_detail[OUT] set to details about the coin's melting permission (if valid) * @return #GNUNET_YES if coin public info in JSON was valid * #GNUNET_NO JSON was invalid, response was generated * #GNUNET_SYSERR on internal error @@ -272,7 +278,8 @@ static int get_and_verify_coin_public_info (struct MHD_Connection *connection, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, json_t *coin_info, - struct TALER_CoinPublicInfo *r_public_info) + struct TALER_CoinPublicInfo *r_public_info, + struct MeltDetails *r_melt_detail) { int ret; struct GNUNET_CRYPTO_EcdsaSignature melt_sig; @@ -281,11 +288,13 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection, struct RefreshMeltConfirmSignRequestBody body; struct MintKeyState *key_state; struct TALER_MINT_DenomKeyIssuePriv *dki; + struct TALER_Amount amount; struct GNUNET_MINT_ParseFieldSpec spec[] = { TALER_MINT_PARSE_FIXED ("coin_pub", &r_public_info->coin_pub), TALER_MINT_PARSE_RSA_SIGNATURE ("denom_sig", &sig), TALER_MINT_PARSE_RSA_PUBLIC_KEY ("denom_pub", &pk), TALER_MINT_PARSE_FIXED ("confirm_sig", &melt_sig), + /* FIXME: #3636! */ TALER_MINT_PARSE_END }; @@ -296,6 +305,7 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection, return ret; /* FIXME: include amount of coin value to be melted here (#3636!) and in what we return!? */ + memset (&amount, 0, sizeof (amount)); // FIXME: #3636! body.purpose.size = htonl (sizeof (struct RefreshMeltConfirmSignRequestBody)); body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_CONFIRM); body.session_pub = *session_pub; @@ -344,6 +354,8 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection, "error", "coin invalid")) ? GNUNET_NO : GNUNET_SYSERR; } + r_melt_detail->melt_sig = melt_sig; + r_melt_detail->melt_amount = amount; return GNUNET_OK; } @@ -375,6 +387,7 @@ handle_refresh_melt_json (struct MHD_Connection *connection, struct GNUNET_CRYPTO_rsa_PublicKey **denom_pubs; unsigned int num_new_denoms; struct TALER_CoinPublicInfo *coin_public_infos; + struct MeltDetails *coin_melt_details; unsigned int coin_count; num_new_denoms = json_array_size (new_denoms); @@ -395,15 +408,20 @@ handle_refresh_melt_json (struct MHD_Connection *connection, } coin_count = json_array_size (melt_coins); + /* FIXME: make 'struct TALER_CoinPublicInfo' part of `struct MeltDetails` + and combine these two arrays/arguments! */ coin_public_infos = GNUNET_malloc (coin_count * sizeof (struct TALER_CoinPublicInfo)); + coin_melt_details = GNUNET_malloc (coin_count * + sizeof (struct MeltDetails)); for (i=0;i<coin_count;i++) { /* decode JSON data on coin to melt */ res = get_and_verify_coin_public_info (connection, refresh_session_pub, json_array_get (melt_coins, i), - &coin_public_infos[i]); + &coin_public_infos[i], + &coin_melt_details[i]); if (GNUNET_OK != res) { for (j=0;j<i;j++) @@ -414,6 +432,7 @@ handle_refresh_melt_json (struct MHD_Connection *connection, 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 (GNUNET_NO == res) ? MHD_YES : MHD_NO; } @@ -425,6 +444,7 @@ handle_refresh_melt_json (struct MHD_Connection *connection, denom_pubs, coin_count, coin_public_infos, + coin_melt_details, melt_sig_json); for (j=0;j<coin_count;j++) { @@ -436,6 +456,7 @@ handle_refresh_melt_json (struct MHD_Connection *connection, { GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j]); } + GNUNET_free (coin_melt_details); GNUNET_free (denom_pubs); return res; } |