-implementing purse merge DB logic

This commit is contained in:
Christian Grothoff 2022-04-12 11:58:21 +02:00
parent cacb019501
commit 3893afa49c
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
4 changed files with 141 additions and 30 deletions

@ -1 +1 @@
Subproject commit f2babbbdd477eeafb17292e16f335226ea02cb6a Subproject commit 0e7707e441874b8aca9801b389d47003ac7a8f73

View File

@ -157,7 +157,9 @@ reply_merge_success (struct MHD_Connection *connection,
&pcc->target_amount, &pcc->target_amount,
&pcc->wf->wad)) &pcc->wf->wad))
{ {
GNUNET_break_op (0); GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Purse merged, balance of %s benefits exchange as it is below wad fee.\n",
TALER_amount2s (&pcc->target_amount));
return TALER_MHD_reply_with_ec ( return TALER_MHD_reply_with_ec (
connection, connection,
TALER_EC_EXCHANGE_PURSE_MERGE_WAD_FEE_EXCEEDS_PURSE_VALUE, TALER_EC_EXCHANGE_PURSE_MERGE_WAD_FEE_EXCEEDS_PURSE_VALUE,
@ -217,13 +219,19 @@ merge_transaction (void *cls,
struct PurseMergeContext *pcc = cls; struct PurseMergeContext *pcc = cls;
enum GNUNET_DB_QueryStatus qs; enum GNUNET_DB_QueryStatus qs;
bool in_conflict = true; bool in_conflict = true;
bool no_balance = true;
bool no_partner = true;
qs = TEH_plugin->do_purse_merge (TEH_plugin->cls, qs = TEH_plugin->do_purse_merge (TEH_plugin->cls,
pcc->purse_pub, pcc->purse_pub,
&pcc->merge_sig, &pcc->merge_sig,
pcc->merge_timestamp, pcc->merge_timestamp,
&pcc->reserve_sig,
pcc->provider_url, pcc->provider_url,
&pcc->reserve_pub); &pcc->reserve_pub,
&no_partner,
&no_balance,
&in_conflict);
if (qs < 0) if (qs < 0)
{ {
if (GNUNET_DB_STATUS_SOFT_ERROR == qs) if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
@ -237,26 +245,65 @@ merge_transaction (void *cls,
"purse merge"); "purse merge");
return qs; return qs;
} }
if (no_partner)
{
*mhd_ret =
TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_MERGE_PURSE_PARTNER_UNKNOWN,
pcc->provider_url);
return GNUNET_DB_STATUS_HARD_ERROR;
}
if (no_balance)
{
*mhd_ret =
TALER_MHD_reply_with_error (connection,
MHD_HTTP_CONFLICT,
TALER_EC_EXCHANGE_PURSE_NOT_FULL,
NULL);
return GNUNET_DB_STATUS_HARD_ERROR;
}
if (in_conflict)
{
struct TALER_PurseMergeSignatureP merge_sig;
struct GNUNET_TIME_Timestamp merge_timestamp;
char *partner_url = NULL;
struct TALER_ReservePublicKeyP reserve_pub;
qs = TEH_plugin->select_purse_merge (TEH_plugin->cls,
qs = TEH_plugin->do_account_merge (TEH_plugin->cls,
pcc->purse_pub, pcc->purse_pub,
&pcc->reserve_pub, &merge_sig,
&pcc->reserve_sig); &merge_timestamp,
&partner_url,
&reserve_pub);
if (qs < 0) if (qs < 0)
{ {
if (GNUNET_DB_STATUS_SOFT_ERROR == qs) if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
return qs; return qs;
TALER_LOG_WARNING ( TALER_LOG_WARNING (
"Failed to store account purse information in database\n"); "Failed to fetch merge purse information from database\n");
*mhd_ret = *mhd_ret =
TALER_MHD_reply_with_error (connection, TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR, MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_GENERIC_DB_STORE_FAILED, TALER_EC_GENERIC_DB_FETCH_FAILED,
"account merge"); "select purse merge");
return qs; return qs;
} }
*mhd_ret = TALER_MHD_REPLY_JSON_PACK (
connection,
MHD_HTTP_CONFLICT,
GNUNET_JSON_pack_timestamp ("merge_timestamp",
merge_timestamp),
GNUNET_JSON_pack_data_auto ("merge_sig",
&merge_sig),
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_string ("partner_base_url",
partner_url)),
GNUNET_JSON_pack_data_auto ("reserve_pub",
&reserve_pub));
GNUNET_free (partner_url);
return GNUNET_DB_STATUS_HARD_ERROR;
}
return qs; return qs;
} }

View File

@ -3509,16 +3509,18 @@ prepare_statements (struct PostgresClosure *pg)
/* Used in #postgres_do_purse_merge() */ /* Used in #postgres_do_purse_merge() */
GNUNET_PQ_make_prepare ( GNUNET_PQ_make_prepare (
"call_purse_merge", "call_purse_merge",
"SELECT 1" "SELECT"
" out_no_partner AS no_partner"
",out_no_balance AS no_balance"
",out_conflict AS conflict"
" FROM exchange_do_purse_merge" " FROM exchange_do_purse_merge"
" ($1, $2, $3, $4, $5);", " ($1, $2, $3, $4, $5, $6);",
5), 6),
/* Used in #postgres_select_purse_merge */ /* Used in #postgres_select_purse_merge */
GNUNET_PQ_make_prepare ( GNUNET_PQ_make_prepare (
"select_purse_merge", "select_purse_merge",
"SELECT " "SELECT "
" reserve_pub" " reserve_pub"
",purse_pub"
",merge_sig" ",merge_sig"
",merge_timestamp" ",merge_timestamp"
",partner_base_url" ",partner_base_url"
@ -13467,8 +13469,12 @@ postgres_get_purse_deposit (
* @param purse_pub purse to merge * @param purse_pub purse to merge
* @param merge_sig signature affirming the merge * @param merge_sig signature affirming the merge
* @param merge_timestamp time of the merge * @param merge_timestamp time of the merge
* @param reserve_sig signature of the reserve affirming the merge
* @param partner_url URL of the partner exchange, can be NULL if the reserves lives with us * @param partner_url URL of the partner exchange, can be NULL if the reserves lives with us
* @param reserve_pub public key of the reserve to credit * @param reserve_pub public key of the reserve to credit
* @param[out] no_partner set to true if @a partner_url is unknown
* @param[out] no_balance set to true if the @a purse_pub is not paid up yet
* @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already
* @return transaction status code * @return transaction status code
*/ */
static enum GNUNET_DB_QueryStatus static enum GNUNET_DB_QueryStatus
@ -13477,11 +13483,37 @@ postgres_do_purse_merge (
const struct TALER_PurseContractPublicKeyP *purse_pub, const struct TALER_PurseContractPublicKeyP *purse_pub,
const struct TALER_PurseMergeSignatureP *merge_sig, const struct TALER_PurseMergeSignatureP *merge_sig,
const struct GNUNET_TIME_Timestamp merge_timestamp, const struct GNUNET_TIME_Timestamp merge_timestamp,
const struct TALER_ReserveSignatureP *reserve_sig,
const char *partner_url, const char *partner_url,
const struct TALER_ReservePublicKeyP *reserve_pub) const struct TALER_ReservePublicKeyP *reserve_pub,
bool *no_partner,
bool *no_balance,
bool *in_conflict)
{ {
GNUNET_break (0); // FIXME struct PostgresClosure *pg = cls;
return GNUNET_DB_STATUS_HARD_ERROR; struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (purse_pub),
GNUNET_PQ_query_param_auto_from_type (merge_sig),
GNUNET_PQ_query_param_timestamp (&merge_timestamp),
GNUNET_PQ_query_param_auto_from_type (reserve_sig),
GNUNET_PQ_query_param_string (partner_url),
GNUNET_PQ_query_param_auto_from_type (reserve_pub),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_bool ("no_partner",
no_partner),
GNUNET_PQ_result_spec_bool ("no_balance",
no_balance),
GNUNET_PQ_result_spec_bool ("conflict",
in_conflict),
GNUNET_PQ_result_spec_end
};
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
"call_purse_merge",
params,
rs);
} }
@ -13506,8 +13538,31 @@ postgres_select_purse_merge (
char **partner_url, char **partner_url,
struct TALER_ReservePublicKeyP *reserve_pub) struct TALER_ReservePublicKeyP *reserve_pub)
{ {
GNUNET_break (0); // FIXME struct PostgresClosure *pg = cls;
return GNUNET_DB_STATUS_HARD_ERROR; struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (purse_pub),
GNUNET_PQ_query_param_end
};
bool is_null;
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_auto_from_type ("merge_sig",
merge_sig),
GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
reserve_pub),
GNUNET_PQ_result_spec_timestamp ("merge_timestamp",
merge_timestamp),
GNUNET_PQ_result_spec_allow_null (
GNUNET_PQ_result_spec_string ("partner_base_url",
partner_url),
&is_null),
GNUNET_PQ_result_spec_end
};
*partner_url = NULL;
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
"select_purse_merge",
params,
rs);
} }

View File

@ -4628,14 +4628,19 @@ struct TALER_EXCHANGEDB_Plugin
/** /**
* Function called to approve merging a purse into a * Function called to approve merging a purse into a
* reserve by the respective purse merge key. * reserve by the respective purse merge key. The purse
* must not have been merged into a different reserve.
* *
* @param cls the @e cls of this struct with the plugin-specific state * @param cls the @e cls of this struct with the plugin-specific state
* @param purse_pub purse to merge * @param purse_pub purse to merge
* @param merge_sig signature affirming the merge * @param merge_sig signature affirming the merge
* @param merge_timestamp time of the merge * @param merge_timestamp time of the merge
* @param reserve_sig signature of the reserve affirming the merge
* @param partner_url URL of the partner exchange, can be NULL if the reserves lives with us * @param partner_url URL of the partner exchange, can be NULL if the reserves lives with us
* @param reserve_pub public key of the reserve to credit * @param reserve_pub public key of the reserve to credit
* @param[out] no_partner set to true if @a partner_url is unknown
* @param[out] no_balance set to true if the @a purse_pub is not paid up yet
* @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already
* @return transaction status code * @return transaction status code
*/ */
enum GNUNET_DB_QueryStatus enum GNUNET_DB_QueryStatus
@ -4644,8 +4649,12 @@ struct TALER_EXCHANGEDB_Plugin
const struct TALER_PurseContractPublicKeyP *purse_pub, const struct TALER_PurseContractPublicKeyP *purse_pub,
const struct TALER_PurseMergeSignatureP *merge_sig, const struct TALER_PurseMergeSignatureP *merge_sig,
const struct GNUNET_TIME_Timestamp merge_timestamp, const struct GNUNET_TIME_Timestamp merge_timestamp,
const struct TALER_ReserveSignatureP *reserve_sig,
const char *partner_url, const char *partner_url,
const struct TALER_ReservePublicKeyP *reserve_pub); const struct TALER_ReservePublicKeyP *reserve_pub,
bool *no_partner,
bool *no_balance,
bool *in_conflict);
/** /**