synchronize with latest GANA

This commit is contained in:
Christian Grothoff 2020-07-08 19:36:08 +02:00
parent c93f647106
commit c3cd21508b
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
9 changed files with 164 additions and 56 deletions

@ -1 +1 @@
Subproject commit c0fedb8d45c41fb283fec714b48278e6661d51be Subproject commit f805e4f09b45262cbbb6184659754e15aedfadfd

View File

@ -40,6 +40,78 @@
#define MAX_TRANSACTION_COMMIT_RETRIES 100 #define MAX_TRANSACTION_COMMIT_RETRIES 100
/**
* Ensure coin is known in the database, and handle conflicts and errors.
*
* @param coin the coin to make known
* @param connection MHD request context
* @param session database session and transaction to use
* @param[out] mhd_ret set to MHD status on error
* @return transaction status, negative on error (@a mhd_ret will be set in this case)
*/
enum GNUNET_DB_QueryStatus
TEH_make_coin_known (const struct TALER_CoinPublicInfo *coin,
struct MHD_Connection *connection,
struct TALER_EXCHANGEDB_Session *session,
MHD_RESULT *mhd_ret)
{
enum TALER_EXCHANGEDB_CoinKnownStatus cks;
/* make sure coin is 'known' in database */
cks = TEH_plugin->ensure_coin_known (TEH_plugin->cls,
session,
coin);
switch (cks)
{
case TALER_EXCHANGEDB_CKS_ADDED:
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
case TALER_EXCHANGEDB_CKS_PRESENT:
return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
case TALER_EXCHANGEDB_CKS_SOFT_FAIL:
return GNUNET_DB_STATUS_SOFT_ERROR;
case TALER_EXCHANGEDB_CKS_HARD_FAIL:
*mhd_ret
= TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_DB_COIN_HISTORY_STORE_ERROR,
"could not persist coin data");
return GNUNET_DB_STATUS_HARD_ERROR;
case TALER_EXCHANGEDB_CKS_CONFLICT:
break;
}
{
struct TALER_EXCHANGEDB_TransactionList *tl;
enum GNUNET_DB_QueryStatus qs;
qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
session,
&coin->coin_pub,
GNUNET_NO,
&tl);
if (0 > qs)
{
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
*mhd_ret = TALER_MHD_reply_with_error (
connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_DEPOSIT_HISTORY_DB_ERROR,
"could not fetch coin transaction history");
return qs;
}
*mhd_ret
= TEH_RESPONSE_reply_coin_insufficient_funds (
connection,
TALER_EC_COIN_CONFLICTING_DENOMINATION_KEY,
&coin->coin_pub,
tl);
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
tl);
return GNUNET_DB_STATUS_HARD_ERROR;
}
}
/** /**
* Run a database transaction for @a connection. * Run a database transaction for @a connection.
* Starts a transaction and calls @a cb. Upon success, * Starts a transaction and calls @a cb. Upon success,

View File

@ -26,6 +26,22 @@
#include <gnunet/gnunet_mhd_compat.h> #include <gnunet/gnunet_mhd_compat.h>
/**
* Ensure coin is known in the database, and handle conflicts and errors.
*
* @param coin the coin to make known
* @param connection MHD request context
* @param session database session and transaction to use
* @param[out] mhd_ret set to MHD status on error
* @return transaction status, negative on error (@a mhd_ret will be set in this case)
*/
enum GNUNET_DB_QueryStatus
TEH_make_coin_known (const struct TALER_CoinPublicInfo *coin,
struct MHD_Connection *connection,
struct TALER_EXCHANGEDB_Session *session,
MHD_RESULT *mhd_ret);
/** /**
* Function implementing a database transaction. Runs the transaction * Function implementing a database transaction. Runs the transaction
* logic; IF it returns a non-error code, the transaction logic MUST * logic; IF it returns a non-error code, the transaction logic MUST

View File

@ -218,18 +218,12 @@ deposit_transaction (void *cls,
enum GNUNET_DB_QueryStatus qs; enum GNUNET_DB_QueryStatus qs;
/* make sure coin is 'known' in database */ /* make sure coin is 'known' in database */
qs = TEH_plugin->ensure_coin_known (TEH_plugin->cls, qs = TEH_make_coin_known (&deposit->coin,
session, connection,
&deposit->coin); session,
if (GNUNET_DB_STATUS_HARD_ERROR == qs) mhd_ret);
{ if (qs < 0)
*mhd_ret return qs;
= TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_DB_COIN_HISTORY_STORE_ERROR,
"could not persist coin data");
return GNUNET_DB_STATUS_HARD_ERROR;
}
/* Theoretically, someone other threat may have received /* Theoretically, someone other threat may have received
and committed the deposit in the meantime. Check now and committed the deposit in the meantime. Check now

View File

@ -311,18 +311,12 @@ melt_transaction (void *cls,
/* First, make sure coin is 'known' in database */ /* First, make sure coin is 'known' in database */
if (! rmc->coin_is_dirty) if (! rmc->coin_is_dirty)
{ {
qs = TEH_plugin->ensure_coin_known (TEH_plugin->cls, qs = TEH_make_coin_known (&rmc->refresh_session.coin,
session, connection,
&rmc->refresh_session.coin); session,
if (GNUNET_DB_STATUS_HARD_ERROR == qs) mhd_ret);
{ if (qs < 0)
*mhd_ret return qs;
= TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_DB_COIN_HISTORY_STORE_ERROR,
"could not persist coin data");
return GNUNET_DB_STATUS_HARD_ERROR;
}
} }
/* Check if we already created a matching refresh_session */ /* Check if we already created a matching refresh_session */

View File

@ -133,18 +133,12 @@ recoup_transaction (void *cls,
int existing_recoup_found; int existing_recoup_found;
/* make sure coin is 'known' in database */ /* make sure coin is 'known' in database */
qs = TEH_plugin->ensure_coin_known (TEH_plugin->cls, qs = TEH_make_coin_known (&rmc->refresh_session.coin,
session, connection,
pc->coin); session,
if (GNUNET_DB_STATUS_HARD_ERROR == qs) mhd_ret);
{ if (qs < 0)
*mhd_ret return qs;
= TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_DB_COIN_HISTORY_STORE_ERROR,
"could not persist coin data");
return GNUNET_DB_STATUS_HARD_ERROR;
}
/* Check whether a recoup is allowed, and if so, to which /* Check whether a recoup is allowed, and if so, to which
reserve / account the money should go */ reserve / account the money should go */

View File

@ -3187,7 +3187,7 @@ postgres_count_known_coins (void *cls,
* @param coin the coin that must be made known * @param coin the coin that must be made known
* @return database transaction status, non-negative on success * @return database transaction status, non-negative on success
*/ */
static enum GNUNET_DB_QueryStatus static enum TALER_EXCHANGEDB_CoinKnownStatus
postgres_ensure_coin_known (void *cls, postgres_ensure_coin_known (void *cls,
struct TALER_EXCHANGEDB_Session *session, struct TALER_EXCHANGEDB_Session *session,
const struct TALER_CoinPublicInfo *coin) const struct TALER_CoinPublicInfo *coin)
@ -3207,33 +3207,45 @@ postgres_ensure_coin_known (void *cls,
#endif #endif
/* check if the coin is already known */ /* check if the coin is already known */
// FIXME: modify to not also fetch the RSA signature, needlessly costly!
qs = postgres_get_known_coin (pc, qs = postgres_get_known_coin (pc,
session, session,
&coin->coin_pub, &coin->coin_pub,
&known_coin); &known_coin);
if (0 > qs) switch (qs)
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
return GNUNET_SYSERR;
}
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
{ {
case GNUNET_DB_STATUS_HARD_ERROR:
return TALER_EXCHANGEDB_CKS_SOFT_FAIL;
case GNUNET_DB_STATUS_SOFT_ERROR:
return TALER_EXCHANGEDB_CKS_HARD_FAIL;
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
GNUNET_CRYPTO_rsa_signature_free (known_coin.denom_sig.rsa_signature); GNUNET_CRYPTO_rsa_signature_free (known_coin.denom_sig.rsa_signature);
return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; /* no change! */ if (0 == GNUNET_memcmp (&known_coin.denom_pub_hash,
&coin->denom_pub_hash))
return TALER_EXCHANGEDB_CKS_PRESENT;
GNUNET_break_op (0);
return TALER_EXCHANGEDB_CKS_CONFLICT;
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
break;
} }
GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs);
/* if not known, insert it */ /* if not known, insert it */
qs = insert_known_coin (pc, qs = insert_known_coin (pc,
session, session,
coin); coin);
if (0 >= qs) switch (qs)
{ {
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) case GNUNET_DB_STATUS_HARD_ERROR:
qs = GNUNET_DB_STATUS_HARD_ERROR; /* should be impossible */ return TALER_EXCHANGEDB_CKS_SOFT_FAIL;
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); case GNUNET_DB_STATUS_SOFT_ERROR:
return qs; return TALER_EXCHANGEDB_CKS_HARD_FAIL;
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
GNUNET_break (0);
return TALER_EXCHANGEDB_CKS_HARD_FAIL;
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
break;
} }
return qs; return TALER_EXCHANGEDB_CKS_ADDED;
} }

View File

@ -559,7 +559,7 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
session, session,
&refresh_session.rc, &refresh_session.rc,
&ret_refresh_session)); &ret_refresh_session));
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
plugin->ensure_coin_known (plugin->cls, plugin->ensure_coin_known (plugin->cls,
session, session,
&refresh_session.coin)); &refresh_session.coin));
@ -1746,7 +1746,7 @@ run (void *cls)
deposit.coin.denom_sig = cbc.sig; deposit.coin.denom_sig = cbc.sig;
deadline = GNUNET_TIME_absolute_get (); deadline = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&deadline); (void) GNUNET_TIME_round_abs (&deadline);
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
plugin->ensure_coin_known (plugin->cls, plugin->ensure_coin_known (plugin->cls,
session, session,
&deposit.coin)); &deposit.coin));
@ -1921,7 +1921,7 @@ run (void *cls)
deposit.refund_deadline = deadline; deposit.refund_deadline = deadline;
deposit.wire_deadline = deadline; deposit.wire_deadline = deadline;
result = 8; result = 8;
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
plugin->ensure_coin_known (plugin->cls, plugin->ensure_coin_known (plugin->cls,
session, session,
&deposit.coin)); &deposit.coin));

View File

@ -1841,7 +1841,33 @@ struct TALER_EXCHANGEDB_Plugin
* @param coin the coin that must be made known * @param coin the coin that must be made known
* @return database transaction status, non-negative on success * @return database transaction status, non-negative on success
*/ */
enum GNUNET_DB_QueryStatus enum TALER_EXCHANGEDB_CoinKnownStatus
{
/**
* The coin was successfully added.
*/
TALER_EXCHANGEDB_CKS_ADDED = 1,
/**
* The coin was already present.
*/
TALER_EXCHANGEDB_CKS_PRESENT = 0,
/**
* Serialization failure.
*/
TALER_EXCHANGEDB_CKS_SOFT_FAIL = -1,
/**
* Hard database failure.
*/
TALER_EXCHANGEDB_CKS_HARD_FAIL = -2,
/**
* Conflicting coin (different denomination key) already in database.
*/
TALER_EXCHANGEDB_CKS_CONFLICT = -3,
}
(*ensure_coin_known)(void *cls, (*ensure_coin_known)(void *cls,
struct TALER_EXCHANGEDB_Session *session, struct TALER_EXCHANGEDB_Session *session,
const struct TALER_CoinPublicInfo *coin); const struct TALER_CoinPublicInfo *coin);