From 51ee20102fa3818e9e4a4113a59ad700cb7eea42 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 19 Jun 2017 17:53:42 +0200 Subject: [PATCH] address #5010 for /payback --- src/exchange/taler-exchange-httpd_db.c | 143 --------- src/exchange/taler-exchange-httpd_payback.c | 276 +++++++++++++++++- src/exchange/taler-exchange-httpd_responses.c | 63 ---- src/exchange/taler-exchange-httpd_responses.h | 31 -- src/exchangedb/plugin_exchangedb_postgres.c | 98 ++----- src/exchangedb/test_exchangedb.c | 6 +- src/include/taler_exchangedb_plugin.h | 12 +- 7 files changed, 304 insertions(+), 325 deletions(-) diff --git a/src/exchange/taler-exchange-httpd_db.c b/src/exchange/taler-exchange-httpd_db.c index 9e95ff40a..bfe2112c4 100644 --- a/src/exchange/taler-exchange-httpd_db.c +++ b/src/exchange/taler-exchange-httpd_db.c @@ -1622,147 +1622,4 @@ TEH_DB_execute_track_transaction (struct MHD_Connection *connection, } -/** - * Execute a "/payback". The validity of the coin and signature have - * already been checked. The database must now check that the coin is - * not (double) spent, and execute the transaction (record details, - * generate success or failure response). - * - * @param connection the MHD connection to handle - * @param coin information about the coin - * @param value how much are coins of the @a coin's denomination worth? - * @param h_blind blinded coin to use for the lookup - * @param coin_blind blinding factor used (for later verification by the auditor) - * @param coin_sig signature of the coin (to be stored) - * @return MHD result code - */ -int -TEH_DB_execute_payback (struct MHD_Connection *connection, - const struct TALER_CoinPublicInfo *coin, - const struct TALER_Amount *value, - const struct GNUNET_HashCode *h_blind, - const struct TALER_DenominationBlindingKeyP *coin_blind, - const struct TALER_CoinSpendSignatureP *coin_sig) -{ - int ret; - struct TALER_EXCHANGEDB_Session *session; - struct TALER_EXCHANGEDB_TransactionList *tl; - struct TALER_ReservePublicKeyP reserve_pub; - struct TALER_Amount amount; - struct TALER_Amount spent; - struct GNUNET_TIME_Absolute now; - enum GNUNET_DB_QueryStatus qs; - - 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); - - /* Check whether a payback is allowed, and if so, to which - reserve / account the money should go */ - ret = TEH_plugin->get_reserve_by_h_blind (TEH_plugin->cls, - session, - h_blind, - &reserve_pub); - if (GNUNET_SYSERR == ret) - { - GNUNET_break (0); - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_PAYBACK_DB_FETCH_FAILED); - } - if (GNUNET_NO == ret) - { - GNUNET_break_op (0); - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_payback_unknown (connection, - TALER_EC_PAYBACK_WITHDRAW_NOT_FOUND); - } - - /* Calculate remaining balance. */ - qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls, - session, - &coin->coin_pub, - &tl); - (void) qs; /* FIXME #5010 */ - TALER_amount_get_zero (value->currency, - &spent); - if (GNUNET_OK != - TEH_DB_calculate_transaction_list_totals (tl, - &spent, - &spent)) - { - GNUNET_break (0); - TEH_plugin->rollback (TEH_plugin->cls, - session); - TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, - tl); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_PAYBACK_HISTORY_DB_ERROR); - } - if (GNUNET_SYSERR == - TALER_amount_subtract (&amount, - value, - &spent)) - { - GNUNET_break (0); - TEH_plugin->rollback (TEH_plugin->cls, - session); - TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, - tl); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_PAYBACK_COIN_BALANCE_NEGATIVE); - } - if ( (0 == amount.fraction) && - (0 == amount.value) ) - { - TEH_plugin->rollback (TEH_plugin->cls, - session); - ret = TEH_RESPONSE_reply_coin_insufficient_funds (connection, - TALER_EC_PAYBACK_COIN_BALANCE_ZERO, - tl); - TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, - tl); - return ret; - } - TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, - tl); - now = GNUNET_TIME_absolute_get (); - (void) GNUNET_TIME_round_abs (&now); - - /* add coin to list of wire transfers for payback */ - ret = TEH_plugin->insert_payback_request (TEH_plugin->cls, - session, - &reserve_pub, - coin, - coin_sig, - coin_blind, - &amount, - h_blind, - now); - if (GNUNET_SYSERR == ret) - { - TALER_LOG_WARNING ("Failed to store /payback information in database\n"); - TEH_plugin->rollback (TEH_plugin->cls, - session); - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_PAYBACK_DB_PUT_FAILED); - } - - COMMIT_TRANSACTION(session, connection); - - return TEH_RESPONSE_reply_payback_success (connection, - &coin->coin_pub, - &reserve_pub, - &amount, - now); -} - - /* end of taler-exchange-httpd_db.c */ diff --git a/src/exchange/taler-exchange-httpd_payback.c b/src/exchange/taler-exchange-httpd_payback.c index 7c5230d50..8b4051cb7 100644 --- a/src/exchange/taler-exchange-httpd_payback.c +++ b/src/exchange/taler-exchange-httpd_payback.c @@ -34,6 +34,253 @@ #include "taler-exchange-httpd_validation.h" +/** + * A wallet asked for /payback, but we do not know anything about the + * original withdraw operation specified. Generates a 404 reply. + * + * @param connection connection to the client + * @param ec Taler error code + * @return MHD result code + */ +static int +reply_payback_unknown (struct MHD_Connection *connection, + enum TALER_ErrorCode ec) +{ + return TEH_RESPONSE_reply_json_pack (connection, + MHD_HTTP_NOT_FOUND, + "{s:s, s:I}", + "error", "blinded coin unknown", + "code", (json_int_t) ec); +} + + +/** + * A wallet asked for /payback, return the successful response. + * + * @param connection connection to the client + * @param coin_pub coin for which we are processing the payback request + * @param reserve_pub public key of the reserve that will receive the payback + * @param amount the amount we will wire back + * @param timestamp when did the exchange receive the /payback request + * @return MHD result code + */ +static int +reply_payback_success (struct MHD_Connection *connection, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_Amount *amount, + struct GNUNET_TIME_Absolute timestamp) +{ + struct TALER_PaybackConfirmationPS pc; + struct TALER_ExchangePublicKeyP pub; + struct TALER_ExchangeSignatureP sig; + + pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK); + pc.purpose.size = htonl (sizeof (struct TALER_PaybackConfirmationPS)); + pc.timestamp = GNUNET_TIME_absolute_hton (timestamp); + TALER_amount_hton (&pc.payback_amount, + amount); + pc.coin_pub = *coin_pub; + pc.reserve_pub = *reserve_pub; + TEH_KS_sign (&pc.purpose, + &pub, + &sig); + return TEH_RESPONSE_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o, s:o, s:o, s:o, s:o}", + "reserve_pub", GNUNET_JSON_from_data_auto (reserve_pub), + "timestamp", GNUNET_JSON_from_time_abs (timestamp), + "amount", TALER_JSON_from_amount (amount), + "exchange_sig", GNUNET_JSON_from_data_auto (&sig), + "exchange_pub", GNUNET_JSON_from_data_auto (&pub)); +} + + +/** + * Closure for #payback_transaction. + */ +struct PaybackContext +{ + /** + * Hash of the blinded coin. + */ + struct GNUNET_HashCode h_blind; + + /** + * Full value of the coin. + */ + struct TALER_Amount value; + + /** + * Details about the coin. + */ + const struct TALER_CoinPublicInfo *coin; + + /** + * Key used to blind the coin. + */ + const struct TALER_DenominationBlindingKeyP *coin_bks; + + /** + * Signature of the coin requesting payback. + */ + const struct TALER_CoinSpendSignatureP *coin_sig; + + /** + * Set by #payback_transaction() to the reserve that will + * receive the payback. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * Set by #payback_transaction() to the amount that will be paid back + */ + struct TALER_Amount amount; + + /** + * Set by #payback_transaction to the timestamp when the payback + * was accepted. + */ + struct GNUNET_TIME_Absolute now; + +}; + + +/** + * Execute a "/payback". The validity of the coin and signature have + * already been checked. The database must now check that the coin is + * not (double) spent, and execute the transaction. + * + * 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 the `struct PaybackContext *` + * @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 code + */ +static enum GNUNET_DB_QueryStatus +payback_transaction (void *cls, + struct MHD_Connection *connection, + struct TALER_EXCHANGEDB_Session *session, + int *mhd_ret) +{ + struct PaybackContext *pc = cls; + struct TALER_EXCHANGEDB_TransactionList *tl; + struct TALER_Amount spent; + enum GNUNET_DB_QueryStatus qs; + + /* Check whether a payback is allowed, and if so, to which + reserve / account the money should go */ + qs = TEH_plugin->get_reserve_by_h_blind (TEH_plugin->cls, + session, + &pc->h_blind, + &pc->reserve_pub); + if (0 > qs) + { + if (GNUNET_DB_STATUS_HARD_ERROR == qs) + { + GNUNET_break (0); + *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, + TALER_EC_PAYBACK_DB_FETCH_FAILED); + } + return qs; + } + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) + { + GNUNET_break_op (0); + *mhd_ret = reply_payback_unknown (connection, + TALER_EC_PAYBACK_WITHDRAW_NOT_FOUND); + return GNUNET_DB_STATUS_HARD_ERROR; + } + + /* Calculate remaining balance. */ + qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls, + session, + &pc->coin->coin_pub, + &tl); + if (0 > qs) + { + if (GNUNET_DB_STATUS_HARD_ERROR == qs) + { + GNUNET_break (0); + *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, + TALER_EC_PAYBACK_DB_FETCH_FAILED); + } + return qs; + } + TALER_amount_get_zero (pc->value.currency, + &spent); + 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); + *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, + TALER_EC_PAYBACK_HISTORY_DB_ERROR); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if (GNUNET_SYSERR == + TALER_amount_subtract (&pc->amount, + &pc->value, + &spent)) + { + GNUNET_break (0); + TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, + tl); + *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, + TALER_EC_PAYBACK_COIN_BALANCE_NEGATIVE); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if ( (0 == pc->amount.fraction) && + (0 == pc->amount.value) ) + { + TEH_plugin->rollback (TEH_plugin->cls, + session); + *mhd_ret = TEH_RESPONSE_reply_coin_insufficient_funds (connection, + TALER_EC_PAYBACK_COIN_BALANCE_ZERO, + tl); + TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, + tl); + return GNUNET_DB_STATUS_HARD_ERROR; + } + TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, + tl); + pc->now = GNUNET_TIME_absolute_get (); + (void) GNUNET_TIME_round_abs (&pc->now); + + /* add coin to list of wire transfers for payback */ + qs = TEH_plugin->insert_payback_request (TEH_plugin->cls, + session, + &pc->reserve_pub, + pc->coin, + pc->coin_sig, + pc->coin_bks, + &pc->amount, + &pc->h_blind, + pc->now); + if (0 > qs) + { + if (GNUNET_DB_STATUS_HARD_ERROR == qs) + { + TALER_LOG_WARNING ("Failed to store /payback information in database\n"); + *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, + TALER_EC_PAYBACK_DB_PUT_FAILED); + } + return qs; + } + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; +} + + /** * We have parsed the JSON information about the payback request. Do * some basic sanity checks (especially that the signature on the @@ -53,14 +300,14 @@ verify_and_execute_payback (struct MHD_Connection *connection, const struct TALER_DenominationBlindingKeyP *coin_bks, const struct TALER_CoinSpendSignatureP *coin_sig) { + struct PaybackContext pc; struct TEH_KS_StateHandle *key_state; const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki; struct TALER_PaybackRequestPS pr; - struct TALER_Amount value; - struct GNUNET_HashCode h_blind; struct GNUNET_HashCode c_hash; char *coin_ev; size_t coin_ev_size; + int mhd_ret; /* check denomination exists and is in payback mode */ key_state = TEH_KS_acquire (); @@ -75,7 +322,7 @@ verify_and_execute_payback (struct MHD_Connection *connection, TALER_EC_PAYBACK_DENOMINATION_KEY_UNKNOWN, "denom_pub"); } - TALER_amount_ntoh (&value, + TALER_amount_ntoh (&pc.value, &dki->issue.properties.value); /* check denomination signature */ @@ -127,15 +374,24 @@ verify_and_execute_payback (struct MHD_Connection *connection, } GNUNET_CRYPTO_hash (coin_ev, coin_ev_size, - &h_blind); + &pc.h_blind); GNUNET_free (coin_ev); - return TEH_DB_execute_payback (connection, - coin, - &value, - &h_blind, - coin_bks, - coin_sig); + pc.coin_sig = coin_sig; + pc.coin_bks = coin_bks; + pc.coin = coin; + if (GNUNET_OK != + TEH_DB_run_transaction (connection, + &mhd_ret, + &payback_transaction, + &pc)) + return mhd_ret; + + return reply_payback_success (connection, + &coin->coin_pub, + &pc.reserve_pub, + &pc.amount, + pc.now); } diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c index 3f3f57215..7dab61ed6 100644 --- a/src/exchange/taler-exchange-httpd_responses.c +++ b/src/exchange/taler-exchange-httpd_responses.c @@ -1294,67 +1294,4 @@ TEH_RESPONSE_reply_track_transfer_details (struct MHD_Connection *connection, -/** - * A wallet asked for /payback, but we do not know anything about the - * original withdraw operation specified. Generates a 404 reply. - * - * @param connection connection to the client - * @param ec Taler error code - * @return MHD result code - */ -int -TEH_RESPONSE_reply_payback_unknown (struct MHD_Connection *connection, - enum TALER_ErrorCode ec) -{ - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_NOT_FOUND, - "{s:s, s:I}", - "error", "blinded coin unknown", - "code", (json_int_t) ec); -} - - -/** - * A wallet asked for /payback, return the successful response. - * - * @param connection connection to the client - * @param coin_pub coin for which we are processing the payback request - * @param reserve_pub public key of the reserve that will receive the payback - * @param amount the amount we will wire back - * @param timestamp when did the exchange receive the /payback request - * @return MHD result code - */ -int -TEH_RESPONSE_reply_payback_success (struct MHD_Connection *connection, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_Amount *amount, - struct GNUNET_TIME_Absolute timestamp) -{ - struct TALER_PaybackConfirmationPS pc; - struct TALER_ExchangePublicKeyP pub; - struct TALER_ExchangeSignatureP sig; - - pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK); - pc.purpose.size = htonl (sizeof (struct TALER_PaybackConfirmationPS)); - pc.timestamp = GNUNET_TIME_absolute_hton (timestamp); - TALER_amount_hton (&pc.payback_amount, - amount); - pc.coin_pub = *coin_pub; - pc.reserve_pub = *reserve_pub; - TEH_KS_sign (&pc.purpose, - &pub, - &sig); - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o, s:o, s:o, s:o, s:o}", - "reserve_pub", GNUNET_JSON_from_data_auto (reserve_pub), - "timestamp", GNUNET_JSON_from_time_abs (timestamp), - "amount", TALER_JSON_from_amount (amount), - "exchange_sig", GNUNET_JSON_from_data_auto (&sig), - "exchange_pub", GNUNET_JSON_from_data_auto (&pub)); -} - - - /* end of taler-exchange-httpd_responses.c */ diff --git a/src/exchange/taler-exchange-httpd_responses.h b/src/exchange/taler-exchange-httpd_responses.h index 27f253b78..8a51d8d53 100644 --- a/src/exchange/taler-exchange-httpd_responses.h +++ b/src/exchange/taler-exchange-httpd_responses.h @@ -488,37 +488,6 @@ TEH_RESPONSE_reply_refresh_link_success (struct MHD_Connection *connection, const struct TEH_RESPONSE_LinkSessionInfo *sessions); -/** - * A wallet asked for /payback, but we do not know anything about the - * original withdraw operation specified. Generates a 404 reply. - * - * @param connection connection to the client - * @param ec Taler error code - * @return MHD result code - */ -int -TEH_RESPONSE_reply_payback_unknown (struct MHD_Connection *connection, - enum TALER_ErrorCode ec); - - -/** - * A wallet asked for /payback, return the successful response. - * - * @param connection connection to the client - * @param coin_pub coin for which we are processing the payback request - * @param reserve_pub public key of the reserve that will receive the payback - * @param amount the amount we will wire back - * @param timestamp when did the exchange receive the /payback request - * @return MHD result code - */ -int -TEH_RESPONSE_reply_payback_success (struct MHD_Connection *connection, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_ReservePublicKeyP *reserve_pub, - - const struct TALER_Amount *amount, - struct GNUNET_TIME_Absolute timestamp); - /** * Compile the transaction history of a coin into a JSON object. diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 9eec10399..7267ef66f 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -6161,11 +6161,9 @@ postgres_select_reserve_closed_above_serial_id (void *cls, * @param amount total amount to be paid back * @param h_blind_ev hash of the blinded coin's envelope (must match reserves_out entry) * @param timestamp current time (rounded) - * @return #GNUNET_OK on success, - * #GNUNET_NO on transient error - * #GNUNET_SYSERR on DB errors + * @return transaction result status */ -static int +static enum GNUNET_DB_QueryStatus postgres_insert_payback_request (void *cls, struct TALER_EXCHANGEDB_Session *session, const struct TALER_ReservePublicKeyP *reserve_pub, @@ -6193,6 +6191,7 @@ postgres_insert_payback_request (void *cls, enum GNUNET_DB_QueryStatus qs; /* check if the coin is already known */ + // FIXME: #5010! ret = get_known_coin (cls, session, &coin->coin_pub, @@ -6210,31 +6209,29 @@ postgres_insert_payback_request (void *cls, if (0 > qs) { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - return ret; + return qs; } } /* now store actual payback information */ - if (GNUNET_OK != - (ret = execute_prepared_non_select (session, - "payback_insert", - params))) + qs = GNUNET_PQ_eval_prepared_non_select (session->conn, + "payback_insert", + params); + if (0 > qs) { - GNUNET_break (GNUNET_NO == ret); - return ret; + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + return qs; } /* Update reserve balance */ reserve.pub = *reserve_pub; - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - postgres_reserve_get (cls, - session, - &reserve)) + qs = postgres_reserve_get (cls, + session, + &reserve); + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) { - /* FIXME: #5010 */ - /* Should have been checked before we got here... */ - GNUNET_break (0); - return GNUNET_SYSERR; + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + return qs; } if (GNUNET_SYSERR == TALER_amount_add (&reserve.balance, @@ -6242,7 +6239,7 @@ postgres_insert_payback_request (void *cls, amount)) { GNUNET_break (0); - return GNUNET_SYSERR; + return GNUNET_DB_STATUS_HARD_ERROR; } expiry = GNUNET_TIME_absolute_add (timestamp, pg->idle_reserve_expiration_time); @@ -6253,10 +6250,10 @@ postgres_insert_payback_request (void *cls, &reserve); if (0 >= qs) { - GNUNET_break (0); - return GNUNET_SYSERR; + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + return qs; } - return GNUNET_OK; + return qs; } @@ -6268,11 +6265,9 @@ postgres_insert_payback_request (void *cls, * @param session a session * @param h_blind_ev hash of the blinded coin * @param[out] reserve_pub set to information about the reserve (on success only) - * @return #GNUNET_OK on success, - * #GNUNET_NO if there are no entries, - * #GNUNET_SYSERR on DB errors + * @return transaction status code */ -static int +static enum GNUNET_DB_QueryStatus postgres_get_reserve_by_h_blind (void *cls, struct TALER_EXCHANGEDB_Session *session, const struct GNUNET_HashCode *h_blind_ev, @@ -6282,47 +6277,16 @@ postgres_get_reserve_by_h_blind (void *cls, GNUNET_PQ_query_param_auto_from_type (h_blind_ev), GNUNET_PQ_query_param_end }; - PGresult *result; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + reserve_pub), + GNUNET_PQ_result_spec_end + }; - result = GNUNET_PQ_exec_prepared (session->conn, - "reserve_by_h_blind", - params); - if (PGRES_TUPLES_OK != - PQresultStatus (result)) - { - BREAK_DB_ERR (result, session->conn); - PQclear (result); - return GNUNET_SYSERR; - } - int nrows; - - nrows = PQntuples (result); - if (0 == nrows) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "reserve_by_h_blind() returned 0 matching rows\n"); - PQclear (result); - return GNUNET_NO; - } - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - reserve_pub), - 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); - return GNUNET_OK; + return GNUNET_PQ_eval_prepared_singleton_select (session->conn, + "reserve_by_h_blind", + params, + rs); } diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c index 19e8caa2e..380b037cd 100644 --- a/src/exchangedb/test_exchangedb.c +++ b/src/exchangedb/test_exchangedb.c @@ -1598,7 +1598,7 @@ run (void *cls) value.fraction, value.currency)); - FAILIF (GNUNET_YES != + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->get_reserve_by_h_blind (plugin->cls, session, &cbc.h_coin_envelope, @@ -1632,7 +1632,7 @@ run (void *cls) deposit.coin.denom_pub = dkp->pub; deposit.coin.denom_sig = cbc.sig; deadline = GNUNET_TIME_absolute_get (); - FAILIF (GNUNET_OK != + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->insert_payback_request (plugin->cls, session, &reserve_pub, @@ -1913,7 +1913,7 @@ run (void *cls) RND_BLK (&coin_sig); RND_BLK (&coin_blind); - FAILIF (GNUNET_OK != + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->insert_payback_request (plugin->cls, session, &reserve_pub, diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 8a2010819..7045adbbd 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -2169,11 +2169,9 @@ struct TALER_EXCHANGEDB_Plugin * @param receiver_account_details who should receive the funds * @param h_blind_ev hash of the blinded coin's envelope (must match reserves_out entry) * @param now timestamp to store - * @return #GNUNET_OK on success, - * #GNUNET_NO on transient error - * #GNUNET_SYSERR on DB errors + * @return transaction result status */ - int + enum GNUNET_DB_QueryStatus (*insert_payback_request)(void *cls, struct TALER_EXCHANGEDB_Session *session, const struct TALER_ReservePublicKeyP *reserve_pub, @@ -2193,11 +2191,9 @@ struct TALER_EXCHANGEDB_Plugin * @param session a session * @param h_blind_ev hash of the blinded coin * @param[out] reserve_pub set to information about the reserve (on success only) - * @return #GNUNET_OK on success, - * #GNUNET_NO if there are no entries, - * #GNUNET_SYSERR on DB errors + * @return transaction status code */ - int + enum GNUNET_DB_QueryStatus (*get_reserve_by_h_blind)(void *cls, struct TALER_EXCHANGEDB_Session *session, const struct GNUNET_HashCode *h_blind_ev,