summaryrefslogtreecommitdiff
path: root/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
diff options
context:
space:
mode:
authorChristian Grothoff <grothoff@gnunet.org>2023-10-13 20:51:04 +0200
committerChristian Grothoff <grothoff@gnunet.org>2023-10-13 21:16:50 +0200
commit0f3490dc022620c7e42b86426e14198a04c2e17f (patch)
tree0b16661ae6aa9273bf81652fe6a8806060b31fb0 /src/backend/taler-merchant-httpd_post-orders-ID-pay.c
parenta5f50083e65a3e9a0945b150701349afa81a0e9e (diff)
downloadmerchant-0f3490dc022620c7e42b86426e14198a04c2e17f.tar.gz
merchant-0f3490dc022620c7e42b86426e14198a04c2e17f.tar.bz2
merchant-0f3490dc022620c7e42b86426e14198a04c2e17f.zip
more work on multicurrency support: use checks everywhere...
Diffstat (limited to 'src/backend/taler-merchant-httpd_post-orders-ID-pay.c')
-rw-r--r--src/backend/taler-merchant-httpd_post-orders-ID-pay.c159
1 files changed, 113 insertions, 46 deletions
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
index d17e98c8..9edc553c 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
@@ -399,6 +399,18 @@ struct PayContext
*/
enum GNUNET_GenericReturnValue suspended;
+ /**
+ * Set to true if the deposit currency of a coin
+ * does not match the contract currency.
+ */
+ bool deposit_currency_mismatch;
+
+ /**
+ * Set to true if the database contains a (bogus)
+ * refund for a different currency.
+ */
+ bool refund_currency_mismatch;
+
};
@@ -909,11 +921,13 @@ batch_deposit_transaction (const struct ExchangeGroup *eg,
{
const struct PayContext *pc = eg->pc;
enum GNUNET_DB_QueryStatus qs;
- struct TALER_Amount total_without_fees = { 0 };
+ struct TALER_Amount total_without_fees;
uint64_t b_dep_serial;
uint32_t off = 0;
- bool found = false;
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (pc->amount.currency,
+ &total_without_fees));
for (unsigned int i = 0; i<pc->coins_cnt; i++)
{
struct DepositConfirmation *dc = &pc->dc[i];
@@ -925,25 +939,14 @@ batch_deposit_transaction (const struct ExchangeGroup *eg,
continue;
if (dc->found_in_db)
continue;
- /* FIXME: #7951 */
GNUNET_assert (0 <=
TALER_amount_subtract (&amount_without_fees,
&dc->cdd.amount,
&dc->deposit_fee));
- if (! found)
- {
- found = true;
- total_without_fees = amount_without_fees;
- }
- else
- {
- /* FIXME: #7951 */
- GNUNET_assert (
- 0 <=
- TALER_amount_add (&total_without_fees,
- &total_without_fees,
- &amount_without_fees));
- }
+ GNUNET_assert (0 <=
+ TALER_amount_add (&total_without_fees,
+ &total_without_fees,
+ &amount_without_fees));
}
qs = TMH_db->insert_deposit_confirmation (
TMH_db->cls,
@@ -960,13 +963,6 @@ batch_deposit_transaction (const struct ExchangeGroup *eg,
if (qs <= 0)
return qs; /* Entire batch already known or failure, we're done */
- if (! found)
- {
- /* All coins already done, but the batch was not? Invariant violation! */
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
-
for (unsigned int i = 0; i<pc->coins_cnt; i++)
{
struct DepositConfirmation *dc = &pc->dc[i];
@@ -1596,14 +1592,26 @@ check_coin_paid (void *cls,
(0 !=
strcmp (exchange_url,
dc->exchange_url)) ||
- /* FIXME: #7951 */
+ (GNUNET_OK !=
+ TALER_amount_cmp_currency (amount_with_fee,
+ &dc->cdd.amount)) ||
(0 != TALER_amount_cmp (amount_with_fee,
&dc->cdd.amount)) )
continue; /* does not match, skip */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Deposit of coin `%s' already in our DB.\n",
TALER_B2S (coin_pub));
- /* FIXME: #7951 */
+ if ( (GNUNET_OK !=
+ TALER_amount_cmp_currency (&pc->total_paid,
+ amount_with_fee)) ||
+ (GNUNET_OK !=
+ TALER_amount_cmp_currency (&pc->total_fees_paid,
+ deposit_fee)) )
+ {
+ GNUNET_break_op (0);
+ pc->deposit_currency_mismatch = true;
+ break;
+ }
GNUNET_assert (0 <=
TALER_amount_add (&pc->total_paid,
&pc->total_paid,
@@ -1654,7 +1662,14 @@ check_coin_refunded (void *cls,
if (0 != GNUNET_memcmp (coin_pub,
&dc->cdd.coin_pub))
continue;
- /* FIXME: #7951 */
+ if (GNUNET_OK !=
+ TALER_amount_cmp_currency (&pc->total_refunded,
+ refund_amount))
+ {
+ GNUNET_break (0);
+ pc->refund_currency_mismatch = true;
+ break;
+ }
GNUNET_assert (0 <=
TALER_amount_add (&pc->total_refunded,
&pc->total_refunded,
@@ -1681,15 +1696,12 @@ check_payment_sufficient (struct PayContext *pc)
struct TALER_Amount total_needed;
if (0 == pc->coins_cnt)
+ return TALER_amount_is_zero (&pc->amount);
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (pc->amount.currency,
+ &total_wire_fee));
+ for (unsigned int i = 0; i < pc->num_exchanges; i++)
{
- return ((0 == pc->amount.value) &&
- (0 == pc->amount.fraction));
- }
-
- total_wire_fee = pc->egs[0]->wire_fee;
- for (unsigned int i = 1; i < pc->num_exchanges; i++)
- {
- /* FIXME: #7951 */
if (GNUNET_OK !=
TALER_amount_cmp_currency (&total_wire_fee,
&pc->egs[i]->wire_fee))
@@ -1700,7 +1712,6 @@ check_payment_sufficient (struct PayContext *pc)
total_wire_fee.currency);
return false;
}
- /* FIXME: #7951 */
if (0 >
TALER_amount_add (&total_wire_fee,
&total_wire_fee,
@@ -1714,19 +1725,34 @@ check_payment_sufficient (struct PayContext *pc)
}
}
- acc_fee = pc->dc[0].deposit_fee;
- acc_amount = pc->dc[0].cdd.amount;
-
/**
* This loops calculates what are the deposit fee / total
* amount with fee / and wire fee, for all the coins.
*/
- for (unsigned int i = 1; i<pc->coins_cnt; i++)
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (pc->amount.currency,
+ &acc_fee));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (pc->amount.currency,
+ &acc_amount));
+ for (unsigned int i = 0; i<pc->coins_cnt; i++)
{
struct DepositConfirmation *dc = &pc->dc[i];
GNUNET_assert (dc->found_in_db);
- /* FIXME: #7951 */
+ if ( (GNUNET_OK !=
+ TALER_amount_cmp_currency (&acc_fee,
+ &dc->deposit_fee)) ||
+ (GNUNET_OK !=
+ TALER_amount_cmp_currency (&acc_amount,
+ &dc->cdd.amount)) )
+ {
+ GNUNET_break_op (0);
+ resume_pay_with_error (pc,
+ TALER_EC_GENERIC_CURRENCY_MISMATCH,
+ dc->deposit_fee.currency);
+ return false;
+ }
if ( (0 >
TALER_amount_add (&acc_fee,
&dc->deposit_fee,
@@ -1743,7 +1769,6 @@ check_payment_sufficient (struct PayContext *pc)
"Overflow adding up amounts");
return false;
}
- /* FIXME: #7951 */
if (1 ==
TALER_amount_cmp (&dc->deposit_fee,
&dc->cdd.amount))
@@ -1786,9 +1811,7 @@ check_payment_sufficient (struct PayContext *pc)
return false;
}
-
/* add wire fee to the total fees */
- /* FIXME: #7951 */
if (0 >
TALER_amount_add (&acc_fee,
&acc_fee,
@@ -1800,7 +1823,6 @@ check_payment_sufficient (struct PayContext *pc)
"Overflow adding up amounts");
return false;
}
- /* FIXME: #7951 */
if (-1 == TALER_amount_cmp (&pc->max_fee,
&acc_fee))
{
@@ -2045,6 +2067,14 @@ execute_pay_transaction (struct PayContext *pc)
"lookup deposits");
return;
}
+ if (pc->deposit_currency_mismatch)
+ {
+ GNUNET_break_op (0);
+ resume_pay_with_error (pc,
+ TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH,
+ pc->amount.currency);
+ return;
+ }
}
@@ -2072,6 +2102,14 @@ execute_pay_transaction (struct PayContext *pc)
"lookup refunds");
return;
}
+ if (pc->refund_currency_mismatch)
+ {
+ TMH_db->rollback (TMH_db->cls);
+ resume_pay_with_error (pc,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "refund currency in database does not match order currency");
+ return;
+ }
}
/* Check if there are coins that still need to be processed */
@@ -2299,7 +2337,6 @@ parse_pay (struct PayContext *pc)
GNUNET_break_op (0);
return res;
}
-
for (unsigned int j = 0; j<coins_index; j++)
{
if (0 ==
@@ -2657,6 +2694,36 @@ check_contract (struct PayContext *pc)
}
}
+ if (GNUNET_OK !=
+ TALER_amount_cmp_currency (&pc->max_fee,
+ &pc->amount))
+ {
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (pc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "'max_fee' in database does not match currency of contract price");
+ }
+
+ for (unsigned int i=0;i<pc->coins_cnt;i++)
+ {
+ struct DepositConfirmation *dc = &pc->dc[i];
+
+ if (GNUNET_OK !=
+ TALER_amount_cmp_currency (&dc->cdd.amount,
+ &pc->amount))
+ {
+ GNUNET_break_op (0);
+ return (MHD_YES ==
+ TALER_MHD_reply_with_error (pc->connection,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH,
+ pc->amount.currency))
+ ? GNUNET_NO
+ : GNUNET_SYSERR;
+ }
+ }
+
if (GNUNET_TIME_timestamp_cmp (pc->wire_transfer_deadline,
<,
pc->refund_deadline))