/* This file is part of TALER (C) 2016-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. TALER is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with TALER; see the file COPYING. If not, see */ /** * @file bank-lib/fakebank_api_check.c * @brief library that fakes being a Taler bank for testcases * @author Christian Grothoff */ #include "platform.h" #include "taler_fakebank_lib.h" #include "taler_bank_service.h" #include "taler_mhd_lib.h" #include #include "fakebank.h" #include "fakebank_common_lookup.h" /** * Generate log messages for failed check operation. * * @param h handle to output transaction log for */ static void check_log (struct TALER_FAKEBANK_Handle *h) { for (uint64_t i = 0; iram_limit; i++) { struct Transaction *t = h->transactions[i]; if (NULL == t) continue; if (! t->unchecked) continue; switch (t->type) { case T_DEBIT: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s -> %s (%s) %s (%s)\n", t->debit_account->account_name, t->credit_account->account_name, TALER_amount2s (&t->amount), t->subject.debit.exchange_base_url, "DEBIT"); break; case T_CREDIT: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s -> %s (%s) %s (%s)\n", t->debit_account->account_name, t->credit_account->account_name, TALER_amount2s (&t->amount), TALER_B2S (&t->subject.credit.reserve_pub), "CREDIT"); break; case T_WAD: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s -> %s (%s) %s[%s] (%s)\n", t->debit_account->account_name, t->credit_account->account_name, TALER_amount2s (&t->amount), t->subject.wad.origin_base_url, TALER_B2S (&t->subject.wad), "WAD"); break; } } } enum GNUNET_GenericReturnValue TALER_FAKEBANK_check_debit (struct TALER_FAKEBANK_Handle *h, const struct TALER_Amount *want_amount, const char *want_debit, const char *want_credit, const char *exchange_base_url, struct TALER_WireTransferIdentifierRawP *wtid) { struct Account *debit_account; struct Account *credit_account; GNUNET_assert (0 == strcasecmp (want_amount->currency, h->currency)); debit_account = TALER_FAKEBANK_lookup_account_ (h, want_debit, NULL); credit_account = TALER_FAKEBANK_lookup_account_ (h, want_credit, NULL); if (NULL == debit_account) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "I wanted: %s->%s (%s) from exchange %s (DEBIT), but debit account does not even exist!\n", want_debit, want_credit, TALER_amount2s (want_amount), exchange_base_url); return GNUNET_SYSERR; } if (NULL == credit_account) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "I wanted: %s->%s (%s) from exchange %s (DEBIT), but credit account does not even exist!\n", want_debit, want_credit, TALER_amount2s (want_amount), exchange_base_url); return GNUNET_SYSERR; } for (struct Transaction *t = debit_account->out_tail; NULL != t; t = t->prev_out) { if ( (t->unchecked) && (credit_account == t->credit_account) && (T_DEBIT == t->type) && (0 == TALER_amount_cmp (want_amount, &t->amount)) && (0 == strcasecmp (exchange_base_url, t->subject.debit.exchange_base_url)) ) { *wtid = t->subject.debit.wtid; t->unchecked = false; return GNUNET_OK; } } GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not find matching transaction! I have:\n"); check_log (h); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "I wanted: %s->%s (%s) from exchange %s (DEBIT)\n", want_debit, want_credit, TALER_amount2s (want_amount), exchange_base_url); return GNUNET_SYSERR; } enum GNUNET_GenericReturnValue TALER_FAKEBANK_check_credit (struct TALER_FAKEBANK_Handle *h, const struct TALER_Amount *want_amount, const char *want_debit, const char *want_credit, const struct TALER_ReservePublicKeyP *reserve_pub) { struct Account *debit_account; struct Account *credit_account; GNUNET_assert (0 == strcasecmp (want_amount->currency, h->currency)); debit_account = TALER_FAKEBANK_lookup_account_ (h, want_debit, NULL); credit_account = TALER_FAKEBANK_lookup_account_ (h, want_credit, NULL); if (NULL == debit_account) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "I wanted:\n%s -> %s (%s) with subject %s (CREDIT) but debit account is unknown.\n", want_debit, want_credit, TALER_amount2s (want_amount), TALER_B2S (reserve_pub)); return GNUNET_SYSERR; } if (NULL == credit_account) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "I wanted:\n%s -> %s (%s) with subject %s (CREDIT) but credit account is unknown.\n", want_debit, want_credit, TALER_amount2s (want_amount), TALER_B2S (reserve_pub)); return GNUNET_SYSERR; } for (struct Transaction *t = credit_account->in_tail; NULL != t; t = t->prev_in) { if ( (t->unchecked) && (debit_account == t->debit_account) && (T_CREDIT == t->type) && (0 == TALER_amount_cmp (want_amount, &t->amount)) && (0 == GNUNET_memcmp (reserve_pub, &t->subject.credit.reserve_pub)) ) { t->unchecked = false; return GNUNET_OK; } } GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not find matching transaction!\nI have:\n"); check_log (h); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "I wanted:\n%s -> %s (%s) with subject %s (CREDIT)\n", want_debit, want_credit, TALER_amount2s (want_amount), TALER_B2S (reserve_pub)); return GNUNET_SYSERR; } enum GNUNET_GenericReturnValue TALER_FAKEBANK_check_empty (struct TALER_FAKEBANK_Handle *h) { for (uint64_t i = 0; iram_limit; i++) { struct Transaction *t = h->transactions[i]; if ( (NULL != t) && (t->unchecked) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected empty transaction set, but I have:\n"); check_log (h); return GNUNET_SYSERR; } } return GNUNET_OK; }