diff options
author | Christian Grothoff <grothoff@gnunet.org> | 2023-10-13 20:51:04 +0200 |
---|---|---|
committer | Christian Grothoff <grothoff@gnunet.org> | 2023-10-13 21:16:50 +0200 |
commit | 0f3490dc022620c7e42b86426e14198a04c2e17f (patch) | |
tree | 0b16661ae6aa9273bf81652fe6a8806060b31fb0 /src/backend/taler-merchant-httpd_post-orders-ID-pay.c | |
parent | a5f50083e65a3e9a0945b150701349afa81a0e9e (diff) | |
download | merchant-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.c | 159 |
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)) |