diff options
author | Christian Grothoff <christian@grothoff.org> | 2024-07-16 15:03:44 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2024-07-29 12:18:45 +0200 |
commit | fa22c593f4c8ca85978329c22dcfdd5da9ba6d7b (patch) | |
tree | a524059d059e8e864b6c80a71557224200d51fe5 | |
parent | b74676950a547f203459c9d274646c356bf07e7c (diff) |
start with wire-gateway API v1 implementation
-rw-r--r-- | src/auditor/taler-helper-auditor-wire.c | 147 | ||||
-rw-r--r-- | src/bank-lib/Makefile.am | 5 | ||||
-rw-r--r-- | src/bank-lib/bank_api_admin_add_incoming.c (renamed from src/bank-lib/bank_api_admin.c) | 4 | ||||
-rw-r--r-- | src/bank-lib/bank_api_admin_add_kycauth.c | 260 | ||||
-rw-r--r-- | src/bank-lib/bank_api_credit.c | 71 | ||||
-rw-r--r-- | src/bank-lib/taler-exchange-wire-gateway-client.c | 33 | ||||
-rw-r--r-- | src/exchange/taler-exchange-wirewatch.c | 121 | ||||
-rw-r--r-- | src/include/taler_bank_service.h | 258 | ||||
-rw-r--r-- | src/include/taler_exchangedb_plugin.h | 44 | ||||
-rw-r--r-- | src/testing/testing_api_cmd_bank_history_credit.c | 162 |
10 files changed, 938 insertions, 167 deletions
diff --git a/src/auditor/taler-helper-auditor-wire.c b/src/auditor/taler-helper-auditor-wire.c index d63e741a2..3d6f04ebf 100644 --- a/src/auditor/taler-helper-auditor-wire.c +++ b/src/auditor/taler-helper-auditor-wire.c @@ -361,7 +361,7 @@ struct ReserveInInfo * The member "account_url" is to be allocated * at the end of this struct! */ - struct TALER_BANK_CreditDetails details; + struct TALER_BANK_CreditDetails credit_details; /** * RowID in reserves_in table. @@ -2151,10 +2151,11 @@ reserve_in_cb (void *cls, slen = strlen (sender_account_details) + 1; rii = GNUNET_malloc (sizeof (struct ReserveInInfo) + slen); rii->rowid = rowid; - rii->details.amount = *credit; - rii->details.execution_date = execution_date; - rii->details.reserve_pub = *reserve_pub; - rii->details.debit_account_uri = (const char *) &rii[1]; + rii->credit_details.type = TALER_BANK_CT_RESERVE; + rii->credit_details.amount = *credit; + rii->credit_details.execution_date = execution_date; + rii->credit_details.details.reserve.reserve_pub = *reserve_pub; + rii->credit_details.debit_account_uri = (const char *) &rii[1]; GNUNET_memcpy (&rii[1], sender_account_details, slen); @@ -2237,19 +2238,22 @@ complain_in_not_found (void *cls, { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); } + GNUNET_assert (TALER_BANK_CT_RESERVE == + rii->credit_details.type); TALER_ARL_report ( report_reserve_in_inconsistencies, GNUNET_JSON_PACK ( GNUNET_JSON_pack_uint64 ("row", rii->rowid), TALER_JSON_pack_amount ("amount_exchange_expected", - &rii->details.amount), + &rii->credit_details.amount), TALER_JSON_pack_amount ("amount_wired", &zero), GNUNET_JSON_pack_data_auto ("reserve_pub", - &rii->details.reserve_pub), + &rii->credit_details.reserve.reserve_pub), TALER_JSON_pack_time_abs_human ("timestamp", - rii->details.execution_date.abs_time), + rii->credit_details.execution_date. + abs_time), GNUNET_JSON_pack_string ("account", wa->ai->section_name), GNUNET_JSON_pack_string ("diagnostic", @@ -2257,7 +2261,7 @@ complain_in_not_found (void *cls, #endif TALER_ARL_amount_add (&total_bad_amount_in_minus, &total_bad_amount_in_minus, - &rii->details.amount); + &rii->credit_details.amount); return GNUNET_OK; } @@ -2306,8 +2310,9 @@ conclude_account (struct WireAccount *wa) * @return true on success, false to stop loop at this point */ static bool -analyze_credit (struct WireAccount *wa, - const struct TALER_BANK_CreditDetails *details) +analyze_credit ( + struct WireAccount *wa, + const struct TALER_BANK_CreditDetails *credit_details) { struct ReserveInInfo *rii; struct GNUNET_HashCode key; @@ -2318,13 +2323,15 @@ analyze_credit (struct WireAccount *wa, // struct TALER_AUDITORDB_MisattributionInInconsistency mii; // struct TALER_AUDITORDB_RowMinorInconsistencies rmi; + GNUNET_assert (TALER_BANK_CT_RESERVE == + credit_details->type); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Analyzing bank CREDIT at %s of %s with Reserve-pub %s\n", - GNUNET_TIME_timestamp2s (details->execution_date), - TALER_amount2s (&details->amount), - TALER_B2S (&details->reserve_pub)); - GNUNET_CRYPTO_hash (&details->serial_id, - sizeof (details->serial_id), + GNUNET_TIME_timestamp2s (credit_details->execution_date), + TALER_amount2s (&credit_details->amount), + TALER_B2S (&credit_details->details.reserve.reserve_pub)); + GNUNET_CRYPTO_hash (&credit_details->serial_id, + sizeof (credit_details->serial_id), &key); rii = GNUNET_CONTAINER_multihashmap_get (in_map, &key); @@ -2332,24 +2339,24 @@ analyze_credit (struct WireAccount *wa, { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Failed to find wire transfer at `%s' in exchange database. Audit ends at this point in time.\n", - GNUNET_TIME_timestamp2s (details->execution_date)); + GNUNET_TIME_timestamp2s (credit_details->execution_date)); process_credits (wa->next); return false; /* not an error, just end of processing */ } /* Update offset */ - wa->wire_off_in = details->serial_id; + wa->wire_off_in = credit_details->serial_id; /* compare records with expected data */ - if (0 != GNUNET_memcmp (&details->reserve_pub, - &rii->details.reserve_pub)) + if (0 != GNUNET_memcmp (&credit_details->details.reserve.reserve_pub, + &rii->credit_details.details.reserve.reserve_pub)) { #if FIXME riiDb.diagnostic = "wire subject does not match"; riiDb.account = details->serial_id; - riiDb.amount_exchange_expected = &rii->details.amount; + riiDb.amount_exchange_expected = &rii->credit_details.amount; riiDb.amount_wired = &zero; - riiDb.reserve_pub = &rii->details.reserve_pub; - riiDb.timestamp = rii->details.execution_date.abs_time; + riiDb.reserve_pub = &rii->credit_details.detaisl.reserve.reserve_pub; + riiDb.timestamp = rii->credit_details.execution_date.abs_time; qs = TALER_ARL_adb->insert_reserve_in_inconsistency ( TALER_ARL_adb->cls, @@ -2365,28 +2372,30 @@ analyze_credit (struct WireAccount *wa, GNUNET_JSON_pack_uint64 ("row", rii->rowid), GNUNET_JSON_pack_uint64 ("bank_row", - details->serial_id), + credit_details->serial_id), TALER_JSON_pack_amount ("amount_exchange_expected", - &rii->details.amount), + &rii->credit_details.amount), TALER_JSON_pack_amount ("amount_wired", &zero), GNUNET_JSON_pack_data_auto ("reserve_pub", - &rii->details.reserve_pub), + &rii->credit_details.details.reserve. + reserve_pub), TALER_JSON_pack_time_abs_human ("timestamp", - rii->details.execution_date.abs_time), + rii->credit_details.execution_date. + abs_time), GNUNET_JSON_pack_string ("diagnostic", "wire subject does not match"))); #endif TALER_ARL_amount_add (&total_bad_amount_in_minus, &total_bad_amount_in_minus, - &rii->details.amount); + &rii->credit_details.amount); #if FIXME riiDb2.diagnostic = "wire subject does not match"; - riiDb2.account = details->serial_id; - riiDb2.amount_exchange_expected = &rii->details.amount; + riiDb2.account = credit_details->serial_id; + riiDb2.amount_exchange_expected = &rii->credit_details.amount; riiDb2.amount_wired = &zero; - riiDb2.reserve_pub = &rii->details.reserve_pub; - riiDb2.timestamp = rii->details.execution_date.abs_time; + riiDb2.reserve_pub = &rii->credit_details.details.reserve.reserve_pub; + riiDb2.timestamp = rii->credit_details.execution_date.abs_time; qs = TALER_ARL_adb->insert_reserve_in_inconsistency ( TALER_ARL_adb->cls, @@ -2402,33 +2411,35 @@ analyze_credit (struct WireAccount *wa, GNUNET_JSON_pack_uint64 ("row", rii->rowid), GNUNET_JSON_pack_uint64 ("bank_row", - details->serial_id), + credit_details->serial_id), TALER_JSON_pack_amount ("amount_exchange_expected", &zero), TALER_JSON_pack_amount ("amount_wired", - &details->amount), + &credit_details->amount), GNUNET_JSON_pack_data_auto ("reserve_pub", - &details->reserve_pub), + &credit_details->details.reserve.reserve_pub + ), TALER_JSON_pack_time_abs_human ("timestamp", - details->execution_date.abs_time), + credit_details->execution_date.abs_time) + , GNUNET_JSON_pack_string ("diagnostic", "wire subject does not match"))); #endif TALER_ARL_amount_add (&total_bad_amount_in_plus, &total_bad_amount_in_plus, - &details->amount); + &credit_details->amount); goto cleanup; } - if (0 != TALER_amount_cmp (&rii->details.amount, - &details->amount)) + if (0 != TALER_amount_cmp (&rii->credit_details.amount, + &credit_details->amount)) { #if FIXME riiDb3.diagnostic = "wire amount does not match"; - riiDb3.account = details->serial_id; - riiDb3.amount_exchange_expected = &rii->details.amount; - riiDb3.amount_wired = &details->amount; - riiDb3.reserve_pub = &rii->details.reserve_pub; - riiDb3.timestamp = rii->details.execution_date.abs_time; + riiDb3.account = credit_details->serial_id; + riiDb3.amount_exchange_expected = &rii->credit_details.amount; + riiDb3.amount_wired = &credit_details->amount; + riiDb3.reserve_pub = &rii->credit_details.details.reserve.reserve_pub; + riiDb3.timestamp = rii->credit_details.execution_date.abs_time; qs = TALER_ARL_adb->insert_reserve_in_inconsistency ( TALER_ARL_adb->cls, @@ -2444,27 +2455,29 @@ analyze_credit (struct WireAccount *wa, GNUNET_JSON_pack_uint64 ("row", rii->rowid), GNUNET_JSON_pack_uint64 ("bank_row", - details->serial_id), + credit_details->serial_id), TALER_JSON_pack_amount ("amount_exchange_expected", - &rii->details.amount), + &rii->credit_details.amount), TALER_JSON_pack_amount ("amount_wired", - &details->amount), + &credit_details->amount), GNUNET_JSON_pack_data_auto ("reserve_pub", - &details->reserve_pub), + &credit_details->details.reserve.reserve_pub + ), TALER_JSON_pack_time_abs_human ("timestamp", - details->execution_date.abs_time), + credit_details->execution_date.abs_time) + , GNUNET_JSON_pack_string ("diagnostic", "wire amount does not match"))); #endif - if (0 < TALER_amount_cmp (&details->amount, - &rii->details.amount)) + if (0 < TALER_amount_cmp (&credit_details->amount, + &rii->credit_details.amount)) { /* details->amount > rii->details.amount: wire transfer was larger than it should have been */ struct TALER_Amount delta; TALER_ARL_amount_subtract (&delta, - &details->amount, - &rii->details.amount); + &credit_details->amount, + &rii->credit_details.amount); TALER_ARL_amount_add (&total_bad_amount_in_plus, &total_bad_amount_in_plus, &delta); @@ -2475,21 +2488,21 @@ analyze_credit (struct WireAccount *wa, struct TALER_Amount delta; TALER_ARL_amount_subtract (&delta, - &rii->details.amount, - &details->amount); + &rii->credit_details.amount, + &credit_details->amount); TALER_ARL_amount_add (&total_bad_amount_in_minus, &total_bad_amount_in_minus, &delta); } goto cleanup; } - if (0 != strcasecmp (details->debit_account_uri, - rii->details.debit_account_uri)) + if (0 != strcasecmp (credit_details->debit_account_uri, + rii->credit_details.debit_account_uri)) { #if FIXME - mii.reserve_pub = &rii->details.reserve_pub; - mii.amount = &rii->details.amount; - mii.bank_row = details->serial_id; + mii.reserve_pub = &rii->credit_details.details.reserve.reserve_pub; + mii.amount = &rii->credit_details.amount; + mii.bank_row = credit_details->serial_id; qs = TALER_ARL_adb->insert_misattribution_in_inconsistency ( TALER_ARL_adb->cls, @@ -2502,22 +2515,22 @@ analyze_credit (struct WireAccount *wa, TALER_ARL_report (report_misattribution_in_inconsistencies, GNUNET_JSON_PACK ( TALER_JSON_pack_amount ("amount", - &rii->details.amount), + &rii->credit_details.amount), GNUNET_JSON_pack_uint64 ("row", rii->rowid), GNUNET_JSON_pack_uint64 ("bank_row", - details->serial_id), + credit_details->serial_id), GNUNET_JSON_pack_data_auto ( "reserve_pub", - &rii->details.reserve_pub))); + &rii->credit_details.details.reserve.reserve_pub))); #endif TALER_ARL_amount_add (&total_misattribution_in, &total_misattribution_in, - &rii->details.amount); + &rii->credit_details.amount); } - if (GNUNET_TIME_timestamp_cmp (details->execution_date, + if (GNUNET_TIME_timestamp_cmp (credit_details->execution_date, !=, - rii->details.execution_date)) + rii->credit_details.execution_date)) { #if FIXME rmi.diagnostic = "execution date mismatch"; @@ -2538,7 +2551,7 @@ analyze_credit (struct WireAccount *wa, GNUNET_JSON_pack_uint64 ("row", rii->rowid), GNUNET_JSON_pack_uint64 ("bank_row", - details->serial_id), + credit_details->serial_id), GNUNET_JSON_pack_string ("diagnostic", "execution date mismatch"))); #endif diff --git a/src/bank-lib/Makefile.am b/src/bank-lib/Makefile.am index ef7704684..816395cdd 100644 --- a/src/bank-lib/Makefile.am +++ b/src/bank-lib/Makefile.am @@ -34,10 +34,11 @@ lib_LTLIBRARIES = \ libtalerfakebank.la libtalerbank_la_LDFLAGS = \ - -version-info 1:0:0 \ + -version-info 2:0:0 \ -no-undefined libtalerbank_la_SOURCES = \ - bank_api_admin.c \ + bank_api_admin_add_incoming.c \ + bank_api_admin_add_kycauth.c \ bank_api_common.c bank_api_common.h \ bank_api_credit.c \ bank_api_debit.c \ diff --git a/src/bank-lib/bank_api_admin.c b/src/bank-lib/bank_api_admin_add_incoming.c index f12ab6ee2..ffc89ccc5 100644 --- a/src/bank-lib/bank_api_admin.c +++ b/src/bank-lib/bank_api_admin_add_incoming.c @@ -15,7 +15,7 @@ <http://www.gnu.org/licenses/> */ /** - * @file bank-lib/bank_api_admin.c + * @file bank-lib/bank_api_admin_add_incoming.c * @brief Implementation of the /admin/add-incoming requests of the bank's HTTP API * @author Christian Grothoff */ @@ -262,4 +262,4 @@ TALER_BANK_admin_add_incoming_cancel ( } -/* end of bank_api_admin.c */ +/* end of bank_api_admin_add_incoming.c */ diff --git a/src/bank-lib/bank_api_admin_add_kycauth.c b/src/bank-lib/bank_api_admin_add_kycauth.c new file mode 100644 index 000000000..1660305b1 --- /dev/null +++ b/src/bank-lib/bank_api_admin_add_kycauth.c @@ -0,0 +1,260 @@ +/* + This file is part of TALER + Copyright (C) 2015--2024 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 + <http://www.gnu.org/licenses/> +*/ +/** + * @file bank-lib/bank_api_admin_add_kycauth.c + * @brief Implementation of the /admin/add-kycauth requests of the bank's HTTP API + * @author Christian Grothoff + */ +#include "platform.h" +#include "bank_api_common.h" +#include <microhttpd.h> /* just for HTTP status codes */ +#include "taler_signatures.h" +#include "taler_curl_lib.h" + + +/** + * @brief An /admin/add-kycauth Handle + */ +struct TALER_BANK_AdminAddKycauthHandle +{ + + /** + * The url for this request. + */ + char *request_url; + + /** + * POST context. + */ + struct TALER_CURL_PostContext post_ctx; + + /** + * Handle for the request. + */ + struct GNUNET_CURL_Job *job; + + /** + * Function to call with the result. + */ + TALER_BANK_AdminAddKycauthCallback cb; + + /** + * Closure for @a cb. + */ + void *cb_cls; + +}; + + +/** + * Function called when we're done processing the + * HTTP /admin/add-kycauth request. + * + * @param cls the `struct TALER_BANK_AdminAddKycauthHandle` + * @param response_code HTTP response code, 0 on error + * @param response parsed JSON result, NULL on error + */ +static void +handle_admin_add_kycauth_finished (void *cls, + long response_code, + const void *response) +{ + struct TALER_BANK_AdminAddKycauthHandle *aai = cls; + const json_t *j = response; + struct TALER_BANK_AdminAddKycauthResponse ir = { + .http_status = response_code, + .response = response + }; + + aai->job = NULL; + switch (response_code) + { + case 0: + ir.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + break; + case MHD_HTTP_OK: + { + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_uint64 ("row_id", + &ir.details.ok.serial_id), + GNUNET_JSON_spec_timestamp ("timestamp", + &ir.details.ok.timestamp), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (j, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + ir.http_status = 0; + ir.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + break; + } + } + break; + case MHD_HTTP_BAD_REQUEST: + /* This should never happen, either us or the bank is buggy + (or API version conflict); just pass JSON reply to the application */ + GNUNET_break_op (0); + ir.ec = TALER_JSON_get_error_code (j); + break; + case MHD_HTTP_FORBIDDEN: + /* Access denied */ + ir.ec = TALER_JSON_get_error_code (j); + break; + case MHD_HTTP_UNAUTHORIZED: + /* Nothing really to verify, bank says the password is invalid; we should + pass the JSON reply to the application */ + ir.ec = TALER_JSON_get_error_code (j); + break; + case MHD_HTTP_NOT_FOUND: + /* Nothing really to verify, maybe account really does not exist. + We should pass the JSON reply to the application */ + ir.ec = TALER_JSON_get_error_code (j); + break; + case MHD_HTTP_INTERNAL_SERVER_ERROR: + /* Server had an internal issue; we should retry, but this API + leaves this to the application */ + ir.ec = TALER_JSON_get_error_code (j); + break; + default: + /* unexpected response code */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u\n", + (unsigned int) response_code); + GNUNET_break (0); + ir.ec = TALER_JSON_get_error_code (j); + break; + } + aai->cb (aai->cb_cls, + &ir); + TALER_BANK_admin_add_kycauth_cancel (aai); +} + + +struct TALER_BANK_AdminAddKycauthHandle * +TALER_BANK_admin_add_kycauth ( + struct GNUNET_CURL_Context *ctx, + const struct TALER_BANK_AuthenticationData *auth, + const union TALER_AccountPublicKeyP *account_pub, + const struct TALER_Amount *amount, + const char *debit_account, + TALER_BANK_AdminAddKycauthCallback res_cb, + void *res_cb_cls) +{ + struct TALER_BANK_AdminAddKycauthHandle *aai; + json_t *admin_obj; + CURL *eh; + + if (NULL == debit_account) + { + GNUNET_break (0); + return NULL; + } + if (NULL == account_pub) + { + GNUNET_break (0); + return NULL; + } + if (NULL == amount) + { + GNUNET_break (0); + return NULL; + } + admin_obj = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_data_auto ("account_pub", + account_pub), + TALER_JSON_pack_amount ("amount", + amount), + GNUNET_JSON_pack_string ("debit_account", + debit_account)); + if (NULL == admin_obj) + { + GNUNET_break (0); + return NULL; + } + aai = GNUNET_new (struct TALER_BANK_AdminAddKycauthHandle); + aai->cb = res_cb; + aai->cb_cls = res_cb_cls; + aai->request_url = TALER_url_join (auth->wire_gateway_url, + "admin/add-kycauth", + NULL); + if (NULL == aai->request_url) + { + GNUNET_free (aai); + json_decref (admin_obj); + return NULL; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Requesting administrative transaction at `%s' for account %s\n", + aai->request_url, + TALER_B2S (account_pub)); + aai->post_ctx.headers + = curl_slist_append ( + aai->post_ctx.headers, + "Content-Type: application/json"); + + eh = curl_easy_init (); + if ( (NULL == eh) || + (GNUNET_OK != + TALER_BANK_setup_auth_ (eh, + auth)) || + (CURLE_OK != + curl_easy_setopt (eh, + CURLOPT_URL, + aai->request_url)) || + (GNUNET_OK != + TALER_curl_easy_post (&aai->post_ctx, + eh, + admin_obj)) ) + { + GNUNET_break (0); + TALER_BANK_admin_add_kycauth_cancel (aai); + if (NULL != eh) + curl_easy_cleanup (eh); + json_decref (admin_obj); + return NULL; + } + json_decref (admin_obj); + + aai->job = GNUNET_CURL_job_add2 (ctx, + eh, + aai->post_ctx.headers, + &handle_admin_add_kycauth_finished, + aai); + return aai; +} + + +void +TALER_BANK_admin_add_kycauth_cancel ( + struct TALER_BANK_AdminAddKycauthHandle *aai) +{ + if (NULL != aai->job) + { + GNUNET_CURL_job_cancel (aai->job); + aai->job = NULL; + } + TALER_curl_easy_post_finished (&aai->post_ctx); + GNUNET_free (aai->request_url); + GNUNET_free (aai); +} + + +/* end of bank_api_admin_add_kycauth.c */ diff --git a/src/bank-lib/bank_api_credit.c b/src/bank-lib/bank_api_credit.c index 124415b80..ebcdb56cc 100644 --- a/src/bank-lib/bank_api_credit.c +++ b/src/bank-lib/bank_api_credit.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2017--2023 Taler Systems SA + Copyright (C) 2017--2024 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -108,15 +108,16 @@ parse_account_history (struct TALER_BANK_CreditHistoryHandle *hh, for (size_t i = 0; i<len; i++) { struct TALER_BANK_CreditDetails *td = &cd[i]; + const char *type; struct GNUNET_JSON_Specification hist_spec[] = { + GNUNET_JSON_spec_string ("type", + &type), TALER_JSON_spec_amount_any ("amount", &td->amount), GNUNET_JSON_spec_timestamp ("date", &td->execution_date), GNUNET_JSON_spec_uint64 ("row_id", &td->serial_id), - GNUNET_JSON_spec_fixed_auto ("reserve_pub", - &td->reserve_pub), GNUNET_JSON_spec_string ("debit_account", &td->debit_account_uri), GNUNET_JSON_spec_end () @@ -133,6 +134,70 @@ parse_account_history (struct TALER_BANK_CreditHistoryHandle *hh, GNUNET_break_op (0); return GNUNET_SYSERR; } + if (0 == strcasecmp ("RESERVE", + type)) + { + struct GNUNET_JSON_Specification reserve_spec[] = { + GNUNET_JSON_spec_fixed_auto ("reserve_pub", + &td->details.reserve.reserve_pub), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (transaction, + reserve_spec, + NULL, + NULL)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + } + else if (0 == strcasecmp ("KYCAUTH", + type)) + { + struct GNUNET_JSON_Specification kycauth_spec[] = { + GNUNET_JSON_spec_fixed_auto ("account_pub", + &td->details.kycauth.account_pub), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (transaction, + kycauth_spec, + NULL, + NULL)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + } + else if (0 == strcasecmp ("WAD", + type)) + { + struct GNUNET_JSON_Specification wad_spec[] = { + GNUNET_JSON_spec_string ("origin_exchange_url", + &td->details.wad.origin_exchange_url), + GNUNET_JSON_spec_fixed_auto ("wad_id", + &td->details.wad.wad_id), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (transaction, + wad_spec, + NULL, + NULL)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + } + else + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } } chr.details.ok.details_length = len; chr.details.ok.details = cd; diff --git a/src/bank-lib/taler-exchange-wire-gateway-client.c b/src/bank-lib/taler-exchange-wire-gateway-client.c index b0d387b71..81b63401c 100644 --- a/src/bank-lib/taler-exchange-wire-gateway-client.c +++ b/src/bank-lib/taler-exchange-wire-gateway-client.c @@ -193,14 +193,31 @@ credit_history_cb (void *cls, (0 != strcasecmp (debit_account, cd->debit_account_uri) ) ) continue; - fprintf (stdout, - "%llu: %s->%s (%s) over %s at %s\n", - (unsigned long long) cd->serial_id, - cd->debit_account_uri, - reply->details.ok.credit_account_uri, - TALER_B2S (&cd->reserve_pub), - TALER_amount2s (&cd->amount), - GNUNET_TIME_timestamp2s (cd->execution_date)); + switch (cd->type) + { + case TALER_BANK_CT_RESERVE: + fprintf (stdout, + "%llu: %s->%s (%s) over %s at %s\n", + (unsigned long long) cd->serial_id, + cd->debit_account_uri, + reply->details.ok.credit_account_uri, + TALER_B2S (&cd->details.reserve.reserve_pub), + TALER_amount2s (&cd->amount), + GNUNET_TIME_timestamp2s (cd->execution_date)); + break; + case TALER_BANK_CT_KYCAUTH: + fprintf (stdout, + "%llu: %s->%s (KYC:%s) over %s at %s\n", + (unsigned long long) cd->serial_id, + cd->debit_account_uri, + reply->details.ok.credit_account_uri, + TALER_B2S (&cd->details.kycauth.account_pub), + TALER_amount2s (&cd->amount), + GNUNET_TIME_timestamp2s (cd->execution_date)); + case TALER_BANK_CT_WAD: + GNUNET_break (0); // FIXME + break; + } } global_ret = 0; break; diff --git a/src/exchange/taler-exchange-wirewatch.c b/src/exchange/taler-exchange-wirewatch.c index da5d9c098..12aebbcae 100644 --- a/src/exchange/taler-exchange-wirewatch.c +++ b/src/exchange/taler-exchange-wirewatch.c @@ -563,6 +563,7 @@ process_reply (const struct TALER_BANK_CreditDetails *details, { enum GNUNET_DB_QueryStatus qss[details_length]; struct TALER_EXCHANGEDB_ReserveInInfo reserves[details_length]; + unsigned int j = 0; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Importing %u transactions\n", @@ -570,39 +571,107 @@ process_reply (const struct TALER_BANK_CreditDetails *details, for (unsigned int i = 0; i<details_length; i++) { const struct TALER_BANK_CreditDetails *cd = &details[i]; - struct TALER_EXCHANGEDB_ReserveInInfo *res = &reserves[i]; - - res->reserve_pub = &cd->reserve_pub; - res->balance = &cd->amount; - res->execution_time = cd->execution_date; - res->sender_account_details = cd->debit_account_uri; - res->exchange_account_name = ai->section_name; - res->wire_reference = cd->serial_id; + + switch (cd->type) + { + case TALER_BANK_CT_RESERVE: + { + struct TALER_EXCHANGEDB_ReserveInInfo *res = &reserves[j++]; + + /* add to batch, do later */ + res->reserve_pub = &cd->details.reserve.reserve_pub; + res->balance = &cd->amount; + res->execution_time = cd->execution_date; + res->sender_account_details = cd->debit_account_uri; + res->exchange_account_name = ai->section_name; + res->wire_reference = cd->serial_id; + } + break; + case TALER_BANK_CT_KYCAUTH: + { + qs = db_plugin->kycauth_in_insert ( + db_plugin->cls, + &cd->details.kycauth.account_pub, + cd->execution_date, + cd->debit_account_uri, + ai->section_name, + cd->serial_id); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + return; + case GNUNET_DB_STATUS_SOFT_ERROR: + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Got DB soft error for kycauth_in_insert (%u). Rolling back.\n", + i); + handle_soft_error (); + return; + default: + break; + } + break; + } + case TALER_BANK_CT_WAD: + { + qs = db_plugin->wad_in_insert ( + db_plugin->cls, + &cd->details.wad.wad_id, + cd->details.wad.origin_exchange_url, + cd->execution_date, + cd->debit_account_uri, + ai->section_name, + cd->serial_id); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + return; + case GNUNET_DB_STATUS_SOFT_ERROR: + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Got DB soft error for wad_in_insert (%u). Rolling back.\n", + i); + handle_soft_error (); + return; + default: + break; + } + + } + } } - qs = db_plugin->reserves_in_insert (db_plugin->cls, - reserves, - details_length, - qss); - switch (qs) + if (j > 0) { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - GNUNET_SCHEDULER_shutdown (); - return; - case GNUNET_DB_STATUS_SOFT_ERROR: - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Got DB soft error for reserves_in_insert (%u). Rolling back.\n", - details_length); - handle_soft_error (); - return; - default: - break; + qs = db_plugin->reserves_in_insert (db_plugin->cls, + reserves, + j, + qss); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + return; + case GNUNET_DB_STATUS_SOFT_ERROR: + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Got DB soft error for reserves_in_insert (%u). Rolling back.\n", + details_length); + handle_soft_error (); + return; + default: + break; + } } + j = 0; for (unsigned int i = 0; i<details_length; i++) { const struct TALER_BANK_CreditDetails *cd = &details[i]; - switch (qss[i]) + if (TALER_BANK_CT_RESERVE != cd->type) + continue; + switch (qss[j++]) { case GNUNET_DB_STATUS_HARD_ERROR: GNUNET_break (0); diff --git a/src/include/taler_bank_service.h b/src/include/taler_bank_service.h index e8e32947b..5cf7d8ca9 100644 --- a/src/include/taler_bank_service.h +++ b/src/include/taler_bank_service.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2015-2021 Taler Systems SA + Copyright (C) 2015-2024 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software @@ -27,6 +27,11 @@ #include "taler_util.h" #include "taler_error_codes.h" +/** + * Version of the Bank API, in hex. + * Thus 0.12.0-0 = 0x000C0000. + */ +#define TALER_BANK_SERVICE_API_VERSION 0x000C0000 /** * Authentication method types. @@ -163,8 +168,7 @@ typedef void /** * Perform a wire transfer from some account to the exchange to fill a * reserve. Note that this API is usually only used for testing (with - * fakebank and our Python bank) and thus may not be accessible in a - * production setting. + * fakebank) and thus may not be accessible in a production setting. * * @param ctx curl context for the event loop * @param auth authentication data to send to the bank @@ -192,13 +196,119 @@ TALER_BANK_admin_add_incoming ( * Cancel an add incoming operation. This function cannot be used on a * request handle if a response is already served for it. * - * @param aai the admin add incoming request handle + * @param[in] aai the admin add incoming request handle */ void TALER_BANK_admin_add_incoming_cancel ( struct TALER_BANK_AdminAddIncomingHandle *aai); +/** + * @brief A /admin/add-kycauth Handle + */ +struct TALER_BANK_AdminAddKycauthHandle; + + +/** + * Response details for a history request. + */ +struct TALER_BANK_AdminAddKycauthResponse +{ + + /** + * HTTP status. + */ + unsigned int http_status; + + /** + * Taler error code, #TALER_EC_NONE on success. + */ + enum TALER_ErrorCode ec; + + /** + * Full response, NULL if body was not in JSON format. + */ + const json_t *response; + + /** + * Details returned depending on the @e http_status. + */ + union + { + + /** + * Details if status was #MHD_HTTP_OK + */ + struct + { + /** + * unique ID of the wire transfer in the bank's records + */ + uint64_t serial_id; + + /** + * time when the transaction was made. + */ + struct GNUNET_TIME_Timestamp timestamp; + + } ok; + + } details; + +}; + +/** + * Callbacks of this type are used to return the result of submitting + * a request to transfer funds to the exchange. + * + * @param cls closure + * @param air response details + */ +typedef void +(*TALER_BANK_AdminAddKycauthCallback) ( + void *cls, + const struct TALER_BANK_AdminAddKycauthResponse *air); + + +/** + * Perform a wire transfer from some account to the exchange to register a + * public key for KYC authentication of the origin account. Note that this + * API is usually only used for testing (with fakebank) and thus may not be + * accessible in a production setting. + * + * @param ctx curl context for the event loop + * @param auth authentication data to send to the bank + * @param account_pub wire transfer subject for the transfer + * @param amount amount that is to be deposited + * @param debit_account account to deposit from (payto URI, but used as 'payfrom') + * @param res_cb the callback to call when the final result for this request is available + * @param res_cb_cls closure for the above callback + * @return NULL + * if the inputs are invalid (i.e. invalid amount) or internal errors. + * In this case, the callback is not called. + */ +struct TALER_BANK_AdminAddKycauthHandle * +TALER_BANK_admin_add_kycauth ( + struct GNUNET_CURL_Context *ctx, + const struct TALER_BANK_AuthenticationData *auth, + const union TALER_AccountPublicKeyP *account_pub, + const struct TALER_Amount *amount, + const char *debit_account, + TALER_BANK_AdminAddKycauthCallback res_cb, + void *res_cb_cls); + + +/** + * Cancel an add kycauth operation. This function cannot be used on a + * request handle if a response is already served for it. + * + * @param[in] aai the admin add kycauth request handle + */ +void +TALER_BANK_admin_add_kycauth_cancel ( + struct TALER_BANK_AdminAddKycauthHandle *aai); + + /* ********************* /transfer *********************** */ /** @@ -302,12 +412,13 @@ typedef void * @return NULL on error */ struct TALER_BANK_TransferHandle * -TALER_BANK_transfer (struct GNUNET_CURL_Context *ctx, - const struct TALER_BANK_AuthenticationData *auth, - const void *buf, - size_t buf_size, - TALER_BANK_TransferCallback cc, - void *cc_cls); +TALER_BANK_transfer ( + struct GNUNET_CURL_Context *ctx, + const struct TALER_BANK_AuthenticationData *auth, + const void *buf, + size_t buf_size, + TALER_BANK_TransferCallback cc, + void *cc_cls); /** @@ -323,15 +434,40 @@ TALER_BANK_transfer (struct GNUNET_CURL_Context *ctx, * This function cannot be used on a request handle if a response is already * served for it. * - * @param th handle of the wire transfer request to cancel + * @param[in] th handle of the wire transfer request to cancel */ void -TALER_BANK_transfer_cancel (struct TALER_BANK_TransferHandle *th); +TALER_BANK_transfer_cancel ( + struct TALER_BANK_TransferHandle *th); /* ********************* /history/incoming *********************** */ /** + * Different types of wire transfers that might be + * credited to an exchange account. + */ +enum TALER_BANK_CreditType +{ + /** + * Common wire transfer into a reserve account. + */ + TALER_BANK_CT_RESERVE, + + /** + * KYC authentication wire transfer with an account + * public key. + */ + TALER_BANK_CT_KYCAUTH, + + /** + * WAD transfer between exchanges. + */ + TALER_BANK_CT_WAD + +}; + +/** * Handle for querying the bank for transactions * made to the exchange. */ @@ -342,6 +478,12 @@ struct TALER_BANK_CreditHistoryHandle; */ struct TALER_BANK_CreditDetails { + + /** + * Type of the wire transfer. + */ + enum TALER_BANK_CreditType type; + /** * Serial ID of the wire transfer. */ @@ -358,14 +500,61 @@ struct TALER_BANK_CreditDetails struct GNUNET_TIME_Timestamp execution_date; /** - * Reserve public key encoded in the wire transfer subject. + * payto://-URL of the source account that send the funds. */ - struct TALER_ReservePublicKeyP reserve_pub; + const char *debit_account_uri; /** - * payto://-URL of the source account that send the funds. + * Details that depend on the @e type. */ - const char *debit_account_uri; + union + { + + /** + * Details for @e type #TALER_BANK_CT_RESERVE. + */ + struct + { + + /** + * Reserve public key encoded in the wire transfer subject. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + } reserve; + + /** + * Details for @e type #TALER_BANK_CT_KYCAUTH. + */ + struct + { + + /** + * Public key to associate with the owner of the + * origin bank account. + */ + union TALER_AccountPublicKeyP account_pub; + + } kycauth; + + /** + * Details for @e type #TALER_BANK_CT_WAD. + */ + struct + { + + /** + * WAD identifier for the transfer. + */ + struct TALER_WadIdentifierP wad_id; + + /** + * Base URL of the exchange originating the transfer. + */ + const char *origin_exchange_url; + } wad; + + } details; }; @@ -473,10 +662,11 @@ TALER_BANK_credit_history ( * handle if the last response (anything with a status code other than * 200) is already served for it. * - * @param hh the history request handle + * @param[in] hh the history request handle */ void -TALER_BANK_credit_history_cancel (struct TALER_BANK_CreditHistoryHandle *hh); +TALER_BANK_credit_history_cancel ( + struct TALER_BANK_CreditHistoryHandle *hh); /* ********************* /history/outgoing *********************** */ @@ -614,13 +804,14 @@ typedef void * In this case, the callback is not called. */ struct TALER_BANK_DebitHistoryHandle * -TALER_BANK_debit_history (struct GNUNET_CURL_Context *ctx, - const struct TALER_BANK_AuthenticationData *auth, - uint64_t start_row, - int64_t num_results, - struct GNUNET_TIME_Relative timeout, - TALER_BANK_DebitHistoryCallback hres_cb, - void *hres_cb_cls); +TALER_BANK_debit_history ( + struct GNUNET_CURL_Context *ctx, + const struct TALER_BANK_AuthenticationData *auth, + uint64_t start_row, + int64_t num_results, + struct GNUNET_TIME_Relative timeout, + TALER_BANK_DebitHistoryCallback hres_cb, + void *hres_cb_cls); /** @@ -628,10 +819,11 @@ TALER_BANK_debit_history (struct GNUNET_CURL_Context *ctx, * handle if the last response (anything with a status code other than * 200) is already served for it. * - * @param hh the history request handle + * @param[in] hh the history request handle */ void -TALER_BANK_debit_history_cancel (struct TALER_BANK_DebitHistoryHandle *hh); +TALER_BANK_debit_history_cancel ( + struct TALER_BANK_DebitHistoryHandle *hh); /* ******************** Convenience functions **************** */ @@ -647,19 +839,21 @@ TALER_BANK_debit_history_cancel (struct TALER_BANK_DebitHistoryHandle *hh); * @return #GNUNET_OK on success */ enum GNUNET_GenericReturnValue -TALER_BANK_auth_parse_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *section, - struct TALER_BANK_AuthenticationData *auth); +TALER_BANK_auth_parse_cfg ( + const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section, + struct TALER_BANK_AuthenticationData *auth); /** * Free memory inside of @a auth (but not @a auth itself). * Dual to #TALER_BANK_auth_parse_cfg(). * - * @param auth authentication data to free + * @param[in,out] auth authentication data to free */ void -TALER_BANK_auth_free (struct TALER_BANK_AuthenticationData *auth); +TALER_BANK_auth_free ( + struct TALER_BANK_AuthenticationData *auth); #endif /* _TALER_BANK_SERVICE_H */ diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 98cf36569..0594461d0 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -3891,6 +3891,50 @@ struct TALER_EXCHANGEDB_Plugin /** + * Insert an incoming KCYAUTH wire transfer into + * the database and update the authentication key + * for the origin account. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param account_pub public key of the account + * @param execution_date when was the transfer made + * @param debit_account_uri URI of the debit account + * @param section_name section of the exchange bank account that received the transfer + * @param serial_id bank-specific row identifying the transfer + */ + enum GNUNET_DB_QueryStatus + (*kycauth_in_insert)( + void *cls, + const union TALER_AccountPublicKeyP *account_pub, + struct GNUNET_TIME_Timestamp execution_date, + const char *debit_account_uri, + const char *section_name, + uint64_t serial_id); + + + /** + * Insert an incoming WAD wire transfer into the database. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param wad_id WAD identifier + * @param origin_exchange_url exchange base URL originating the transfer + * @param execution_date when was the transfer made + * @param debit_account_uri URI of the debit account + * @param section_name section of the exchange bank account that received the transfer + * @param serial_id bank-specific row identifying the transfer + */ + enum GNUNET_DB_QueryStatus + (*wad_in_insert)( + void *cls, + const struct TALER_WadIdentifierP *wad_id, + const char *origin_exchange_url, + struct GNUNET_TIME_Timestamp execution_date, + const char *debit_account_uri, + const char *section_name, + uint64_t serial_id); + + + /** * Locate a nonce for use with a particular public key. * * @param cls the @e cls of this struct with the plugin-specific state diff --git a/src/testing/testing_api_cmd_bank_history_credit.c b/src/testing/testing_api_cmd_bank_history_credit.c index 956e6c857..81b538b2a 100644 --- a/src/testing/testing_api_cmd_bank_history_credit.c +++ b/src/testing/testing_api_cmd_bank_history_credit.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2018-2021 Taler Systems SA + Copyright (C) 2018-2024 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 @@ -41,7 +41,7 @@ struct History /** * Wire details. */ - struct TALER_BANK_CreditDetails details; + struct TALER_BANK_CreditDetails credit_details; /** * Serial ID of the wire transfer. @@ -136,14 +136,42 @@ print_expected (struct History *h, "Expected history:\n"); for (unsigned int i = 0; i<h_len; i++) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "H(%u): %s (serial: %llu, subject: %s," - " counterpart: %s)\n", - i, - TALER_amount2s (&h[i].details.amount), - (unsigned long long) h[i].row_id, - TALER_B2S (&h[i].details.reserve_pub), - h[i].details.debit_account_uri); + const struct TALER_BANK_CreditDetails *cd = &h[i].credit_details; + + switch (cd->type) + { + case TALER_BANK_CT_RESERVE: + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "H(%u): %s (serial: %llu, RES: %s," + " counterpart: %s)\n", + i, + TALER_amount2s (&cd->amount), + (unsigned long long) h[i].row_id, + TALER_B2S (&cd->details.reserve.reserve_pub), + cd->debit_account_uri); + break; + case TALER_BANK_CT_KYCAUTH: + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "H(%u): %s (serial: %llu, KYC: %s," + " counterpart: %s)\n", + i, + TALER_amount2s (&cd->amount), + (unsigned long long) h[i].row_id, + TALER_B2S (&cd->details.kycauth.account_pub), + cd->debit_account_uri); + break; + case TALER_BANK_CT_WAD: + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "H(%u): %s (serial: %llu, WAD: %s-%s," + " counterpart: %s)\n", + i, + TALER_amount2s (&cd->amount), + (unsigned long long) h[i].row_id, + TALER_B2S (&cd->details.wad.wad_id), + cd->details.wad.origin_exchange_url, + cd->debit_account_uri); + break; + } } } @@ -233,6 +261,8 @@ command_cb (void *cls, cmd, &exchange_credit_url)) ) return; // Not an interesting event + // FIXME: support KYCAUTH transfer events! + // FIXME: support WAD transfer events! /** * Is the interesting event a match with regard to @@ -272,10 +302,11 @@ command_cb (void *cls, ic->total, ic->pos * 2); ic->h[ic->pos].url = GNUNET_strdup (debit_account); - ic->h[ic->pos].details.debit_account_uri = ic->h[ic->pos].url; - ic->h[ic->pos].details.amount = *amount; ic->h[ic->pos].row_id = *row_id; - ic->h[ic->pos].details.reserve_pub = *reserve_pub; + ic->h[ic->pos].credit_details.type = TALER_BANK_CT_RESERVE; + ic->h[ic->pos].credit_details.debit_account_uri = ic->h[ic->pos].url; + ic->h[ic->pos].credit_details.amount = *amount; + ic->h[ic->pos].credit_details.details.reserve.reserve_pub = *reserve_pub; ic->pos++; } @@ -409,14 +440,14 @@ normalize (const char *in) * @param total length of @a h * @param off the offset (of the CMD list) where the command * to check is. - * @param details the expected transaction details. + * @param credit_details the expected transaction details. * @return #GNUNET_OK if the transaction is what we expect. */ static enum GNUNET_GenericReturnValue check_result (struct History *h, unsigned int total, unsigned int off, - const struct TALER_BANK_CreditDetails *details) + const struct TALER_BANK_CreditDetails *credit_details) { char *u1; char *u2; @@ -433,33 +464,31 @@ check_result (struct History *h, off); return GNUNET_SYSERR; } - u1 = normalize (h[off].details.debit_account_uri); + u1 = normalize (h[off].credit_details.debit_account_uri); if (NULL == u1) return GNUNET_SYSERR; - u2 = normalize (details->debit_account_uri); + u2 = normalize (credit_details->debit_account_uri); if (NULL == u2) { GNUNET_free (u1); return GNUNET_SYSERR; } - if ( (0 != GNUNET_memcmp (&h[off].details.reserve_pub, - &details->reserve_pub)) || - (0 != TALER_amount_cmp (&h[off].details.amount, - &details->amount)) || + if ( (h[off].credit_details.type != + credit_details->type) || + (0 != TALER_amount_cmp (&h[off].credit_details.amount, + &credit_details->amount)) || (0 != strcasecmp (u1, u2)) ) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "expected debit_account_uri: %s with %s for %s\n", + "expected debit_account_uri: %s with %s\n", u1, - TALER_amount2s (&h[off].details.amount), - TALER_B2S (&h[off].details.reserve_pub)); + TALER_amount2s (&h[off].credit_details.amount)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "actual debit_account_uri: %s with %s for %s\n", + "actual debit_account_uri: %s with %s\n", u2, - TALER_amount2s (&details->amount), - TALER_B2S (&details->reserve_pub)); + TALER_amount2s (&credit_details->amount)); print_expected (h, total, off); @@ -467,6 +496,85 @@ check_result (struct History *h, GNUNET_free (u2); return GNUNET_SYSERR; } + switch (credit_details->type) + { + case TALER_BANK_CT_RESERVE: + if (0 != GNUNET_memcmp (&h[off].credit_details.details.reserve.reserve_pub, + &credit_details->details.reserve.reserve_pub)) + { + GNUNET_break (0); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "expected debit_account_uri: %s with %s for %s\n", + u1, + TALER_amount2s (&h[off].credit_details.amount), + TALER_B2S (&h[off].credit_details.details.reserve.reserve_pub) + ); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "actual debit_account_uri: %s with %s for %s\n", + u2, + TALER_amount2s (&credit_details->amount), + TALER_B2S (&credit_details->details.reserve.reserve_pub)); + print_expected (h, + total, + off); + GNUNET_free (u1); + GNUNET_free (u2); + return GNUNET_SYSERR; + } + break; + case TALER_BANK_CT_KYCAUTH: + if (0 != GNUNET_memcmp (&h[off].credit_details.details.kycauth.account_pub, + &credit_details->details.kycauth.account_pub)) + { + GNUNET_break (0); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "expected debit_account_uri: %s with %s for %s\n", + u1, + TALER_amount2s (&h[off].credit_details.amount), + TALER_B2S (&h[off].credit_details.details.kycauth.account_pub) + ); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "actual debit_account_uri: %s with %s for %s\n", + u2, + TALER_amount2s (&credit_details->amount), + TALER_B2S (&credit_details->details.kycauth.account_pub)); + print_expected (h, + total, + off); + GNUNET_free (u1); + GNUNET_free (u2); + return GNUNET_SYSERR; + } + break; + case TALER_BANK_CT_WAD: + if ( (0 != GNUNET_memcmp (&h[off].credit_details.details.wad.wad_id, + &credit_details->details.wad.wad_id)) || + (0 != strcmp (h[off].credit_details.details.wad.origin_exchange_url, + credit_details->details.wad.origin_exchange_url)) ) + { + GNUNET_break (0); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "expected debit_account_uri: %s with %s for %s-%s\n", + u1, + TALER_amount2s (&h[off].credit_details.amount), + h[off].credit_details.details.wad.origin_exchange_url, + TALER_B2S (&h[off].credit_details.details.wad.wad_id)); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "actual debit_account_uri: %s with %s for %s-%s\n", + u2, + TALER_amount2s (&credit_details->amount), + credit_details->details.wad.origin_exchange_url, + TALER_B2S (&credit_details->details.wad.wad_id)); + print_expected (h, + total, + off); + GNUNET_free (u1); + GNUNET_free (u2); + return GNUNET_SYSERR; + } + break; + } + GNUNET_free (u1); GNUNET_free (u2); return GNUNET_OK; |