From f8e62141f27c296b326fc810f18206d16d41b468 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 19 Jun 2017 21:04:49 +0200 Subject: split httpd_refresh.c into refresh_melt, refresh_link and refresh_reveal --- src/exchange/taler-exchange-httpd_db.c | 945 --------------------------------- 1 file changed, 945 deletions(-) (limited to 'src/exchange/taler-exchange-httpd_db.c') diff --git a/src/exchange/taler-exchange-httpd_db.c b/src/exchange/taler-exchange-httpd_db.c index 9871b7f34..e7be6af09 100644 --- a/src/exchange/taler-exchange-httpd_db.c +++ b/src/exchange/taler-exchange-httpd_db.c @@ -32,85 +32,6 @@ */ #define MAX_TRANSACTION_COMMIT_RETRIES 3 -/** - * Code to begin a transaction, must be inline as we define a block - * that ends with #COMMIT_TRANSACTION() within which we perform a number - * of retries. Note that this code may call "return" internally, so - * it must be called within a function where any cleanup will be done - * by the caller. Furthermore, the function's return value must - * match that of a #TEH_RESPONSE_reply_internal_db_error() status code. - * - * @param session session handle - * @param connection connection handle - */ -#define START_TRANSACTION(session,connection) \ -{ /* start new scope, will be ended by COMMIT_TRANSACTION() */\ - unsigned int transaction_retries = 0; \ - enum GNUNET_DB_QueryStatus transaction_commit_result; \ -transaction_start_label: /* we will use goto for retries */ \ - if (GNUNET_OK != \ - TEH_plugin->start (TEH_plugin->cls, \ - session)) \ - { \ - GNUNET_break (0); \ - return TEH_RESPONSE_reply_internal_db_error (connection, \ - TALER_EC_DB_START_FAILED); \ - } - -/** - * Code to conclude a transaction, dual to #START_TRANSACTION(). Note - * that this code may call "return" internally, so it must be called - * within a function where any cleanup will be done by the caller. - * Furthermore, the function's return value must match that of a - * #TEH_RESPONSE_reply_internal_db_error() status code. - * - * @param session session handle - * @param connection connection handle - */ -#define COMMIT_TRANSACTION(session,connection) \ - transaction_commit_result = \ - TEH_plugin->commit (TEH_plugin->cls, \ - session); \ - if (GNUNET_DB_STATUS_HARD_ERROR == transaction_commit_result) \ - { \ - TALER_LOG_WARNING ("Transaction commit failed in %s\n", __FUNCTION__); \ - return TEH_RESPONSE_reply_commit_error (connection, \ - TALER_EC_DB_COMMIT_FAILED_HARD); \ - } \ - if (GNUNET_DB_STATUS_SOFT_ERROR == transaction_commit_result) \ - { \ - TALER_LOG_WARNING ("Transaction commit failed in %s\n", __FUNCTION__); \ - if (transaction_retries++ <= MAX_TRANSACTION_COMMIT_RETRIES) \ - goto transaction_start_label; \ - TALER_LOG_WARNING ("Transaction commit failed %u times in %s\n", \ - transaction_retries, \ - __FUNCTION__); \ - return TEH_RESPONSE_reply_commit_error (connection, \ - TALER_EC_DB_COMMIT_FAILED_ON_RETRY); \ - } \ -} /* end of scope opened by BEGIN_TRANSACTION */ - - -/** - * Code to include to retry a transaction, must only be used in between - * #START_TRANSACTION and #COMMIT_TRANSACTION. - * - * @param session session handle - * @param connection connection handle - */ -#define RETRY_TRANSACTION(session,connection) \ - do { \ - TEH_plugin->rollback (TEH_plugin->cls, \ - session); \ - if (transaction_retries++ <= MAX_TRANSACTION_COMMIT_RETRIES) \ - goto transaction_start_label; \ - TALER_LOG_WARNING ("Transaction commit failed %u times in %s\n", \ - transaction_retries, \ - __FUNCTION__); \ - return TEH_RESPONSE_reply_commit_error (connection, \ - TALER_EC_DB_COMMIT_FAILED_ON_RETRY); \ - } while (0) - /** * Run a database transaction for @a connection. @@ -279,870 +200,4 @@ TEH_DB_calculate_transaction_list_totals (struct TALER_EXCHANGEDB_TransactionLis } -/** - * Parse coin melt requests from a JSON object and write them to - * the database. - * - * @param connection the connection to send errors to - * @param session the database connection - * @param key_state the exchange's key state - * @param session_hash hash identifying the refresh session - * @param coin_details details about the coin being melted - * @param[out] meltp on success, set to melt details - * @return #GNUNET_OK on success, - * #GNUNET_NO if an error message was generated, - * #GNUNET_SYSERR on internal errors (no response generated) - */ -static int -refresh_check_melt (struct MHD_Connection *connection, - struct TALER_EXCHANGEDB_Session *session, - const struct TEH_KS_StateHandle *key_state, - const struct GNUNET_HashCode *session_hash, - const struct TEH_DB_MeltDetails *coin_details, - struct TALER_EXCHANGEDB_RefreshMelt *meltp) -{ - struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dk; - struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki; - struct TALER_EXCHANGEDB_TransactionList *tl; - struct TALER_Amount coin_value; - struct TALER_Amount coin_residual; - struct TALER_Amount spent; - int res; - enum GNUNET_DB_QueryStatus qs; - - dk = TEH_KS_denomination_key_lookup (key_state, - &coin_details->coin_info.denom_pub, - TEH_KS_DKU_DEPOSIT); - if (NULL == dk) - return (MHD_YES == - TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_REFRESH_MELT_DB_DENOMINATION_KEY_NOT_FOUND, - "denomination key no longer available while executing transaction")) - ? GNUNET_NO : GNUNET_SYSERR; - dki = &dk->issue; - TALER_amount_ntoh (&coin_value, - &dki->properties.value); - /* fee for THIS transaction; the melt amount includes the fee! */ - spent = coin_details->melt_amount_with_fee; - /* add historic transaction costs of this coin */ - qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls, - session, - &coin_details->coin_info.coin_pub, - &tl); - (void) qs; /* FIXME #5010 */ - if (GNUNET_OK != - TEH_DB_calculate_transaction_list_totals (tl, - &spent, - &spent)) - { - GNUNET_break (0); - TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, - tl); - return (MHD_YES == - TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_MELT_COIN_HISTORY_COMPUTATION_FAILED)) - ? GNUNET_NO : GNUNET_SYSERR; - } - /* Refuse to refresh when the coin's value is insufficient - for the cost of all transactions. */ - if (TALER_amount_cmp (&coin_value, - &spent) < 0) - { - GNUNET_assert (GNUNET_SYSERR != - TALER_amount_subtract (&coin_residual, - &spent, - &coin_details->melt_amount_with_fee)); - res = (MHD_YES == - TEH_RESPONSE_reply_refresh_melt_insufficient_funds (connection, - &coin_details->coin_info.coin_pub, - coin_value, - tl, - coin_details->melt_amount_with_fee, - coin_residual)) - ? GNUNET_NO : GNUNET_SYSERR; - TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, - tl); - return res; - } - TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, - tl); - - meltp->coin = coin_details->coin_info; - meltp->coin_sig = coin_details->melt_sig; - meltp->session_hash = *session_hash; - meltp->amount_with_fee = coin_details->melt_amount_with_fee; - meltp->melt_fee = coin_details->melt_fee; - return GNUNET_OK; -} - - -/** - * Execute a "/refresh/melt". We have been given a list of valid - * coins and a request to melt them into the given - * @a refresh_session_pub. Check that the coins all have the - * required value left and if so, store that they have been - * melted and confirm the melting operation to the client. - * - * @param connection the MHD connection to handle - * @param session_hash hash code of the session the coins are melted into - * @param num_new_denoms number of entries in @a denom_pubs, size of y-dimension of @a commit_coin array - * @param denom_pubs public keys of the coins we want to withdraw in the end - * @param coin_melt_detail signature and (residual) value of the respective coin should be melted - * @param commit_coin 2d array of coin commitments (what the exchange is to sign - * once the "/refres/reveal" of cut and choose is done), - * x-dimension must be #TALER_CNC_KAPPA - * @param transfer_pubs array of transfer public keys (what the exchange is - * to return via "/refresh/link" to enable linkage in the - * future) of length #TALER_CNC_KAPPA - * @return MHD result code - */ -int -TEH_DB_execute_refresh_melt (struct MHD_Connection *connection, - const struct GNUNET_HashCode *session_hash, - unsigned int num_new_denoms, - const struct TALER_DenominationPublicKey *denom_pubs, - const struct TEH_DB_MeltDetails *coin_melt_detail, - struct TALER_EXCHANGEDB_RefreshCommitCoin *const* commit_coin, - const struct TALER_TransferPublicKeyP *transfer_pubs) -{ - struct TEH_KS_StateHandle *key_state; - struct TALER_EXCHANGEDB_RefreshSession refresh_session; - struct TALER_EXCHANGEDB_Session *session; - int res; - - if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls))) - { - GNUNET_break (0); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_DB_SETUP_FAILED); - } - START_TRANSACTION (session, connection); - res = TEH_plugin->get_refresh_session (TEH_plugin->cls, - session, - session_hash, - &refresh_session); - if (GNUNET_YES == res) - { - TEH_plugin->rollback (TEH_plugin->cls, - session); - res = TEH_RESPONSE_reply_refresh_melt_success (connection, - session_hash, - refresh_session.noreveal_index); - return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; - } - if (GNUNET_SYSERR == res) - { - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_MELT_DB_FETCH_ERROR); - } - - /* store 'global' session data */ - refresh_session.num_newcoins = num_new_denoms; - refresh_session.noreveal_index - = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, - TALER_CNC_KAPPA); - key_state = TEH_KS_acquire (); - if (GNUNET_OK != - (res = refresh_check_melt (connection, - session, - key_state, - session_hash, - coin_melt_detail, - &refresh_session.melt))) - { - TEH_KS_release (key_state); - TEH_plugin->rollback (TEH_plugin->cls, - session); - return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; - } - TEH_KS_release (key_state); - - if (GNUNET_OK != - (res = TEH_plugin->create_refresh_session (TEH_plugin->cls, - session, - session_hash, - &refresh_session))) - { - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_MELT_DB_STORE_SESSION_ERROR); - } - - /* store requested new denominations */ - if (GNUNET_OK != - TEH_plugin->insert_refresh_order (TEH_plugin->cls, - session, - session_hash, - num_new_denoms, - denom_pubs)) - { - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_MELT_DB_STORE_ORDER_ERROR); - } - - if (GNUNET_OK != - TEH_plugin->insert_refresh_commit_coins (TEH_plugin->cls, - session, - session_hash, - num_new_denoms, - commit_coin[refresh_session.noreveal_index])) - { - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_MELT_DB_STORE_ORDER_ERROR); - } - if (GNUNET_OK != - TEH_plugin->insert_refresh_transfer_public_key (TEH_plugin->cls, - session, - session_hash, - &transfer_pubs[refresh_session.noreveal_index])) - { - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_MELT_DB_STORE_TRANSFER_ERROR); - } - - COMMIT_TRANSACTION (session, connection); - return TEH_RESPONSE_reply_refresh_melt_success (connection, - session_hash, - refresh_session.noreveal_index); -} - - -/** - * Check if the given @a transfer_privs correspond to an honest - * commitment for the given session. - * Checks that the transfer private keys match their commitments. - * Then derives the shared secret for each #TALER_CNC_KAPPA, and check that they match. - * - * @param connection the MHD connection to handle - * @param session database connection to use - * @param session_hash hash of session to query - * @param off commitment offset to check - * @param transfer_priv private transfer key - * @param melt information about the melted coin - * @param num_newcoins number of newcoins being generated - * @param denom_pubs array of @a num_newcoins keys for the new coins - * @param hash_context hash context to update by hashing in the data - * from this offset - * @return #GNUNET_OK if the committment was honest, - * #GNUNET_NO if there was a problem and we generated an error message - * #GNUNET_SYSERR if we could not even generate an error message - */ -static int -check_commitment (struct MHD_Connection *connection, - struct TALER_EXCHANGEDB_Session *session, - const struct GNUNET_HashCode *session_hash, - unsigned int off, - const struct TALER_TransferPrivateKeyP *transfer_priv, - const struct TALER_EXCHANGEDB_RefreshMelt *melt, - unsigned int num_newcoins, - const struct TALER_DenominationPublicKey *denom_pubs, - struct GNUNET_HashContext *hash_context) -{ - struct TALER_TransferSecretP transfer_secret; - unsigned int j; - - TALER_link_reveal_transfer_secret (transfer_priv, - &melt->coin.coin_pub, - &transfer_secret); - - /* Check that the commitments for all new coins were correct */ - for (j = 0; j < num_newcoins; j++) - { - struct TALER_FreshCoinP fc; - struct TALER_CoinSpendPublicKeyP coin_pub; - struct GNUNET_HashCode h_msg; - char *buf; - size_t buf_len; - - TALER_setup_fresh_coin (&transfer_secret, - j, - &fc); - GNUNET_CRYPTO_eddsa_key_get_public (&fc.coin_priv.eddsa_priv, - &coin_pub.eddsa_pub); - GNUNET_CRYPTO_hash (&coin_pub, - sizeof (struct TALER_CoinSpendPublicKeyP), - &h_msg); - if (GNUNET_YES != - GNUNET_CRYPTO_rsa_blind (&h_msg, - &fc.blinding_key.bks, - denom_pubs[j].rsa_public_key, - &buf, - &buf_len)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Blind failed (bad denomination key!?)\n"); - return (MHD_YES == - TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_REFRESH_REVEAL_BLINDING_ERROR, - "Blinding error")) - ? GNUNET_NO : GNUNET_SYSERR; - } - GNUNET_CRYPTO_hash_context_read (hash_context, - buf, - buf_len); - GNUNET_free (buf); - } - return GNUNET_OK; -} - - -/** - * Exchange a coin as part of a refresh operation. Obtains the - * envelope from the database and performs the signing operation. - * - * @param connection the MHD connection to handle - * @param session database connection to use - * @param session_hash hash of session to query - * @param key_state key state to lookup denomination pubs - * @param denom_pub denomination key for the coin to create - * @param commit_coin the coin that was committed - * @param coin_off number of the coin - * @return NULL on error, otherwise signature over the coin - */ -static struct TALER_DenominationSignature -refresh_exchange_coin (struct MHD_Connection *connection, - struct TALER_EXCHANGEDB_Session *session, - const struct GNUNET_HashCode *session_hash, - struct TEH_KS_StateHandle *key_state, - const struct TALER_DenominationPublicKey *denom_pub, - const struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coin, - unsigned int coin_off) -{ - struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki; - struct TALER_DenominationSignature ev_sig; - - dki = TEH_KS_denomination_key_lookup (key_state, - denom_pub, - TEH_KS_DKU_WITHDRAW); - if (NULL == dki) - { - GNUNET_break (0); - ev_sig.rsa_signature = NULL; - return ev_sig; - } - if (GNUNET_OK == - TEH_plugin->get_refresh_out (TEH_plugin->cls, - session, - session_hash, - coin_off, - &ev_sig)) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Returning cached reply for /refresh/reveal signature\n"); - return ev_sig; - } - - ev_sig.rsa_signature - = GNUNET_CRYPTO_rsa_sign_blinded (dki->denom_priv.rsa_private_key, - commit_coin->coin_ev, - commit_coin->coin_ev_size); - if (NULL == ev_sig.rsa_signature) - { - GNUNET_break (0); - return ev_sig; - } - if (GNUNET_SYSERR == - TEH_plugin->insert_refresh_out (TEH_plugin->cls, - session, - session_hash, - coin_off, - &ev_sig)) - { - GNUNET_break (0); - GNUNET_CRYPTO_rsa_signature_free (ev_sig.rsa_signature); - ev_sig.rsa_signature = NULL; - } - - return ev_sig; -} - - -/** - * The client request was well-formed, now execute the DB transaction - * of a "/refresh/reveal" operation. We use the @a ev_sigs and - * @a commit_coins to clean up resources after this function returns - * as we might experience retries of the database transaction. - * - * @param connection the MHD connection to handle - * @param session database session - * @param session_hash hash identifying the refresh session - * @param refresh_session information about the refresh operation we are doing - * @param denom_pubs array of "num_newcoins" denomination keys for the new coins - * @param[out] ev_sigs where to store generated signatures for the new coins, - * array of length "num_newcoins", memory released by the - * caller - * @param[out] commit_coins array of length "num_newcoins" to be used for - * information about the new coins from the commitment. - * @return MHD result code - */ -static int -execute_refresh_reveal_transaction (struct MHD_Connection *connection, - struct TALER_EXCHANGEDB_Session *session, - const struct GNUNET_HashCode *session_hash, - const struct TALER_EXCHANGEDB_RefreshSession *refresh_session, - const struct TALER_DenominationPublicKey *denom_pubs, - struct TALER_DenominationSignature *ev_sigs, - struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins) -{ - unsigned int j; - struct TEH_KS_StateHandle *key_state; - int ret; - - START_TRANSACTION (session, connection); - key_state = TEH_KS_acquire (); - for (j=0;jnum_newcoins;j++) - { - if (NULL == ev_sigs[j].rsa_signature) /* could be non-NULL during retries */ - ev_sigs[j] = refresh_exchange_coin (connection, - session, - session_hash, - key_state, - &denom_pubs[j], - &commit_coins[j], - j); - if (NULL == ev_sigs[j].rsa_signature) - { - TEH_plugin->rollback (TEH_plugin->cls, - session); - ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_REVEAL_SIGNING_ERROR); - goto cleanup; - } - } - COMMIT_TRANSACTION (session, connection); - ret = TEH_RESPONSE_reply_refresh_reveal_success (connection, - refresh_session->num_newcoins, - ev_sigs); - cleanup: - TEH_KS_release (key_state); - return ret; -} - - -/** - * Execute a "/refresh/reveal". The client is revealing to us the - * transfer keys for @a #TALER_CNC_KAPPA-1 sets of coins. Verify that the - * revealed transfer keys would allow linkage to the blinded coins, - * and if so, return the signed coins for corresponding to the set of - * coins that was not chosen. - * - * @param connection the MHD connection to handle - * @param session_hash hash identifying the refresh session - * @param transfer_privs array with the revealed transfer keys, - * length must be #TALER_CNC_KAPPA - 1 - * @return MHD result code - */ -int -TEH_DB_execute_refresh_reveal (struct MHD_Connection *connection, - const struct GNUNET_HashCode *session_hash, - struct TALER_TransferPrivateKeyP *transfer_privs) -{ - int res; - struct TALER_EXCHANGEDB_Session *session; - struct TALER_EXCHANGEDB_RefreshSession refresh_session; - struct TALER_DenominationPublicKey *denom_pubs; - struct TALER_DenominationSignature *ev_sigs; - struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins; - unsigned int i; - unsigned int j; - unsigned int off; - struct GNUNET_HashContext *hash_context; - struct GNUNET_HashCode sh_check; - int ret; - struct TALER_TransferPublicKeyP gamma_tp; - - if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls))) - { - GNUNET_break (0); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_DB_SETUP_FAILED); - } - - res = TEH_plugin->get_refresh_session (TEH_plugin->cls, - session, - session_hash, - &refresh_session); - if (GNUNET_NO == res) - return TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_REFRESH_REVEAL_SESSION_UNKNOWN, - "session_hash"); - if ( (GNUNET_SYSERR == res) || - (refresh_session.noreveal_index >= TALER_CNC_KAPPA) ) - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_REVEAL_DB_FETCH_SESSION_ERROR); - denom_pubs = GNUNET_new_array (refresh_session.num_newcoins, - struct TALER_DenominationPublicKey); - if (GNUNET_OK != - TEH_plugin->get_refresh_order (TEH_plugin->cls, - session, - session_hash, - refresh_session.num_newcoins, - denom_pubs)) - { - GNUNET_break (0); - GNUNET_free (denom_pubs); - GNUNET_CRYPTO_rsa_signature_free (refresh_session.melt.coin.denom_sig.rsa_signature); - GNUNET_CRYPTO_rsa_public_key_free (refresh_session.melt.coin.denom_pub.rsa_public_key); - return (MHD_YES == TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_REVEAL_DB_FETCH_ORDER_ERROR)) - ? GNUNET_NO : GNUNET_SYSERR; - } - - hash_context = GNUNET_CRYPTO_hash_context_start (); - /* first, iterate over transfer public keys for hash_context */ - off = 0; - for (i=0;iget_refresh_transfer_public_key (TEH_plugin->cls, - session, - session_hash, - &gamma_tp)) - { - GNUNET_break (0); - GNUNET_free (denom_pubs); - GNUNET_CRYPTO_rsa_signature_free (refresh_session.melt.coin.denom_sig.rsa_signature); - GNUNET_CRYPTO_rsa_public_key_free (refresh_session.melt.coin.denom_pub.rsa_public_key); - GNUNET_CRYPTO_hash_context_abort (hash_context); - return (MHD_YES == TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_REVEAL_DB_FETCH_TRANSFER_ERROR)) - ? GNUNET_NO : GNUNET_SYSERR; - } - GNUNET_CRYPTO_hash_context_read (hash_context, - &gamma_tp, - sizeof (struct TALER_TransferPublicKeyP)); - } - else - { - /* compute tp from private key */ - struct TALER_TransferPublicKeyP tp; - - GNUNET_CRYPTO_ecdhe_key_get_public (&transfer_privs[i - off].ecdhe_priv, - &tp.ecdhe_pub); - GNUNET_CRYPTO_hash_context_read (hash_context, - &tp, - sizeof (struct TALER_TransferPublicKeyP)); - } - } - - /* next, add all of the hashes from the denomination keys to the - hash_context */ - { - struct TALER_DenominationPublicKey denom_pubs[refresh_session.num_newcoins]; - - if (GNUNET_OK != - TEH_plugin->get_refresh_order (TEH_plugin->cls, - session, - session_hash, - refresh_session.num_newcoins, - denom_pubs)) - { - GNUNET_break (0); - GNUNET_free (denom_pubs); - GNUNET_CRYPTO_rsa_signature_free (refresh_session.melt.coin.denom_sig.rsa_signature); - GNUNET_CRYPTO_rsa_public_key_free (refresh_session.melt.coin.denom_pub.rsa_public_key); - GNUNET_CRYPTO_hash_context_abort (hash_context); - return (MHD_YES == TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_REVEAL_DB_FETCH_ORDER_ERROR)) - ? GNUNET_NO : GNUNET_SYSERR; - } - for (i=0;iget_refresh_commit_coins (TEH_plugin->cls, - session, - session_hash, - refresh_session.num_newcoins, - commit_coins)) - { - GNUNET_break (0); - GNUNET_free (denom_pubs); - GNUNET_CRYPTO_rsa_signature_free (refresh_session.melt.coin.denom_sig.rsa_signature); - GNUNET_CRYPTO_rsa_public_key_free (refresh_session.melt.coin.denom_pub.rsa_public_key); - GNUNET_CRYPTO_hash_context_abort (hash_context); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_REVEAL_DB_FETCH_COMMIT_ERROR); - } - /* add envelopes to hash_context */ - for (j=0;jstatus) - return; - ldl = TEH_plugin->get_link_data_list (TEH_plugin->cls, - ctx->session, - session_hash); - if (NULL == ldl) - { - ctx->status = GNUNET_NO; - if (MHD_NO == - TEH_RESPONSE_reply_json_pack (ctx->connection, - MHD_HTTP_NOT_FOUND, - "{s:s}", - "error", - "link data not found (link)")) - ctx->status = GNUNET_SYSERR; - return; - } - GNUNET_array_grow (ctx->sessions, - ctx->num_sessions, - ctx->num_sessions + 1); - lsi = &ctx->sessions[ctx->num_sessions - 1]; - lsi->transfer_pub = *transfer_pub; - lsi->ldl = ldl; -} - - -/** - * Execute a "/refresh/link". Returns the linkage information that - * will allow the owner of a coin to follow the refresh trail to - * the refreshed coin. - * - * @param connection the MHD connection to handle - * @param coin_pub public key of the coin to link - * @return MHD result code - */ -int -TEH_DB_execute_refresh_link (struct MHD_Connection *connection, - const struct TALER_CoinSpendPublicKeyP *coin_pub) -{ - struct HTD_Context ctx; - int res; - unsigned int i; - - if (NULL == (ctx.session = TEH_plugin->get_session (TEH_plugin->cls))) - { - GNUNET_break (0); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_DB_SETUP_FAILED); - } - ctx.connection = connection; - ctx.num_sessions = 0; - ctx.sessions = NULL; - ctx.status = GNUNET_OK; - res = TEH_plugin->get_transfer (TEH_plugin->cls, - ctx.session, - coin_pub, - &handle_transfer_data, - &ctx); - if (GNUNET_SYSERR == ctx.status) - { - res = MHD_NO; - goto cleanup; - } - if (GNUNET_NO == ctx.status) - { - res = MHD_YES; - goto cleanup; - } - GNUNET_assert (GNUNET_OK == ctx.status); - if (0 == ctx.num_sessions) - return TEH_RESPONSE_reply_arg_unknown (connection, - TALER_EC_REFRESH_LINK_COIN_UNKNOWN, - "coin_pub"); - res = TEH_RESPONSE_reply_refresh_link_success (connection, - ctx.num_sessions, - ctx.sessions); - cleanup: - for (i=0;ifree_link_data_list (TEH_plugin->cls, - ctx.sessions[i].ldl); - GNUNET_free_non_null (ctx.sessions); - return res; -} - - /* end of taler-exchange-httpd_db.c */ -- cgit v1.2.3