aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2022-04-12 11:58:21 +0200
committerChristian Grothoff <christian@grothoff.org>2022-04-12 11:58:21 +0200
commit3893afa49c689288734bfee9091afc1010ae4f11 (patch)
treee1c514c4e1d7ebfbeab49358ea4d065b4bc6c359 /src
parentcacb0195015bcffbbdcbd6b2c8a6578911b27df1 (diff)
downloadexchange-3893afa49c689288734bfee9091afc1010ae4f11.tar.xz
-implementing purse merge DB logic
Diffstat (limited to 'src')
-rw-r--r--src/exchange/taler-exchange-httpd_purses_merge.c83
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c75
-rw-r--r--src/include/taler_exchangedb_plugin.h13
3 files changed, 141 insertions, 30 deletions
diff --git a/src/exchange/taler-exchange-httpd_purses_merge.c b/src/exchange/taler-exchange-httpd_purses_merge.c
index 602463373..526238221 100644
--- a/src/exchange/taler-exchange-httpd_purses_merge.c
+++ b/src/exchange/taler-exchange-httpd_purses_merge.c
@@ -157,7 +157,9 @@ reply_merge_success (struct MHD_Connection *connection,
&pcc->target_amount,
&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 (
connection,
TALER_EC_EXCHANGE_PURSE_MERGE_WAD_FEE_EXCEEDS_PURSE_VALUE,
@@ -217,13 +219,19 @@ merge_transaction (void *cls,
struct PurseMergeContext *pcc = cls;
enum GNUNET_DB_QueryStatus qs;
bool in_conflict = true;
+ bool no_balance = true;
+ bool no_partner = true;
qs = TEH_plugin->do_purse_merge (TEH_plugin->cls,
pcc->purse_pub,
&pcc->merge_sig,
pcc->merge_timestamp,
+ &pcc->reserve_sig,
pcc->provider_url,
- &pcc->reserve_pub);
+ &pcc->reserve_pub,
+ &no_partner,
+ &no_balance,
+ &in_conflict);
if (qs < 0)
{
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
@@ -237,26 +245,65 @@ merge_transaction (void *cls,
"purse merge");
return qs;
}
-
-
- qs = TEH_plugin->do_account_merge (TEH_plugin->cls,
- pcc->purse_pub,
- &pcc->reserve_pub,
- &pcc->reserve_sig);
- if (qs < 0)
+ if (no_partner)
{
- if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
- return qs;
- TALER_LOG_WARNING (
- "Failed to store account purse information in database\n");
*mhd_ret =
TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_STORE_FAILED,
- "account merge");
- return qs;
+ 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,
+ pcc->purse_pub,
+ &merge_sig,
+ &merge_timestamp,
+ &partner_url,
+ &reserve_pub);
+ if (qs < 0)
+ {
+ if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+ return qs;
+ TALER_LOG_WARNING (
+ "Failed to fetch merge purse information from database\n");
+ *mhd_ret =
+ TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "select purse merge");
+ 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;
}
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
index b79c8dd89..9d3171c2e 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -3509,16 +3509,18 @@ prepare_statements (struct PostgresClosure *pg)
/* Used in #postgres_do_purse_merge() */
GNUNET_PQ_make_prepare (
"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"
- " ($1, $2, $3, $4, $5);",
- 5),
+ " ($1, $2, $3, $4, $5, $6);",
+ 6),
/* Used in #postgres_select_purse_merge */
GNUNET_PQ_make_prepare (
"select_purse_merge",
"SELECT "
" reserve_pub"
- ",purse_pub"
",merge_sig"
",merge_timestamp"
",partner_base_url"
@@ -13467,9 +13469,13 @@ postgres_get_purse_deposit (
* @param purse_pub purse to merge
* @param merge_sig signature affirming 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 reserve_pub public key of the reserve to credit
- * @return transaction status code
+ * @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
*/
static enum GNUNET_DB_QueryStatus
postgres_do_purse_merge (
@@ -13477,11 +13483,37 @@ postgres_do_purse_merge (
const struct TALER_PurseContractPublicKeyP *purse_pub,
const struct TALER_PurseMergeSignatureP *merge_sig,
const struct GNUNET_TIME_Timestamp merge_timestamp,
+ const struct TALER_ReserveSignatureP *reserve_sig,
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
- return GNUNET_DB_STATUS_HARD_ERROR;
+ struct PostgresClosure *pg = cls;
+ 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,
struct TALER_ReservePublicKeyP *reserve_pub)
{
- GNUNET_break (0); // FIXME
- return GNUNET_DB_STATUS_HARD_ERROR;
+ struct PostgresClosure *pg = cls;
+ 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);
}
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
index 39fa2ecdf..18f2fd924 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -4628,14 +4628,19 @@ struct TALER_EXCHANGEDB_Plugin
/**
* 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 purse_pub purse to merge
* @param merge_sig signature affirming 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 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
*/
enum GNUNET_DB_QueryStatus
@@ -4644,8 +4649,12 @@ struct TALER_EXCHANGEDB_Plugin
const struct TALER_PurseContractPublicKeyP *purse_pub,
const struct TALER_PurseMergeSignatureP *merge_sig,
const struct GNUNET_TIME_Timestamp merge_timestamp,
+ const struct TALER_ReserveSignatureP *reserve_sig,
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);
/**