merge known_coin transaction into main transaction (for #6416)

This commit is contained in:
Christian Grothoff 2020-07-08 18:20:44 +02:00
parent 8e03498a48
commit c93f647106
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
5 changed files with 53 additions and 135 deletions

View File

@ -40,46 +40,6 @@
#define MAX_TRANSACTION_COMMIT_RETRIES 100
/**
* Execute database transaction to ensure coin is known. Run the transaction
* logic; 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 a `struct TEH_DB_KnowCoinContext`
* @param connection MHD request context, must not be NULL
* @param session database session and transaction to use
* @param[out] mhd_ret set to MHD status on error, must not be NULL
* @return transaction status
*/
enum GNUNET_DB_QueryStatus
TEH_DB_know_coin_transaction (void *cls,
struct MHD_Connection *connection,
struct TALER_EXCHANGEDB_Session *session,
MHD_RESULT *mhd_ret)
{
struct TEH_DB_KnowCoinContext *kcc = cls;
enum GNUNET_DB_QueryStatus qs;
GNUNET_assert (NULL != mhd_ret);
qs = TEH_plugin->ensure_coin_known (TEH_plugin->cls,
session,
kcc->coin);
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
{
*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;
}
return qs;
}
/**
* Run a database transaction for @a connection.
* Starts a transaction and calls @a cb. Upon success,

View File

@ -26,44 +26,6 @@
#include <gnunet/gnunet_mhd_compat.h>
/**
* Type of closure for #TEH_DB_know_coin_transaction.
*/
struct TEH_DB_KnowCoinContext
{
/**
* The coin to make sure it is known.
*/
const struct TALER_CoinPublicInfo *coin;
/**
* MHD connection to queue errors with.
*/
struct MHD_Connection *connection;
};
/**
* Execute database transaction to ensure coin is known. Run the transaction
* logic; 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 a `struct TEH_DB_KnowCoinContext`
* @param connection MHD request context, must not be NULL
* @param session database session and transaction to use
* @param[out] mhd_ret set to MHD status on error, must not be NULL
* @return transaction status
*/
enum GNUNET_DB_QueryStatus
TEH_DB_know_coin_transaction (void *cls,
struct MHD_Connection *connection,
struct TALER_EXCHANGEDB_Session *session,
MHD_RESULT *mhd_ret);
/**
* Function implementing a database transaction. Runs the transaction
* logic; IF it returns a non-error code, the transaction logic MUST

View File

@ -217,6 +217,20 @@ deposit_transaction (void *cls,
struct TALER_Amount spent;
enum GNUNET_DB_QueryStatus qs;
/* make sure coin is 'known' in database */
qs = TEH_plugin->ensure_coin_known (TEH_plugin->cls,
session,
&deposit->coin);
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
{
*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;
}
/* Theoretically, someone other threat may have received
and committed the deposit in the meantime. Check now
that we are in the transaction scope. */
@ -493,26 +507,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
"deposited amount smaller than depositing fee");
}
/* make sure coin is 'known' in database */
{
MHD_RESULT mhd_ret;
struct TEH_DB_KnowCoinContext kcc = {
.coin = &deposit.coin,
.connection = connection
};
if (GNUNET_OK !=
TEH_DB_run_transaction (connection,
"know coin for deposit",
&mhd_ret,
&TEH_DB_know_coin_transaction,
&kcc))
{
GNUNET_JSON_parse_free (spec);
return mhd_ret;
}
}
/* check deposit signature */
{
struct TALER_DepositRequestPS dr = {

View File

@ -157,6 +157,12 @@ struct MeltContext
*/
int zombie_required;
/**
* We already checked and noticed that the coin is known. Hence we
* can skip the "ensure_coin_known" step of the transaction.
*/
bool coin_is_dirty;
};
@ -302,6 +308,23 @@ melt_transaction (void *cls,
enum GNUNET_DB_QueryStatus qs;
uint32_t noreveal_index;
/* First, make sure coin is 'known' in database */
if (! rmc->coin_is_dirty)
{
qs = TEH_plugin->ensure_coin_known (TEH_plugin->cls,
session,
&rmc->refresh_session.coin);
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
{
*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;
}
}
/* Check if we already created a matching refresh_session */
qs = TEH_plugin->get_melt_index (TEH_plugin->cls,
session,
@ -437,7 +460,6 @@ check_for_denomination_key (struct MHD_Connection *connection,
struct MeltContext *rmc)
{
struct TEH_KS_StateHandle *key_state;
int coin_is_dirty = GNUNET_NO;
key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
if (NULL == key_state)
@ -507,8 +529,8 @@ check_for_denomination_key (struct MHD_Connection *connection,
else
{
/* Minor optimization: no need to run the
#TEH_DB_know_coin_transaction below */
coin_is_dirty = GNUNET_YES;
"ensure_coin_known" part of the transaction */
rmc->coin_is_dirty = true;
}
}
}
@ -568,24 +590,6 @@ check_for_denomination_key (struct MHD_Connection *connection,
}
TEH_KS_release (key_state);
/* run actual logic, now that the request was parsed */
/* First, make sure coin is 'known' in database */
if (GNUNET_NO == coin_is_dirty)
{
struct TEH_DB_KnowCoinContext kcc;
MHD_RESULT mhd_ret;
kcc.coin = &rmc->refresh_session.coin;
kcc.connection = connection;
if (GNUNET_OK !=
TEH_DB_run_transaction (connection,
"know coin for melt",
&mhd_ret,
&TEH_DB_know_coin_transaction,
&kcc))
return mhd_ret;
}
/* sanity-check that "total melt amount > melt fee" */
if (0 <
TALER_amount_cmp (&rmc->coin_refresh_fee,

View File

@ -132,6 +132,20 @@ recoup_transaction (void *cls,
enum GNUNET_DB_QueryStatus qs;
int existing_recoup_found;
/* make sure coin is 'known' in database */
qs = TEH_plugin->ensure_coin_known (TEH_plugin->cls,
session,
pc->coin);
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
{
*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;
}
/* Check whether a recoup is allowed, and if so, to which
reserve / account the money should go */
if (pc->refreshed)
@ -450,22 +464,6 @@ verify_and_execute_recoup (struct MHD_Connection *connection,
&pc.h_blind);
GNUNET_free (coin_ev);
/* make sure coin is 'known' in database */
{
struct TEH_DB_KnowCoinContext kcc;
MHD_RESULT mhd_ret;
kcc.coin = coin;
kcc.connection = connection;
if (GNUNET_OK !=
TEH_DB_run_transaction (connection,
"know coin for recoup",
&mhd_ret,
&TEH_DB_know_coin_transaction,
&kcc))
return mhd_ret;
}
/* Perform actual recoup transaction */
pc.coin_sig = coin_sig;
pc.coin_bks = coin_bks;