summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-06-19 17:53:42 +0200
committerChristian Grothoff <christian@grothoff.org>2017-06-19 17:53:42 +0200
commit51ee20102fa3818e9e4a4113a59ad700cb7eea42 (patch)
tree1a357666eb4811fbacc3fd72e5dc94a7556f9196
parent92e6744ac032a3c4c4118ac6b251f769c5478aa6 (diff)
downloadexchange-51ee20102fa3818e9e4a4113a59ad700cb7eea42.tar.gz
exchange-51ee20102fa3818e9e4a4113a59ad700cb7eea42.tar.bz2
exchange-51ee20102fa3818e9e4a4113a59ad700cb7eea42.zip
address #5010 for /payback
-rw-r--r--src/exchange/taler-exchange-httpd_db.c143
-rw-r--r--src/exchange/taler-exchange-httpd_payback.c276
-rw-r--r--src/exchange/taler-exchange-httpd_responses.c63
-rw-r--r--src/exchange/taler-exchange-httpd_responses.h31
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c98
-rw-r--r--src/exchangedb/test_exchangedb.c6
-rw-r--r--src/include/taler_exchangedb_plugin.h12
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
@@ -35,6 +35,253 @@
/**
+ * 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
* request and coin is valid) and then execute the payback operation.
@@ -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;
-
- 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
- };
+ 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,