From 053096475fdb1d6d81aa87bce36f1aceb6264038 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 20 Jun 2017 22:30:15 +0200 Subject: fixing #5010 for /refresh/reveal --- src/exchange/taler-exchange-httpd_refresh_melt.c | 22 +- src/exchange/taler-exchange-httpd_refresh_reveal.c | 674 ++++++++++----------- src/exchangedb/plugin_exchangedb_postgres.c | 333 ++++------ src/exchangedb/test_exchangedb.c | 45 +- src/include/taler_exchangedb_plugin.h | 33 +- 5 files changed, 451 insertions(+), 656 deletions(-) (limited to 'src') diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c b/src/exchange/taler-exchange-httpd_refresh_melt.c index 1c4e5e864..1b7e67918 100644 --- a/src/exchange/taler-exchange-httpd_refresh_melt.c +++ b/src/exchange/taler-exchange-httpd_refresh_melt.c @@ -500,7 +500,6 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, struct TALER_EXCHANGEDB_RefreshCommitCoin *const* commit_coin, const struct TALER_TransferPublicKeyP *transfer_pubs) { - unsigned int i; struct TEH_KS_StateHandle *key_state; struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dk; struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki; @@ -519,7 +518,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, TALER_amount_get_zero (TEH_exchange_currency_string, &total_cost)); key_state = TEH_KS_acquire (); - for (i=0;istart (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) - - - - - /** * Send a response for "/refresh/reveal". * @@ -133,14 +44,15 @@ reply_refresh_reveal_success (struct MHD_Connection *connection, unsigned int num_newcoins, const struct TALER_DenominationSignature *sigs) { - int newcoin_index; json_t *root; json_t *obj; json_t *list; int ret; list = json_array (); - for (newcoin_index = 0; newcoin_index < num_newcoins; newcoin_index++) + for (unsigned int newcoin_index = 0; + newcoin_index < num_newcoins; + newcoin_index++) { obj = json_object (); json_object_set_new (obj, @@ -182,11 +94,10 @@ reply_refresh_reveal_missmatch (struct MHD_Connection *connection, { json_t *info_new; json_t *info_commit_k; - unsigned int i; info_new = json_array (); info_commit_k = json_array (); - for (i=0;inum_newcoins;i++) + for (unsigned int i=0;inum_newcoins;i++) { const struct TALER_EXCHANGEDB_RefreshCommitCoin *cc; json_t *cc_json; @@ -220,7 +131,6 @@ reply_refresh_reveal_missmatch (struct MHD_Connection *connection, } - /** * Check if the given @a transfer_privs correspond to an honest * commitment for the given session. @@ -253,14 +163,13 @@ check_commitment (struct MHD_Connection *connection, 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++) + for (unsigned int j = 0; j < num_newcoins; j++) { struct TALER_FreshCoinP fc; struct TALER_CoinSpendPublicKeyP coin_pub; @@ -300,6 +209,58 @@ check_commitment (struct MHD_Connection *connection, } +/** + * State for a /refresh/reveal operation. + */ +struct RevealContext +{ + + /** + * Hash of the refresh session. + */ + const struct GNUNET_HashCode *session_hash; + + /** + * Database session used to execute the transaction. + */ + struct TALER_EXCHANGEDB_Session *session; + + /** + * Session state from the database. + */ + struct TALER_EXCHANGEDB_RefreshSession refresh_session; + + /** + * Array of denomination public keys used for the refresh. + */ + struct TALER_DenominationPublicKey *denom_pubs; + + /** + * Envelopes with the signatures to be returned. + */ + struct TALER_DenominationSignature *ev_sigs; + + /** + * Commitment data from the DB giving data about original + * commitments, in particular the blinded envelopes (for + * index gamma). + */ + struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins; + + /** + * Transfer public key associated with the gamma value + * selected by the exchange. + */ + struct TALER_TransferPublicKeyP gamma_tp; + + /** + * Transfer private keys revealed to us. + */ + struct TALER_TransferPrivateKeyP transfer_privs[TALER_CNC_KAPPA - 1]; + +}; + + /** * Exchange a coin as part of a refresh operation. Obtains the * envelope from the database and performs the signing operation. @@ -311,19 +272,21 @@ check_commitment (struct MHD_Connection *connection, * @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 + * @param[out] ev_sig set to signature over the coin upon success + * @return database transaction status */ -static struct TALER_DenominationSignature +static enum GNUNET_DB_QueryStatus 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) + unsigned int coin_off, + struct TALER_DenominationSignature *ev_sig) { struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki; - struct TALER_DenominationSignature ev_sig; + enum GNUNET_DB_QueryStatus qs; dki = TEH_KS_denomination_key_lookup (key_state, denom_pub, @@ -331,105 +294,91 @@ refresh_exchange_coin (struct MHD_Connection *connection, if (NULL == dki) { GNUNET_break (0); - ev_sig.rsa_signature = NULL; - return ev_sig; + ev_sig->rsa_signature = NULL; + return GNUNET_DB_STATUS_HARD_ERROR; } - if (GNUNET_OK == - TEH_plugin->get_refresh_out (TEH_plugin->cls, - session, - session_hash, - coin_off, - &ev_sig)) + qs = TEH_plugin->get_refresh_out (TEH_plugin->cls, + session, + session_hash, + coin_off, + ev_sig); + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Returning cached reply for /refresh/reveal signature\n"); - return ev_sig; + return qs; } + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs) + return qs; - ev_sig.rsa_signature + 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) + if (NULL == ev_sig->rsa_signature) { GNUNET_break (0); - return ev_sig; + return GNUNET_DB_STATUS_HARD_ERROR; } - if (GNUNET_SYSERR == - TEH_plugin->insert_refresh_out (TEH_plugin->cls, - session, - session_hash, - coin_off, - &ev_sig)) + qs = TEH_plugin->insert_refresh_out (TEH_plugin->cls, + session, + session_hash, + coin_off, + ev_sig); + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) { - GNUNET_break (0); - GNUNET_CRYPTO_rsa_signature_free (ev_sig.rsa_signature); - ev_sig.rsa_signature = NULL; + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + if (NULL != ev_sig->rsa_signature) + { + GNUNET_CRYPTO_rsa_signature_free (ev_sig->rsa_signature); + ev_sig->rsa_signature = NULL; + } } - - return ev_sig; + return qs; } /** - * 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. + * Cleanup state of the transaction stored in @a rc. * - * @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 + * @param rc context to clean up */ -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) +static void +cleanup_rc (struct RevealContext *rc) { - 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 != rc->denom_pubs) { - 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; - } + for (unsigned int i=0;irefresh_session.num_newcoins;i++) + if (NULL != rc->denom_pubs[i].rsa_public_key) + GNUNET_CRYPTO_rsa_public_key_free (rc->denom_pubs[i].rsa_public_key); + GNUNET_free (rc->denom_pubs); + rc->denom_pubs = NULL; + } + if (NULL != rc->commit_coins) + { + for (unsigned int j=0;jrefresh_session.num_newcoins;j++) + GNUNET_free_non_null (rc->commit_coins[j].coin_ev); + GNUNET_free (rc->commit_coins); + rc->commit_coins = NULL; + } + if (NULL != rc->ev_sigs) + { + for (unsigned int j=0;jrefresh_session.num_newcoins;j++) + if (NULL != rc->ev_sigs[j].rsa_signature) + GNUNET_CRYPTO_rsa_signature_free (rc->ev_sigs[j].rsa_signature); + GNUNET_free (rc->ev_sigs); + rc->ev_sigs = NULL; + } + if (NULL != rc->refresh_session.melt.coin.denom_sig.rsa_signature) + { + GNUNET_CRYPTO_rsa_signature_free (rc->refresh_session.melt.coin.denom_sig.rsa_signature); + rc->refresh_session.melt.coin.denom_sig.rsa_signature = NULL; + } + if (NULL != rc->refresh_session.melt.coin.denom_pub.rsa_public_key) + { + GNUNET_CRYPTO_rsa_public_key_free (rc->refresh_session.melt.coin.denom_pub.rsa_public_key); + rc->refresh_session.melt.coin.denom_pub.rsa_public_key = NULL; } - COMMIT_TRANSACTION (session, connection); - ret = reply_refresh_reveal_success (connection, - refresh_session->num_newcoins, - ev_sigs); - cleanup: - TEH_KS_release (key_state); - return ret; } @@ -440,94 +389,98 @@ execute_refresh_reveal_transaction (struct MHD_Connection *connection, * 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 + * IF it returns a non-error code, the transaction logic MUST + * NOT queue a MHD response. IF it returns an hard error, the + * transaction logic MUST queue a MHD response and set @a mhd_ret. IF + * it returns the soft error code, the function MAY be called again to + * retry and MUST not queue a MHD response. + * + * @param cls closure of type `struct RevealContext` + * @param connection MHD request which triggered the transaction + * @param session database session to use + * @param[out] mhd_ret set to MHD response status for @a connection, + * if transaction failed (!) + * @return transaction status */ -static int -execute_refresh_reveal (struct MHD_Connection *connection, - const struct GNUNET_HashCode *session_hash, - struct TALER_TransferPrivateKeyP *transfer_privs) +static enum GNUNET_DB_QueryStatus +refresh_reveal_transaction (void *cls, + struct MHD_Connection *connection, + struct TALER_EXCHANGEDB_Session *session, + int *mhd_ret) { - 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; + struct RevealContext *rc = cls; 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))) + enum GNUNET_DB_QueryStatus qs; + + rc->session = session; + qs = TEH_plugin->get_refresh_session (TEH_plugin->cls, + session, + rc->session_hash, + &rc->refresh_session); + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) + { + *mhd_ret = TEH_RESPONSE_reply_arg_invalid (connection, + TALER_EC_REFRESH_REVEAL_SESSION_UNKNOWN, + "session_hash"); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if (GNUNET_DB_STATUS_SOFT_ERROR == qs) + return qs; + if ( (GNUNET_DB_STATUS_HARD_ERROR == qs) || + (rc->refresh_session.noreveal_index >= TALER_CNC_KAPPA) ) { GNUNET_break (0); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_DB_SETUP_FAILED); + cleanup_rc (rc); + *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, + TALER_EC_REFRESH_REVEAL_DB_FETCH_SESSION_ERROR); + return GNUNET_DB_STATUS_HARD_ERROR; } - - 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)) + rc->denom_pubs = GNUNET_new_array (rc->refresh_session.num_newcoins, + struct TALER_DenominationPublicKey); + qs = TEH_plugin->get_refresh_order (TEH_plugin->cls, + session, + rc->session_hash, + rc->refresh_session.num_newcoins, + rc->denom_pubs); + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) { + cleanup_rc (rc); + if (GNUNET_DB_STATUS_SOFT_ERROR == qs) + return qs; 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; + *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, + TALER_EC_REFRESH_REVEAL_DB_FETCH_ORDER_ERROR); + return GNUNET_DB_STATUS_HARD_ERROR; } hash_context = GNUNET_CRYPTO_hash_context_start (); /* first, iterate over transfer public keys for hash_context */ off = 0; - for (i=0;irefresh_session.noreveal_index) { off = 1; /* obtain gamma_tp from db */ - if (GNUNET_OK != - TEH_plugin->get_refresh_transfer_public_key (TEH_plugin->cls, - session, - session_hash, - &gamma_tp)) + qs = TEH_plugin->get_refresh_transfer_public_key (TEH_plugin->cls, + session, + rc->session_hash, + &rc->gamma_tp); + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) { - 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; + cleanup_rc (rc); + if (GNUNET_DB_STATUS_SOFT_ERROR == qs) + return qs; + GNUNET_break (0); + *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, + TALER_EC_REFRESH_REVEAL_DB_FETCH_TRANSFER_ERROR); + return GNUNET_DB_STATUS_HARD_ERROR; } GNUNET_CRYPTO_hash_context_read (hash_context, - &gamma_tp, + &rc->gamma_tp, sizeof (struct TALER_TransferPublicKeyP)); } else @@ -535,7 +488,7 @@ execute_refresh_reveal (struct MHD_Connection *connection, /* compute tp from private key */ struct TALER_TransferPublicKeyP tp; - GNUNET_CRYPTO_ecdhe_key_get_public (&transfer_privs[i - off].ecdhe_priv, + GNUNET_CRYPTO_ecdhe_key_get_public (&rc->transfer_privs[i - off].ecdhe_priv, &tp.ecdhe_pub); GNUNET_CRYPTO_hash_context_read (hash_context, &tp, @@ -545,38 +498,17 @@ execute_refresh_reveal (struct MHD_Connection *connection, /* next, add all of the hashes from the denomination keys to the hash_context */ + for (unsigned int i=0;irefresh_session.num_newcoins;i++) { - 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;idenom_pubs[i].rsa_public_key, + &buf); + GNUNET_CRYPTO_hash_context_read (hash_context, + buf, + buf_size); + GNUNET_free (buf); } /* next, add public key of coin and amount being refreshed */ @@ -584,71 +516,67 @@ execute_refresh_reveal (struct MHD_Connection *connection, struct TALER_AmountNBO melt_amountn; GNUNET_CRYPTO_hash_context_read (hash_context, - &refresh_session.melt.coin.coin_pub, + &rc->refresh_session.melt.coin.coin_pub, sizeof (struct TALER_CoinSpendPublicKeyP)); TALER_amount_hton (&melt_amountn, - &refresh_session.melt.amount_with_fee); + &rc->refresh_session.melt.amount_with_fee); GNUNET_CRYPTO_hash_context_read (hash_context, &melt_amountn, sizeof (struct TALER_AmountNBO)); } - commit_coins = GNUNET_new_array (refresh_session.num_newcoins, - struct TALER_EXCHANGEDB_RefreshCommitCoin); + rc->commit_coins = GNUNET_new_array (rc->refresh_session.num_newcoins, + struct TALER_EXCHANGEDB_RefreshCommitCoin); off = 0; - for (i=0;irefresh_session.noreveal_index) { off = 1; /* obtain commit_coins for the selected gamma value from DB */ - if (GNUNET_OK != - TEH_plugin->get_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); + qs = TEH_plugin->get_refresh_commit_coins (TEH_plugin->cls, + session, + rc->session_hash, + rc->refresh_session.num_newcoins, + rc->commit_coins); + if (0 >= qs) + { + cleanup_rc (rc); GNUNET_CRYPTO_hash_context_abort (hash_context); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_REVEAL_DB_FETCH_COMMIT_ERROR); + if (GNUNET_DB_STATUS_SOFT_ERROR == qs) + return qs; + GNUNET_break (0); + *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, + TALER_EC_REFRESH_REVEAL_DB_FETCH_COMMIT_ERROR); + return GNUNET_DB_STATUS_HARD_ERROR; } /* add envelopes to hash_context */ - for (j=0;jrefresh_session.num_newcoins;j++) { GNUNET_CRYPTO_hash_context_read (hash_context, - commit_coins[j].coin_ev, - commit_coins[j].coin_ev_size); + rc->commit_coins[j].coin_ev, + rc->commit_coins[j].coin_ev_size); } continue; } if (GNUNET_OK != (res = check_commitment (connection, session, - session_hash, + rc->session_hash, i, - &transfer_privs[i - off], - &refresh_session.melt, - refresh_session.num_newcoins, - denom_pubs, + &rc->transfer_privs[i - off], + &rc->refresh_session.melt, + rc->refresh_session.num_newcoins, + rc->denom_pubs, hash_context))) { GNUNET_break_op (0); - for (j=0;jsession_hash, sizeof (struct GNUNET_HashCode))) { GNUNET_break_op (0); - ret = reply_refresh_reveal_missmatch (connection, - &refresh_session, - commit_coins, - denom_pubs, - &gamma_tp); - for (j=0;jrefresh_session, + rc->commit_coins, + rc->denom_pubs, + &rc->gamma_tp); + cleanup_rc (rc); + return GNUNET_DB_STATUS_HARD_ERROR; + } + + /* Client request OK, sign coins */ + rc->ev_sigs = GNUNET_new_array (rc->refresh_session.num_newcoins, + struct TALER_DenominationSignature); + { + struct TEH_KS_StateHandle *key_state; + + key_state = TEH_KS_acquire (); + for (unsigned int j=0;jrefresh_session.num_newcoins;j++) { - GNUNET_free (commit_coins[j].coin_ev); - GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j].rsa_public_key); + qs = refresh_exchange_coin (connection, + session, + rc->session_hash, + key_state, + &rc->denom_pubs[j], + &rc->commit_coins[j], + j, + &rc->ev_sigs[j]); + if ( (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) || + (NULL == rc->ev_sigs[j].rsa_signature) ) + { + *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, + TALER_EC_REFRESH_REVEAL_SIGNING_ERROR); + qs = GNUNET_DB_STATUS_HARD_ERROR; + break; + } } - GNUNET_free (commit_coins); - 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 ret; + TEH_KS_release (key_state); } - - /* Client request OK, start transaction */ - ev_sigs = GNUNET_new_array (refresh_session.num_newcoins, - struct TALER_DenominationSignature); - - /* FIXME: might need to store revealed transfer private keys for - the auditor for later; should pass them as arguments here! #4792*/ - res = execute_refresh_reveal_transaction (connection, - session, - session_hash, - &refresh_session, - denom_pubs, - ev_sigs, - commit_coins); - for (i=0;i= qs) { - if (NULL != ev_sigs[i].rsa_signature) - GNUNET_CRYPTO_rsa_signature_free (ev_sigs[i].rsa_signature); - GNUNET_free (commit_coins[i].coin_ev); + cleanup_rc (rc); + return qs; } - for (j=0;jnum_newcoins), + GNUNET_PQ_result_spec_uint16 ("noreveal_index", + &refresh_session->noreveal_index), + GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", + &refresh_session->melt.coin.coin_pub), + GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig", + &refresh_session->melt.coin_sig), + TALER_PQ_result_spec_amount ("amount_with_fee", + &refresh_session->melt.amount_with_fee), + TALER_PQ_result_spec_amount ("fee_refresh", + &refresh_session->melt.melt_fee), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; - result = GNUNET_PQ_exec_prepared (session->conn, - "get_refresh_session", - params); - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - BREAK_DB_ERR (result, session->conn); - PQclear (result); - return GNUNET_SYSERR; - } - if (0 == PQntuples (result)) - { - PQclear (result); - return GNUNET_NO; - } - GNUNET_assert (1 == PQntuples (result)); - if (NULL == refresh_session) - { - /* We're done if the caller is only interested in whether the - * session exists or not */ - PQclear (result); - return GNUNET_YES; - } memset (refresh_session, 0, sizeof (struct TALER_EXCHANGEDB_RefreshSession)); - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint16 ("num_newcoins", - &refresh_session->num_newcoins), - GNUNET_PQ_result_spec_uint16 ("noreveal_index", - &refresh_session->noreveal_index), - GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", - &refresh_session->melt.coin.coin_pub), - GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig", - &refresh_session->melt.coin_sig), - TALER_PQ_result_spec_amount ("amount_with_fee", - &refresh_session->melt.amount_with_fee), - TALER_PQ_result_spec_amount ("fee_refresh", - &refresh_session->melt.melt_fee), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - 0)) - { - GNUNET_break (0); - PQclear (result); - return GNUNET_SYSERR; - } - } - PQclear (result); - if (GNUNET_OK != - get_known_coin (cls, - session, - &refresh_session->melt.coin.coin_pub, - &refresh_session->melt.coin)) + qs = GNUNET_PQ_eval_prepared_singleton_select (session->conn, + "get_refresh_session", + params, + rs); + if ( (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) && + (GNUNET_OK != + get_known_coin (cls, + session, + &refresh_session->melt.coin.coin_pub, + &refresh_session->melt.coin)) ) { GNUNET_break (0); - return GNUNET_SYSERR; + return GNUNET_DB_STATUS_HARD_ERROR; } refresh_session->melt.session_hash = *session_hash; - return GNUNET_YES; + return qs; } @@ -3501,69 +3469,49 @@ free_dpk_result (struct TALER_DenominationPublicKey *denom_pubs, * @param session_hash hash to identify refresh session * @param num_newcoins size of the array of the @a denom_pubs array * @param denom_pubs where to store the deomination keys - * @return #GNUNET_OK on success - * #GNUNET_SYSERR on internal error + * @return transaction status */ -static int +static enum GNUNET_DB_QueryStatus postgres_get_refresh_order (void *cls, struct TALER_EXCHANGEDB_Session *session, const struct GNUNET_HashCode *session_hash, uint16_t num_newcoins, struct TALER_DenominationPublicKey *denom_pubs) -{ - unsigned int i; - - for (i=0;i<(unsigned int) num_newcoins;i++) +{ + for (unsigned i=0;i<(unsigned int) num_newcoins;i++) { uint16_t newcoin_off = (uint16_t) i; - PGresult *result; - - { - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (session_hash), - GNUNET_PQ_query_param_uint16 (&newcoin_off), - GNUNET_PQ_query_param_end - }; - - result = GNUNET_PQ_exec_prepared (session->conn, - "get_refresh_order", - params); - } - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - BREAK_DB_ERR (result, session->conn); - PQclear (result); - free_dpk_result (denom_pubs, i); - return GNUNET_SYSERR; - } - if (0 == PQntuples (result)) + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (session_hash), + GNUNET_PQ_query_param_uint16 (&newcoin_off), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_rsa_public_key ("denom_pub", + &denom_pubs[i].rsa_public_key), + GNUNET_PQ_result_spec_end + }; + + qs = GNUNET_PQ_eval_prepared_singleton_select (session->conn, + "get_refresh_order", + params, + rs); + switch (qs) { - PQclear (result); - /* FIXME: may want to distinguish between different error cases! */ + case GNUNET_DB_STATUS_HARD_ERROR: + case GNUNET_DB_STATUS_SOFT_ERROR: + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: free_dpk_result (denom_pubs, i); - return GNUNET_SYSERR; - } - GNUNET_assert (1 == PQntuples (result)); - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_rsa_public_key ("denom_pub", - &denom_pubs[i].rsa_public_key), - GNUNET_PQ_result_spec_end - }; - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - 0)) - { - PQclear (result); - GNUNET_break (0); - free_dpk_result (denom_pubs, i); - return GNUNET_SYSERR; - } - PQclear (result); + return qs; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + break; + default: + GNUNET_break (0); + break; } } - return GNUNET_OK; + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; } @@ -3639,11 +3587,9 @@ postgres_free_refresh_commit_coins (void *cls, * @param session_hash hash to identify refresh session * @param num_newcoins size of the @a commit_coins array * @param[out] commit_coins array of coin commitments to return - * @return #GNUNET_OK on success - * #GNUNET_NO if not found - * #GNUNET_SYSERR on error + * @return transaction status */ -static int +static enum GNUNET_DB_QueryStatus postgres_get_refresh_commit_coins (void *cls, struct TALER_EXCHANGEDB_Session *session, const struct GNUNET_HashCode *session_hash, @@ -3660,53 +3606,29 @@ postgres_get_refresh_commit_coins (void *cls, }; void *c_buf; size_t c_buf_size; - PGresult *result; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_variable_size ("coin_ev", + &c_buf, + &c_buf_size), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; - result = GNUNET_PQ_exec_prepared (session->conn, - "get_refresh_commit_coin", - params); - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - BREAK_DB_ERR (result, session->conn); - PQclear (result); - postgres_free_refresh_commit_coins (cls, - i, - commit_coins); - return GNUNET_SYSERR; - } - if (0 == PQntuples (result)) + qs = GNUNET_PQ_eval_prepared_singleton_select (session->conn, + "get_refresh_commit_coin", + params, + rs); + if (0 >= qs) { - PQclear (result); postgres_free_refresh_commit_coins (cls, i, commit_coins); - return GNUNET_NO; - } - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_variable_size ("coin_ev", - &c_buf, - &c_buf_size), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_YES != - GNUNET_PQ_extract_result (result, - rs, - 0)) - { - PQclear (result); - postgres_free_refresh_commit_coins (cls, - i, - commit_coins); - return GNUNET_SYSERR; - } + return qs; } - PQclear (result); commit_coins[i].coin_ev = c_buf; commit_coins[i].coin_ev_size = c_buf_size; } - return GNUNET_YES; + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; } @@ -3748,11 +3670,9 @@ postgres_insert_refresh_transfer_public_key (void *cls, * @param session database connection to use * @param session_hash hash to identify refresh session * @param[out] tp information to return - * @return #GNUNET_SYSERR on internal error, - * #GNUNET_NO if commitment was not found - * #GNUNET_OK on success + * @return transaction status */ -static int +static enum GNUNET_DB_QueryStatus postgres_get_refresh_transfer_public_key (void *cls, struct TALER_EXCHANGEDB_Session *session, const struct GNUNET_HashCode *session_hash, @@ -3762,40 +3682,16 @@ postgres_get_refresh_transfer_public_key (void *cls, GNUNET_PQ_query_param_auto_from_type (session_hash), GNUNET_PQ_query_param_end }; - PGresult *result; - - result = GNUNET_PQ_exec_prepared (session->conn, - "get_refresh_transfer_public_key", - params); - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - BREAK_DB_ERR (result, session->conn); - PQclear (result); - return GNUNET_SYSERR; - } - if (0 == PQntuples (result)) - { - PQclear (result); - return GNUNET_NO; - } - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("transfer_pub", - tp), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_YES != - GNUNET_PQ_extract_result (result, - rs, - 0)) - { - PQclear (result); - return GNUNET_SYSERR; - } - } - PQclear (result); - return GNUNET_OK; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("transfer_pub", + tp), + GNUNET_PQ_result_spec_end + }; + + return GNUNET_PQ_eval_prepared_singleton_select (session->conn, + "get_refresh_transfer_public_key", + params, + rs); } @@ -3809,17 +3705,15 @@ postgres_get_refresh_transfer_public_key (void *cls, * @param session_hash hash to identify refresh session * @param newcoin_index coin index * @param ev_sig coin signature - * @return #GNUNET_OK on success, #GNUNET_NO if we have no such result - * #GNUNET_SYSERR on error + * @return transaction result status */ -static int +static enum GNUNET_DB_QueryStatus postgres_get_refresh_out (void *cls, struct TALER_EXCHANGEDB_Session *session, const struct GNUNET_HashCode *session_hash, uint16_t newcoin_index, struct TALER_DenominationSignature *ev_sig) { - PGresult *result; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (session_hash), GNUNET_PQ_query_param_uint16 (&newcoin_index), @@ -3831,31 +3725,10 @@ postgres_get_refresh_out (void *cls, GNUNET_PQ_result_spec_end }; - result = GNUNET_PQ_exec_prepared (session->conn, - "get_refresh_out", - params); - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - BREAK_DB_ERR (result, session->conn); - PQclear (result); - return GNUNET_SYSERR; - } - if (1 != PQntuples (result)) - { - PQclear (result); - return GNUNET_NO; - } - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - 0)) - { - PQclear (result); - GNUNET_break (0); - return GNUNET_SYSERR; - } - PQclear (result); - return GNUNET_OK; + return GNUNET_PQ_eval_prepared_singleton_select (session->conn, + "get_refresh_out", + params, + rs); } @@ -3870,11 +3743,9 @@ postgres_get_refresh_out (void *cls, * @param session_hash hash to identify refresh session * @param newcoin_index coin index * @param ev_sig coin signature - * @return #GNUNET_OK on success - * #GNUNET_NO on transient error - * #GNUNET_SYSERR on error + * @return transaction result status */ -static int +static enum GNUNET_DB_QueryStatus postgres_insert_refresh_out (void *cls, struct TALER_EXCHANGEDB_Session *session, const struct GNUNET_HashCode *session_hash, @@ -3888,9 +3759,9 @@ postgres_insert_refresh_out (void *cls, GNUNET_PQ_query_param_end }; - return execute_prepared_non_select (session, - "insert_refresh_out", - params); + return GNUNET_PQ_eval_prepared_non_select (session->conn, + "insert_refresh_out", + params); } diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c index df730a07e..673d51446 100644 --- a/src/exchangedb/test_exchangedb.c +++ b/src/exchangedb/test_exchangedb.c @@ -357,7 +357,7 @@ test_refresh_commit_coins (struct TALER_EXCHANGEDB_Session *session, commit_coins)); ret_commit_coins = GNUNET_new_array (MELT_NEW_COINS, struct TALER_EXCHANGEDB_RefreshCommitCoin); - FAILIF (GNUNET_OK != + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->get_refresh_commit_coins (plugin->cls, session, session_hash, @@ -410,7 +410,7 @@ test_refresh_commit_links (struct TALER_EXCHANGEDB_Session *session, unsigned int i; ret = GNUNET_SYSERR; - FAILIF (GNUNET_NO != + FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != plugin->get_refresh_transfer_public_key (plugin->cls, session, session_hash, @@ -422,7 +422,7 @@ test_refresh_commit_links (struct TALER_EXCHANGEDB_Session *session, session, session_hash, &rctp[MELT_NOREVEAL_INDEX])); - FAILIF (GNUNET_OK != + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->get_refresh_transfer_public_key (plugin->cls, session, session_hash, @@ -572,21 +572,24 @@ test_melting (struct TALER_EXCHANGEDB_Session *session) meltp->melt_fee = fee_refresh; } - FAILIF (GNUNET_OK != plugin->create_refresh_session (plugin->cls, - session, - &session_hash, - &refresh_session)); - FAILIF (GNUNET_OK != plugin->get_refresh_session (plugin->cls, - session, - &session_hash, - &ret_refresh_session)); + FAILIF (GNUNET_OK != + plugin->create_refresh_session (plugin->cls, + session, + &session_hash, + &refresh_session)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->get_refresh_session (plugin->cls, + session, + &session_hash, + &ret_refresh_session)); auditor_row_cnt = 0; - FAILIF (GNUNET_OK != plugin->select_refreshs_above_serial_id (plugin->cls, - session, - 0, - &audit_refresh_session_cb, - NULL)); + FAILIF (GNUNET_OK != + plugin->select_refreshs_above_serial_id (plugin->cls, + session, + 0, + &audit_refresh_session_cb, + NULL)); FAILIF (1 != auditor_row_cnt); FAILIF (ret_refresh_session.num_newcoins != refresh_session.num_newcoins); FAILIF (ret_refresh_session.noreveal_index != refresh_session.noreveal_index); @@ -633,7 +636,7 @@ test_melting (struct TALER_EXCHANGEDB_Session *session) &fee_refund); new_denom_pubs[cnt] = new_dkp[cnt]->pub; } - FAILIF (GNUNET_OK != + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->insert_refresh_order (plugin->cls, session, &session_hash, @@ -641,7 +644,7 @@ test_melting (struct TALER_EXCHANGEDB_Session *session) new_denom_pubs)); ret_denom_pubs = GNUNET_new_array (MELT_NEW_COINS, struct TALER_DenominationPublicKey); - FAILIF (GNUNET_OK != + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->get_refresh_order (plugin->cls, session, &session_hash, @@ -672,19 +675,19 @@ test_melting (struct TALER_EXCHANGEDB_Session *session) = GNUNET_CRYPTO_rsa_sign_fdh (new_dkp[cnt]->priv.rsa_private_key, &hc); GNUNET_assert (NULL != ev_sigs[cnt].rsa_signature); - FAILIF (GNUNET_NO != + FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != plugin->get_refresh_out (plugin->cls, session, &session_hash, cnt, &test_sig)); - FAILIF (GNUNET_OK != + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->insert_refresh_out (plugin->cls, session, &session_hash, cnt, &ev_sigs[cnt])); - FAILIF (GNUNET_OK != + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->get_refresh_out (plugin->cls, session, &session_hash, diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 0406c8d19..9fe0874bd 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -1441,11 +1441,9 @@ struct TALER_EXCHANGEDB_Plugin * @param session database handle to use * @param session_hash hash over the melt to use for the lookup * @param[out] refresh_session where to store the result - * @return #GNUNET_YES on success, - * #GNUNET_NO if not found, - * #GNUNET_SYSERR on DB failure + * @return transaction status */ - int + enum GNUNET_DB_QueryStatus (*get_refresh_session) (void *cls, struct TALER_EXCHANGEDB_Session *session, const struct GNUNET_HashCode *session_hash, @@ -1500,10 +1498,9 @@ struct TALER_EXCHANGEDB_Plugin * @param session_hash hash to identify refresh session * @param num_newcoins size of the @a denom_pubs array * @param[out] denom_pubs where to write @a num_newcoins denomination keys - * @return #GNUNET_OK on success - * #GNUNET_SYSERR on internal error + * @return transaction status */ - int + enum GNUNET_DB_QueryStatus (*get_refresh_order) (void *cls, struct TALER_EXCHANGEDB_Session *session, const struct GNUNET_HashCode *session_hash, @@ -1541,11 +1538,9 @@ struct TALER_EXCHANGEDB_Plugin * @param session_hash hash to identify refresh session * @param num_coins size of the @a commit_coins array * @param[out] commit_coins array of coin commitments to return - * @return #GNUNET_OK on success - * #GNUNET_NO if not found - * #GNUNET_SYSERR on error + * @return transaction status */ - int + enum GNUNET_DB_QueryStatus (*get_refresh_commit_coins) (void *cls, struct TALER_EXCHANGEDB_Session *session, const struct GNUNET_HashCode *session_hash, @@ -1591,11 +1586,9 @@ struct TALER_EXCHANGEDB_Plugin * @param session database connection to use * @param session_hash hash to identify refresh session * @param[out] tp information to return - * @return #GNUNET_SYSERR on internal error, - * #GNUNET_NO if commitment was not found - * #GNUNET_OK on success + * @return transaction status */ - int + enum GNUNET_DB_QueryStatus (*get_refresh_transfer_public_key) (void *cls, struct TALER_EXCHANGEDB_Session *session, const struct GNUNET_HashCode *session_hash, @@ -1612,10 +1605,9 @@ struct TALER_EXCHANGEDB_Plugin * @param session_hash hash to identify refresh session * @param newcoin_index coin index * @param[out] ev_sig coin signature - * @return #GNUNET_OK on success, #GNUNET_NO if we have no such entry, - * #GNUNET_SYSERR on error + * @return transaction result status */ - int + enum GNUNET_DB_QueryStatus (*get_refresh_out) (void *cls, struct TALER_EXCHANGEDB_Session *session, const struct GNUNET_HashCode *session_hash, @@ -1634,10 +1626,9 @@ struct TALER_EXCHANGEDB_Plugin * @param session_hash hash to identify refresh session * @param newcoin_index coin index * @param ev_sig coin signature - * @return #GNUNET_OK on success - * #GNUNET_SYSERR on error + * @return transaction result status */ - int + enum GNUNET_DB_QueryStatus (*insert_refresh_out) (void *cls, struct TALER_EXCHANGEDB_Session *session, const struct GNUNET_HashCode *session_hash, -- cgit v1.2.3