From 579f465c9b2ed1cd4602ee102073d633fda60cb9 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 9 Mar 2015 12:29:41 +0100 Subject: implementing #3632: generate proof of insufficient funds by converting transaction history to JSON --- src/mint/mint_db.h | 13 ++++--- src/mint/taler-mint-httpd_db.c | 15 ++++---- src/mint/taler-mint-httpd_db.h | 5 ++- src/mint/taler-mint-httpd_refresh.c | 4 ++- src/mint/taler-mint-httpd_responses.c | 68 ++++++++++++++++++++++++++++------- 5 files changed, 78 insertions(+), 27 deletions(-) (limited to 'src/mint') diff --git a/src/mint/mint_db.h b/src/mint/mint_db.h index 74f0c2d14..c3a300a57 100644 --- a/src/mint/mint_db.h +++ b/src/mint/mint_db.h @@ -222,8 +222,6 @@ TALER_MINT_DB_reserves_in_insert (PGconn *db, const struct TALER_Amount balance, const struct GNUNET_TIME_Absolute expiry); -/* FIXME: need call to convert CollectableBlindcoin to JSON (#3527) */ - /** * Locate the response for a /withdraw request under the @@ -529,10 +527,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! */ +struct RefreshMelt { /** * Information about the coin that is being melted. @@ -544,8 +540,15 @@ struct RefreshMelt /* FIXME: name to make it clearer this is about ONE coin! */ */ struct GNUNET_CRYPTO_EcdsaSignature coin_sig; + /** + * Which melting operation should the coin become a part of. + */ + struct GNUNET_HashCode melt_hash; + /** * How much value is being melted? + * This amount includes the fees, so the final amount contributed + * to the melt is this value minus the fee for melting the coin. */ struct TALER_Amount amount; diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index e3f7b754c..ed9119313 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -22,10 +22,6 @@ * - actually abstract DB implementation (i.e. via plugin logic) * (this file should remain largely unchanged with the exception * of the PQ-specific DB handle types) - * - /refresh/link: - * + check low-level API - * + separate DB logic from response generation - * + check for leaks */ #include "platform.h" #include @@ -354,8 +350,8 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, break; } } - - /* FIXME: good place to assert deposit_total > withdraw_total... */ + GNUNET_break (0 > TALER_amount_cmp (withdraw_total, + deposit_total)); balance = TALER_amount_subtract (deposit_total, withdraw_total); if (0 < TALER_amount_cmp (amount_required, @@ -382,8 +378,6 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, return TALER_MINT_reply_internal_error (connection, "Internal error"); } - - // FIXME: can we avoid the cast? collectable.denom_pub = (struct GNUNET_CRYPTO_rsa_PublicKey *) denomination_pub; collectable.sig = sig; collectable.reserve_pub = *reserve; @@ -430,6 +424,7 @@ static int refresh_accept_melts (struct MHD_Connection *connection, PGconn *db_conn, const struct MintKeyState *key_state, + const struct GNUNET_HashCode *melt_hash, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, const struct TALER_CoinPublicInfo *coin_public_info, const struct MeltDetails *coin_details, @@ -474,6 +469,7 @@ refresh_accept_melts (struct MHD_Connection *connection, melt.coin = *coin_public_info; melt.coin_sig = coin_details->melt_sig; + melt.melt_hash = *melt_hash; melt.amount = coin_details->melt_amount; if (GNUNET_OK != TALER_MINT_DB_insert_refresh_melt (db_conn, @@ -496,6 +492,7 @@ refresh_accept_melts (struct MHD_Connection *connection, * melted and confirm the melting operation to the client. * * @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 * @param client_signature signature of the client (matching @a refresh_session_pub) * over the melting request @@ -508,6 +505,7 @@ refresh_accept_melts (struct MHD_Connection *connection, */ 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, @@ -558,6 +556,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, (res = refresh_accept_melts (connection, db_conn, key_state, + melt_hash, refresh_session_pub, &coin_public_infos[i], &coin_melt_details[i], diff --git a/src/mint/taler-mint-httpd_db.h b/src/mint/taler-mint-httpd_db.h index b945a7f65..dcd5e6fa0 100644 --- a/src/mint/taler-mint-httpd_db.h +++ b/src/mint/taler-mint-httpd_db.h @@ -93,7 +93,8 @@ struct MeltDetails /** * How much of the coin's value did the client allow to be melted? - * (FIXME: are the fees included here!?) + * This amount includes the fees, so the final amount contributed + * to the melt is this value minus the fee for melting the coin. */ struct TALER_Amount melt_amount; }; @@ -107,6 +108,7 @@ struct MeltDetails * melted and confirm the melting operation to the client. * * @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 * @param client_signature signature of the client (matching @a refresh_session_pub) * over the melting request @@ -119,6 +121,7 @@ struct MeltDetails */ 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, diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index cae001acc..5625dc8c7 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -195,9 +195,10 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, GNUNET_CRYPTO_hash_context_finish (hash_context, &melt_hash); - body.melt_hash = melt_hash; body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT); body.purpose.size = htonl (sizeof (struct RefreshMeltSignatureBody)); + body.melt_hash = melt_hash; + body.amount = TALER_amount_hton (coin_melt_details->melt_amount); if (GNUNET_OK != (res = request_json_check_signature (connection, @@ -247,6 +248,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, /* FIXME: we must also store the signature over the melt! (#3635) */ return TALER_MINT_db_execute_refresh_melt (connection, + &melt_hash, refresh_session_pub, NULL, /* FIXME: #3635! */ num_new_denoms, diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index 77cdb4078..ec8fdc03b 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c @@ -305,7 +305,7 @@ TALER_MINT_reply_deposit_success (struct MHD_Connection *connection, dc.merchant = *merchant; TALER_MINT_keys_sign (&dc.purpose, &sig); - sig_json = TALER_JSON_from_sig (&dc.purpose, &sig); + sig_json = TALER_JSON_from_eddsa_sig (&dc.purpose, &sig); ret = TALER_MINT_reply_json_pack (connection, MHD_HTTP_OK, "{s:s, s:o}", @@ -332,28 +332,72 @@ TALER_MINT_reply_insufficient_funds (struct MHD_Connection *connection, { const struct TALER_MINT_DB_TransactionList *pos; int ret; + json_t *history; + json_t *transaction; + const char *type; + struct TALER_Amount value; - // FIXME: implement properly! (#3632) + history = json_array (); for (pos = tl; NULL != pos; pos = pos->next) { switch (pos->type) { case TALER_MINT_DB_TT_DEPOSIT: - /* FIXME: add operation details to json reply */ - break; + { + struct TALER_DepositRequest dr; + const struct Deposit *deposit = pos->details.deposit; + + type = "deposit"; + value = deposit->amount; + dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_DEPOSIT); + dr.purpose.size = htonl (sizeof (struct TALER_DepositRequest)); + dr.h_contract = deposit->h_contract; + dr.h_wire = deposit->h_wire; + dr.transaction_id = GNUNET_htonll (deposit->transaction_id); + dr.amount = TALER_amount_hton (deposit->amount); + dr.coin_pub = deposit->coin.coin_pub; + transaction = TALER_JSON_from_ecdsa_sig (&dr.purpose, + &deposit->csig); + break; + } case TALER_MINT_DB_TT_REFRESH_MELT: - /* FIXME: add operation details to json reply */ + { + struct RefreshMeltSignatureBody ms; + const struct RefreshMelt *melt = pos->details.melt; + + type = "melt"; + value = melt->amount; + ms.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT); + ms.purpose.size = htonl (sizeof (struct RefreshMeltSignatureBody)); + ms.melt_hash = melt->melt_hash; + ms.amount = TALER_amount_hton (melt->amount); + transaction = TALER_JSON_from_ecdsa_sig (&ms.purpose, + &melt->coin_sig); + } break; case TALER_MINT_DB_TT_LOCK: - /* FIXME: add operation details to json reply */ - break; + { + type = "lock"; + value = pos->details.lock->amount; + transaction = NULL; + GNUNET_break (0); /* #3625: Lock NOT implemented! */ + break; + } + default: + GNUNET_assert (0); } + json_array_append_new (history, + json_pack ("{s:s, s:o}", + "type", type, + "amount", TALER_JSON_from_amount (value), + "signature", transaction)); } ret = TALER_MINT_reply_json_pack (connection, MHD_HTTP_FORBIDDEN, - "{s:s}", - "error", "insufficient funds"); + "{s:s, s:o}", + "error", "insufficient funds", + "history", history); return ret; } @@ -517,7 +561,7 @@ TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection, char *sig_buf; int ret; - /* FIXME: use TALER_JSON_from_sig here instead!? */ + /* FIXME: use TALER_JSON_from_eddsa_sig here instead!? */ sig_buf_size = GNUNET_CRYPTO_rsa_signature_encode (collectable->sig, &sig_buf); sig_json = TALER_JSON_from_data (sig_buf, @@ -561,7 +605,7 @@ TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, body.kappa = htonl (kappa); TALER_MINT_keys_sign (&body.purpose, &sig); - sig_json = TALER_JSON_from_sig (&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}", @@ -595,7 +639,7 @@ TALER_MINT_reply_refresh_commit_success (struct MHD_Connection *connection, body.noreveal_index = htons (refresh_session->noreveal_index); TALER_MINT_keys_sign (&body.purpose, &sig); - sig_json = TALER_JSON_from_sig (&body.purpose, &sig); + sig_json = TALER_JSON_from_eddsa_sig (&body.purpose, &sig); GNUNET_assert (NULL != sig_json); ret = TALER_MINT_reply_json_pack (connection, MHD_HTTP_OK, -- cgit v1.2.3