summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-01-30 15:34:01 +0100
committerChristian Grothoff <christian@grothoff.org>2015-01-30 15:34:01 +0100
commit1102b7dace09012087ca38d143788e5ae74ae2c5 (patch)
tree75eb2300f90807d613a5c47035838ea38fa820f4
parent29ee8a41a46136f0aa23a27b073dd368b0b4c62a (diff)
downloadexchange-1102b7dace09012087ca38d143788e5ae74ae2c5.tar.gz
exchange-1102b7dace09012087ca38d143788e5ae74ae2c5.tar.bz2
exchange-1102b7dace09012087ca38d143788e5ae74ae2c5.zip
working on /refresh/melt operation
-rw-r--r--src/mint/mint_db.c259
-rw-r--r--src/mint/mint_db.h80
-rw-r--r--src/mint/taler-mint-httpd_db.c245
-rw-r--r--src/mint/taler-mint-httpd_db.h24
-rw-r--r--src/mint/taler-mint-httpd_refresh.c33
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;
}